/* ==========================================================================
   DNA SenangUrus — Sponsor Dashboard
   Design system. Brand red #D81B2A, sourced from Quickro app.css.
   ========================================================================== */

/* ---- Tokens -------------------------------------------------------------- */
:root {
  /* Quickro brand red ladder */
  --brand-50:  #fef2f3;
  --brand-100: #fde8ea;
  --brand-200: #fbd5d9;
  --brand-300: #f7aeb5;
  --brand-400: #f27e8a;
  --brand-500: #e74e5f;
  --brand-600: #d81b2a;
  --brand-700: #b91525;
  --brand-800: #9a1422;
  --brand-900: #7f1520;
  --brand-950: #46060d;

  /* Semantic — light */
  --bg:           #faf8f7;
  --bg-deep:      #f3efee;
  --surface:      #ffffff;
  --surface-alt:  #f7f4f3;
  --surface-sunk: #efeae9;
  --border:       #e7e0df;
  --border-strong:#d6cdcb;
  --text:         #1a1416;
  --text-dim:     #5c5154;
  --text-mute:    #756a6d;

  --accent:       var(--brand-600);
  --accent-hover: var(--brand-700);
  --accent-soft:  var(--brand-50);
  --accent-line:  var(--brand-200);
  --on-accent:    #ffffff;

  --positive:      #0f7b52;
  --positive-soft: #e6f5ee;
  --positive-line: #b7e0cd;
  --warning:       #9a5b00;
  --warning-soft:  #fdf1de;
  --warning-line:  #f0d5a8;
  --negative:      #b3182b;
  --negative-soft: #fdecee;
  --negative-line: #f5c6cc;
  --info:          #1d4ed8;
  --info-soft:     #e8eefc;
  --info-line:     #c3d3f7;
  --neutral:       #6b6164;
  --neutral-soft:  #f0ecec;

  /* Sequential ramp for map + heat, brand-derived */
  --ramp-1: #fde8ea;
  --ramp-2: #f7aeb5;
  --ramp-3: #ef6d7d;
  --ramp-4: #d81b2a;
  --ramp-5: #9a1422;
  --ramp-1-fg: #7f1520;
  --ramp-2-fg: #7f1520;
  --ramp-3-fg: #46060d;
  --ramp-4-fg: #ffffff;
  --ramp-5-fg: #ffffff;

  /* Type */
  --font-display: 'Bricolage Grotesque', 'Manrope', system-ui, sans-serif;
  --font-body:    'IBM Plex Sans', system-ui, -apple-system, sans-serif;
  --font-num:     'IBM Plex Mono', ui-monospace, monospace;

  /* Elevation — one system, shadow only */
  --lift-1: 0 1px 2px rgba(26, 20, 22, .05), 0 2px 8px -4px rgba(26, 20, 22, .08);
  --lift-2: 0 2px 6px rgba(26, 20, 22, .06), 0 12px 28px -12px rgba(26, 20, 22, .16);
  --lift-3: 0 8px 20px rgba(26, 20, 22, .10), 0 32px 64px -24px rgba(26, 20, 22, .26);
  --lift-brand: 0 2px 6px rgba(216, 27, 42, .18), 0 16px 32px -16px rgba(216, 27, 42, .34);
  /* Floating surfaces declare their edge inside the shadow, not as a border. */
  --lift-float: 0 0 0 1px var(--border), 0 4px 12px rgba(26, 20, 22, .08), 0 16px 30px -16px rgba(26, 20, 22, .20);

  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;
  --r-pill: 999px;

  --ease: cubic-bezier(.22, 1, .36, 1);
  --ease-soft: cubic-bezier(.4, 0, .2, 1);

  --shell-max: 1440px;
  --pad-x: clamp(16px, 3vw, 40px);

  color-scheme: light;
}

[data-theme='dark'] {
  --bg:           #14100f;
  --bg-deep:      #0d0a0a;
  --surface:      #1d1817;
  --surface-alt:  #262020;
  --surface-sunk: #100d0d;
  --border:       #342c2c;
  --border-strong:#4a3f3f;
  --text:         #f7f2f1;
  --text-dim:     #b5a8a8;
  --text-mute:    #9e9292;

  --accent:       #ff5a68;
  --accent-hover: #ff7a85;
  --accent-soft:  #3a1518;
  --accent-line:  #5e2126;
  --on-accent:    #1a0709;

  --positive:      #3fcf8e;
  --positive-soft: #13301f;
  --positive-line: #1d4a30;
  --warning:       #f0b54d;
  --warning-soft:  #382a11;
  --warning-line:  #5a4319;
  --negative:      #ff6b7a;
  --negative-soft: #3a1418;
  --negative-line: #5c2029;
  --info:          #7aa2ff;
  --info-soft:     #1a2340;
  --info-line:     #2a3a63;
  --neutral:       #9c8f8f;
  --neutral-soft:  #292222;

  --ramp-1: #4a1f24;
  --ramp-2: #7d2630;
  --ramp-3: #b3303f;
  --ramp-4: #e64b5a;
  --ramp-5: #ff8a94;
  --ramp-1-fg: #ffd9dd;
  --ramp-2-fg: #ffd9dd;
  --ramp-3-fg: #ffffff;
  --ramp-4-fg: #1a0709;
  --ramp-5-fg: #1a0709;

  --lift-1: 0 1px 2px rgba(0, 0, 0, .4), 0 2px 8px -4px rgba(0, 0, 0, .5);
  --lift-2: 0 2px 6px rgba(0, 0, 0, .44), 0 12px 28px -12px rgba(0, 0, 0, .6);
  --lift-3: 0 8px 20px rgba(0, 0, 0, .5), 0 32px 64px -24px rgba(0, 0, 0, .7);
  --lift-brand: 0 2px 6px rgba(255, 90, 104, .2), 0 16px 32px -16px rgba(255, 90, 104, .3);
  --lift-float: 0 0 0 1px var(--border), 0 4px 12px rgba(0, 0, 0, .38), 0 16px 30px -16px rgba(0, 0, 0, .52);

  color-scheme: dark;
}

/* ---- Reset --------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-variant-numeric: tabular-nums;
  transition: background .32s var(--ease-soft), color .32s var(--ease-soft);
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.028em;
  margin: 0;
  text-wrap: balance;
}

button, input, select, textarea { font: inherit; color: inherit; }

button {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-variant-numeric: tabular-nums;
}

a { color: inherit; text-decoration: none; }

/* ---- Browser surfaces ---------------------------------------------------- */
::selection { background: var(--accent); color: var(--on-accent); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
*::-webkit-scrollbar { width: 11px; height: 11px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: var(--r-pill);
  border: 3px solid var(--bg);
}
*::-webkit-scrollbar-thumb:hover { background: var(--text-mute); }

input { caret-color: var(--accent); }

/* ---- Utility ------------------------------------------------------------- */
.num { font-family: var(--font-num); font-feature-settings: 'tnum' 1; letter-spacing: -0.02em; }

.u-dim  { color: var(--text-dim); }
.u-mute { color: var(--text-mute); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; top: 8px; left: 8px; z-index: 200;
  padding: 10px 16px; border-radius: var(--r-sm);
  background: var(--accent); color: var(--on-accent);
  font-weight: 600; font-size: 13px;
  transform: translateY(-160%);
  transition: transform .2s var(--ease);
}
.skip-link:focus { transform: translateY(0); }

/* ==========================================================================
   Shell
   ========================================================================== */
.shell { min-height: 100vh; display: flex; flex-direction: column; }

/* ---- Masthead ------------------------------------------------------------ */
.masthead {
  position: sticky; top: 0; z-index: 60;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: saturate(1.6) blur(14px);
  -webkit-backdrop-filter: saturate(1.6) blur(14px);
  border-bottom: 1px solid var(--border);
}

.masthead__bar {
  max-width: var(--shell-max); margin: 0 auto;
  padding: 0 var(--pad-x); height: 68px;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}

.brand { display: flex; align-items: center; gap: 12px; min-width: 0; }

.brand__mark {
  width: 38px; height: 38px; border-radius: 11px;
  background: linear-gradient(145deg, var(--brand-500), var(--brand-700));
  display: grid; place-items: center;
  box-shadow: var(--lift-brand);
  flex-shrink: 0;
}
.brand__mark svg { display: block; }
/* Marka KPT / JPPKK pada masthead + sidenav dashboard — rawatan sama seperti
   slot auth (.subhead__brand .subhead__mark--gov): lockup berwarna penuh
   membawa plat putihnya sendiri, jadi plat gradien merah 38px + box-shadow
   tidak lagi dipakai. Ditulis .brand__mark.brand__mark--gov (kekhususan 0,2,0)
   supaya ia menang atas .brand__mark tanpa bergantung pada urutan sheet. */
.brand__mark.brand__mark--gov {
  width: auto; height: auto; border-radius: 0;
  background: none; box-shadow: none;
}
.brand__mark.brand__mark--gov img { height: 48px; width: auto; border-radius: 10px; }
/* Drawer telefon/tablet (≤860px, iaitu julat di mana .menu-btn wujud): lockup
   104px dalam kepala drawer 310px + butang tutup + padding menolak teks brand
   keluar — nama perlu 132px, tag perlu 148px, hanya ~117px tinggal → kedua-dua
   terpotong ("DNA Senang…"). 24px memulihkan kedua-duanya. Masthead tidak
   terjejas (tag-nya sudah disembunyikan pada julat ini). */
@media (max-width: 860px) {
  .sidenav .brand__mark--gov img { height: 32px; border-radius: 8px; }
  /* Lockup 151px dalam kepala drawer 310px hanya tinggalkan ~75px untuk teks,
     sedangkan ".sidenav__tag" (BSN × DNA Referral Program) perlu 148px → ia
     terpotong jadi "BSN × DNA R…". Sembunyikan baris itu pada julat ini supaya
     kepala drawer = lockup + butang tutup sahaja. (Nama brand sudah dibuang
     atas permintaan.) */
  .sidenav .sidenav__tag { display: none; }
}
/* Marka KPT / JPPKK (assets/img/jppkk-logo.png) dalam slot masthead dashboard
   (.brand__mark--gov) dan slot auth (.subhead__mark--gov / .auth__mark--gov);
   marka rasmi lama (assets/img/brand-mark.png) masih dipakai oleh
   jppkk-platform.html. */
.brand__mark img, .subhead__mark img, .auth__mark img { display: block; }

.brand__text { display: flex; flex-direction: column; line-height: 1.16; min-width: 0; }
.brand__name {
  font-family: var(--font-display); font-weight: 800;
  font-size: 16.5px; letter-spacing: -0.035em; white-space: nowrap;
}
.brand__tag {
  font-size: 12px; color: var(--text-mute); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}


.masthead__tools { display: flex; align-items: center; gap: 10px; }

/* Period segmented control */
.segmented {
  display: flex; padding: 3px; gap: 2px;
  background: var(--surface-sunk); border-radius: 10px;
  border: 1px solid var(--border);
  position: relative;
}
.segmented__btn {
  padding: 6px 13px; border-radius: 7px;
  font-size: 12px; font-weight: 600; color: var(--text-dim);
  white-space: nowrap; position: relative; z-index: 1;
  transition: color .22s var(--ease);
}
.segmented__btn[aria-pressed='true'] { color: var(--text); }
.segmented__btn:hover { color: var(--text); }
.segmented__thumb {
  position: absolute; top: 3px; bottom: 3px; left: 0;
  background: var(--surface); border-radius: 7px;
  box-shadow: var(--lift-1); z-index: 0;
  pointer-events: none;
}

.icon-btn {
  width: 36px; height: 36px; border-radius: 10px;
  display: grid; place-items: center;
  color: var(--text-dim); border: 1px solid transparent;
  transition: background .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
  position: relative;
}
.icon-btn:hover { background: var(--surface-alt); color: var(--text); border-color: var(--border); }

/* Hamburger. Desktop never needs it: the nav bar and the masthead tools both
   fit above 860px, so showing it there would be a second door to the same
   room. Declared after .icon-btn on purpose — at equal specificity the later
   rule wins, and .icon-btn sets display:grid. */
.icon-btn.menu-btn { display: none; flex-shrink: 0; margin-right: 2px; }

.icon-btn__dot {
  position: absolute; top: 6px; right: 6px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent); border: 2px solid var(--surface);
}

.rule-v { width: 1px; height: 26px; background: var(--border); }

/* Theme toggle */
.theme-toggle {
  width: 52px; height: 28px; border-radius: var(--r-pill);
  background: var(--surface-sunk); border: 1px solid var(--border);
  position: relative; display: flex; align-items: center; padding: 0 3px;
  transition: background .3s var(--ease);
}
.theme-toggle__knob {
  width: 22px; height: 22px; border-radius: 50%;
  background: linear-gradient(145deg, var(--brand-500), var(--brand-700));
  box-shadow: 0 2px 6px rgba(216, 27, 42, .34);
  display: grid; place-items: center; color: #fff;
  transform: translateX(0);
  transition: transform .34s var(--ease);
}
[data-theme='dark'] .theme-toggle__knob { transform: translateX(24px); }
.theme-toggle__knob svg { width: 12px; height: 12px; }

/* Profile */
.profile { position: relative; }
.profile__trigger {
  display: flex; align-items: center; gap: 9px;
  padding: 5px 9px 5px 5px; border-radius: 10px;
  border: 1px solid transparent;
  transition: background .2s var(--ease), border-color .2s var(--ease);
}
.profile__trigger:hover,
.profile__trigger[aria-expanded='true'] { background: var(--surface-alt); border-color: var(--border); }

.avatar {
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent);
  border: 1px solid var(--accent-line);
  display: grid; place-items: center;
  font-weight: 700; font-size: 12px; flex-shrink: 0;
  font-family: var(--font-display); letter-spacing: -0.02em;
}
.avatar--sq { border-radius: 9px; }

.profile__id { line-height: 1.2; text-align: left; }
.profile__name { font-size: 12.5px; font-weight: 600; }

.profile__chev { color: var(--text-mute); transition: transform .24s var(--ease); }
.profile__trigger[aria-expanded='true'] .profile__chev { transform: rotate(180deg); }

.menu {
  position: absolute; top: calc(100% + 10px); right: 0; width: 262px;
  background: var(--surface);
  border-radius: var(--r-lg); box-shadow: var(--lift-float);
  padding: 7px; z-index: 70;
  transform-origin: top right;
}
.menu[hidden] { display: none; }

.menu__head { padding: 10px 11px 12px; border-bottom: 1px solid var(--border); margin-bottom: 6px; }
.menu__name { font-size: 13px; font-weight: 700; }
.menu__mail { font-size: 12px; color: var(--text-mute); margin-top: 1px; }
.menu__badge {
  margin-top: 8px; display: inline-block; padding: 3px 9px;
  border-radius: var(--r-pill); background: var(--accent-soft);
  color: var(--accent); border: 1px solid var(--accent-line);
  font-size: 11.5px; font-weight: 700;
}
.menu__item {
  width: 100%; display: flex; align-items: center; gap: 10px;
  padding: 9px 11px; border-radius: 9px;
  font-size: 12.5px; font-weight: 500; text-align: left;
  color: var(--text-dim);
  transition: background .16s var(--ease), color .16s var(--ease);
}
.menu__item:hover { background: var(--surface-alt); color: var(--text); }
.menu__item svg { flex-shrink: 0; }
.menu__item--danger { color: var(--negative); font-weight: 600; }
.menu__item--danger:hover { background: var(--negative-soft); color: var(--negative); }
.menu__sep { height: 1px; background: var(--border); margin: 6px 3px; }

.scrim { position: fixed; inset: 0; z-index: 65; }
.scrim[hidden] { display: none; }

/* ---- Nav ----------------------------------------------------------------- */
.nav {
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  overflow-x: auto; scrollbar-width: none;
}
.nav::-webkit-scrollbar { display: none; }
.nav__inner {
  max-width: var(--shell-max); margin: 0 auto;
  padding: 0 var(--pad-x); height: 46px;
  display: flex; align-items: stretch; gap: 4px; position: relative;
}
.nav__link {
  display: flex; align-items: center; gap: 7px; padding: 0 13px;
  font-size: 13px; font-weight: 500; color: var(--text-dim);
  white-space: nowrap; position: relative;
  transition: color .2s var(--ease);
}
.nav__link:hover { color: var(--text); }
.nav__link[aria-current='page'] { color: var(--accent); font-weight: 700; }
.nav__link svg { opacity: .78; }
.nav__count {
  padding: 1px 6px; border-radius: var(--r-pill);
  background: var(--surface-sunk); color: var(--text-dim);
  font-size: 12px; font-weight: 700;
}
.nav__link[aria-current='page'] .nav__count { background: var(--accent-soft); color: var(--accent); }
.nav__ink {
  position: absolute; bottom: 0; height: 2px; left: 0; width: 0;
  background: var(--accent); border-radius: 2px 2px 0 0;
}

/* ---- Main ---------------------------------------------------------------- */
.main { flex: 1; }
.page {
  max-width: var(--shell-max); margin: 0 auto;
  padding: 26px var(--pad-x) 90px;
}
.page[hidden] { display: none; }

.page-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 20px; flex-wrap: wrap; margin-bottom: 22px;
}
.page-head h1 { font-size: clamp(22px, 2.6vw, 29px); }
.page-head__sub { font-size: 13px; color: var(--text-dim); margin-top: 5px; }
.page-head__actions { display: flex; gap: 9px; flex-wrap: wrap; }

/* ---- Buttons ------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 9px 15px; border-radius: 10px;
  font-size: 12.5px; font-weight: 600; white-space: nowrap;
  border: 1px solid var(--border); background: var(--surface); color: var(--text);
  transition: background .18s var(--ease), border-color .18s var(--ease),
              box-shadow .18s var(--ease), transform .12s var(--ease), color .18s var(--ease);
}
.btn:hover { background: var(--surface-alt); border-color: var(--border-strong); }
.btn:active { transform: translateY(1px); }
.btn[disabled] { opacity: .45; pointer-events: none; }

.btn--primary {
  background: var(--accent); border-color: transparent; color: var(--on-accent);
  font-weight: 700; box-shadow: var(--lift-brand);
}
.btn--primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }

.btn--ghost { background: transparent; border-color: transparent; color: var(--text-dim); }
.btn--ghost:hover { background: var(--surface-alt); color: var(--text); }

.btn--sm { padding: 6px 11px; font-size: 12px; border-radius: 8px; }
.btn--block { width: 100%; }

/* ---- Card ---------------------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  position: relative;
}
.card__head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 14px; padding: 17px 19px 0;
}
.card__title { font-size: 14.5px; font-weight: 700; font-family: var(--font-display); letter-spacing: -0.025em; }
.card__sub { font-size: 12px; color: var(--text-mute); margin-top: 3px; }
.card__body { padding: 15px 19px 19px; }

/* A card that ends in a table has no foot to close it, so the last row's
   border lands flush on the card's own border. Give the scroll box the inset
   the card body would have provided. */
.card > .table-wrap:last-child { padding-bottom: 14px; }

/* Eyebrow label. Weight, colour and tracking mark it as chrome; uppercase is
   deliberately not used here. The detector counts an all-caps run of this
   length as body text, and it is right to: this label sits directly above the
   thing it names rather than inside a table header, so sentence case reads
   faster and loses nothing. */
.eyebrow {
  font-size: 12px; font-weight: 700; color: var(--text-mute);
  letter-spacing: .04em;
  display: flex; align-items: center; gap: 7px; margin-bottom: 6px;
}
.card__foot {
  padding: 12px 19px; border-top: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}

/* ---- Stat tiles ---------------------------------------------------------- */
.stat-row {
  display: grid; gap: 13px; margin-bottom: 20px;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}


.stat {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: 15px 16px 16px;
  position: relative; overflow: hidden;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease), transform .2s var(--ease);
  text-align: left; width: 100%; display: block;
  container: stat-card / inline-size;
}
button.stat { cursor: pointer; }
button.stat:hover { border-color: var(--border-strong); box-shadow: var(--lift-2); transform: translateY(-2px); }
.stat[aria-pressed='true'] {
  border-color: transparent;
  box-shadow: inset 0 0 0 1.5px var(--accent), var(--lift-brand);
}

.stat__top { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 13px; }

/* The delta/badge pill carries a live number ("24 perlu perhatian") that can
   grow on any given day. On narrow cards (2-up mobile grid, ~172-189px) it
   can outgrow the space left after the 30px icon, and .stat's overflow:hidden
   then flattens the pill's rounded end against the card edge. Rather than
   truncating a number that matters, let the pill drop to its own full-width
   line below the icon whenever it does not fit — this only ever activates
   when needed, so wide cards are unaffected. */
@container stat-card (max-width: 200px) {
  .stat__top { flex-wrap: wrap; row-gap: 8px; }
  .stat__top .delta,
  .stat__top .badge { white-space: normal; flex-basis: 100%; }
}
.stat__ico {
  width: 30px; height: 30px; border-radius: 9px;
  display: grid; place-items: center; flex-shrink: 0;
}
.stat__val {
  font-family: var(--font-display); font-size: clamp(20px, 2.2vw, 25px);
  font-weight: 800; letter-spacing: -0.04em; line-height: 1.05;
  display: flex; align-items: baseline; gap: 3px;
}
.stat__val small { font-size: .58em; font-weight: 700; color: var(--text-mute); letter-spacing: -0.02em; }
.stat__label { font-size: 12px; color: var(--text-dim); margin-top: 5px; }
.stat__spark { position: absolute; right: 0; bottom: 0; opacity: .16; pointer-events: none; }

/* Delta pill */
.delta {
  display: inline-flex; align-items: center; gap: 3px;
  padding: 3px 7px; border-radius: var(--r-pill);
  font-size: 12px; font-weight: 700; white-space: nowrap;
  border: 1px solid transparent;
}
.delta svg { flex-shrink: 0; }
.delta--positive { background: var(--positive-soft); color: var(--positive); border-color: var(--positive-line); }
.delta--negative { background: var(--negative-soft); color: var(--negative); border-color: var(--negative-line); }
.delta--warning  { background: var(--warning-soft);  color: var(--warning);  border-color: var(--warning-line); }
.delta--accent   { background: var(--accent-soft);   color: var(--accent);   border-color: var(--accent-line); }
.delta--neutral  { background: var(--neutral-soft);  color: var(--neutral);  border-color: var(--border); }
.delta--info     { background: var(--info-soft);     color: var(--info);     border-color: var(--info-line); }

/* Status badge */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3.5px 10px; border-radius: var(--r-pill);
  font-size: 12px; font-weight: 700; white-space: nowrap;
  border: 1px solid transparent;
}
.badge::before {
  content: ''; width: 5px; height: 5px; border-radius: 50%;
  background: currentColor; flex-shrink: 0;
}
.badge--positive { background: var(--positive-soft); color: var(--positive); border-color: var(--positive-line); }
.badge--negative { background: var(--negative-soft); color: var(--negative); border-color: var(--negative-line); }
.badge--warning  { background: var(--warning-soft);  color: var(--warning);  border-color: var(--warning-line); }
.badge--accent   { background: var(--accent-soft);   color: var(--accent);   border-color: var(--accent-line); }
.badge--neutral  { background: var(--neutral-soft);  color: var(--neutral);  border-color: var(--border); }
.badge--info     { background: var(--info-soft);     color: var(--info);     border-color: var(--info-line); }
.badge--plain::before { display: none; }

/* Daftar DNA — per-row pill (Pendaftaran Program table).
   Values taken from the Registrations design mockup: 6px 13px padding, 20px
   radius, 10.5px/700 label. Active pill = accent fill with surface-coloured
   label; done = positive-soft with a tick; disabled = surface-alt at 55% with
   a not-allowed cursor. Enabled state is decided in registrations-ui.js
   (layak + Diluluskan) — this file only paints it. */
.dna-pill {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 6px 13px; border: 0; border-radius: 20px;
  font-family: inherit; font-size: 10.5px; font-weight: 700; white-space: nowrap;
  background: var(--accent); color: var(--surface);
  cursor: pointer;
  transition: background .16s var(--ease), opacity .16s var(--ease);
}
.dna-pill:hover { background: var(--accent-hover); }
.dna-pill:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.dna-pill:disabled { background: var(--surface-alt); color: var(--text-mute); opacity: .55; cursor: not-allowed; }
.dna-pill:disabled:hover { background: var(--surface-alt); }
.dna-pill.is-done { background: var(--positive-soft); color: var(--positive); opacity: 1; cursor: default; }

/* Rows in the Pendaftaran table open the applicant dialog, so they are real
   controls and need a visible keyboard focus ring — the table cursor:pointer
   alone only tells a mouse. */
#regTableBody tr:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ---- DNA provisioning overlay (Daftar DNA) --------------------------------
   A load screen, not a dialog with a form: one number, one bar, one line of
   system output, and nothing to click until it finishes. The status line uses
   --font-num so it reads as machine output, which is the point. */
.dna-load { position: fixed; inset: 0; z-index: 120; display: flex; align-items: center; justify-content: center; padding: 24px; }
.dna-load[hidden] { display: none; }
.dna-load__scrim {
  position: absolute; inset: 0;
  background: rgba(20, 14, 15, .55);
  backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
}
.dna-load__panel {
  position: relative; width: 420px; max-width: 100%;
  background: var(--surface); border-radius: 16px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .30);
  padding: 22px 22px 18px; outline: none;
}

.dna-load__head { display: flex; align-items: center; gap: 12px; }
.dna-load__spin {
  width: 38px; height: 38px; border-radius: 11px; flex-shrink: 0;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent);
}
.dna-load__spin svg { animation: dnaSpin 1.1s linear infinite; }
@keyframes dnaSpin { to { transform: rotate(360deg); } }
/* Once the account exists the spinner stops being a spinner: it becomes a tick,
   so a finished run cannot be mistaken for a hung one. */
.dna-load.is-done .dna-load__spin { background: var(--positive-soft); color: var(--positive); }
.dna-load.is-done .dna-load__spin svg { animation: none; }
.dna-load__id { min-width: 0; }
.dna-load__title { font-size: 15px; font-weight: 800; font-family: var(--font-display); letter-spacing: -.01em; }
.dna-load__sub { font-size: 12px; color: var(--text-mute); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.dna-load__meter { display: flex; align-items: center; gap: 12px; margin: 18px 0 14px; }
.dna-load__pct {
  font-family: var(--font-num); font-size: 21px; font-weight: 700;
  font-variant-numeric: tabular-nums; min-width: 62px;
}
.dna-load__bar {
  flex: 1; height: 7px; border-radius: var(--r-pill);
  background: var(--surface-alt); overflow: hidden;
}
.dna-load__fill {
  display: block; height: 100%; width: 0;
  border-radius: var(--r-pill); background: var(--accent);
  transition: width .5s var(--ease), background .3s var(--ease);
}
.dna-load.is-done .dna-load__fill { background: var(--positive); }

.dna-load__log {
  font-family: var(--font-num); font-size: 12px; color: var(--text);
  display: flex; align-items: center; gap: 8px; min-height: 18px;
}
.dna-load__log::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent); flex-shrink: 0;
  animation: dnaBlink 1s steps(2, end) infinite;
}
@keyframes dnaBlink { 50% { opacity: .25; } }
.dna-load.is-done .dna-load__log::before { animation: none; background: var(--positive); }
.dna-load__sub2 { font-size: 11.5px; color: var(--text-mute); margin: 4px 0 0 14px; }

.dna-load__done { margin-top: 16px; }
.dna-load__done[hidden] { display: none; }
.dna-load__ok {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border-radius: 9px;
  background: var(--positive-soft); color: var(--positive);
  font-size: 11.5px; font-weight: 600;
}
.dna-load__rows { display: grid; gap: 2px; margin: 12px 0 14px; }
.dna-load__row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 5px 2px; font-size: 12px; }
.dna-load__row + .dna-load__row { border-top: 1px solid var(--border); }
.dna-load__row span:first-child { color: var(--text-mute); }
.dna-load__row span:last-child { font-weight: 600; min-width: 0; overflow-wrap: anywhere; text-align: right; }
.dna-load__note { font-size: 10.5px; color: var(--text-mute); text-align: center; margin-top: 12px; }

/* ---- Live inflow (Pendaftaran) --------------------------------------------
   The page shows applications arriving while it is open: a pulsing LIVE pill
   that doubles as the pause control, one line naming whoever is mid-form, and
   rows that land at the top of the table with a soft tint that fades out. Nothing
   here is a box — the only new chrome is a dot and a line of text. */
.live-pill {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 13px; border-radius: var(--r-pill);
  border: 1px solid var(--border); background: var(--surface);
  font-size: 11.5px; font-weight: 700; letter-spacing: .02em;
  color: var(--text-dim); white-space: nowrap;
}
.live-pill:hover { border-color: var(--border-strong); color: var(--text); }
.live-pill__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--negative); flex-shrink: 0; animation: livePulse 1.6s var(--ease) infinite; }
.live-pill__n { font-family: var(--font-num); color: var(--accent); }
.live-pill[aria-pressed='true'] { color: var(--text-mute); }
.live-pill[aria-pressed='true'] .live-pill__dot { animation: none; background: var(--border-strong); }
.live-pill[aria-pressed='true'] .live-pill__n { color: var(--text-mute); }
@keyframes livePulse { 50% { opacity: .3; transform: scale(.78); } }

.live-line {
  display: flex; align-items: center; gap: 8px;
  font-size: 11.5px; color: var(--text-dim);
  margin: -4px 0 12px; min-height: 17px;
}
.live-line__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex-shrink: 0; animation: livePulse 1.2s var(--ease) infinite; }
.live-line.is-idle .live-line__dot { animation: none; background: var(--border-strong); }
.live-line.is-draft { color: var(--warning); }
.live-line.is-draft .live-line__dot { background: var(--warning); }

/* A row that just arrived, and the ghost row of a form being filled in now. */
@keyframes rowIn { from { background: var(--accent-soft); } to { background: transparent; } }
#regTableBody tr.is-new { animation: rowIn 3.4s var(--ease) forwards; }
#regTableBody tr.is-draft { background: var(--warning-soft); cursor: default; }
#regTableBody tr.is-draft:hover { background: var(--warning-soft); }
#regTableBody tr.is-draft .cell-id__name { font-weight: 600; }
.draft-bar { height: 3px; border-radius: var(--r-pill); background: var(--surface); overflow: hidden; margin-top: 6px; }
.draft-bar > span { display: block; height: 100%; border-radius: var(--r-pill); background: var(--warning); transition: width .35s var(--ease); }
.draft-pill { font-size: 10.5px; font-weight: 700; color: var(--warning); white-space: nowrap; }

.tag {
  display: inline-block; padding: 2.5px 8px; border-radius: 6px;
  background: var(--surface-sunk); color: var(--text-dim);
  font-size: 12px; font-weight: 600; white-space: nowrap;
}

/* ---- Grid ---------------------------------------------------------------- */
.grid { display: grid; gap: 18px; }
.grid--split   { grid-template-columns: minmax(0, 1.65fr) minmax(0, 1fr); align-items: start; }
.grid--halves  { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--thirds  { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--map     { grid-template-columns: minmax(0, 1.9fr) minmax(0, 1fr); align-items: stretch; }
.stack { display: flex; flex-direction: column; gap: 18px; }

@media (max-width: 1080px) {
  .grid--split, .grid--map, .grid--halves, .grid--thirds { grid-template-columns: minmax(0, 1fr); }
}

/* ---- Chart primitives ---------------------------------------------------- */
.chart { position: relative; width: 100%; }
.chart svg { display: block; width: 100%; overflow: visible; }

.chart-legend { display: flex; gap: 15px; flex-wrap: wrap; font-size: 12px; color: var(--text-dim); }
.chart-legend__item { display: flex; align-items: center; gap: 6px; }
.chart-legend__swatch { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }
.chart-legend__line { width: 13px; height: 0; border-top: 2px dashed currentColor; flex-shrink: 0; }

.axis-label { font-size: 12px; fill: var(--text-mute); font-family: var(--font-body); }
.grid-line { stroke: var(--border); stroke-width: 1; }
.grid-line--target { stroke: var(--text-mute); stroke-width: 1.3; stroke-dasharray: 5 4; opacity: .7; }

/* Tooltip */
.tip {
  position: fixed; z-index: 120; pointer-events: none;
  background: var(--surface);
  border-radius: var(--r-md); box-shadow: var(--lift-float);
  padding: 10px 12px; min-width: 132px; max-width: 260px;
  font-size: 12px; opacity: 0;
  transition: opacity .14s var(--ease);
}
.tip[data-show='1'] { opacity: 1; }
.tip__title { font-weight: 700; font-size: 12.5px; margin-bottom: 5px; }
.tip__row { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-top: 3px; }
.tip__key { color: var(--text-mute); font-size: 12px; }
.tip__val { font-weight: 700; font-family: var(--font-num); font-size: 12px; }

/* Bars */
.bars { display: flex; align-items: flex-end; gap: 10px; height: 168px; }
.bar-col {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 7px;
  height: 100%; justify-content: flex-end; cursor: pointer;
}
.bar-col__val { font-size: 12px; font-weight: 700; color: var(--text-dim); font-family: var(--font-num); }
.bar-col__bar {
  width: 100%; max-width: 40px; border-radius: 6px 6px 2px 2px;
  background: var(--accent-line); min-height: 3px;
  transition: background .2s var(--ease), filter .2s var(--ease);
  transform-origin: bottom;
}
.bar-col:hover .bar-col__bar { filter: brightness(1.08); }
.bar-col--on .bar-col__bar { background: var(--accent); }
.bar-col__label { font-size: 12px; color: var(--text-mute); }

/* Donut */
.donut-wrap { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.donut { position: relative; width: 132px; height: 132px; flex-shrink: 0; }
.donut svg { transform: rotate(-90deg); overflow: visible; }
.donut__seg { transition: opacity .2s var(--ease); cursor: pointer; }
.donut svg:hover .donut__seg { opacity: .38; }
.donut svg .donut__seg:hover { opacity: 1; }
.donut__hub {
  position: absolute; inset: 0; display: grid; place-content: center;
  text-align: center; pointer-events: none;
}
.donut__hub b { font-family: var(--font-display); font-size: 25px; font-weight: 800; letter-spacing: -0.04em; display: block; line-height: 1; }
.donut__hub span { font-size: 11.5px; color: var(--text-mute); }

.legend-list { flex: 1; min-width: 165px; display: flex; flex-direction: column; gap: 2px; }
.legend-row {
  display: flex; align-items: center; gap: 9px; font-size: 12px;
  padding: 5px 7px; border-radius: 7px; width: 100%; text-align: left;
  transition: background .16s var(--ease);
}
.legend-row:hover { background: var(--surface-alt); }
.legend-row__dot { width: 9px; height: 9px; border-radius: 3px; flex-shrink: 0; }
.legend-row__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.legend-row__val { font-weight: 700; font-family: var(--font-num); font-size: 12px; white-space: nowrap; }
.legend-row--off { opacity: .4; }

/* ---- Map ----------------------------------------------------------------- */
.map-card { display: flex; flex-direction: column; overflow: hidden; }
.map-canvas {
  flex: 1; min-height: 430px; background: var(--surface-sunk);
  position: relative; z-index: 0;
}
.leaflet-container { background: var(--surface-sunk); font-family: var(--font-body); }
.leaflet-control-attribution {
  background: color-mix(in srgb, var(--surface) 84%, transparent) !important;
  color: var(--text-mute) !important; font-size: 11.5px !important;
}
.leaflet-control-attribution a { color: var(--text-dim) !important; }
.leaflet-bar a {
  background: var(--surface) !important; color: var(--text) !important;
  border-bottom-color: var(--border) !important;
}
.leaflet-bar a:hover { background: var(--surface-alt) !important; }
[data-theme='dark'] .leaflet-tile-pane { filter: invert(1) hue-rotate(180deg) brightness(.86) contrast(1.06) saturate(.6); }

/* Shown only when the basemap cannot be reached. The state boundaries are
   drawn from a local file, so the map still works; this explains the bare
   canvas rather than leaving the viewer guessing. */
.map__offline {
  position: absolute; left: 12px; bottom: 12px; z-index: 500;
  max-width: min(330px, calc(100% - 24px));
  padding: 8px 11px; border-radius: 8px;
  background: var(--warning-soft); color: var(--warning);
  border: 1px solid var(--warning-line);
  font-size: 12px; font-weight: 500; line-height: 1.45;
}

.pin {
  border-radius: 50%; display: grid; place-items: center;
  font-family: var(--font-display); font-weight: 800;
  border: 2.5px solid var(--surface);
  box-shadow: 0 2px 8px rgba(0,0,0,.28);
  transition: transform .2s var(--ease);
  cursor: pointer;
}
.pin:hover { transform: scale(1.14); z-index: 500; }

.map-legend {
  display: flex; align-items: center; gap: 7px;
  font-size: 12px; color: var(--text-mute);
}
.map-legend__ramp { display: flex; gap: 2px; }
.map-legend__step { width: 17px; height: 8px; border-radius: 2px; }

.map-note {
  display: flex; align-items: center; gap: 9px;
  padding: 10px 14px; border-top: 1px solid var(--border);
  background: var(--warning-soft); color: var(--warning);
  font-size: 12px; font-weight: 500;
}
.map-note button { color: inherit; font-weight: 700; text-decoration: underline; text-underline-offset: 2px; }

/* ---- Filter chips -------------------------------------------------------- */
.chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.chip {
  padding: 5.5px 12px; border-radius: var(--r-pill);
  font-size: 12px; font-weight: 600; white-space: nowrap;
  background: var(--surface); color: var(--text-dim);
  border: 1px solid var(--border);
  transition: background .18s var(--ease), color .18s var(--ease),
              border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.chip:hover { border-color: var(--border-strong); color: var(--text); }
.chip[aria-pressed='true'] {
  background: var(--accent); color: var(--on-accent);
  border-color: transparent; box-shadow: var(--lift-brand);
}
.chip__n { opacity: .62; margin-left: 2px; font-variant-numeric: tabular-nums; }
.chips__sep { width: 1px; height: 16px; background: var(--border); margin: 0 4px; }

/* ---- Alert list ---------------------------------------------------------- */
.alert-list { display: flex; flex-direction: column; flex: 1; overflow: auto; max-height: 460px; }
.alert {
  padding: 13px 19px; border-bottom: 1px solid var(--border);
  text-align: left; width: 100%; display: block;
  transition: background .16s var(--ease);
  position: relative;
}
.alert:hover { background: var(--surface-alt); }
.alert__top { display: flex; align-items: center; justify-content: space-between; gap: 9px; margin-bottom: 5px; }
.alert__id { display: flex; align-items: center; gap: 8px; min-width: 0; }
.alert__dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.alert__name {
  font-weight: 600; font-size: 12.5px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.alert__issue { font-size: 12px; font-weight: 500; margin-bottom: 8px; }
.alert__foot { display: flex; align-items: center; justify-content: space-between; gap: 9px; }
.alert__meta { font-size: 12px; color: var(--text-mute); }

/* ---- Table --------------------------------------------------------------- */
.table-wrap { overflow-x: auto; }
/* No blanket min-width here. The tables that genuinely need one (directory,
   ledger, payouts, team) declare it inline, sized for their own columns. A
   default forced the narrower leaderboard to overflow its card and scroll
   sideways even on a 1512px display. */
.tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.tbl thead th {
  text-align: left; padding: 11px 13px;
  font-size: 12px; font-weight: 700; color: var(--text-mute);
  text-transform: uppercase; letter-spacing: 0.04em;
  border-bottom: 1px solid var(--border); white-space: nowrap;
  background: var(--surface); position: sticky; top: 0; z-index: 2;
}
.tbl thead th.is-sortable { cursor: pointer; user-select: none; }
.tbl thead th.is-sortable:hover { color: var(--text); }
.tbl thead th .sort-ind { display: inline-block; margin-left: 4px; opacity: .45; transition: opacity .16s; }
.tbl thead th[aria-sort] .sort-ind { opacity: 1; color: var(--accent); }
.tbl td { padding: 11px 13px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.tbl tbody tr { transition: background .14s var(--ease); cursor: pointer; }
.tbl tbody tr:hover { background: var(--surface-alt); }
.tbl tbody tr:last-child td { border-bottom: 0; }
.t-right { text-align: right; }
.t-center { text-align: center; }
.t-num { font-family: var(--font-num); font-weight: 600; font-size: 12.5px; }

/* ---- Leaderboard column priority ------------------------------------------
   Rules for this live at the end of the sheet; see the note there. */

.cell-id { display: flex; align-items: center; gap: 10px; min-width: 0; }
.cell-id__main { min-width: 0; }
.cell-id__name {
  font-size: 12.5px; font-weight: 600; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; max-width: 250px;
}
.cell-id__sub { font-size: 12px; color: var(--text-mute); margin-top: 1px; }

.rank-pip {
  width: 22px; height: 22px; border-radius: 7px; flex-shrink: 0;
  display: grid; place-items: center;
  background: var(--surface-sunk); color: var(--text-dim);
  font-size: 12px; font-weight: 700; font-family: var(--font-num);
}
.rank-pip--1 { background: var(--accent); color: var(--on-accent); }
.rank-pip--2 { background: var(--accent-line); color: var(--brand-800); }
.rank-pip--3 { background: var(--accent-soft); color: var(--accent); }
[data-theme='dark'] .rank-pip--2 { color: var(--brand-50); }

/* ---- Bar in cell --------------------------------------------------------- */
.meter { height: 5px; border-radius: 3px; background: var(--surface-sunk); overflow: hidden; min-width: 48px; }
.meter__fill { height: 100%; border-radius: 3px; background: var(--accent); transform-origin: left; }

/* ---- Forms --------------------------------------------------------------- */
.field { display: flex; flex-direction: column; gap: 6px; }
.field__label { font-size: 12px; color: var(--text-dim); font-weight: 500; }
.input, .select {
  width: 100%; padding: 10px 13px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--surface); color: var(--text);
  font-size: 12.5px;
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.input:focus, .select:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent);
}
.input::placeholder { color: var(--text-mute); }

.select {
  appearance: none; padding-right: 32px; font-weight: 600; cursor: pointer;
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23756a6d' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center;
}
[data-theme='dark'] .select {
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239e9292' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}

.search {
  position: relative; flex: 1; min-width: 210px;
}
.search > svg { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); color: var(--text-mute); pointer-events: none; }
.search .input { padding-left: 36px; padding-right: 34px; }
/* Chrome/Edge/Safari draw their own clear button inside type=search. We ship a
   styled one, so the native twin has to go or the field shows two X icons. */
.search input[type='search']::-webkit-search-cancel-button,
.search input[type='search']::-webkit-search-decoration { -webkit-appearance: none; appearance: none; display: none; }
.search__clear {
  position: absolute; right: 9px; top: 50%; transform: translateY(-50%);
  width: 20px; height: 20px; border-radius: 50%;
  display: grid; place-items: center; color: var(--text-mute);
  background: var(--surface-sunk);
}
/* `display: grid` above outranks the UA rule for [hidden], which would leave the
   clear button painted and clickable on an empty field. Restore it here. */
.search__clear[hidden] { display: none; }
.search__clear:hover { color: var(--text); }

.filter-bar { display: flex; gap: 9px; flex-wrap: wrap; align-items: center; margin-bottom: 15px; }

/* Switch */
.switch {
  width: 42px; height: 24px; border-radius: var(--r-pill);
  background: var(--surface-sunk); border: 1px solid var(--border);
  position: relative; flex-shrink: 0;
  transition: background .26s var(--ease), border-color .26s var(--ease);
}
.switch[aria-checked='true'] { background: var(--accent); border-color: var(--accent); }
.switch__knob {
  position: absolute; top: 2px; left: 2px;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--surface); box-shadow: 0 1px 3px rgba(0,0,0,.26);
  transition: transform .26s var(--ease);
}
.switch[aria-checked='true'] .switch__knob { transform: translateX(20px); background: #fff; }

.setting-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 13px 0; border-top: 1px solid var(--border);
}
.setting-row__title { font-size: 12.5px; font-weight: 600; }
.setting-row__desc { font-size: 12px; color: var(--text-mute); margin-top: 2px; }

/* Checkbox */
.check { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 12px; font-weight: 600; }
.check__box {
  width: 17px; height: 17px; border-radius: 5px;
  border: 1.5px solid var(--border-strong); flex-shrink: 0;
  display: grid; place-items: center; color: transparent;
  transition: background .18s var(--ease), border-color .18s var(--ease), color .18s var(--ease);
}
.check[aria-checked='true'] .check__box { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

/* ---- Sidenav (mobile) ---------------------------------------------------- */
.sidenav {
  position: fixed; top: 0; left: 0; bottom: 0; z-index: 100;
  width: min(310px, 86vw);
  background: var(--surface);
  box-shadow: 1px 0 0 0 var(--border), 8px 0 24px -8px rgba(0, 0, 0, .16), 18px 0 34px -18px rgba(0, 0, 0, .22);
  display: flex; flex-direction: column;
  transform: translateX(-100%);
}
.sidenav[hidden] { display: none; }

.scrim--nav {
  z-index: 95;
  background: rgba(20, 14, 15, .48);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  opacity: 0;
}

.sidenav__head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 14px 14px 13px 16px;
  border-bottom: 1px solid var(--border); flex-shrink: 0;
}
.sidenav__tag {
  font-size: 11.5px; color: var(--text-mute); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
/* The mark and the close button are fixed; the text is what gives way. */
.sidenav__head .brand { min-width: 0; flex: 1 1 auto; }
.sidenav__head .brand__name { overflow: hidden; text-overflow: ellipsis; }

.sidenav__body {
  flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 14px 12px 18px;
  display: flex; flex-direction: column; gap: 18px;
}

.sidenav__who {
  display: flex; align-items: center; gap: 11px;
  padding: 11px 12px; border-radius: var(--r-md);
  background: var(--surface-sunk); border: 1px solid var(--border);
}
.sidenav__whoid { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
.sidenav__whoname { font-size: 13.5px; font-weight: 700; }
.sidenav__whomail {
  font-size: 11.5px; color: var(--text-mute);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.sidenav__group { display: flex; flex-direction: column; gap: 3px; }
.sidenav__label {
  font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-mute); padding: 0 10px 6px;
}

/* One row, one target. 46px tall so a thumb hits it without aiming, and the
   whole row is the hit area rather than the glyph. */
.sidenav__link {
  display: flex; align-items: center; gap: 11px;
  min-height: 46px; padding: 0 11px; border-radius: 10px;
  font-size: 14px; font-weight: 500; color: var(--text-dim);
  text-align: left; width: 100%;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.sidenav__link svg { flex-shrink: 0; opacity: .8; }
.sidenav__link:hover { background: var(--surface-alt); color: var(--text); }
.sidenav__link[aria-current='page'] {
  background: var(--accent-soft); color: var(--accent); font-weight: 700;
}
.sidenav__link[aria-current='page'] svg { opacity: 1; }
.sidenav__link .nav__count { margin-left: auto; }
.sidenav__link--danger { color: var(--negative); font-weight: 600; }
.sidenav__link--danger:hover { background: var(--negative-soft); color: var(--negative); }
.sidenav__link--flat { color: var(--text-dim); }

.nav__count--warn { background: var(--warning-soft); color: var(--warning); }

.sidenav__foot {
  border-top: 1px solid var(--border); flex-shrink: 0;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: 3px;
  background: var(--surface);
}

.segmented--block { width: 100%; }
.segmented--block .segmented__btn { flex: 1; text-align: center; padding: 9px 6px; }

/* ---- Drawer -------------------------------------------------------------- */
.overlay {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(20, 14, 15, .48);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  opacity: 0;
}
.overlay[hidden] { display: none; }

.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 100;
  width: min(520px, 100vw);
  background: var(--surface);
  box-shadow: -1px 0 0 0 var(--border), -8px 0 24px -8px rgba(0, 0, 0, .12), -18px 0 30px -18px rgba(0, 0, 0, .20);
  display: flex; flex-direction: column;
  transform: translateX(100%);
}
.drawer[hidden] { display: none; }

.drawer__head {
  padding: 18px 20px 15px; border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.drawer__body { flex: 1; overflow-y: auto; padding: 18px 20px 26px; }
.drawer__foot {
  padding: 13px 20px; border-top: 1px solid var(--border);
  display: flex; gap: 9px; flex-shrink: 0;
  background: var(--surface);
}

/* ---- Tanya AI ------------------------------------------------------------ */
.icon-btn--ai {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 26%, var(--border));
  background: color-mix(in srgb, var(--accent) 7%, var(--surface));
}
.icon-btn--ai:hover { background: color-mix(in srgb, var(--accent) 15%, var(--surface)); }

.drawer--chat { width: min(560px, 100vw); }

.ai-head__row { display: flex; align-items: center; gap: 10px; }
.ai-mark {
  width: 32px; height: 32px; border-radius: 9px; display: grid; place-items: center;
  background: var(--accent); color: #fff; flex-shrink: 0; box-shadow: var(--lift-brand);
}
.ai-head__text { flex: 1; min-width: 0; }
.ai-head__text h2 { margin: 0; font-size: 16px; font-weight: 800; letter-spacing: -.02em; }
.ai-head__sub { font-size: 12px; color: var(--text-mute); margin-top: 1px; }

.ai-body { padding: 16px 18px 20px; display: flex; flex-direction: column; gap: 14px; }

/* How-to card, shown until the first question is asked. */
.ai-intro {
  border: 1px solid var(--border); border-radius: 12px;
  padding: 14px 15px; background: var(--surface-alt);
}
.ai-intro h3 { margin: 0 0 9px; font-size: 13px; font-weight: 700; }
.ai-intro ol { margin: 0; padding-left: 17px; font-size: 12.5px; color: var(--text-dim); line-height: 1.62; }
.ai-intro li + li { margin-top: 3px; }

.ai-presets { display: flex; flex-direction: column; gap: 7px; }
.ai-presets__label {
  font-size: 11.5px; font-weight: 700; color: var(--text-mute);
  text-transform: uppercase; letter-spacing: .05em;
}
.ai-preset {
  text-align: left; padding: 10px 13px; border-radius: 10px; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface); color: var(--text);
  font: 500 13px/1.45 var(--font-body);
  transition: border-color .16s var(--ease), background .16s var(--ease);
}
.ai-preset:hover { border-color: var(--accent); background: var(--accent-soft); }

.msg { display: flex; }
.msg--user { justify-content: flex-end; }
.msg__b {
  max-width: 86%; padding: 10px 13px; border-radius: 13px;
  font-size: 13.5px; line-height: 1.62; white-space: pre-wrap; word-break: break-word;
}
.msg--user .msg__b { background: var(--accent); color: var(--on-accent); border-bottom-right-radius: 4px; }
.msg--ai .msg__b { background: var(--surface-sunk); border-bottom-left-radius: 4px; }
.msg__tools { display: flex; gap: 4px; margin-top: 5px; }
.msg__tool {
  border: 0; background: none; color: var(--text-mute); cursor: pointer;
  font: 600 11.5px var(--font-body); padding: 3px 8px; border-radius: 5px;
  /* Measured at 21px with padding alone, below the 24px minimum for a
     standalone target. An explicit min-height does not depend on font
     metrics, so it stays correct if the type scale changes. */
  display: inline-flex; align-items: center; min-height: 26px;
}
.msg__tool:hover { background: var(--surface-sunk); color: var(--text); }

/* An AI answer is a vertical stack: bubble, then its tools, then suggestions.
   Left-aligned so the stack grows downward rather than sideways. */
.msg--ai { flex-direction: column; align-items: flex-start; }

/* A merchant name inside an answer. Looks like a link, is a button. */
.msg__link {
  display: inline; padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; color: var(--accent); font-weight: 600; text-align: left;
  text-decoration: underline; text-underline-offset: 2px;
  text-decoration-color: color-mix(in srgb, var(--accent) 40%, transparent);
}
.msg__link:hover { text-decoration-color: var(--accent); }
.msg__link:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-radius: 3px; }
.msg--user .msg__link { color: var(--on-accent); text-decoration-color: rgba(255, 255, 255, .5); }

/* Suggested next steps, derived from what the answer actually mentioned. */
.msg__actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; max-width: 100%; }
.msg__action {
  border: 1px solid var(--accent-line); background: var(--accent-soft); color: var(--accent);
  cursor: pointer; border-radius: var(--r-pill);
  font: 600 12px/1 var(--font-body); padding: 7px 12px;
  transition: background .16s var(--ease), color .16s var(--ease), border-color .16s var(--ease);
}
.msg__action:hover { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.msg__action:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Typing indicator. Three dots, or a still mark when motion is unwanted. */
.typing { display: inline-flex; gap: 4px; align-items: center; padding: 3px 1px; }
.typing i {
  width: 6px; height: 6px; border-radius: 50%; background: var(--text-mute);
  animation: aiDot 1.1s infinite;
}
.typing i:nth-child(2) { animation-delay: .16s; }
.typing i:nth-child(3) { animation-delay: .32s; }
@keyframes aiDot {
  0%, 60%, 100% { opacity: .26; transform: translateY(0); }
  30%           { opacity: 1;   transform: translateY(-3px); }
}
@media (prefers-reduced-motion: reduce) {
  .typing i { animation: none; opacity: .55; }
}

.ai-error {
  border: 1px solid var(--negative-line); background: var(--negative-soft);
  color: var(--negative); border-radius: 10px; padding: 11px 13px;
  font-size: 12.5px; line-height: 1.55;
}
.ai-error code { font: 11.5px var(--font-num); background: rgba(0,0,0,.05); padding: 1px 4px; border-radius: 3px; }

.ai-foot {
  border-top: 1px solid var(--border); padding: 11px 14px 12px;
  flex-shrink: 0; background: var(--surface);
}
.ai-ask { display: flex; gap: 8px; align-items: flex-end; }
.ai-ask textarea {
  flex: 1; resize: none; max-height: 132px; min-height: 40px;
  padding: 10px 12px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--surface-alt); color: var(--text);
  font: 13.5px/1.5 var(--font-body);
}
.ai-ask textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; background: var(--surface); }
.ai-send {
  width: 40px; height: 40px; border-radius: 10px; border: 0; cursor: pointer;
  background: var(--accent); color: var(--on-accent); display: grid; place-items: center;
  transition: background .16s var(--ease), opacity .16s var(--ease);
}
.ai-send:hover:not(:disabled) { background: var(--accent-hover); }
.ai-send:disabled { opacity: .45; cursor: not-allowed; }
.ai-foot__hint { font-size: 11.5px; color: var(--text-mute); margin-top: 7px; }

.back-link {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12px; font-weight: 600; color: var(--text-dim);
  margin-bottom: 13px;
  transition: color .18s var(--ease), gap .18s var(--ease);
}
.back-link:hover { color: var(--accent); gap: 10px; }

.close-btn {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--surface-sunk); color: var(--text-dim);
  display: grid; place-items: center; flex-shrink: 0;
  transition: background .18s var(--ease), color .18s var(--ease), transform .18s var(--ease);
}
.close-btn:hover { background: var(--negative-soft); color: var(--negative); transform: rotate(90deg); }

/* Mini stat inside drawer */
.mini-grid { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 9px; }
.mini {
  background: var(--surface-alt); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: 12px 13px;
}
.mini__val { font-family: var(--font-display); font-size: 17px; font-weight: 800; letter-spacing: -0.035em; }
.mini__label { font-size: 12px; color: var(--text-mute); margin-top: 2px; }

/* Timeline notes */
.note-list { display: flex; flex-direction: column; gap: 13px; }
.note { display: flex; gap: 11px; position: relative; }
.note__rail { display: flex; flex-direction: column; align-items: center; flex-shrink: 0; padding-top: 5px; }
.note__pip { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); flex-shrink: 0; }
.note__line { width: 1.5px; flex: 1; background: var(--border); margin-top: 4px; }
.note:last-child .note__line { display: none; }
.note__date { font-size: 12px; color: var(--text-mute); margin-bottom: 2px; }
.note__text { font-size: 12.5px; line-height: 1.5; }
.note__author { font-size: 12px; color: var(--text-mute); margin-top: 3px; }

.note-compose {
  border: 1px dashed var(--border-strong); border-radius: var(--r-md);
  padding: 4px; margin-top: 13px;
  transition: border-color .2s var(--ease);
}
.note-compose:focus-within { border-color: var(--accent); border-style: solid; }
.note-compose textarea {
  width: 100%; border: 0; background: none; resize: vertical;
  min-height: 56px; padding: 9px 11px; font-size: 12.5px; line-height: 1.5;
}
.note-compose textarea:focus { outline: none; }
.note-compose__bar { display: flex; justify-content: space-between; align-items: center; gap: 9px; padding: 0 5px 5px; }

/* ---- Spotlight ----------------------------------------------------------- */
.spotlight {
  border-radius: var(--r-lg); padding: 19px 21px;
  background:
    radial-gradient(120% 140% at 0% 0%, color-mix(in srgb, var(--accent) 16%, transparent), transparent 62%),
    var(--surface);
  border: 1px solid var(--accent-line);
  display: flex; align-items: center; gap: 17px; flex-wrap: wrap;
}
.spotlight__ico {
  width: 44px; height: 44px; border-radius: var(--r-md);
  background: var(--surface); color: var(--accent);
  display: grid; place-items: center; flex-shrink: 0;
  box-shadow: var(--lift-1); border: 1px solid var(--accent-line);
}
.spotlight__body { flex: 1; min-width: 210px; }
.spotlight__title { font-size: 13.5px; font-weight: 700; margin-bottom: 3px; }
.spotlight__sub { font-size: 12px; color: var(--text-dim); }

/* ---- Balance card -------------------------------------------------------- */
.balance {
  border-radius: var(--r-lg); padding: 22px;
  background: linear-gradient(142deg, var(--brand-600), var(--brand-800));
  color: #fff; box-shadow: var(--lift-brand);
  position: relative; overflow: hidden;
}
.balance::after {
  content: ''; position: absolute; right: -44px; top: -44px;
  width: 190px; height: 190px; border-radius: 50%;
  background: radial-gradient(circle, rgba(255,255,255,.16), transparent 66%);
  pointer-events: none;
}
.balance__label { font-size: 12px; opacity: .84; }
.balance__val {
  font-family: var(--font-display); font-size: 34px; font-weight: 800;
  letter-spacing: -0.045em; margin: 7px 0 4px; line-height: 1;
}
.balance__note { font-size: 12px; opacity: .84; }
.balance__split {
  display: flex; gap: 20px; margin-top: 16px; padding-top: 14px;
  border-top: 1px solid rgba(255,255,255,.2); position: relative;
}
.balance__split b { display: block; font-family: var(--font-num); font-size: 14px; font-weight: 700; }
.balance__split span { font-size: 12px; opacity: .8; }

/* ---- Heatmap ------------------------------------------------------------- */
.heat { display: grid; grid-template-columns: 30px repeat(24, minmax(0, 1fr)); gap: 2px; }
.heat__cell {
  aspect-ratio: 1; border-radius: 2.5px; background: var(--surface-sunk);
  transition: transform .14s var(--ease), outline-color .14s var(--ease);
  outline: 1.5px solid transparent; outline-offset: 0;
}
.heat__cell:hover { transform: scale(1.4); outline-color: var(--text); z-index: 2; position: relative; }
.heat__lbl { font-size: 11.5px; color: var(--text-mute); display: grid; place-items: center; }
.heat__hours { display: grid; grid-template-columns: 30px repeat(24, minmax(0, 1fr)); gap: 2px; margin-top: 4px; }
.heat__hour { font-size: 11.5px; color: var(--text-mute); text-align: center; }

/* ---- Empty state --------------------------------------------------------- */
.empty {
  padding: 46px 22px; text-align: center; color: var(--text-mute);
}
.empty__ico {
  width: 46px; height: 46px; border-radius: var(--r-md); margin: 0 auto 13px;
  background: var(--surface-sunk); display: grid; place-items: center; color: var(--text-mute);
}
.empty__title { font-size: 13.5px; font-weight: 700; color: var(--text); margin-bottom: 5px; }
.empty__body { font-size: 12px; max-width: 320px; margin: 0 auto; line-height: 1.55; }

/* ---- Toast --------------------------------------------------------------- */
.toast-stack {
  position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%);
  z-index: 200; display: flex; flex-direction: column-reverse; gap: 9px;
  pointer-events: none; width: min(420px, calc(100vw - 32px));
}
.toast {
  display: flex; align-items: center; gap: 11px;
  padding: 12px 15px; border-radius: var(--r-md);
  background: var(--text); color: var(--bg);
  box-shadow: var(--lift-3); font-size: 12.5px; font-weight: 500;
  pointer-events: auto;
}
.toast__ico { flex-shrink: 0; display: grid; place-items: center; }
.toast__body { flex: 1; }
.toast--positive .toast__ico { color: #4ade80; }
.toast--negative .toast__ico { color: #ff8a94; }
.toast--accent .toast__ico { color: var(--brand-400); }

/* ---- Progress rail (export) ---------------------------------------------- */
.rail { height: 3px; border-radius: 2px; background: var(--surface-sunk); overflow: hidden; }
.rail__fill { height: 100%; width: 0; background: var(--accent); border-radius: 2px; }

/* ---- Sync pulse ---------------------------------------------------------- */
.pulse { position: relative; display: inline-grid; place-items: center; }
.pulse__core { width: 7px; height: 7px; border-radius: 50%; background: var(--positive); }
.pulse__ring {
  position: absolute; width: 7px; height: 7px; border-radius: 50%;
  background: var(--positive); opacity: .55;
}

/* ---- Key metric strip ---------------------------------------------------- */
.strip {
  display: grid; gap: 1px; background: var(--border);
  border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden;
  grid-template-columns: repeat(auto-fit, minmax(146px, 1fr));
}
.strip__cell { background: var(--surface); padding: 13px 15px; }
.strip__val { font-family: var(--font-display); font-size: 18px; font-weight: 800; letter-spacing: -0.035em; }
.strip__label { font-size: 12px; color: var(--text-mute); margin-top: 2px; }

/* ---- Reveal (GSAP sets final state; this is the pre-paint guard) ---------- */
.reveal { will-change: transform, opacity; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .reveal { opacity: 1 !important; transform: none !important; }
}

/* ---- Pendaftaran Program -------------------------------------------------
   The AI auto-filter banner reads as a control surface, not a card: a tinted
   panel that states the rule in words, because a sponsor approving people
   deserves to see the criteria rather than trust a label. The rule runs in
   the browser over local data — no applicant detail is ever sent anywhere. */
/* The accent treatment belongs to the card, not to its body. Painting it on
   .card__body instead drew a second box inside .card, and the body's own
   margin left a bare strip between the two borders. */
.card--accent { border-color: var(--accent-line); background: var(--accent-soft); }
/* .reg-ai used to carry this margin itself; it moves with the border. */
#regAiCard { margin-bottom: 16px; }

.reg-ai {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
}
.reg-ai__title {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-display); font-size: 14px; font-weight: 700;
  color: var(--text); margin-bottom: 4px;
}
.reg-ai__spark { display: inline-flex; color: var(--accent); flex-shrink: 0; }
.reg-ai__title svg { color: var(--accent); flex-shrink: 0; }
/* No measure cap here: the flex line sets the width. A `ch` cap stopped the
   copy at 446px inside a 1178px card and left the right half empty. */
.reg-ai__main { flex: 1 1 320px; min-width: 0; }
.reg-ai__toggle { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.reg-ai__toggle-label { font-size: 12.5px; font-weight: 600; color: var(--text-dim); }
/* Sits outside .card__body, so it carries the card's horizontal padding
   itself instead of running into the border. */
.reg-ai__note {
  font-size: 11.5px; padding: 10px 19px 15px;
  border-top: 1px solid var(--accent-line);
}

/* ---- Urus Borang (Pendaftaran Program, second tab) ------------------------
   Grid values come from the Registrations design mockup: Soalan 1.4fr,
   Seksyen 1fr, and two 90px switch columns. The switches are the app's own
   .switch component, not the mockup's inline ones. */
#regFormsNote { margin-bottom: 16px; }
.reg-forms__note {
  display: flex; align-items: center; gap: 10px;
  font-size: 12.5px; color: var(--text);
}
.reg-forms__note svg { color: var(--accent); flex-shrink: 0; }

.reg-forms__head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px; margin-bottom: 16px;
}

.reg-field {
  display: grid; grid-template-columns: 1.4fr 1fr 90px 90px;
  gap: 12px; align-items: center; padding: 12px 4px;
  border-top: 1px solid var(--border);
}
.reg-field--head {
  border-top: 0; padding: 0 4px 10px;
  font-size: 10.5px; font-weight: 600; color: var(--text-mute);
  text-transform: uppercase; letter-spacing: .02em;
}
.reg-field--head > :nth-child(3),
.reg-field--head > :nth-child(4) { text-align: center; }
.reg-field__label { font-size: 12.5px; font-weight: 600; min-width: 0; }
.reg-field__section { font-size: 11.5px; color: var(--text-mute); }
.reg-field__toggle { display: flex; justify-content: center; }
/* Spelled-out name for the two switches, shown only where the column header
   that named them is hidden (see the ≤700px block below). */
.reg-field__switch-label { display: none; }
.reg-field .input { font-size: 12.5px; padding: 6px 10px; }

.reg-forms__foot {
  display: flex; align-items: center; gap: 8px;
  margin-top: 20px; flex-wrap: wrap;
}
.reg-forms__foot .btn { flex: 0 1 auto; }
.reg-forms__hint { font-size: 11.5px; }
.reg-forms__footnote {
  font-size: 11px; text-align: center; margin-top: 20px;
}

/* ---- Applicant detail drawer (Pendaftaran, row click) --------------------
   The same object as the Directory's "details usahawan": .drawer + .overlay,
   slide from the right. Only the CONTENT is registrations-specific — section
   headings and the field cells (surface-alt, 10px radius, 10.5px label over a
   12.5px value, from the Registrations design mockup). */
#regDrawerFoot.is-stacked { flex-direction: column; align-items: stretch; gap: 10px; }
.reg-drawer__sec {
  font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: .02em;
  color: var(--text-mute); margin-bottom: 8px;
}
.reg-drawer__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 16px; }
.reg-drawer__cell { background: var(--surface-alt); border-radius: 10px; padding: 11px 13px; min-width: 0; }
.reg-drawer__cell--wide { grid-column: 1 / -1; }
.reg-drawer__lbl { font-size: 10.5px; color: var(--text-mute); margin-bottom: 2px; }
.reg-drawer__val { font-size: 12.5px; font-weight: 600; overflow-wrap: anywhere; }

.reg-drawer__sent {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border-radius: 9px;
  background: var(--positive-soft); color: var(--positive);
  font-size: 11.5px; font-weight: 600;
}
.reg-drawer__note { text-align: center; font-size: 10.5px; color: var(--text-mute); margin-top: 6px; }
/* The drawer foot is a row of equal actions; a lone Tutup stretches instead. */
#regDrawerFoot > .btn { flex: 1; justify-content: center; }

/* Decision buttons. The mockup fills "Luluskan" with the positive colour and
   outlines "Tolak" in the negative one; the shell's .btn only had primary and
   ghost, so these two modifiers fill the gap. */
.btn--positive { background: var(--positive); border-color: var(--positive); color: #fff; font-weight: 700; }
.btn--positive:hover { background: var(--positive); border-color: var(--positive); filter: brightness(1.06); }
.btn--danger { background: transparent; border-color: var(--negative); color: var(--negative); font-weight: 700; }
.btn--danger:hover { background: var(--negative-soft); border-color: var(--negative); }

/* Eligibility marker in the table. Two states only, so they are distinguished
   by icon and text as well as colour. */
.reg-flag { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }

/* ---- Sub-apps (jppkk-login.html, jppkk-platform.html, jppkk-peserta.html) -------------------
   These three are separate documents from the dashboard, so they need their
   own page chrome. Everything inside them reuses the dashboard's components
   (.card, .tbl, .btn, .switch, .field) — only the shell is new. */

.sub-body { background: var(--bg); min-height: 100vh; }

.subhead {
  position: sticky; top: 0; z-index: 40;
  background: var(--surface); border-bottom: 1px solid var(--border);
}
.subhead__in {
  max-width: var(--shell-max); margin: 0 auto;
  padding: 12px var(--pad-x);
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.subhead__brand {
  display: inline-flex; align-items: center; gap: 10px;
  text-decoration: none; color: inherit;
}
.subhead__mark {
  width: 32px; height: 32px; border-radius: 9px; flex-shrink: 0;
  background: var(--accent); color: var(--on-accent);
  display: grid; place-items: center;
}
/* Marka KPT / JPPKK (assets/img/jppkk-logo.png) pada slot auth: lockup berwarna
   penuh yang membawa plat putihnya sendiri — putih tulen dibakar dalam PNG,
   jadi ia hilang pada permukaan putih dan jadi plat bersih atas panel merah.
   Tinggi tetap + lebar auto supaya nisbah asal kekal; radius inilah yang
   memotong sudut plat. Kekhususan .subhead__brand … supaya ia menang atas
   .subhead__mark di atas (kotak 32px tetap). */
.subhead__brand .subhead__mark--gov { width: auto; height: auto; background: none; border-radius: 0; }
.subhead__brand .subhead__mark--gov img { height: 44px; width: auto; border-radius: 10px; }

.subhead__brand strong {
  display: block; font-family: var(--font-display);
  font-size: 15px; line-height: 1.2;
}
.subhead__brand small {
  display: block; color: var(--text-mute); font-size: 12px; line-height: 1.3;
}
.subhead__actions { display: flex; align-items: center; gap: 8px; }

.sub-main { padding-top: 24px; padding-bottom: 56px; }

/* A KPI strip that wraps instead of overflowing on narrow screens. */
.kpi-row {
  display: grid; gap: 12px; margin-bottom: 20px;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}

/* A label on the left, a control on the right — the settings-row shape. */
.set-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 12px 0;
  border-bottom: 1px solid var(--border);
}
.set-row:last-child { border-bottom: 0; padding-bottom: 0; }
.set-row__label { font-size: 14px; line-height: 1.45; }

.plat__seg { margin-bottom: 22px; }
.plat__settings { display: grid; gap: 16px; max-width: 640px; }
.plat__set-body { display: grid; gap: 2px; }

@media (max-width: 720px) {
  .subhead__brand small { display: none; }
  .set-row { flex-direction: row; align-items: flex-start; }
}

/* ---- Portal Peserta (jppkk-peserta.html) ---------------------------------------- */

.psr__gate { max-width: 460px; margin: 0 auto; }
.psr__note { font-size: 12px; color: var(--text-mute); margin-top: 10px; text-align: center; }
.psr__hint { font-size: 12px; color: var(--text-mute); margin: -4px 0 12px; }
.psr__eyebrow {
  font-family: var(--font-num);
  font-size: 11px; font-weight: 700; letter-spacing: .12em;
  color: var(--accent); margin-bottom: 4px;
}

.psr__form { display: grid; gap: 16px; }

/* Two columns on wide screens; the full-width fields opt out with .psr__wide.
   Collapses to one column below the tablet breakpoint so labels keep their
   text width instead of squeezing. */
.psr__grid { display: grid; gap: 0 18px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.psr__wide { grid-column: 1 / -1; }

.psr__meta { display: grid; grid-template-columns: max-content 1fr; gap: 8px 18px; margin: 0; }
.psr__meta dt { font-size: 12px; color: var(--text-mute); }
.psr__meta dd { margin: 0; font-size: 14px; font-weight: 600; }

/* The simulated e-mail, framed so it reads as a preview and not as page copy. */
.psr__mail { border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden; }
.psr__mail-head {
  background: var(--surface-sunk); padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  font-size: 12px; line-height: 1.7; color: var(--text-dim);
}
.psr__mail-body { padding: 14px; font-size: 13.5px; line-height: 1.65; }
.psr__mail-body p { margin: 0 0 10px; }
.psr__mail-body p:last-child { margin-bottom: 0; }

@media (max-width: 720px) {
  .psr__grid { grid-template-columns: minmax(0, 1fr); }
}

/* ---- Login (jppkk-login.html) ---------------------------------------------------
   A two-panel gate: the pitch on the left, the forms on the right. It drops to
   a single column below 900px, where the pitch panel is hidden rather than
   stacked, because on a phone the form is the only thing that matters. */
.auth-body { min-height: 100vh; background: var(--bg); }

.auth { display: grid; grid-template-columns: 1.15fr .85fr; min-height: 100vh; position: relative; }

.auth__aside {
  /* Gap dan padding sedar-tinggi (vh): pada skrin 14" dengan bar pelayar,
     tinggi yang tinggal cuma ~560-640px, jadi nilai tetap 28/64px menghabiskan
     semua ruang bebas dan tajuk terpaku pada logo. min(5vw, 5.2vh) mengecil
     ikut mana yang lebih ketat. */
  display: flex; flex-direction: column;
  gap: clamp(18px, 3.2vh, 28px);
  padding: clamp(22px, min(5vw, 5.2vh), 64px);
  background: var(--accent); color: #fff;
}
.auth__brand { display: flex; align-items: center; gap: 12px; }
.auth__mark {
  display: grid; place-items: center; width: 38px; height: 38px; border-radius: 11px;
  /* Tiada plat di belakang marka: panel ini sudah merah (--accent), dan plat putih
     16% menghilangkan kontras cincin putih marka. Marka duduk terus atas panel. */
  background: none; color: #fff; flex: none;
}
/* Marka KPT / JPPKK pada panel log masuk. Panel ini merah (--accent), jadi plat
   putih yang dibawa PNG itulah yang memisahkan lockup berwarna penuh daripada
   latar; tiada plat CSS berasingan perlu ditambah. */
.auth__brand .auth__mark--gov,
.auth__brand .auth__mark--polis { width: auto; height: auto; border-radius: 0; }
/* Saiz dinaikkan 50% (56 → 84px) atas permintaan. `min()` menjaga panel sempit:
   dua plat berdampingan (JPPKK 4.71:1, POLISAS 1.70:1, gap 12px) makan ~6.4×
   tinggi, dan kandungan panel cuma 0.575vw tolak padding clamp — jadi 6.9vw
   menguncupkan kedua-duanya secara berterusan sebelum aside disembunyikan pada
   900px (di situ tinggi ≈ 62px, jumlah ≈ 410px < 427px kandungan). Mulai
   ~1220px viewport kedua-duanya kekal pada 84px. */
.auth__brand .auth__mark--gov img,
.auth__brand .auth__mark--polis img { height: min(84px, 6.9vw, 14vh); width: auto; border-radius: 14px; }

.auth__brand strong { display: block; font-size: 15px; letter-spacing: -.01em; }
.auth__brand small { display: block; font-size: 11.5px; opacity: .82; margin-top: 1px; }

.auth__title {
  font-family: var(--font-display);
  /* Saiz ikut lebar DAN tinggi viewport (5.4vh): pada 1366x640 tajuk jadi ~30px
     — masih berbobot tetapi tidak lagi memakan 93px tinggi. line-height
     dilonggarkan 1.16 → 1.2 dan letter-spacing -.02em → -.015em supaya blok dua
     baris ini tidak nampak sempit. `padding-top` (bukan margin) menjamin ruang
     antara logo dan tajuk walaupun `margin-top: auto` kehabisan ruang. */
  font-size: clamp(24px, min(3.4vw, 5.4vh), 40px); line-height: 1.2; letter-spacing: -.015em;
  margin: auto 0 0; padding-top: clamp(22px, 3.6vh, 48px); font-weight: 800;
}
.auth__ver { font-weight: 500; font-size: .62em; letter-spacing: 0; color: var(--auth-ink-mute); }
.auth__points { list-style: none; margin: 0; padding: 0; display: grid; gap: clamp(10px, 1.7vh, 13px); max-width: 74ch; }
.auth__points li {
  display: flex; gap: 11px; align-items: flex-start; font-size: 14px; line-height: 1.55;
  color: var(--auth-ink-soft); opacity: 1;
}
.auth__tick {
  display: grid; place-items: center; width: 19px; height: 19px; border-radius: 50%;
  background: rgba(255,255,255,.2); flex: none; margin-top: 1px;
}
.auth__demo-note {
  margin: 0; font-size: 12px; line-height: 1.55; opacity: .8;
  border-top: 1px solid rgba(255,255,255,.22); padding-top: 16px; max-width: none;
}

.auth__panel { display: grid; place-items: center; padding: clamp(24px, 4vw, 48px); }
.auth__card { width: 100%; max-width: 380px; }
.auth__form-title { margin: 0 0 4px; font-size: 21px; letter-spacing: -.015em; }
.auth__form-sub { margin: 0 0 22px; font-size: 13px; color: var(--text-mute); line-height: 1.5; }
.auth__form .field { margin-bottom: 15px; }
.auth__row { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 4px 0 20px; }
.auth__link { font-size: 12.5px; color: var(--accent); text-decoration: none; }
.auth__link:hover { text-decoration: underline; }
.auth__foot {
  margin: 20px 0 12px; font-size: 12.5px; color: var(--text-mute); line-height: 1.6;
  border-top: 1px solid var(--border); padding-top: 16px;
}

/* ---- Auth: warna sisi ditukar (dia minta merah ke kanan, putih ke kiri) ---
   Susunan asal ialah pitch merah di kiri + borang putih di kanan. Sekarang
   pitch di kiri memakai latar putih dan SEMUA teksnya merah, manakala panel
   borang di kanan memakai --accent dengan teks --on-accent — pasangan token
   yang sama seperti .btn--primary, jadi ia sah dalam tema cerah (putih atas
   merah) dan tema gelap (hampir hitam atas merah cerah). */
/* Side ditukar ialah WARNA latar, bukan kedudukan blok: pitch kekal di kiri
   (kini putih dengan teks merah), borang kekal di kanan (kini merah dengan
   kawalan ter-invert). Urutan DOM dan markup tidak disentuh. */
/* Teks panel pitch = dark grey (dia minta ganti merah). Tiga tangga ink supaya
   hierarki tajuk → isi → nota kekal tanpa warna jenama; logo, panel merah di
   kanan dan butang tidak disentuh. */
.auth__aside {
  --auth-ink:      #3a3a3a;
  --auth-ink-soft: #4d4d4d;
  --auth-ink-mute: #6d6d6d;
  background: var(--surface); color: var(--auth-ink);
}
/* Jaring keselamatan: halaman login memaksa tema cerah (data-theme="light" pada
   <html>, theme.js tidak dimuat); kalau ia pernah mengikut tema, dark grey di
   atas --surface gelap jadi tidak terbaca. */
[data-theme='dark'] .auth__aside {
  --auth-ink: #e9e5e5; --auth-ink-soft: #cfc9c9; --auth-ink-mute: #a79f9f;
}
.auth__panel { background: var(--accent); color: var(--on-accent); }

/* Latar seni garisan (hasilan ChatGPT) pada panel putih auth sahaja — panel
   merah tidak menerimanya. Watermark ini sengaja SANGAT pudar (dia minta
   opacity 'sngt light') supaya teks merah kekal senang dibaca: .06 pada putih
   hanya menggelapkan garisan ke sekitar #f2f2f2, jadi kontras teks hampir
   tidak berubah. `cover` + `bottom`: bangunan diisi penuh dari bawah SAMPAI
   ATAS panel (dia minta dibesarkan lagi) — sisa langit yang lapang di bahagian
   atas kekal, jadi logo tidak ditimpa garisan. Dalam tema gelap garisan yang
   sama dicerahkan supaya kelihatan. */
.auth__aside { position: relative; overflow: hidden; }
.auth__aside::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: url('./img/auth-bg-lines.png') no-repeat center bottom / cover;
  opacity: .06;
}
.auth__aside > * { position: relative; z-index: 1; }
[data-theme='dark'] .auth__aside::before { opacity: .14; filter: brightness(1.7) saturate(.85); }

/* Pitch di atas latar putih: teks merah, tint merah ganti tint putih. */
.auth__aside .auth__tick {
  background: color-mix(in srgb, var(--auth-ink) 11%, transparent);
  color: var(--auth-ink-mute);
}
.auth__aside .auth__demo-note {
  border-top-color: color-mix(in srgb, var(--auth-ink) 20%, transparent);
  opacity: 1; color: var(--auth-ink-mute);
}

/* Borang di atas merah: setiap kawalan di-‘invert’ ikut --on-accent. */
.auth__panel .auth__form-title { color: var(--on-accent); }
.auth__panel .auth__form-sub { color: color-mix(in srgb, var(--on-accent) 80%, transparent); }
.auth__panel .field__label { color: color-mix(in srgb, var(--on-accent) 85%, transparent); }
.auth__panel .input {
  background: color-mix(in srgb, var(--on-accent) 20%, transparent);
  border-color: color-mix(in srgb, var(--on-accent) 44%, transparent);
  color: var(--on-accent);
}
.auth__panel .input::placeholder { color: color-mix(in srgb, var(--on-accent) 80%, transparent); }
.auth__panel .input:focus {
  border-color: color-mix(in srgb, var(--on-accent) 72%, transparent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--on-accent) 22%, transparent);
}
.auth__panel .check { color: color-mix(in srgb, var(--on-accent) 88%, transparent); }
.auth__panel .check input { accent-color: var(--on-accent); }
.auth__panel .auth__link { color: var(--on-accent); text-decoration: underline; text-underline-offset: 2px; }
.auth__panel .auth__link:hover { text-decoration: underline; opacity: .82; }
.auth__panel .auth__foot {
  border-top-color: color-mix(in srgb, var(--on-accent) 26%, transparent);
  color: color-mix(in srgb, var(--on-accent) 82%, transparent);
}
.auth__panel .auth__foot strong, .auth__panel .auth__foot b { color: var(--on-accent); }
.auth__panel .auth__alt { color: color-mix(in srgb, var(--on-accent) 80%, transparent); }
.auth__panel .auth__err { color: var(--on-accent); font-weight: 700; }

/* Butang: primary jadi plat --on-accent (merah pada putih, hitam pada merah
   cerah) dan ghost jadi garis --on-accent — kalau tidak, butang merah atas
   panel merah hilang. */
.auth__panel .btn--primary {
  background: var(--on-accent); border-color: transparent; color: var(--accent);
  box-shadow: none;
}
.auth__panel .btn--primary:hover {
  background: color-mix(in srgb, var(--on-accent) 88%, transparent);
  border-color: transparent; color: var(--accent);
}
.auth__panel .btn--ghost {
  color: var(--on-accent);
  border-color: color-mix(in srgb, var(--on-accent) 42%, transparent);
}
.auth__panel .btn--ghost:hover {
  background: color-mix(in srgb, var(--on-accent) 12%, transparent);
  border-color: color-mix(in srgb, var(--on-accent) 60%, transparent);
  color: var(--on-accent);
}

/* Tetingkap desktop sempit (901–1150px): beri lajur pitch bahagian yang lebih
   besar dan kurangkan padding sisi, supaya baris teks tidak berpecah jadi 3–4
   baris (dia minta "lebarkan width ni supaya tulisan tak perlu line banyak"). */
@media (min-width: 901px) and (max-width: 1150px) {
  .auth__aside { padding: clamp(26px, 3.4vw, 52px); }
}

/* Tajuk: nama rasmi PPIPB ini panjang (59 aksara). Di bawah ~1300px, saiznya
   diturunkan sedikit supaya ia kekal 2 baris dan bukannya 3 — lajur pitch
   sudah dilebarkan (1.15fr) tetapi ruang masih terhad pada tetingkap sempit. */
@media (min-width: 901px) and (max-width: 1300px) {
  .auth__title { font-size: clamp(23px, min(2.7vw, 5vh), 34px); }
}

@media (max-width: 900px) {
  .auth { grid-template-columns: 1fr; }
  .auth__aside { display: none; }
}

/* ---- Print --------------------------------------------------------------- */
@media print {
  .masthead, .nav, .page-head__actions, .toast-stack, .drawer, .overlay { display: none !important; }
  body { background: #fff; }
  .card, .stat { break-inside: avoid; box-shadow: none; }
}

/* ---- Responsive ---------------------------------------------------------- */
@media (max-width: 860px) {
  /* The masthead keeps only what a thumb needs mid-scroll: a way into the
     menu, the identity, and the one destructive-free action worth a tap.
     Everything else moved into the sidenav, which has room to label it. */
  .icon-btn.menu-btn { display: grid; }
  .masthead__bar { height: 60px; gap: 10px; }
  .brand__tag { display: none; }
  .profile { display: none; }
  .rule-v { display: none; }
  /* The sidenav carries its own copy; only the masthead one is dropped. */
  .segmented:not(.segmented--block) { display: none; }
  .nav { display: none; }
  #syncBtn { display: none; }
  #alertBtn { display: none; }
  /* The sidenav has a labelled theme row; a 52x28 switch here would be both a
     duplicate and the only remaining target under 44px. */
  .theme-toggle { display: none; }

  /* The brand is the flexible element, not the tools: squeezing the tools
     produces overlapping icons, squeezing the name produces an ellipsis. */
  .brand { flex: 1 1 auto; min-width: 0; }
  .brand__text { min-width: 0; }
  .brand__name { overflow: hidden; text-overflow: ellipsis; }
  .masthead__tools { flex-shrink: 0; }

  .page { padding-top: 20px; }
  .heat { grid-template-columns: 26px repeat(24, minmax(0, 1fr)); }
  .heat__hours { grid-template-columns: 26px repeat(24, minmax(0, 1fr)); }
  .balance__val { font-size: 29px; }

  /* Comfortable tap targets. The whole row is the target, not the glyph. */
  .icon-btn { width: 42px; height: 42px; }
  .search__clear { width: 26px; height: 26px; right: 8px; }
  .switch { width: 46px; height: 28px; }
  .switch__knob { width: 22px; height: 22px; }
  .switch[aria-checked='true'] .switch__knob { transform: translateX(20px); }
  .tbl tbody .icon-btn, #teamBody .icon-btn { width: 34px !important; height: 34px !important; }
  .close-btn { width: 40px; height: 40px; }
  .btn { padding: 12px 16px; min-height: 44px; }
  .btn--sm { padding: 10px 13px; min-height: 40px; }
  .chip { padding: 9px 14px; min-height: 40px; }
  .segmented__btn { padding: 9px 14px; }
  .menu__item { padding: 12px 11px; }
  .legend-row { padding: 10px 7px; min-height: 42px; }
  .alert { padding: 15px 17px; }
  .nav__link { padding: 0 12px; }

  /* Two controls stay visually small on purpose: the switch reads as a switch
     at 28px, and the inline link sits inside a sentence. Growing the box would
     break both, so the hit area is extended past the paint instead. */
  .switch, .link-inline { position: relative; }
  .switch::after, .link-inline::after {
    content: ''; position: absolute; left: 0; right: 0;
    top: 50%; transform: translateY(-50%); height: 44px;
  }
  .input, .select { font-size: 16px; padding: 11px 13px; }

  /* iOS zooms the whole page when a focused field is under 16px and never
     zooms back out. Every text-entry control gets 16px on touch layouts. */
  .select { padding-right: 34px; }
  .search__input { font-size: 16px; }
}

@media (max-width: 560px) {
  .stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .donut-wrap { justify-content: center; }
  .drawer { width: 100vw; }
  .page-head { gap: 12px; }
  .page-head__actions { width: 100%; }
  .page-head__actions .btn { flex: 1; }
  .map-canvas { min-height: 340px; }
  .tbl td, .tbl thead th { padding-left: 10px; padding-right: 10px; }
  .drawer__body { padding: 15px 16px 22px; }
  .mini-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* At 210px the spotlight body's min-width forces the icon and the merchant
     name onto a shared row that no longer has room for either: the title
     wraps mid-word and the button drops to its own line anyway, so the
     "shared row" buys nothing but a cramped headline. Stack top-to-bottom
     instead so the title gets the card's full width. */
  .spotlight { flex-direction: column; align-items: flex-start; }
  .spotlight__body { min-width: 0; width: 100%; }
  .spotlight .btn { width: 100%; justify-content: center; }

  /* Export band (Laporan Ringkasan Bulanan untuk BSN): the intro row reuses
     .spotlight__ico with align-items:center inline on its parent, which
     vertically centres the icon against a two-line title instead of pinning
     it to the top. Force top alignment on mobile, where the title reliably
     wraps. The auto-email toggle is the one action that changes standing
     behaviour (versus CSV/Excel/PDF, which are one-off exports), so it gets
     its own full-width row instead of sharing space as a squeezed chip. */
  .export-band__intro { align-items: flex-start !important; }
  .export-band__actions { flex-wrap: wrap; }
  .export-band__actions .check.btn { width: 100%; justify-content: center; order: -1; }

  /* Map card header: the legend gradient chip sits beside the title in a
     nowrap flex row, so on mobile it eats the width the title and subtitle
     need to wrap normally, squeezing "Menunjukkan 30 usahawan di 9 negeri..."
     into a narrow column instead of the card's full width. Drop the legend
     to its own line below the title so both get the full row. */
  .map-card .card__head { flex-wrap: wrap; }
  .map-card .card__head > div:first-child { width: 100%; }
  .map-card .map-legend { width: 100%; }
}

/* Reports date filter: keep Dari/Hingga inline side-by-side, Tapis full-width. */
@media (max-width: 560px) {
  .filter-bar__date { flex: 1 1 0; min-width: 0; flex-direction: column !important; align-items: stretch !important; gap: 4px !important; }
  .filter-bar__date .input { width: 100%; }
  #repRangeNote { width: 100%; order: 4; }
  .filter-bar__apply { width: 100%; order: 3; }
}

/* ==========================================================================
   Leaderboard column priority
   ==========================================================================
   The leaderboard card is sized by the surrounding grid, not by the window, so
   its columns drop on the panel's own width. Below 1080px the split grid
   collapses and the card is suddenly wide again, which no viewport media query
   can see.

   Rank, name, sales and status are kept longest: they are what the panel is
   read for. Whatever drops stays one click away in the profile drawer and in
   full on the Directory page.

   These live at the end of the sheet on purpose. At equal specificity the last
   declaration wins, so an override placed earlier is simply ignored: that is
   what happened to the first attempt at these rules.
   -------------------------------------------------------------------------- */
.table-wrap--lb { container: lb / inline-size; }

@container lb (max-width: 759px) { .c-trend  { display: none; } }
@container lb (max-width: 667px) { .c-sector { display: none; } }
@container lb (max-width: 543px) { .c-mom    { display: none; } }

@container lb (max-width: 470px) {
  .tbl td, .tbl thead th { padding-left: 7px; padding-right: 7px; }
  .cell-id__name,
  .cell-id__sub {
    max-width: 100px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
}

@container lb (max-width: 380px) {
  .tbl td, .tbl thead th { padding-left: 6px; padding-right: 6px; }
  .cell-id__name,
  .cell-id__sub { max-width: 84px; }
  /* Reclaim width from the two fixed-size decorations rather than from the
     merchant name, which is what the panel is actually scanned for. */
  .badge { font-size: 11px; padding: 3px 7px; }
  .rank-pip { width: 18px; height: 18px; font-size: 11px; }
}

/* ==========================================================================
   Pendaftaran Program — head tabs + Urus Borang (placed last, same reason as
   the block above: these override the shared responsive guards).
   ========================================================================== */

/* The ≤860px guard hides every .segmented except .segmented--block, because the
   mobile sidenav carries a copy of the masthead's switches. It has no copy of
   this view switch, so hiding it would strand the Urus Borang tab completely on
   a phone. Keep it visible, with the larger tap padding the guard applies. */
@media (max-width: 860px) {
  #regSeg { display: flex; }
  #regSeg .segmented__btn { padding: 9px 14px; }
}
@media (max-width: 560px) {
  #regSeg { width: 100%; }
  #regSeg .segmented__btn { flex: 1; text-align: center; }
}

/* Below 700px the Soalan | Seksyen | 90px | 90px grid leaves ~50px for the
   question text, which wraps mid-word. Stack instead: the question and section
   get the full row, and the two switches keep their meaning from a spelled-out
   label because the column header is gone at this width. */
@media (max-width: 700px) {
  .reg-field { grid-template-columns: 1fr auto auto; gap: 10px; }
  .reg-field--head { display: none; }
  .reg-field > :nth-child(1) { grid-column: 1 / -1; }        /* soalan */
  .reg-field > :nth-child(2) { grid-column: 1 / -1; margin-top: -6px; }
  .reg-field > :nth-child(3) { grid-column: 2; }             /* wajib  */
  .reg-field > :nth-child(4) { grid-column: 3; }             /* aktif  */
  .reg-field__toggle { align-items: center; gap: 7px; }
  .reg-field__switch-label { display: inline; font-size: 11.5px; color: var(--text-mute); }
  .reg-forms__head { flex-direction: column; align-items: stretch; }
  .reg-forms__head .btn { justify-content: center; }
  .reg-forms__foot .btn { flex: 1 1 auto; justify-content: center; }
  .reg-field .input { font-size: 16px; }                     /* no iOS zoom */
}

/* ==========================================================================
   Kata laluan set semula + pautan sekunder bawah borang
   (jppkk-login.html and jppkk-peserta.html). Placed last for the same reason as the two
   blocks above: the shared responsive guards are declared earlier.
   ========================================================================== */

/* The one line of secondary links under a form — "Sudah ada akaun? Log masuk". */
.auth__alt,
.psr__alt {
  margin: 14px 0 0; font-size: 12.5px; line-height: 1.6;
  color: var(--text-mute); text-align: center;
}
.psr__alt + .psr__alt { margin-top: 5px; }

/* Inline validation line, under the field it belongs to. */
.auth__err,
.psr__err { margin: -6px 0 12px; font-size: 12.5px; line-height: 1.55; color: var(--negative); }
.auth__err[hidden],
.psr__err[hidden] { display: none; }

/* Intro line on the gate card's set-semula view; the daftar form has none, so
   this only ever renders inside the reset panel. */
.psr__sub { margin: 4px 0 18px; font-size: 12.5px; line-height: 1.6; color: var(--text-mute); }

/* ---- Gate peserta (daftar akaun / set semula) -----------------------------
   Kad ini satu-satunya skrin auth dalam jppkk-peserta.html. Ia memakai rawatan
   yang sama seperti panel borang login (merah + kawalan ter-invert) supaya
   aliran auth seragam; latar halaman kekal cerah dan layout kad tidak diubah.
   --on-accent ialah pasangan --accent (putih dalam tema cerah, hampir hitam
   dalam tema gelap), jadi satu set peraturan sah untuk dua tema. */
.psr__gate {
  background: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
  color: var(--on-accent);
}
.psr__gate .card__title { color: var(--on-accent); }
.psr__gate .card__sub,
.psr__gate .psr__sub,
.psr__gate .psr__note { color: color-mix(in srgb, var(--on-accent) 80%, transparent); }
.psr__gate .psr__alt { color: color-mix(in srgb, var(--on-accent) 78%, transparent); }
.psr__gate .psr__err { color: var(--on-accent); font-weight: 700; }
.psr__gate .field__label { color: color-mix(in srgb, var(--on-accent) 85%, transparent); }
.psr__gate .input {
  background: color-mix(in srgb, var(--on-accent) 20%, transparent);
  border-color: color-mix(in srgb, var(--on-accent) 44%, transparent);
  color: var(--on-accent);
}
.psr__gate .input::placeholder { color: color-mix(in srgb, var(--on-accent) 80%, transparent); }
.psr__gate .input:focus {
  border-color: color-mix(in srgb, var(--on-accent) 72%, transparent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--on-accent) 22%, transparent);
}
.psr__gate .auth__link { color: var(--on-accent); text-decoration: underline; text-underline-offset: 2px; }
.psr__gate .btn--primary {
  background: var(--on-accent); border-color: transparent; color: var(--accent); box-shadow: none;
}
.psr__gate .btn--primary:hover {
  background: color-mix(in srgb, var(--on-accent) 88%, transparent); color: var(--accent);
}


/* ==========================================================================
   Portal Peserta — program, produk, laporan, profil.
   Placed last for the same reason as the blocks above: these override the
   shared .psr__* defaults declared earlier in the sheet.
   ========================================================================== */

/* Short description line on a program or product card. */
.psr__blurb { margin: 0 0 12px; font-size: 12.5px; line-height: 1.6; color: var(--text-dim); }

/* A definition list packed tighter than the status card's. */
.psr__meta--tight { gap: 6px 16px; margin: 0 0 14px; }
.psr__meta--tight dt { font-size: 11.5px; }
.psr__meta--tight dd { font-size: 13px; }

/* Action row at the foot of an inline form. */
.psr__formbtns { display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px; }

/* The two longer participant forms carry vertical rhythm; the short
   registration card stays flush, which is how it was approved. */
#psrActForm .psr__grid,
#psrProfilForm .psr__grid { gap: 14px 18px; }

/* Textareas borrow the .input skin, which is tuned for single-line inputs. */
.psr__grid textarea.input { resize: vertical; min-height: 62px; font: inherit; font-size: 12.5px; }

/* Photo tiles — a hidden file input inside a styled label, matching the
   Aktiviti Usahawan uploader on the sponsor side. */
.psr__photos { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 0; }
.psr__photos:empty { margin: 0; }
.psr__photo {
  position: relative; width: 68px; height: 68px; flex: none;
  border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden;
}
.psr__photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.psr__photodel {
  position: absolute; top: 2px; right: 2px; width: 20px; height: 20px;
  display: grid; place-items: center; border: 0; border-radius: 50%;
  background: rgba(20, 14, 15, .58); color: #fff; font-size: 11px; line-height: 1;
}
.psr__photodel:hover { background: rgba(20, 14, 15, .8); }
.psr__photopick { align-self: flex-start; cursor: pointer; }

/* The profile cards hold very different amounts of text (10 rows next to 4),
   so let them size to their own content instead of stretching to the tallest —
   otherwise the short card is mostly empty space. */
#psrProfil .grid { align-items: start; }

/* Programme and product cards are grid items, so they stretch to equal height;
   without this the call-to-action floats up under the copy that happens to be
   shortest and the row's buttons sit at different heights. */
#psrProgGrid .card__body,
#psrProdGrid .card__body { display: flex; flex-direction: column; }
#psrProgGrid .card__body .btn,
#psrProdGrid .card__body .btn { margin-top: auto; }

/* The portal nav sits between the sub-head and the content, like the sponsor
   app's own .nav. Keep the phone's tap target honest. */
@media (max-width: 720px) {
  #psrNav .nav__inner { height: 44px; }
}

/* ---- Rekod laporan: dialog + helaian cetak -------------------------------- */

/* `.overlay` cannot be reused here: its opacity is animated from app.js, which
   does not load on jppkk-peserta.html, so it would sit at opacity 0 and still swallow
   every click. */
.psr__scrim { position: fixed; inset: 0; z-index: 90; background: rgba(20, 14, 15, .48); }
.psr__scrim[hidden] { display: none; }

.psr__dlg {
  position: fixed; z-index: 100; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: min(560px, calc(100vw - 32px)); max-height: 88vh;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: 0 24px 56px -24px rgba(20, 14, 15, .38);
}
.psr__dlg[hidden] { display: none; }
.psr__dlg-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  padding: 17px 19px 14px; border-bottom: 1px solid var(--border);
}
.psr__dlg-sub { font-size: 12px; color: var(--text-mute); margin-top: 3px; }
.psr__dlg-body { padding: 16px 19px; overflow-y: auto; }
.psr__dlg-foot {
  display: flex; align-items: center; justify-content: flex-end; gap: 10px;
  padding: 13px 19px; border-top: 1px solid var(--border);
}
.psr__dlg-foot .psr__err { margin: 0 auto 0 0; }

.psr__rec-h {
  margin: 18px 0 6px; font-size: 11px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-mute);
}
.psr__rec-p { margin: 0; font-size: 13px; line-height: 1.65; }

/* Printing the record goes through the Cetak button, which builds a clean A4
   sheet in its own window — a stray Ctrl+P on the portal must not print the
   page with this dialog sitting on top of it. */
@media print {
  .psr__dlg, .psr__scrim { display: none !important; }
}

/* ---- Blue action button ---------------------------------------------------
   The Lihat button on a participant's own report. Filled with --info and
   lettered in --info-soft: the two swap places in the dark theme (light blue
   surface, dark navy text), so one rule stays legible in both without a
   second colour or a theme-specific override. */
.btn--info {
  background: var(--info); border-color: transparent;
  color: var(--info-soft); font-weight: 700;
}
.btn--info:hover {
  background: var(--info); border-color: transparent;
  filter: brightness(.93);
}

/* ---- Program card images + active highlight ------------------------------ */
.psr__prog-img {
  display: block; width: 100%; height: 160px; object-fit: cover;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}
.card--aktif {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 22%, transparent),
              0 4px 18px -6px color-mix(in srgb, var(--accent) 18%, transparent);
}
.card--aktif .card__head { background: color-mix(in srgb, var(--accent) 6%, transparent); }

/* Rows in Laporan Dihantar open the record dialog, so the row is the control.
   Same recipe as #regTableBody on the Pendaftaran screen. */
#psrActBody tr[data-lihat]:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* The programme filter bar: the search takes the slack, the two selects keep
   their natural width, and the whole row wraps on a phone rather than
   squeezing. `.search` is a flex item here, so it needs a basis of its own. */
#psrPrograms .filter-bar .search { flex: 1 1 220px; max-width: 360px; }
#psrPrograms .filter-bar .select { width: auto; }
#psrProgCount { margin-left: auto; }
@media (max-width: 560px) {
  #psrPrograms .filter-bar .search { flex-basis: 100%; max-width: none; }
  #psrProgCount { margin-left: 0; }
}

/* ---- Wizard permohonan (enam langkah) ------------------------------------ */

.psr__dlg--wide { width: min(680px, calc(100vw - 32px)); }

/* Step progress: a thin rail directly under the dialog head, so the count is
   legible at a glance without a numbered stepper to read. */
.psr__wiz-bar { height: 4px; flex: none; background: var(--surface-sunk); }
.psr__wiz-fill {
  display: block; width: 0; height: 100%;
  background: var(--accent);
  transition: width .28s var(--ease);
}

.psr__wiz-note {
  margin: 0 0 15px; padding: 10px 13px;
  font-size: 12.5px; line-height: 1.55; color: var(--text-dim);
  background: var(--accent-soft); border-radius: var(--r-md);
}
.psr__wiz-note strong { color: var(--text); }

/* Back · step count · next. */
#psrWizard .psr__dlg-foot { justify-content: space-between; }
.psr__wiz-count { font-size: 12px; color: var(--text-mute); }

/* A required marker that is quiet about it. */
.psr__req { color: var(--accent); font-weight: 700; }

/* The wizard's own field rhythm — the dialog is long enough to need it. */
#psrWizStepBox .psr__grid { gap: 15px 18px; }
#psrWizStepBox .check { align-items: flex-start; font-size: 12.5px; line-height: 1.6; }
#psrWizStepBox .check input { margin-top: 2px; }

@media (max-width: 560px) {
  #psrWizard .psr__dlg-foot { flex-wrap: wrap; justify-content: stretch; }
  .psr__wiz-count { order: 3; width: 100%; text-align: center; }
}

/* ---- Pengurusan mentor (Directory -> tab Mentor) -------------------------
   Dialog berpusat, bukan #drawer: panel sisi ditolak untuk skrin pengurusan.
   Panel guna var(--surface) — tiada --card dalam palet ini, dan scrim tempatan
   (bukan .overlay) kerana .overlay hanya kelihatan selepas app.js menyala-kannya. */
.mtr__scrim { position: fixed; inset: 0; z-index: 90; background: rgba(20, 14, 15, .48); }
.mtr__scrim[hidden] { display: none; }
.mtr__dlg {
  position: fixed; z-index: 91; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: min(680px, calc(100vw - 28px)); max-height: 88vh;
  display: flex; flex-direction: column;
  background: var(--surface, #fff); border: 1px solid var(--border);
  border-radius: 16px; box-shadow: 0 24px 60px rgba(20, 14, 15, .3); overflow: hidden;
}
.mtr__dlg[hidden] { display: none; }
.mtr__dlg-head {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 14px;
  padding: 18px 20px 14px; border-bottom: 1px solid var(--border); flex: none;
}
.mtr__eyebrow {
  margin: 0 0 4px; font-size: 10.5px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--accent);
}
.mtr__dlg-sub { margin: 6px 0 0; font-size: 12.5px; line-height: 1.55; color: var(--text-mute); }
.mtr__dlg-body {
  padding: 18px 20px; overflow-y: auto;
  /* min-height:0 — tanpanya flex item ini enggan mengecil dan dialog
     melebihi max-height, lalu footer (Simpan/Batal) terkeluar skrin. */
  min-height: 0;
}
.mtr__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 13px 16px; }
.mtr__sec { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--border); }
.mtr__sec-title { margin: 0; font-size: 14px; font-weight: 700; }
.mtr__count { margin-left: 6px; font-size: 11.5px; font-weight: 600; color: var(--text-mute); }
.mtr__count.mtr__over { color: var(--negative); }
.mtr__sec-sub { margin: 6px 0 12px; font-size: 12.5px; line-height: 1.6; color: var(--text-dim); }
.mtr__warn { color: var(--warning); font-weight: 600; }
.mtr__picks { display: grid; gap: 7px; max-height: 240px; overflow-y: auto; padding-right: 2px; }
.mtr__pick {
  display: flex; align-items: center; gap: 10px; padding: 9px 11px;
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface-alt); cursor: pointer; font-size: 13px;
}
.mtr__pick:hover { border-color: var(--border-strong); }
.mtr__pick input { flex: none; width: 16px; height: 16px; accent-color: var(--accent); }
.mtr__pick-txt { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.mtr__pick-txt .u-mute { font-size: 11.5px; }
.mtr__empty { margin: 0; font-size: 12.5px; color: var(--text-mute); }
.mtr__acct { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.mtr__note {
  margin: 14px 0 0; padding: 10px 13px; border-radius: var(--r-md);
  font-size: 12.5px; line-height: 1.6; color: var(--text-dim); background: var(--accent-soft);
}
.mtr__note[hidden] { display: none; }
.mtr__err { margin: 0 0 10px; font-size: 12.5px; font-weight: 600; color: var(--negative); }
.mtr__dlg-foot {
  display: flex; justify-content: flex-end; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 14px 20px; border-top: 1px solid var(--border); background: var(--surface-alt); flex: none;
}
.mtr__dlg-foot .mtr__err { flex: 1 1 100%; margin: 0 0 4px; }
.mtr__hint {
  margin-left: auto; max-width: 150px; font-size: 11.5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  /* Sel ini membawa .t-num (IBM Plex Mono) untuk angka; nama mentee di dalamnya
     ialah prosa dan tidak boleh mewarisi fon itu. */
  font-family: var(--font-body); font-weight: 500; font-variant-numeric: normal;
}
#mtrNote { margin: 0 0 15px; }
/* Slot ganjil pada grid .strip mewarisi --border dan kelihatan sebagai blok
   berwarna; latar ini menjadikannya tidak kelihatan. */
#mtrStrip { background: var(--surface); }

@media (max-width: 640px) {
  .mtr__grid { grid-template-columns: 1fr; }
  .mtr__dlg { max-height: 92vh; }
  .mtr__hint { max-width: 96px; }
}

/* ---- Mentor: kad "Mentor Anda" di dashboard peserta ---------------------- */
.psr__mt-title {
  margin: 18px 0 9px; font-size: 11px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-mute);
}
.psr__mt-list {
  margin: 0; padding-left: 18px; display: grid; gap: 6px;
  font-size: 12.5px; line-height: 1.55; color: var(--text-dim);
}
.psr__mt-list li::marker { color: var(--accent); }

/* The application summary is one long line ("4 permohonan · 1 diluluskan ·
   1 ditolak · 1 dibatalkan"). Without a shrinkable child the card head pushes
   the whole page 5px wider than a 390px screen. */
#psrAppCard .card__head > div { min-width: 0; }
@media (max-width: 620px) {
  #psrAppCard .card__head { flex-wrap: wrap; }
}

/* A definition-list value can be one long unbreakable token — an e-mail
   address, a URL, a company name. The 1fr track keeps its min-content width
   otherwise, and the grid pushes the page wider than the screen (the mentor
   card's e-mail did exactly that at 390px). */
.psr__meta dd { min-width: 0; overflow-wrap: anywhere; }

/* The shared 1080px rule drops .grid--thirds straight from three columns to
   one, which leaves a 960px-wide programme card on a laptop. Two steps down
   instead — scoped to this grid so the product grid keeps its own behaviour. */
@media (max-width: 1080px) {
  #psrProgGrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
  #psrProgGrid { grid-template-columns: minmax(0, 1fr); }
}

/* Bar penapis produk mengikut geometri bar program — carian ambil slack,
   dua select kekal saiz sendiri, kiraan di hujung kanan. */
#psrProduk .filter-bar .search { flex: 1 1 220px; max-width: 360px; }
#psrProduk .filter-bar .select { width: auto; }
#psrProdCount { margin-left: auto; }

@media (max-width: 720px) {
  #psrProduk .filter-bar .search { flex-basis: 100%; max-width: none; }
  #psrProdCount { margin-left: 0; }
}
/* ---- Dashboard peserta: "Program Anda" + "Mentor Anda" bersebelahan ------
   Dua kad yang peserta paling kerap cari, jadi satu baris. Grid ini
   di-top-align, bukan diregangkan: kad mentor jauh lebih panjang kerana
   senarai tugasan, dan regangan hanya meninggalkan ruang kosong di bawah kad
   program. .grid--halves sendiri runtuh ke satu kolum pada 1080px (peraturan
   kongsi) — tiada breakpoint tambahan di sini. */
.psr__pair { margin-bottom: 18px; align-items: start; }

/* Gambar passport yang belum ditetapkan `src` ialah kotak kosong: sembunyikan
   sehingga render menetapkan src. `[hidden]` tidak boleh dipakai di sini —
   peraturan kelas (.psr__passport) mengalahkan peraturan [hidden] UA. */
.psr__passport:not([src]) { display: none; }

/* Gambar passport mentor: kad ID nisbah 3.5:4.5 di kiri, butiran di kanan. */
.psr__idcard { display: flex; align-items: flex-start; gap: 16px; }
.psr__idcard .psr__meta { flex: 1 1 auto; min-width: 0; }
.psr__passport {
  flex: none; width: 92px; height: 118px; object-fit: cover;
  border-radius: var(--r-sm); border: 1px solid var(--border);
  background: var(--surface-sunk);
}

@media (max-width: 560px) {
  .psr__idcard { gap: 12px; }
  .psr__passport { width: 76px; height: 98px; }
}

/* Consent block inside the wizard last step */
.psr__consent-head { margin: 12px 0 8px; }
.psr__consent-title {
  font-size: 15px; font-weight: 700; margin: 0 0 6px;
  color: var(--text);
}
.psr__consent-note {
  font-size: 13px; line-height: 1.5; color: var(--text-dim);
  margin: 0 0 10px;
}
.psr__consent-foot {
  font-size: 12px; line-height: 1.5; color: var(--text-dim);
  margin: 10px 0 0; font-style: italic;
}

/* ==== Penapis IPT pada halaman Laporan (dropdown boleh cari) =============== */
.ssel { display: inline-block; }
.ssel__btn {
  display: inline-flex; align-items: center; gap: 10px;
  min-width: 232px; max-width: 320px; text-align: left; font-weight: 600;
}
.ssel__label { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ssel__btn.is-set { border-color: var(--accent); color: var(--accent); }

.ssel__panel {
  position: fixed; z-index: 9998; display: flex; flex-direction: column;
  padding: 9px; max-height: 356px;
  background: var(--surface, #fff); border: 1px solid var(--border, #e7e0df);
  border-radius: 12px; box-shadow: 0 18px 44px rgba(0, 0, 0, .2);
}
.ssel__search { display: block; margin-bottom: 7px; }
.ssel__search .input { font-size: 12.5px; }
.ssel__list { overflow-y: auto; max-height: 288px; }
.ssel__group-head {
  position: sticky; top: 0; z-index: 1; padding: 9px 9px 5px;
  background: var(--surface, #fff); font-size: 10.5px; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase; color: var(--text-mute);
}
.ssel__opt {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  width: 100%; padding: 7px 9px; border: 0; border-radius: 8px;
  background: none; color: var(--text); font: inherit; font-size: 12.5px;
  text-align: left; cursor: pointer;
}
.ssel__opt:hover, .ssel__opt:focus-visible { background: var(--surface-sunk); outline: none; }
.ssel__opt--all { font-weight: 700; }
.ssel__opt.is-active { background: color-mix(in srgb, var(--accent) 12%, transparent); font-weight: 700; }
.ssel__opt-name { min-width: 0; }
.ssel__opt-state { flex: none; font-size: 11px; color: var(--text-mute); }
/* `hidden` di sini mesti eksplisit: `.ssel__opt` menetapkan `display: flex`
   dan itu mengalahkan peraturan `[hidden]` lalai pelayar. */
.ssel__opt[hidden], .ssel__group[hidden] { display: none; }
.ssel__empty { padding: 15px 9px; font-size: 12px; color: var(--text-mute); }

/* Kolum IPT dalam jadual laporan: nama institusi panjang, biar membalut kemas. */
.ledger-ipt { font-size: 12px; line-height: 1.4; }

@media (max-width: 700px) {
  .ssel, .ssel__btn { width: 100%; max-width: none; }
}

/* ==== Pengurusan Program (halaman #programs) ============================== */
.prog-thumb {
  width: 40px; height: 40px; border-radius: 10px; object-fit: contain;
  background: var(--surface-sunk); border: 1px solid var(--border); padding: 3px;
}
.prog-thumb--kosong {
  display: grid; place-items: center; font-size: 11px; font-weight: 700;
  color: var(--text-mute); letter-spacing: .02em;
}

.prog-scrim {
  position: fixed; inset: 0; z-index: 9999; background: rgba(0, 0, 0, .55);
  display: flex; align-items: center; justify-content: center; padding: 18px;
}
.prog-dlg {
  width: 720px; max-width: 96vw; max-height: 92vh; display: flex; flex-direction: column;
  background: var(--surface, #fff); border: 1px solid var(--border, #e7e0df);
  border-radius: 16px; box-shadow: 0 22px 60px rgba(0, 0, 0, .28); overflow: hidden;
}
.prog-dlg__head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  padding: 20px 22px 14px; border-bottom: 1px solid var(--border);
}
.prog-dlg__title { font-size: 15.5px; font-weight: 800; letter-spacing: -.02em; margin: 0 0 4px; }
.prog-dlg__sub { font-size: 12px; color: var(--text-dim); margin: 0; }
.prog-dlg__body { padding: 18px 22px; overflow-y: auto; min-height: 0; }
.prog-dlg__foot {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 22px; border-top: 1px solid var(--border); background: var(--surface-sunk);
}
.prog-form { display: grid; grid-template-columns: 1fr 1fr; gap: 13px 15px; }
.prog-field--wide { grid-column: 1 / -1; }
.prog-form .field { min-width: 0; }
.prog-form textarea.input { resize: vertical; font-family: var(--font-body); }
.prog-hint { font-size: 11.5px; color: var(--text-mute); line-height: 1.5; }
.prog-err { margin: 0 22px 6px; font-size: 12px; color: var(--negative); }

.prog-logo {
  display: flex; align-items: center; gap: 12px; margin-top: 2px;
  padding: 10px 12px; border: 1px dashed var(--border); border-radius: 12px;
  background: var(--surface-sunk); cursor: pointer; min-height: 64px;
}
.prog-logo:hover { border-color: var(--accent); }
.prog-logo__img { width: 76px; height: 44px; object-fit: contain; background: var(--surface); border-radius: 8px; }
.prog-logo__hint { font-size: 12px; font-weight: 600; color: var(--text-dim); }

@media (max-width: 620px) {
  .prog-form { grid-template-columns: 1fr; }
  .prog-dlg { max-height: 94vh; }
}

/* ---- Laporan Aktiviti peserta (halaman #reports) -------------------------
   Jadual = satu baris per laporan peserta; drawer kanan = rekod penuh laporan
   itu. Senarai medan dirender oleh assets/laporan.js (recordHtml) dengan kelas
   .rep__meta, jadi drawer pemilik program dan dialog rekod portal peserta
   memaparkan medan yang SAMA. Ditulis di hujung helaian, mengikut konvensyen
   projek ini untuk CSS satu halaman. */
.rep__meta {
  display: grid; grid-template-columns: max-content 1fr; gap: 6px 16px;
  margin: 0 0 16px;
}
.rep__meta dt { font-size: 11.5px; color: var(--text-mute); }
.rep__meta dd { margin: 0; font-size: 13px; font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
.rep__meta dd .u-mute { font-weight: 500; }
.rep__h { font-size: 12px; font-weight: 800; letter-spacing: -.01em; margin: 16px 0 6px; }
.rep__p { margin: 0 0 12px; font-size: 13px; line-height: 1.6; color: var(--text-dim); }
.rep__p:last-child { margin-bottom: 0; }
#ledgerBody tr[role="button"]:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ==== Footer global (keempat-empat shell) =================================
   Markup yang sama: kiri ayat hak cipta, kanan nama sistem + versinya.
   `.shell` (dashboard) sudah lajur flex; `.sub-body` / `.auth-body` dijadikan
   lajur flex supaya footer jatuh ke bawah walaupun kandungan pendek. */
.gfoot {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px 22px; padding: 13px var(--pad-x);
  border-top: 1px solid var(--border); background: var(--surface);
  color: var(--text-mute); font-size: 11.5px; line-height: 1.55;
}
.gfoot__copy { margin: 0; text-align: left; }
.gfoot__sys {
  margin: 0; flex: none; text-align: right; font-weight: 600;
  color: var(--text-dim); white-space: nowrap;
}
@media (max-width: 760px) {
  .gfoot { flex-direction: column; align-items: flex-start; }
  .gfoot__sys { text-align: left; white-space: normal; }
}

.sub-body, .auth-body { display: flex; flex-direction: column; }
/* KENAPA `width: 100%` WAJIB: dalam lajur flex, paksi silang ialah lebar, dan
   `align-items: stretch` menetapkan lebar SEMUA item kepada item terlebar.
   Satu anak berlebar max-content (jadual/pair kad di portal peserta) melebarkan
   <main> hingga 934px dalam skrin 390px. Lebar pasti mematikan kesan itu
   (`min-width: 0` tidak membantu — ia paksi utama, bukan paksi silang). */
.sub-body > .sub-main, .auth-body > .auth, .shell > .main {
  flex: 1 1 auto; min-width: 0; width: 100%;
}
/* `.auth` asalnya min-height: 100vh; biar lajur flex yang tentukan tinggi,
   jika tidak footer didorong ke bawah lipatan. */
.auth-body > .auth { min-height: auto; }

/* ==== Plat POLISAS di sebelah lockup JPPKK ================================
   PNG POLISAS membawa plat putihnya sendiri (sama seperti lockup JPPKK), jadi
   tiada plat CSS perlu ditambah. Kekhususan `.brand__mark.brand__mark--polis`
   (0,2,0) supaya ia menang atas `.brand__mark` (38px + gradien merah). */
.brand__mark.brand__mark--polis {
  width: auto; height: auto; border-radius: 0;
  background: none; box-shadow: none;
}
.brand__mark.brand__mark--polis img {
  height: 48px; width: auto; border-radius: 10px; display: block;
}
.subhead__brand .subhead__mark--polis { width: auto; height: auto; background: none; border-radius: 0; }
.subhead__brand .subhead__mark--polis img { height: 44px; width: auto; border-radius: 10px; }

/* Masthead sempit: kedua-dua plat dikecilkan serentak. Disebut dengan
   `.masthead` (bukan hanya `.brand__mark…`) supaya kekhususan menang atas
   peraturan `.sidenav .brand__mark--gov img` dan lockup dalam sidenav tidak
   terbawa-bawa. */
@media (max-width: 900px) {
  .masthead .brand__mark.brand__mark--gov img { height: 36px; }
  .masthead .brand__mark.brand__mark--polis img { height: 36px; }
}
@media (max-width: 560px) {
  .masthead .brand__mark.brand__mark--gov img { height: 34px; }
  .masthead .brand__mark.brand__mark--polis img { height: 34px; }
}

/* Subhead peserta / platform pada telefon: plat POLISAS menambah ~85px pada
   baris yang sudah memuatkan butang tema + cip pengguna, jadi kedua-dua plat
   dikecilkan. Peraturan ini berbaris kemudian daripada peraturan 44px di
   atas (kekhususan sama) supaya ia menang. */
@media (max-width: 860px) {
  .subhead__brand .subhead__mark--gov img,
  .subhead__brand .subhead__mark--polis img { height: 34px; border-radius: 8px; }
}
@media (max-width: 560px) {
  .subhead__brand .subhead__mark--gov img,
  .subhead__brand .subhead__mark--polis img { height: 30px; border-radius: 7px; }
}
/* ==== Plat logo penaja (assets/penaja.js) =================================
   Logo penaja membawa plat birunya sendiri (PNG), jadi hanya tinggi + radius
   yang dikawal di sini. `--sm` untuk teks kecil (baris kad), `--md` untuk
   senarai definisi, baris jadual pentadbir dan pratonton borang. */
.penaja { display: inline-flex; align-items: center; gap: 7px; }

/* Kad "Program Anda" pada dashboard peserta (#psrMyProgram): nama penaja di
   BAWAH plat logo, sama seperti sel Penaja dalam jadual Pengurusan Program.
   Aturan asas di atas kekal inline-flex supaya plat penaja pada kad halaman
   Program (`.card__sub`) tidak berubah. */
#psrMyProgram .penaja { flex-direction: column; align-items: flex-start; gap: 3px; }
.penaja__logo { height: 20px; width: auto; border-radius: 6px; flex: none; }
.penaja__logo--sm { height: 17px; border-radius: 5px; }
.penaja__logo--md { height: 26px; border-radius: 7px; }
.penaja-row { display: flex; align-items: center; gap: 9px; min-width: 0; }

/* Sel Penaja dalam jadual Pengurusan Program (#progBody): nama penaja di
   BAWAH plat logo, bukan di sebelahnya. Satu-satunya pengguna `.penaja-row`
   ialah sel itu, tetapi pengecekan `#progBody` dikekalkan supaya aturan ini
   tidak terbawa ke tempat lain yang memakai plat penaja. Peraturan asas di
   atas ialah flex row; yang ini menegakkannya untuk sel itu sahaja. */
#progBody .penaja-row { flex-direction: column; align-items: flex-start; gap: 3px; }
.penaja-prev { margin-top: 8px; display: flex; align-items: center; gap: 8px; }
/* `display: flex` di atas mengalahkan atribut [hidden], jadi ini wajib. */
.penaja-prev[hidden] { display: none; }
@media (max-width: 560px) {
  .penaja__logo--md { height: 22px; }
}

/* ==========================================================================
   Carta bar liputan IPT (Overview) + susunan senarai penapis IPT
   ========================================================================== */
/* Kepala kad dengan kawalan di kanan: pada layar sempit kawalan turun ke
   barisnya sendiri dan tidak lagi menolak tajuk. */
.card__head--wrap { flex-wrap: wrap; row-gap: 12px; }

.iptbar__seg {
  transition: opacity .18s var(--ease);
  /* Naik dari garis dasar; `fill-box` menjadikan asalan pada kotak segmen itu
     sendiri. Tiada `forwards`, jadi tiada transform sisa selepas animasi. */
  transform-box: fill-box; transform-origin: bottom;
  animation: iptbar-rise .55s cubic-bezier(.22, .68, .32, 1) backwards;
}
@keyframes iptbar-rise { from { transform: scaleY(0); } to { transform: scaleY(1); } }
.iptbar__val {
  font-family: var(--font-num); font-size: 11.5px; font-weight: 700;
  fill: var(--text-dim);
}

/* Panel penapis IPT: baris "Susun" + angka peserta di kanan setiap baris. */
.ssel__sort {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 2px 4px 9px; margin-bottom: 6px; border-bottom: 1px solid var(--border);
}
.ssel__sort-label {
  margin-right: 2px; font-size: 10.5px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--text-mute);
}
.ssel__sort-btn {
  padding: 4px 10px; border: 1px solid var(--border); border-radius: 999px;
  background: none; color: var(--text-dim); font: inherit; font-size: 11.5px;
  font-weight: 600; cursor: pointer;
  transition: color .18s var(--ease), border-color .18s var(--ease), background .18s var(--ease);
}
.ssel__sort-btn:hover { color: var(--accent); border-color: var(--accent); }
.ssel__sort-btn.is-on {
  color: var(--accent); border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.ssel__opt-meta { flex: none; display: flex; align-items: baseline; gap: 9px; }
.ssel__opt-n { font-family: var(--font-num); font-size: 10.5px; color: var(--text-dim); }
.ssel__opt-n.is-zero { color: var(--text-mute); }

/* 12 bar dalam 390px tidak boleh dibaca: carta boleh ditatal mendatar pada
   telefon (bekasnya sendiri, jadi halaman tidak melebar). */
@media (max-width: 860px) {
  .chart--scroll { overflow-x: auto; overflow-y: hidden; }
  .chart--scroll svg { min-width: 720px; }
  /* Satu-satunya salinan kawalan ini — tiada di sidenav — jadi ia mesti
     dikecualikan daripada peraturan `.segmented { display: none }` ≤860px. */
  #iptChartSeg { display: flex; }
  #iptChartSeg .segmented__btn { padding: 6px 10px; font-size: 11.5px; }
}
@media (max-width: 560px) {
  .card__head--wrap { flex-direction: column; align-items: stretch; }
  .iptbar__val { font-size: 10px; }
}
@media (prefers-reduced-motion: reduce) {
  .iptbar__seg { animation: none; }
}
/* ==== Permohonan peserta: sunting semula + dokumen sokongan ===============
   Klien: “semua peserta boleh edit semula borang permohonan program … mungkin
   peserta tak hantar borang SSM dia boleh upload semula.” Butang Sunting
   memakai .btn--primary (merah jenama), medan fail menggantikan fail lama. */
.psr__file { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.psr__file-btn { cursor: pointer; }
.psr__file-nama { font-size: 12.5px; color: var(--text-dim); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.psr__file-thumb {
  width: 42px; height: 42px; object-fit: cover; border-radius: 8px;
  border: 1px solid var(--border); background: var(--surface-alt); flex: none;
}
.psr__file-hint { display: block; margin-top: 6px; font-size: 11.5px; color: var(--text-mute); }
.psr__dok-pill {
  display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .02em; vertical-align: 1px;
  background: color-mix(in srgb, var(--positive) 14%, transparent);
  color: color-mix(in srgb, var(--positive) 78%, var(--text));
}
.psr__dok-pill--sun {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: color-mix(in srgb, var(--accent) 82%, var(--text));
}
/* ==== Hebahan program awam (jppkk-program.html) ==========================
   Dua kad sebelah menyebelah pada desktop, bertindan pada telefon. Logo
   program sengaja besar — ia yang menarik perhatian dalam tangkapan skrin
   pautan WhatsApp. */
.awam__hero {
  display: grid; place-items: center; padding: 18px;
  background: var(--surface-alt); border-bottom: 1px solid var(--border);
}
.awam__logo {
  max-width: 100%; width: auto; max-height: 190px; object-fit: contain;
  border-radius: 12px; background: var(--surface);
}
.awam__penaja {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px; margin-bottom: 16px;
  border-radius: 12px; background: var(--surface-alt); border: 1px solid var(--border);
}
.awam__tajuk-kecil { margin: 4px 0 10px; font-family: var(--font-display); font-size: 13.5px;
  text-transform: uppercase; letter-spacing: .06em; color: var(--text-mute); }
.awam__langkah { list-style: none; margin: 0 0 16px; padding: 0; display: grid; gap: 10px; }
.awam__langkah li { display: flex; gap: 10px; align-items: flex-start; font-size: 13.5px;
  line-height: 1.5; color: var(--text-dim); }
.awam__nombor {
  flex: none; width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center;
  font-size: 11px; font-weight: 700; background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
}
.awam__cta { display: grid; gap: 9px; margin-bottom: 12px; }
.awam__penuh { margin: 12px 0 0; font-size: 13.5px; line-height: 1.6; color: var(--text-dim); }
@media (min-width: 900px) {
  #awamKandungan { grid-template-columns: 1.15fr .85fr; align-items: start; }
}
.awam-link { display: flex; gap: 8px; align-items: center; }
.awam-link .input { font-size: 12.5px; }
/* Halaman hebahan: dua butang dalam subhead (Log Masuk + Mohon Sekarang)
   melebihi lebar telefon, jadi yang kedua (sudah ada di badan halaman)
   disembunyikan pada skrin kecil. */
@media (max-width: 700px) {
  .subhead__actions--awam .btn--ghost { display: none; }
}
@media (max-width: 560px) {
  /* Hebahan: teks brand ("Hebahan Program") + butang CTA lebih lebar daripada
     telefon 320-390px, jadi teks itu disembunyikan — dua plat logo sudah
     cukup untuk mengenal pasti halaman. */
  .subhead--awam .subhead__brand > span:last-child { display: none; }
}
@media (max-width: 380px) {
  .subhead--awam .subhead__brand .subhead__mark img { height: 26px; }
}
@media (max-width: 340px) {
  /* Telefon tersempit: CTA kepala berundur — butang yang sama ada pada kad. */
  .subhead__actions--awam { display: none; }
}
