/* ============================================================
   CVN OS — Components
   ============================================================ */

/* ---------- Toast ---------- */
#toast-root {
  position: fixed;
  bottom: var(--sp-5); right: var(--sp-5);
  z-index: var(--z-toast);
  display: flex; flex-direction: column; gap: var(--sp-2);
  pointer-events: none;
}
.toast {
  display: flex; align-items: center; gap: var(--sp-3);
  min-width: 260px; max-width: 380px;
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  background: var(--bg-raised);
  border: 1px solid var(--line-soft);
  box-shadow: var(--shadow-lg);
  font-size: var(--fs-sm);
  color: var(--ink-bright);
  transform: translateY(10px); opacity: 0;
  transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-base);
  pointer-events: auto;
}
.toast.is-in { transform: none; opacity: 1; }
.toast svg { width: 17px; height: 17px; flex-shrink: 0; }
.toast--ok    svg { color: var(--ok); }
.toast--error svg { color: var(--danger); }
.toast--info  svg { color: var(--info); }

@media (max-width: 720px) {
  #toast-root { left: var(--sp-4); right: var(--sp-4); bottom: calc(var(--bottombar-h) + var(--sp-4)); }
  .toast { min-width: 0; max-width: none; }
}

/* ---------- Modal ---------- */
.modal-scrim {
  position: fixed; inset: 0; z-index: var(--z-modal);
  display: grid; place-items: center;
  padding: var(--sp-4);
  background: var(--bg-scrim);
  backdrop-filter: blur(3px);
  opacity: 0; transition: opacity var(--dur-base) var(--ease-out);
}
.modal-scrim.is-open { opacity: 1; }

.modal {
  width: 100%; max-height: 88dvh;
  display: flex; flex-direction: column;
  background: var(--bg-surface);
  box-shadow: var(--shadow-lg), var(--edge-hi);
  backdrop-filter: var(--glass-ctrl-blur);
  -webkit-backdrop-filter: var(--glass-ctrl-blur);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
  transform: scale(0.97) translateY(8px);
  transition: transform var(--dur-base) var(--ease-out);
}
.modal-scrim.is-open .modal { transform: none; }
.modal--sm { max-width: 400px; }
.modal--md { max-width: 560px; }
.modal--lg { max-width: 820px; }
.modal--xl { max-width: 1080px; }

.modal__head {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--line-hair);
}
.modal__title { font-size: var(--fs-lg); flex: 1; }
.modal__x {
  display: grid; place-items: center;
  width: 30px; height: 30px; border-radius: var(--r-sm);
  color: var(--ink-muted);
}
.modal__x:hover { background: var(--bg-overlay); color: var(--ink-bright); }
.modal__x svg { width: 17px; height: 17px; }
.modal__body { padding: var(--sp-5); overflow-y: auto; flex: 1; }
.modal__foot {
  display: flex; justify-content: flex-end; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--line-hair);
}

@media (max-width: 560px) {
  .modal-scrim { padding: 0; align-items: flex-end; }
  .modal { max-width: none; max-height: 92dvh; border-radius: var(--r-xl) var(--r-xl) 0 0; }
}

/* ---------- Form tambahan ---------- */
.form { display: grid; gap: var(--sp-3); grid-template-columns: 1fr 1fr; }
.form .field { margin: 0; }
.field--wide { grid-column: 1 / -1; }
.field--inline {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: var(--sp-3);
  cursor: pointer;
}
.field--inline input { width: 17px; height: 17px; accent-color: var(--accent); }
.field__hint { margin-top: var(--sp-1); font-size: var(--fs-xs); color: var(--ink-faint); }
.field__error { margin-top: var(--sp-1); font-size: var(--fs-xs); color: var(--danger); min-height: 1em; }
textarea.input { resize: vertical; min-height: 76px; font-family: inherit; }
select.input { appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238A92A6' stroke-width='2'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 16px;
  padding-right: var(--sp-10);
}
.input-group { display: flex; align-items: stretch; }
.input-group__prefix {
  display: grid; place-items: center;
  padding: 0 var(--sp-3);
  background: var(--bg-overlay);
  border: 1px solid var(--line-soft); border-right: none;
  border-radius: var(--r-md) 0 0 var(--r-md);
  font-size: var(--fs-sm); color: var(--ink-muted);
}
.input-group .input { border-radius: 0 var(--r-md) var(--r-md) 0; }

@media (max-width: 560px) { .form { grid-template-columns: 1fr; } }

/* ---------- Tombol tambahan ---------- */
.btn--sm { padding: var(--sp-2) var(--sp-3); font-size: var(--fs-sm); }
.btn--danger { background: var(--danger); color: #fff; }
.btn--danger:hover:not(:disabled) { background: #DC2626; }

.icon-btn {
  display: inline-grid; place-items: center;
  width: 30px; height: 30px; border-radius: var(--r-sm);
  color: var(--ink-muted);
  transition: background var(--dur-fast), color var(--dur-fast);
}
.icon-btn:hover { background: var(--bg-overlay); color: var(--ink-bright); }
.icon-btn--danger:hover { background: var(--danger-glow); color: var(--danger); }
.icon-btn svg { width: 15px; height: 15px; }
.row-actions { display: inline-flex; gap: 2px; }

/* ---------- Badge & chip ---------- */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px var(--sp-2);
  border-radius: var(--r-full);
  font-size: var(--fs-2xs); font-weight: var(--fw-medium);
  color: var(--c); background: color-mix(in srgb, var(--c) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--c) 30%, transparent);
  white-space: nowrap;
}
.chip {
  display: inline-flex; align-items: center;
  padding: 2px var(--sp-2);
  border-radius: var(--r-sm);
  font-size: var(--fs-2xs);
  background: var(--bg-overlay); color: var(--ink-muted);
  border: 1px solid var(--line-hair);
}

/* ---------- Progress ---------- */
.progress {
  height: 6px; border-radius: var(--r-full);
  background: var(--bg-overlay); overflow: hidden;
}
.progress__fill {
  height: 100%; border-radius: inherit;
  transition: width var(--dur-slow) var(--ease-out);
}

/* ---------- Stat ---------- */
.stat {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-4);
  border-radius: var(--r-lg);
}
.stat__icon {
  display: grid; place-items: center;
  width: 40px; height: 40px; border-radius: var(--r-md);
  background: color-mix(in srgb, var(--c) 14%, transparent);
  color: var(--c); flex-shrink: 0;
}
.stat__icon svg { width: 19px; height: 19px; }
.stat__label { font-size: var(--fs-xs); color: var(--ink-muted); }
.stat__value {
  font-family: var(--font-display);
  font-size: var(--fs-2xl); font-weight: var(--fw-bold);
  letter-spacing: var(--track-tighter);
  color: var(--ink-bright); line-height: 1.15;
  margin-top: 2px;
}
.stat__sub { font-size: var(--fs-2xs); color: var(--ink-faint); }

.grid-stats {
  display: grid; gap: var(--sp-3);
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.grid-cards {
  display: grid; gap: var(--sp-3);
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}

/* ---------- Skeleton ---------- */
.skeleton-wrap { display: grid; gap: var(--sp-3); }
.skeleton {
  height: 38px; border-radius: var(--r-sm);
  background: linear-gradient(90deg, var(--bg-overlay) 25%, var(--bg-raised) 50%, var(--bg-overlay) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.3s var(--ease-inout) infinite;
}
@keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* ---------- Table ---------- */
.table-wrap { display: grid; gap: var(--sp-3); }
.table-toolbar {
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
}
.table-toolbar__right { margin-left: auto; display: flex; gap: var(--sp-2); align-items: center; }

.search { position: relative; flex: 1; min-width: 180px; max-width: 320px; }
.search svg {
  position: absolute; left: var(--sp-3); top: 50%; transform: translateY(-50%);
  width: 16px; height: 16px; color: var(--ink-faint); pointer-events: none;
}
.search__input {
  width: 100%; padding: var(--sp-2) var(--sp-3) var(--sp-2) var(--sp-8);
  font-size: var(--fs-sm);
  background: var(--glass-ctrl); color: var(--ink-bright);
  backdrop-filter: var(--glass-ctrl-blur);
  -webkit-backdrop-filter: var(--glass-ctrl-blur);
  border: 1px solid var(--glass-ctrl-line); border-radius: var(--r-md);
}
.search__input::placeholder { color: var(--ink-faint); opacity: 0.55; }
.search__input:focus { outline: none; border-color: var(--cyan); box-shadow: 0 0 0 3px var(--cyan-glow); }

.table-scroll { overflow-x: auto; margin: 0 calc(var(--sp-4) * -1); padding: 0 var(--sp-4); }
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.table th {
  padding: var(--sp-3) var(--sp-3);
  text-align: left;
  font-size: var(--fs-2xs); font-weight: var(--fw-semibold);
  letter-spacing: var(--track-wide); text-transform: uppercase;
  color: var(--ink-muted); white-space: nowrap;
  border-bottom: 1px solid var(--line-soft);
}
.table th.is-sortable { cursor: pointer; user-select: none; }
.table th.is-sortable:hover { color: var(--ink-bright); }
.table th svg { width: 12px; height: 12px; display: inline-block; vertical-align: -2px; margin-left: 3px; opacity: 0.5; }
.table th.is-asc svg, .table th.is-desc svg { opacity: 1; color: var(--cyan); }
.table td {
  padding: var(--sp-3) var(--sp-3);
  border-bottom: 1px solid var(--line-hair);
  color: var(--ink-body); vertical-align: middle;
}
.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr.is-clickable { cursor: pointer; }
.table tbody tr:hover { background: var(--bg-overlay); }
.cell-strong { color: var(--ink-bright); font-weight: var(--fw-medium); }
.cell-sub { font-size: var(--fs-xs); color: var(--ink-faint); }

/* ---------- Tabs ---------- */
.tabs {
  display: flex; gap: var(--sp-1);
  border-bottom: 1px solid var(--line-soft);
  margin-bottom: var(--sp-5);
  overflow-x: auto;
}
.tab {
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-sm); color: var(--ink-muted);
  border-bottom: 2px solid transparent;
  white-space: nowrap;
  transition: color var(--dur-fast);
}
.tab:hover { color: var(--ink-body); }
.tab.is-active { color: var(--ink-bright); border-bottom-color: var(--accent); font-weight: var(--fw-medium); }
.tab.is-active .tab__count { background: var(--accent-soft); color: var(--accent); }
.tab__count {
  margin-left: var(--sp-2); padding: 1px 6px;
  font-size: var(--fs-2xs); border-radius: var(--r-full);
  background: var(--bg-overlay); color: var(--ink-muted);
}

/* ---------- Filter bar ---------- */
/* ---------- Baris filter dropdown ---------- */

/* Dropdown filter memakai .input yang sama dengan form — glassmorphism dan
   penipisan .is-empty ikut apa adanya, jadi filter yang belum dipilih
   langsung ketahuan tanpa aturan warna baru. */
.filterbar {
  display: flex;
  gap: var(--sp-2);
  flex-wrap: wrap;
  margin-bottom: var(--sp-4);
}
.filterbar .input--sm { width: auto; min-width: 148px; }

/* Pemicu dropdown React (.rsel__trigger) adalah .input selebar 100%, dan di
   dalam baris flex itu membuat tiap filter menempati satu baris penuh di
   desktop. Setiap anak langsung diberi lebar dasar yang sama, supaya
   empat filter berjajar dalam satu baris selama muat. */
.filterbar > * { flex: 1 1 180px; max-width: 260px; min-width: 0; }
.filterbar .rsel__trigger { width: 100%; }

.input--sm {
  padding: 6px var(--sp-3);
  font-size: var(--fs-sm);
}

/* Di HP dua kolom, supaya empat dropdown tidak jadi empat baris penuh. */
@media (max-width: 560px) {
  .filterbar { display: grid; grid-template-columns: 1fr 1fr; }
  .filterbar > * { max-width: none; }
  .filterbar .input--sm { width: 100%; min-width: 0; }
}

/* ---------- Navigasi halaman ---------- */

.pager {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
  margin-top: var(--sp-4);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--line-hair);
}
.pager__info { margin-right: auto; }
.pager__nav { display: flex; align-items: center; gap: 4px; }

.pager__btn {
  min-width: 32px;
  height: 32px;
  padding: 0 var(--sp-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  color: var(--ink-body);
  background: var(--glass-ctrl);
  backdrop-filter: var(--glass-ctrl-blur);
  -webkit-backdrop-filter: var(--glass-ctrl-blur);
  border: 1px solid var(--glass-ctrl-line);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.pager__btn:hover:not(:disabled):not(.is-active) {
  color: var(--ink-bright);
  border-color: var(--line-strong);
}
.pager__btn.is-active {
  color: var(--ink-bright);
  border-color: var(--cyan);
  box-shadow: 0 0 0 2px var(--cyan-glow);
  cursor: default;
}
.pager__btn:disabled { opacity: 0.4; cursor: not-allowed; }
.pager__btn svg { width: 14px; height: 14px; }
.pager__gap { color: var(--ink-faint); padding: 0 2px; }

@media (max-width: 560px) {
  .pager { justify-content: center; }
  .pager__info { margin-right: 0; width: 100%; text-align: center; }
}

.filters { display: flex; gap: var(--sp-2); flex-wrap: wrap; margin-bottom: var(--sp-4); }
.filter-pill {
  padding: var(--sp-1) var(--sp-3);
  font-size: var(--fs-sm); color: var(--ink-muted);
  background: var(--glass-ctrl);
  backdrop-filter: var(--glass-ctrl-blur);
  -webkit-backdrop-filter: var(--glass-ctrl-blur);
  border: 1px solid var(--glass-ctrl-line); border-radius: var(--r-full);
  transition: all var(--dur-fast);
}
.filter-pill:hover { border-color: var(--line-strong); color: var(--ink-body); }
.filter-pill.is-active {
  background: var(--accent); border-color: var(--accent); color: #fff;
}

/* ---------- Kanban ---------- */
.kanban {
  display: grid; gap: var(--sp-3);
  grid-auto-flow: column; grid-auto-columns: minmax(268px, 1fr);
  overflow-x: auto; padding-bottom: var(--sp-3);
  align-items: start;
}
.kanban__col {
  border-radius: var(--r-lg);
  padding: var(--sp-3);
  min-height: 130px;
}
.kanban__col.is-over { border-color: var(--cyan); background: var(--cyan-glow); }
/* Kolom yang memang tidak boleh dituju — penolakannya terlihat sebelum
   kartunya dilepas, bukan sesudah. */
.kanban__col.is-nodrop { opacity: 0.4; border-style: dashed; }
.kanban__head {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-2) var(--sp-3);
}
.kanban__dot { width: 8px; height: 8px; border-radius: var(--r-full); background: var(--c); }
.kanban__title { font-size: var(--fs-sm); font-weight: var(--fw-medium); color: var(--ink-bright); }
.kanban__count { margin-left: auto; font-size: var(--fs-2xs); color: var(--ink-faint); }
.kanban__list { display: grid; gap: var(--sp-2); }

.tcard {
  position: relative;
  padding: var(--sp-3);
  padding-left: calc(var(--sp-3) + var(--rail-w));
  background: var(--glass-inset);
  border: 1px solid var(--line-hair);
  border-radius: var(--r-md);
  cursor: grab;
  overflow: hidden;
  transition: border-color var(--dur-fast), transform var(--dur-fast);
}
.tcard::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0;
  width: var(--rail-w); background: var(--rail, var(--unit-holding));
}
.tcard:hover { border-color: var(--line-strong); box-shadow: var(--shadow-md); }
.tcard.is-dragging { opacity: 0.4; cursor: grabbing; }
.tcard__title {
  font-size: var(--fs-sm); color: var(--ink-bright);
  line-height: var(--lh-snug); margin-bottom: var(--sp-2);
}
.tcard__meta { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.tcard__pts {
  font-family: var(--font-mono); font-size: var(--fs-2xs);
  font-weight: var(--fw-bold); color: var(--cyan);
}
.tcard__due { font-size: var(--fs-2xs); color: var(--ink-faint); margin-left: auto; }
.tcard__due.is-late { color: var(--danger); }

/* ---------- Sheet task (PIC menyusun task) ----------
   Tabel yang setiap selnya bisa diisi langsung. Bukan spreadsheet penuh:
   tidak ada seret-isi maupun tempel dari Excel, karena keduanya menuntut
   kode yang jauh lebih rumit untuk dirawat sendiri. */
.sheet-wrap {
  border-radius: var(--r-lg);
  overflow-x: auto;
}
.sheet { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.sheet th {
  padding: var(--sp-2) var(--sp-2);
  font-size: var(--fs-2xs); font-weight: var(--fw-semibold);
  letter-spacing: var(--track-wide); text-transform: uppercase;
  color: var(--ink-muted); text-align: left; white-space: nowrap;
  border-bottom: 1px solid var(--line-soft);
  background: var(--bg-raised);
  position: sticky; top: 0; z-index: 1;
}
/* Kolom pendek dan seragam lebih terbaca kalau judulnya di tengah; kolom
   teks panjang tetap rata kiri supaya sejajar dengan isinya. */
.sheet th.is-center, .sheet td.is-center { text-align: center; }
.sheet td {
  padding: 2px var(--sp-2);
  border-bottom: 1px solid var(--line-hair);
  vertical-align: middle;
}
.sheet tbody tr:last-child td { border-bottom: none; }
.sheet__no { color: var(--ink-faint); text-align: center; white-space: nowrap; }
.sheet__act { white-space: nowrap; text-align: right; }

/* Sel yang bisa diisi terlihat polos sampai disentuh — supaya tabelnya
   terbaca sebagai tabel, bukan sebagai tumpukan kotak input. */
.sheet__in {
  width: 100%; min-width: 108px;
  padding: var(--sp-2);
  font-size: var(--fs-sm);
  background: transparent; color: var(--ink-bright);
  border: 1px solid transparent; border-radius: var(--r-sm);
}
.sheet__in:hover:not(:disabled) { border-color: var(--glass-ctrl-line); }
.sheet__in:focus {
  outline: none;
  background: var(--glass-ctrl);
  backdrop-filter: var(--glass-ctrl-blur);
  -webkit-backdrop-filter: var(--glass-ctrl-blur);
  border-color: var(--cyan);
}
.sheet__in:disabled { color: var(--ink-muted); cursor: not-allowed; }
.sheet__in--num { min-width: 58px; text-align: center; font-family: var(--font-mono); }
select.sheet__in { cursor: pointer; }

/* Sel yang belum diisi ditipiskan — sekali lihat ketahuan mana yang masih
   kosong. Isi dropdown-nya sendiri tetap pekat supaya tetap terbaca. */
.sheet__in::placeholder { color: var(--ink-faint); opacity: 0.5; }
/* Nilai yang belum diisi ditipiskan DI MANA PUN ia muncul, bukan cuma di
   dalam kontrol. Sebelum aturan ini ada, `.is-empty` pada elemen biasa —
   sel Client kosong di daftar project, kartu Budget yang belum diisi —
   tidak berefek apa-apa. Dua aturan ber-scope di bawah tetap menang karena
   selektornya lebih spesifik. */
.is-empty { color: var(--ink-faint); opacity: 0.7; }

.sheet__in.is-empty { color: var(--ink-faint); opacity: 0.6; }
.sheet__in.is-empty:focus { opacity: 1; }
.sheet__in option { color: var(--ink-bright); opacity: 1; }
.sheet tr.is-locked { background: color-mix(in srgb, var(--violet) 7%, transparent); }

.sheet-foot {
  display: flex; align-items: center; gap: var(--sp-3);
  margin-top: var(--sp-3); flex-wrap: wrap;
}

/* Tanda tersimpan sekejap. Perubahan langsung ditulis, jadi yang dibutuhkan
   cuma penegasan singkat — bukan toast yang menumpuk tiap sel diisi. */
.sheet tr.is-saved { animation: sheetSaved 1.1s var(--ease-out); }
@keyframes sheetSaved {
  0%   { background: color-mix(in srgb, var(--ok) 26%, transparent); }
  100% { background: transparent; }
}

/* ---------- Pemilih tampilan (Tabel / Kanban / Kalender) ---------- */
.viewswitch {
  display: inline-flex;
  padding: 3px;
  background: var(--glass-ctrl);
  backdrop-filter: var(--glass-ctrl-blur);
  -webkit-backdrop-filter: var(--glass-ctrl-blur);
  border: 1px solid var(--glass-ctrl-line);
  border-radius: var(--r-md);
}
.viewswitch__btn {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-sm); color: var(--ink-muted);
  border-radius: var(--r-sm);
  white-space: nowrap;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.viewswitch__btn svg { width: 15px; height: 15px; }
.viewswitch__btn:hover { color: var(--ink-body); }
.viewswitch__btn.is-active { background: var(--bg-surface); color: var(--ink-bright); }

/* Di layar sempit tulisannya disembunyikan, ikonnya sudah cukup jelas. */
@media (max-width: 560px) { .viewswitch__btn span { display: none; } }

/* ---------- Kalender task ---------- */
.tcal__bar {
  display: flex; align-items: center; gap: var(--sp-2);
  margin-bottom: var(--sp-4); flex-wrap: wrap;
}
.tcal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.tcal__dow {
  text-align: center; font-size: var(--fs-2xs);
  color: var(--ink-faint); padding-bottom: var(--sp-2);
  text-transform: uppercase; letter-spacing: var(--track-wide);
}
.tcal__cell {
  min-height: 92px;
  padding: var(--sp-2);
  background: var(--bg-overlay);
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  display: flex; flex-direction: column; gap: 3px;
  overflow: hidden;
}
.tcal__cell--out { background: transparent; }
.tcal__cell.is-today { border-color: var(--cyan); }
.tcal__date { font-size: var(--fs-2xs); color: var(--ink-faint); }
.tcal__chip {
  font-size: var(--fs-2xs);
  padding: 2px var(--sp-2);
  border-radius: var(--r-xs);
  color: var(--c);
  background: color-mix(in srgb, var(--c) 16%, transparent);
  border-left: 2px solid var(--c);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Di HP kalender bulanan tidak muat 7 kolom penuh — sel dibuat lebih
   pendek dan judul task dipotong, tanggalnya tetap terbaca. */
@media (max-width: 720px) {
  .tcal__cell { min-height: 62px; padding: 3px; }
  .tcal__chip { padding: 1px 3px; }
}

/* ---------- Kartu sorotan ----------
   Satu per halaman, untuk angka yang dibaca duluan. Gradiennya dekoratif;
   yang membawa data cuma garisnya. */
.hero {
  position: relative;
  padding: var(--sp-6);
  border-radius: var(--r-xl);
  overflow: hidden;
  background:
    radial-gradient(120% 140% at 100% 0%, var(--hero-glow-a), transparent 55%),
    radial-gradient(90% 120% at 0% 100%, var(--hero-glow-b), transparent 60%),
    linear-gradient(160deg, var(--hero-from), var(--hero-via) 50%, var(--hero-to));
  border: 1px solid var(--hero-line);
  box-shadow: var(--shadow-card), var(--edge-hi);
  color: #fff;
}
/* Kisi halus di belakang grafik — dekoratif, tidak membawa data. */
.hero::after {
  content: '';
  position: absolute; inset: 0;
  background-image:
    linear-gradient(var(--hero-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--hero-line) 1px, transparent 1px);
  background-size: 40px 40px;
  mask-image: linear-gradient(180deg, transparent, #000 40%, transparent);
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 40%, transparent);
  opacity: 0.5;
  pointer-events: none;
}
.hero > * { position: relative; z-index: 1; }
.hero__label {
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-xs); color: rgba(255, 255, 255, 0.72);
}
/* Angka utama pakai figur proporsional, bukan tabular — tabular-nums
   membuat angka besar terlihat renggang. */
.hero__value {
  font-family: var(--font-display);
  font-size: var(--fs-3xl); font-weight: var(--fw-bold);
  letter-spacing: var(--track-tighter);
  line-height: 1.05; margin-top: var(--sp-2);
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-2);
}
.hero__delta {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px var(--sp-2);
  border-radius: var(--r-full);
  font-family: var(--font-body);
  font-size: var(--fs-2xs); font-weight: var(--fw-semibold);
  letter-spacing: 0;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.16);
}
.hero__plotwrap { position: relative; margin-top: var(--sp-4); }
.hero__plot { display: block; width: 100%; height: 120px; overflow: visible; }
.hero__area { fill: url(#heroFill); }
.hero__line {
  fill: none; stroke: #fff; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  vector-effect: non-scaling-stroke;   /* tetap 2px walau SVG meregang */
}
/* Cincin sewarna latar kartu supaya titik ujung tetap terbaca di atas garis,
   ditambah lingkar cahaya pink sebagai penanda bulan berjalan. */
.hero__dot {
  position: absolute;
  width: 10px; height: 10px;
  transform: translate(-50%, -50%);
  border-radius: var(--r-full);
  background: #fff;
  box-shadow: 0 0 0 2px var(--hero-via), 0 0 0 6px var(--accent-soft);
}
.hero__foot {
  display: flex; align-items: center; gap: var(--sp-2);
  margin-top: var(--sp-2);
  font-size: var(--fs-2xs); color: rgba(255, 255, 255, 0.66);
}

/* ---------- Chip aksi cepat ---------- */
.qa { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-3); }
.qa__item {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-lg);
  font-size: var(--fs-sm); font-weight: var(--fw-medium); color: var(--ink-bright);
  transition: border-color var(--dur-fast), transform var(--dur-fast);
}
.qa__item:hover { border-color: var(--line-strong); transform: translateY(-1px); }
.qa__item:active { transform: scale(0.98); }
.qa__icon {
  display: grid; place-items: center;
  width: 34px; height: 34px; border-radius: var(--r-md);
  background: color-mix(in srgb, var(--c) 18%, transparent);
  color: var(--c); flex-shrink: 0;
}
.qa__icon svg { width: 15px; height: 15px; }
/* Di HP sempit ikon ditumpuk di atas label. Dulu labelnya disembunyikan
   dengan `.qa__item span`, yang ikut menyembunyikan .qa__icon (juga span) —
   tombolnya jadi kotak kosong. */
@media (max-width: 420px) {
  .qa__item { flex-direction: column; justify-content: center; gap: var(--sp-2); padding: var(--sp-3) var(--sp-2); font-size: var(--fs-xs); }
}

/* ---------- Judul bagian ---------- */
.sect {
  display: flex; align-items: baseline; gap: var(--sp-2);
  margin-bottom: var(--sp-4);
}
.sect__title {
  font-family: var(--font-display);
  font-size: var(--fs-md); font-weight: var(--fw-semibold);
  letter-spacing: var(--track-tight);
  color: var(--ink-bright);
}
.sect__link { margin-left: auto; font-size: var(--fs-xs); font-weight: var(--fw-medium); color: var(--ink-muted); }
.sect__link:hover { color: var(--accent); }

/* ---------- Grafik batang tegak ----------
   Bentuk emphasis: bulan berjalan memakai warna aksen, bulan lain abu.
   Nilainya hanya dilabeli di batang yang disorot — angka di setiap batang
   justru tidak terbaca. */
.cchart { display: flex; align-items: flex-end; gap: var(--sp-2); height: 128px; }
.cchart__col {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  gap: var(--sp-2); height: 100%; justify-content: flex-end;
}
.cchart__track {
  width: 100%; max-width: 24px;          /* batang tipis — jangan penuhi slot */
  flex: 1; display: flex; align-items: flex-end;
}
.cchart__bar {
  width: 100%;
  background: var(--chart-dim);
  border-radius: var(--r-xs) var(--r-xs) 0 0;   /* ujung data membulat, dasar siku */
  min-height: 3px;
  transition: height var(--dur-slow) var(--ease-out), background var(--dur-fast);
}
.cchart__col.is-on .cchart__bar { background: var(--chart-accent); }
.cchart__tip {
  padding: 2px var(--sp-2); border-radius: var(--r-full);
  font-size: var(--fs-2xs); font-weight: var(--fw-semibold);
  font-family: var(--font-mono);
  background: var(--chart-accent); color: #fff; white-space: nowrap;
}
.cchart__x { font-size: var(--fs-2xs); color: var(--ink-faint); }
.cchart__col.is-on .cchart__x { color: var(--ink-bright); }

/* ---------- Grafik batang mendatar (peringkat) ---------- */
.hchart { display: grid; gap: var(--sp-2); }
.hrow { display: flex; align-items: center; gap: var(--sp-3); }
.hrow__rank {
  width: 18px; text-align: center; flex-shrink: 0;
  font-family: var(--font-mono); font-size: var(--fs-2xs); color: var(--ink-faint);
}
.hrow__name {
  width: 78px; flex-shrink: 0;
  font-size: var(--fs-xs); color: var(--ink-body);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hrow.is-me .hrow__name { color: var(--ink-bright); font-weight: var(--fw-semibold); }
.hrow__track { flex: 1; min-width: 0; height: 14px; display: flex; align-items: center; }
.hrow__bar {
  height: 100%;
  background: var(--chart-dim);
  border-radius: 0 var(--r-xs) var(--r-xs) 0;
  min-width: 3px;
  transition: width var(--dur-slow) var(--ease-out);
}
.hrow.is-me .hrow__bar { background: var(--chart-accent); }
.hrow__val {
  width: 42px; text-align: right; flex-shrink: 0;
  font-family: var(--font-mono); font-size: var(--fs-2xs); color: var(--ink-muted);
}
.hrow.is-me .hrow__val { color: var(--ink-bright); }

/* ---------- Leaderboard ---------- */
.lb { display: grid; gap: var(--sp-2); }
.lb__row {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3);
  border-radius: var(--r-md);
  background: var(--glass-inset);
  border: 1px solid var(--line-hair);
}
.lb__row.is-me { border-color: var(--accent); background: var(--accent-soft); }
.lb__rank {
  width: 26px; text-align: center;
  font-family: var(--font-display); font-weight: var(--fw-bold);
  font-size: var(--fs-sm); color: var(--ink-faint);
}
.lb__row:nth-child(1) .lb__rank { color: #FBBF24; }
.lb__row:nth-child(2) .lb__rank { color: #CBD5E1; }
.lb__row:nth-child(3) .lb__rank { color: #D97757; }
.lb__meta { flex: 1; min-width: 0; }
.lb__name { font-size: var(--fs-sm); color: var(--ink-bright); font-weight: var(--fw-medium); }
.lb__sub { font-size: var(--fs-2xs); color: var(--ink-faint); }
.lb__score {
  font-family: var(--font-display); font-size: var(--fs-lg);
  font-weight: var(--fw-bold); color: var(--ink-bright);
  font-variant-numeric: tabular-nums;
}

/* Versi rapat untuk dashboard: satu blok padat, bukan tumpukan kartu.
   Modifier terpisah supaya leaderboard di halaman KPI tidak ikut berubah. */
.lb--dense {
  gap: 0;
  background: var(--glass-inset);
  border: 1px solid var(--line-hair);
  border-radius: var(--r-md);
  overflow: hidden;
}
.lb--dense .lb__row {
  padding: var(--sp-2) var(--sp-3);
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--line-hair);
  border-radius: 0;
}
.lb--dense .lb__row:last-child { border-bottom: none; }
.lb--dense .lb__row.is-me { background: var(--accent-soft); }
.lb--dense .lb__score { font-size: var(--fs-base); }

/* ---------- Baris task ringkas (dashboard) ----------
   Sengaja lebih pendek dari .lrow: dashboard menampilkan sampai 10 task
   sekaligus, jadi tinggi baris menentukan apakah semuanya terlihat tanpa
   menggulir. Tidak memakai brand rail — di sini yang dicari judul dan
   sisa waktunya, bukan unit pemiliknya. */
.tlist {
  border: 1px solid var(--line-hair);
  border-radius: var(--r-md);
  overflow: hidden;
}
.trow {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--line-hair);
}
.trow:last-child { border-bottom: none; }
.trow:hover { background: var(--bg-overlay); }
.trow__meta { flex: 1; min-width: 0; }
.trow__title {
  font-size: var(--fs-sm); color: var(--ink-bright);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.trow__project {
  font-size: var(--fs-2xs); color: var(--ink-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.trow__due {
  flex-shrink: 0; white-space: nowrap;
  font-size: var(--fs-2xs); font-weight: var(--fw-medium);
  color: var(--ink-muted);
}
.trow__due.is-ok   { color: var(--ok); }
.trow__due.is-late { color: var(--danger); }

/* ---------- List rows ---------- */
.lrow {
  position: relative;
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  padding-left: calc(var(--sp-4) + var(--rail-w));
  background: var(--glass-inset);
  border: 1px solid var(--line-hair);
  border-radius: var(--r-md);
  overflow: hidden;
  transition: border-color var(--dur-fast), background var(--dur-fast);
}
.lrow::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0;
  width: var(--rail-w); background: var(--rail, var(--unit-holding));
}
.lrow:hover { border-color: var(--line-strong); background: var(--bg-overlay); }
.lrow__meta { flex: 1; min-width: 0; }
.lrow__title {
  font-size: var(--fs-base); color: var(--ink-bright);
  font-weight: var(--fw-medium);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lrow__sub { font-size: var(--fs-xs); color: var(--ink-muted); }
.lrow__side { text-align: right; flex-shrink: 0; }
.stack { display: grid; gap: var(--sp-2); }

/* ---------- Kalender sederhana ---------- */
.cal { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.cal__dow {
  text-align: center; font-size: var(--fs-2xs);
  color: var(--ink-faint); padding-bottom: var(--sp-2);
  text-transform: uppercase; letter-spacing: var(--track-wide);
}
.cal__day {
  aspect-ratio: 1;
  display: grid; place-items: center;
  border-radius: var(--r-sm);
  font-size: var(--fs-xs);
  font-family: var(--font-mono);
  background: var(--bg-overlay);
  color: var(--ink-muted);
  position: relative;
}
.cal__day--out { opacity: 0.25; }
.cal__day--present { background: color-mix(in srgb, var(--ok) 20%, transparent); color: var(--ok); }
.cal__day--late    { background: color-mix(in srgb, var(--warn) 22%, transparent); color: var(--warn); }
.cal__day--leave   { background: color-mix(in srgb, var(--violet) 22%, transparent); color: var(--violet); }
.cal__day--absent  { background: color-mix(in srgb, var(--danger) 22%, transparent); color: var(--danger); }
.cal__day--today { outline: 2px solid var(--cyan); outline-offset: -2px; }

/* ---------- Bar chart ringan ---------- */
.bars { display: flex; align-items: flex-end; gap: var(--sp-2); height: 130px; }
.bars__item { flex: 1; display: flex; flex-direction: column; align-items: center; gap: var(--sp-2); height: 100%; justify-content: flex-end; }
.bars__bar {
  width: 100%; border-radius: var(--r-xs) var(--r-xs) 0 0;
  background: linear-gradient(180deg, var(--accent), var(--violet));
  min-height: 3px;
  transition: height var(--dur-slow) var(--ease-out);
}
.bars__label { font-size: var(--fs-2xs); color: var(--ink-faint); }

/* ---------- Banner demo & offline ----------
   Pita kaca tipis di atas topbar: siapa yang sedang "login" dan tombol
   untuk berganti akun. Hanya muncul di mode demo. */
.ribbon {
  grid-area: ribbon;
  display: flex; align-items: center; gap: var(--sp-3);
  margin-bottom: var(--sp-2);
  padding: 6px 6px 6px var(--sp-4);
  font-size: var(--fs-xs);
  color: var(--ink-body);
  background: color-mix(in srgb, var(--warn) 12%, var(--glass-bg));
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid color-mix(in srgb, var(--warn) 35%, transparent);
  border-radius: var(--r-full);
}
.ribbon > svg { width: 15px; height: 15px; color: var(--warn); flex-shrink: 0; }
.ribbon__text { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ribbon__text strong { color: var(--ink-bright); font-weight: var(--fw-semibold); }
.ribbon__tag {
  font-size: var(--fs-2xs); font-weight: var(--fw-bold);
  letter-spacing: var(--track-wide); text-transform: uppercase;
  color: var(--warn);
}
.ribbon .btn { padding: 5px var(--sp-3); font-size: var(--fs-xs); border-radius: var(--r-full); }
@media (max-width: 720px) {
  .ribbon { margin: var(--sp-2) var(--sp-2) var(--sp-2); }
  .ribbon__tag { display: none; }
}
body.is-offline .main::before {
  content: 'Kamu sedang offline — perubahan tidak bisa disimpan';
  display: block; margin-bottom: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  background: var(--danger-glow); color: var(--danger);
  border: 1px solid var(--danger);
  font-size: var(--fs-sm);
}

/* ---------- Admin: tanda area belakang ---------- */
body[data-area='admin'] .topbar { border-bottom-color: var(--cyan); }
body[data-area='admin'] .navlink.is-active::before { background: var(--cyan); }
.admin-tag {
  font-size: var(--fs-2xs); font-weight: var(--fw-semibold);
  letter-spacing: var(--track-wide); text-transform: uppercase;
  color: var(--cyan); margin-right: var(--sp-2);
}

/* Varian sidebar: berdiri sendiri di ujung kanan baris menu, bukan
   mendahului teks seperti di judul halaman. Dibuat berpelat tipis
   supaya terbaca sebagai penanda, bukan bagian dari nama menunya.
   Warnanya cyan — warna area admin di seluruh aplikasi. */
.admin-tag--nav {
  margin-right: 0;
  margin-left: auto;
  padding: 0 6px;
  font-size: 10px;
  border-radius: var(--r-sm);
  border: 1px solid color-mix(in srgb, var(--cyan) 35%, transparent);
  background: color-mix(in srgb, var(--cyan) 12%, transparent);
  line-height: 1.5;
  flex: none;
}

/* Penandanya muncul di SETIAP menu terbatas, termasuk anak-anak di dalam
   grup Admin Panel. Sengaja diulang: grup itu bisa dilipat, dan saat
   terlipat hanya induknya yang terlihat — sementara saat terbuka yang
   dibaca orang adalah baris anaknya. */
.navgroup__toggle .admin-tag--nav { margin-right: 0; }

/* ---------- Kode QR & pemindai ---------- */
/*
   Kode QR WAJIB hitam di atas putih, apa pun temanya. Di mode gelap,
   membiarkannya mengikuti warna latar aplikasi membuat kamera tidak bisa
   membacanya sama sekali — jadi putihnya dipasang tegas di sini, bukan
   lewat token tema. Ini satu-satunya tempat di aplikasi yang sengaja
   mengabaikan tema, dan alasannya fisik, bukan selera.
*/
.qr {
  display: inline-flex; flex-direction: column; align-items: center;
  gap: var(--sp-2); margin: 0;
}
.qr__canvas {
  display: block;
  background: #fff;
  padding: var(--sp-2);
  border-radius: var(--r-sm);
}
.qr__label { font-size: var(--fs-2xs); color: var(--ink-muted); letter-spacing: var(--track-wide); }

.scanner { position: relative; display: grid; gap: var(--sp-3); justify-items: center; }
.scanner__video {
  width: 100%; max-width: 320px; aspect-ratio: 1;
  object-fit: cover;
  background: var(--bg-overlay);
  border-radius: var(--r-md);
}
/* Bingkai bidik. Sekadar penuntun mata — pembacaan tetap dari seluruh
   frame, jadi kode yang agak melenceng tetap terbaca. */
.scanner__frame {
  position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: min(60%, 190px); aspect-ratio: 1; margin-top: 12%;
  border: 2px solid var(--cyan);
  border-radius: var(--r-md);
  box-shadow: 0 0 0 100vmax color-mix(in srgb, var(--bg-base) 55%, transparent);
  pointer-events: none;
}
.scanner__hint { text-align: center; }

@media print {
  /* Layar cetak stiker: hanya kode dan labelnya yang ikut tercetak. */
  body * { visibility: hidden; }
  .qr, .qr * { visibility: visible; }
}

/* ---------- Dropdown React (Radix) ---------- */
/*
   SATU-SATUNYA tampilan di aplikasi ini yang tidak punya padanan vanilla.
   Versi vanilla memakai <select> native, dan panel dropdown-nya digambar
   sistem operasi — bukan CSS. Jadi begitu React memakai Radix di desktop,
   panelnya mau tidak mau bentuk baru.

   Pemicunya tetap .input yang sama persis, jadi dalam keadaan tertutup
   tidak ada bedanya sama sekali. Yang di bawah ini hanya berlaku saat
   panelnya terbuka, dan di HP tidak pernah dipakai — di sana Select
   jatuh ke <select> native.

   Semua nilai dari token. Tidak ada satu pun hex di sini.
*/
.rsel__trigger {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
  text-align: left; cursor: pointer;
  padding-right: var(--sp-3);
}
.rsel__label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rsel__caret { display: inline-flex; flex: none; color: var(--ink-muted); }
.rsel__caret svg { width: 16px; height: 16px; }

.rsel__panel {
  z-index: var(--z-modal);
  min-width: var(--radix-popper-anchor-width);
  max-height: 320px;
  display: flex; flex-direction: column;
  overflow: hidden;
  background: var(--bg-raised);
  backdrop-filter: var(--glass-ctrl-blur);
  -webkit-backdrop-filter: var(--glass-ctrl-blur);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
}

.rsel__search {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--line-hair);
  flex: none;
}
.rsel__search svg { width: 14px; height: 14px; color: var(--ink-faint); flex: none; }
.rsel__search input {
  flex: 1; min-width: 0;
  background: none; border: none; outline: none;
  color: var(--ink-bright); font-size: var(--fs-sm);
}
.rsel__search input::placeholder { color: var(--ink-faint); opacity: 0.7; }

.rsel__list { overflow-y: auto; padding: var(--sp-1); }

.rsel__opt {
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  color: var(--ink-body);
  cursor: pointer;
  outline: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Satu penanda untuk dua jalan masuk: tetikus mengarahkannya lewat
   data-active, papan ketik lewat data-highlighted milik Radix. Kalau
   dibedakan, menggeser tetikus di atas panel yang sedang dinavigasi
   papan ketik akan menyorot dua baris sekaligus. */
.rsel__opt[data-active='true'],
.rsel__opt[data-highlighted] {
  background: var(--bg-overlay);
  color: var(--ink-bright);
}
.rsel__opt.is-selected, .rsel__opt[data-state='checked'] {
  color: var(--cyan);
}
.rsel__none {
  padding: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--ink-faint);
  text-align: center;
}

/* ---------- Matriks permission ---------- */
.matrix { width: 100%; border-collapse: collapse; font-size: var(--fs-xs); }
.matrix th, .matrix td { padding: var(--sp-2); border-bottom: 1px solid var(--line-hair); }
.matrix th { text-align: center; color: var(--ink-muted); font-weight: var(--fw-medium); }
.matrix th:first-child, .matrix td:first-child { text-align: left; }
.matrix td:first-child { color: var(--ink-body); }
.matrix tr:hover { background: var(--bg-overlay); }
.matrix input { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }
.matrix__group td {
  padding-top: var(--sp-4);
  font-size: var(--fs-2xs); font-weight: var(--fw-semibold);
  letter-spacing: var(--track-wide); text-transform: uppercase;
  color: var(--ink-faint); border-bottom: none;
}

/* ---------- Util global ---------- */
.u-late { color: var(--danger) !important; }

/* ---------- Tata letak dashboard ----------
   Satu kolom di HP dan tablet. Di layar lebar dua kolom: pekerjaan
   (project, task) di kiri yang lebih lebar, orang (peringkat, aktivitas)
   di kanan. Hero dan pintasan tetap selebar halaman di atasnya. */
.dash-grid { display: grid; gap: var(--sp-4); }
.dash-col  { display: grid; gap: var(--sp-4); align-content: start; min-width: 0; }
@media (min-width: 1180px) {
  .dash-grid { grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); }
  .dash-grid > .hero,
  .dash-grid > .qa { grid-column: 1 / -1; }
}
@media (max-width: 720px) {
  .dash-grid, .dash-col { gap: var(--sp-3); }
  .hero { padding: var(--sp-5); }
}

/* Baris aktivitas tim di dashboard. */
.feed { display: grid; gap: var(--sp-4); }
.feed__row { display: flex; gap: var(--sp-3); align-items: flex-start; }
.feed__text { flex: 1; min-width: 0; font-size: var(--fs-sm); color: var(--ink-body); line-height: var(--lh-snug); }
.feed__text strong { color: var(--ink-bright); font-weight: var(--fw-semibold); }
.feed__target { color: var(--ink-muted); }

/* ============================================================
   PEMILIH AKUN (mode demo)
   ============================================================ */
.switcher { display: grid; gap: var(--sp-5); }
.switcher__search { max-width: none; }
.switcher__group { display: grid; gap: var(--sp-3); }
.switcher__head { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--sp-2); }
.switcher__role { font-family: var(--font-display); font-weight: var(--fw-bold); color: var(--ink-bright); }
.switcher__count {
  padding: 0 7px; border-radius: var(--r-full);
  font-size: var(--fs-2xs); font-weight: var(--fw-semibold);
  background: var(--bg-overlay); color: var(--ink-muted);
}
.switcher__hint { flex-basis: 100%; font-size: var(--fs-xs); color: var(--ink-muted); }
.switcher__list { display: grid; gap: var(--sp-2); grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }

.acct {
  position: relative;
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3);
  padding-left: calc(var(--sp-3) + var(--rail-w));
  border-radius: var(--r-md);
  background: var(--glass-inset);
  border: 1px solid var(--line-soft);
  text-align: left;
  overflow: hidden;
  transition: border-color var(--dur-fast), background var(--dur-fast), transform var(--dur-fast);
}
.acct::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0;
  width: var(--rail-w); background: var(--rail, var(--unit-holding));
}
.acct:hover { border-color: var(--accent); background: var(--accent-soft); transform: translateY(-1px); }
.acct.is-current { border-color: var(--accent-2); background: var(--accent-2-soft); }
.acct__meta { flex: 1; min-width: 0; display: grid; gap: 1px; }
.acct__name { font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--ink-bright); }
.acct__name em { font-style: normal; font-weight: var(--fw-medium); color: var(--accent-2); font-size: var(--fs-2xs); }
.acct__sub { font-size: var(--fs-xs); color: var(--ink-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.acct__pic {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-2xs); color: var(--accent-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.acct__pic svg { width: 11px; height: 11px; flex-shrink: 0; }
.acct__go { width: 16px; height: 16px; color: var(--ink-faint); flex-shrink: 0; }

/* ============================================================
   PALET CARI (⌘K)
   ============================================================ */
.palette { display: grid; gap: var(--sp-3); }
.palette__search { max-width: none; }
.palette__list { display: grid; gap: 2px; max-height: 50dvh; overflow-y: auto; }
.palette__item {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-sm);
  color: var(--ink-body);
}
.palette__item svg { width: 17px; height: 17px; color: var(--ink-muted); flex-shrink: 0; }
.palette__item:hover, .palette__item.is-active { background: var(--accent-soft); color: var(--ink-bright); }
.palette__item.is-active svg { color: var(--accent); }
.palette__label { flex: 1; min-width: 0; font-size: var(--fs-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.palette__label small { margin-left: var(--sp-2); color: var(--ink-faint); font-size: var(--fs-xs); }
.palette__kind { font-size: var(--fs-2xs); color: var(--ink-faint); text-transform: uppercase; letter-spacing: var(--track-wide); }
.palette__none { padding: var(--sp-4); text-align: center; color: var(--ink-faint); font-size: var(--fs-sm); }

/* ============================================================
   PANEL TAMPILAN
   ============================================================ */
.appear { display: grid; gap: var(--sp-6); }
.appear__sect { display: grid; gap: var(--sp-3); }
.appear__label {
  display: flex; justify-content: space-between;
  font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  letter-spacing: var(--track-wide); text-transform: uppercase; color: var(--ink-muted);
}
.appear__themes { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); }
.appear__theme {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  border: 1px solid var(--line-soft);
  background: var(--glass-inset);
  font-weight: var(--fw-semibold); color: var(--ink-body);
}
.appear__theme.is-active { border-color: var(--accent); background: var(--accent-soft); color: var(--ink-bright); }
.appear__swatch { width: 26px; height: 26px; border-radius: var(--r-full); border: 1px solid var(--line-strong); }
.appear__swatch--dark  { background: var(--bg-void); }
.appear__swatch--light { background: var(--ink-bright); }
:root[data-theme='light'] .appear__swatch--dark  { background: var(--ink-bright); }
:root[data-theme='light'] .appear__swatch--light { background: var(--bg-surface); }

.appear__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-3); }
.wpthumb {
  display: grid; gap: var(--sp-2);
  padding: var(--sp-2);
  border-radius: var(--r-md);
  border: 1px solid var(--line-soft);
  background: var(--glass-inset);
  cursor: pointer;
  text-align: left;
}
.wpthumb.is-active { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.wpthumb__img {
  display: grid; place-items: center;
  aspect-ratio: 16 / 10;
  border-radius: var(--r-sm);
  background: var(--wp-aurora);
  background-size: cover; background-position: center;
  color: var(--ink-muted);
}
.wpthumb__img[data-wp='senja']   { background: var(--wp-senja); }
.wpthumb__img[data-wp='samudra'] { background: var(--wp-samudra); }
.wpthumb__img[data-wp='hutan']   { background: var(--wp-hutan); }
.wpthumb__img[data-wp='grafit']  { background: var(--wp-grafit); }
.wpthumb--upload .wpthumb__img { background-color: var(--bg-overlay); border: 1px dashed var(--line-strong); }
.wpthumb__name { font-size: var(--fs-xs); font-weight: var(--fw-medium); color: var(--ink-body); }
@media (max-width: 560px) { .appear__grid { grid-template-columns: repeat(2, 1fr); } }

/* ============================================================
   DASHBOARD
   ============================================================ */
.dash { display: grid; gap: var(--sp-4); grid-template-columns: repeat(3, minmax(0, 1fr)); }
.dash > .span-2 { grid-column: span 2; }
.dash > .span-3 { grid-column: 1 / -1; }

.chipdate {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  height: 40px; padding: 0 var(--sp-4);
  border-radius: var(--r-md);
  background: var(--glass-ctrl);
  border: 1px solid var(--glass-ctrl-line);
  backdrop-filter: var(--glass-ctrl-blur);
  -webkit-backdrop-filter: var(--glass-ctrl-blur);
  font-size: var(--fs-sm); font-weight: var(--fw-medium); color: var(--ink-body);
  white-space: nowrap;
}
.chipdate svg { width: 16px; height: 16px; color: var(--ink-muted); }

/* ---------- Kartu angka + sparkline ---------- */
.kpis { display: grid; gap: var(--sp-4); grid-template-columns: repeat(4, minmax(0, 1fr)); }
.kpi {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto auto;
  column-gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-radius: var(--r-lg);
  overflow: hidden;
  min-height: 136px;
}
/* Cahaya sewarna ikon di pojok — sentuhan kaca berwarna dari referensi. */
.kpi::after {
  content: '';
  position: absolute; left: -30px; top: -30px;
  width: 140px; height: 140px;
  border-radius: 50%;
  background: var(--c);
  opacity: 0.16;
  filter: blur(30px);
  pointer-events: none;
}
.kpi__icon {
  grid-row: 1 / 3;
  display: grid; place-items: center;
  width: 42px; height: 42px;
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--c) 18%, transparent);
  border: 1px solid color-mix(in srgb, var(--c) 35%, transparent);
  color: var(--c);
}
.kpi__icon svg { width: 20px; height: 20px; }
.kpi__label { font-size: var(--fs-xs); font-weight: var(--fw-medium); color: var(--ink-muted); align-self: end; }
.kpi__value {
  font-family: var(--font-display);
  font-size: var(--fs-2xl); font-weight: var(--fw-heavy);
  letter-spacing: var(--track-tighter);
  color: var(--ink-bright);
  line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.kpi__foot {
  grid-column: 1 / -1;
  display: flex; align-items: flex-end; justify-content: space-between; gap: var(--sp-2);
  margin-top: var(--sp-3);
}
.kpi__delta { display: grid; gap: 1px; font-size: var(--fs-2xs); color: var(--ink-faint); white-space: nowrap; }
.kpi__delta b { font-size: var(--fs-xs); font-weight: var(--fw-bold); color: var(--ok); }
.kpi__delta b.is-down { color: var(--danger); }
.kpi__delta b.is-flat { color: var(--ink-muted); }
.spark { width: 46%; max-width: 120px; height: 40px; overflow: visible; }
.spark path.l { fill: none; stroke: url(#sparkGrad); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.spark path.a { fill: url(#sparkFill); }

/* ---------- Kepala kartu ---------- */
.panel-head { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-4); flex-wrap: wrap; }
.panel-head__title { font-family: var(--font-display); font-size: var(--fs-md); font-weight: var(--fw-bold); color: var(--ink-bright); }
.panel-head__link { margin-left: auto; font-size: var(--fs-xs); font-weight: var(--fw-semibold); color: var(--accent); }
.panel-head__link:hover { text-decoration: underline; }
.panel-head__pill {
  margin-left: auto;
  padding: 4px var(--sp-3);
  border-radius: var(--r-full);
  font-size: var(--fs-2xs); font-weight: var(--fw-medium);
  color: var(--ink-muted);
  background: var(--glass-ctrl); border: 1px solid var(--glass-ctrl-line);
}

/* ---------- Grafik performa + donut ---------- */
.perf { display: grid; grid-template-columns: minmax(0, 1fr) 200px; gap: var(--sp-5); align-items: center; }
.legend { display: flex; flex-wrap: wrap; gap: var(--sp-4); margin-bottom: var(--sp-2); }
.legend span { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); color: var(--ink-muted); }
.legend i { width: 8px; height: 8px; border-radius: 50%; background: var(--c); }
.area { width: 100%; height: auto; aspect-ratio: 600 / 220; overflow: visible; }
.area .grid line { stroke: var(--chart-grid); }
.area .ytick, .area .xtick { fill: var(--ink-faint); font-size: 11px; font-family: var(--font-body); }
.area .xtick.is-on { fill: var(--ink-bright); font-weight: 600; }
.area .s1 { fill: none; stroke: var(--chart-accent); stroke-width: 2.5; stroke-linecap: round; }
.area .s2 { fill: none; stroke: var(--chart-accent-2); stroke-width: 2.5; stroke-linecap: round; }
.area .f1 { fill: url(#fill1); }
.area .f2 { fill: url(#fill2); }
.area .dot1 { fill: var(--chart-accent); stroke: var(--bg-surface); stroke-width: 2; }
.area .dot2 { fill: var(--chart-accent-2); stroke: var(--bg-surface); stroke-width: 2; }
.area .tip { fill: var(--ink-bright); font-size: 11px; font-weight: 700; font-family: var(--font-body); }

.donut { display: grid; gap: var(--sp-3); justify-items: center; }
.donut__ring { position: relative; width: 150px; height: 150px; }
.donut__ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.donut__ring circle { fill: none; stroke-width: 14; }
.donut__ring .track { stroke: var(--bg-overlay); }
.donut__center { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; }
.donut__center b { font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: var(--fw-heavy); color: var(--ink-bright); line-height: 1; }
.donut__center span { font-size: var(--fs-2xs); color: var(--ink-muted); margin-top: 2px; }
.donut__list { width: 100%; display: grid; gap: 6px; }
.donut__row { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-xs); color: var(--ink-body); }
.donut__row i { width: 8px; height: 8px; border-radius: 50%; background: var(--c); flex-shrink: 0; }
.donut__row em { margin-left: auto; font-style: normal; color: var(--ink-muted); font-variant-numeric: tabular-nums; }

/* ---------- Aktivitas ---------- */
.acts { display: grid; gap: var(--sp-3); }
.act { display: flex; gap: var(--sp-3); align-items: flex-start; }
.act__icon {
  display: grid; place-items: center;
  width: 36px; height: 36px; flex-shrink: 0;
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--c) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--c) 30%, transparent);
  color: var(--c);
}
.act__icon svg { width: 17px; height: 17px; }
.act__meta { flex: 1; min-width: 0; }
.act__title { font-size: var(--fs-sm); color: var(--ink-bright); font-weight: var(--fw-medium); line-height: var(--lh-snug); }
.act__sub { font-size: var(--fs-xs); color: var(--ink-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.act__time { font-size: var(--fs-2xs); color: var(--ink-faint); white-space: nowrap; }

/* ---------- Tabel project terbaru ---------- */
.ptable { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.ptable th {
  padding: var(--sp-2) var(--sp-3);
  text-align: left;
  font-size: var(--fs-2xs); font-weight: var(--fw-semibold);
  color: var(--ink-faint);
  border-bottom: 1px solid var(--line-soft);
  white-space: nowrap;
}
.ptable td { padding: var(--sp-3); border-bottom: 1px solid var(--line-hair); vertical-align: middle; white-space: nowrap; }
.ptable tbody tr { cursor: pointer; transition: background var(--dur-fast); }
.ptable tbody tr:hover { background: var(--bg-overlay); }
.ptable tbody tr:last-child td { border-bottom: none; }
.ptable__no { color: var(--ink-faint); font-variant-numeric: tabular-nums; width: 1%; }
.pname { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; }
.pname__thumb {
  display: grid; place-items: center;
  width: 38px; height: 38px; flex-shrink: 0;
  border-radius: var(--r-sm);
  background: linear-gradient(135deg, var(--rail), color-mix(in srgb, var(--rail) 40%, var(--bg-void)));
  color: #fff; font-family: var(--font-display); font-size: var(--fs-xs); font-weight: var(--fw-heavy);
  box-shadow: var(--hi-on-color);
}
.pname__text { min-width: 0; }
.pname__title { color: var(--ink-bright); font-weight: var(--fw-semibold); overflow: hidden; text-overflow: ellipsis; max-width: 280px; }
.pname__sub { overflow: hidden; text-overflow: ellipsis; max-width: 280px; }
.pname__sub { font-size: var(--fs-xs); color: var(--ink-muted); }
.team { display: flex; }
.team .avatar { box-shadow: 0 0 0 2px var(--bg-surface); }
.team .avatar + .avatar { margin-left: -8px; }
.pbar { display: flex; align-items: center; gap: var(--sp-2); min-width: 130px; }
.pbar .progress { flex: 1; height: 6px; }
.pbar span { font-size: var(--fs-xs); color: var(--ink-body); font-variant-numeric: tabular-nums; width: 34px; text-align: right; }
.progress__fill--grad { background: var(--grad-primary) !important; }

/* ---------- Jadwal ---------- */
.sched { display: grid; gap: var(--sp-3); }
.sched__row { display: grid; grid-template-columns: 82px 10px 1fr; gap: var(--sp-3); align-items: start; }
.sched__when { font-size: var(--fs-xs); font-weight: var(--fw-semibold); color: var(--ink-body); font-variant-numeric: tabular-nums; line-height: 1.3; }
.sched__when small { display: block; font-weight: var(--fw-normal); color: var(--ink-faint); }
.sched__dot { width: 9px; height: 9px; margin-top: 5px; border-radius: 50%; background: var(--c); box-shadow: 0 0 0 3px color-mix(in srgb, var(--c) 25%, transparent); }
.sched__title { font-size: var(--fs-sm); color: var(--ink-bright); font-weight: var(--fw-medium); line-height: var(--lh-snug); }
.sched__sub { font-size: var(--fs-xs); color: var(--ink-muted); }

/* ---------- Aksi cepat ---------- */
.qgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-2); }
.qbtn {
  display: grid; justify-items: center; gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-2);
  border-radius: var(--r-md);
  background: var(--glass-inset);
  border: 1px solid var(--line-soft);
  font-size: var(--fs-xs); font-weight: var(--fw-medium); color: var(--ink-body);
  text-align: center; line-height: 1.25;
  transition: border-color var(--dur-fast), transform var(--dur-fast), background var(--dur-fast);
}
.qbtn:hover { border-color: var(--accent); background: var(--accent-soft); transform: translateY(-2px); color: var(--ink-bright); }
.qbtn svg { width: 20px; height: 20px; color: var(--ink-bright); }

/* ---------- Kartu promosi ---------- */
.promo {
  position: relative;
  min-height: 170px;
  padding: var(--sp-5);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--promo-bg);
  color: var(--promo-ink);
  border: 1px solid var(--glass-card-line);
  box-shadow: var(--shadow-card), var(--edge-hi);
}
/* Pita kaca melengkung — dekorasi, tidak membawa data. */
.promo::before, .promo::after {
  content: '';
  position: absolute;
  border-radius: 40% 60% 55% 45%;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.35), rgba(255, 255, 255, 0.04));
  border: 1px solid rgba(255, 255, 255, 0.35);
  backdrop-filter: blur(6px);
}
.promo::before { width: 150px; height: 150px; right: -20px; bottom: -40px; transform: rotate(25deg); }
.promo::after  { width: 90px; height: 90px; right: 90px; bottom: 30px; transform: rotate(-20deg); opacity: 0.7; }
.promo__logo { position: absolute; right: var(--sp-5); top: var(--sp-4); font-family: var(--font-display); font-weight: var(--fw-heavy); letter-spacing: 0.04em; z-index: 1; }
.promo__title { position: relative; z-index: 1; font-family: var(--font-display); font-size: var(--fs-xl); font-weight: var(--fw-heavy); line-height: 1.1; max-width: 9ch; color: inherit; }
.promo__sub { position: relative; z-index: 1; margin-top: var(--sp-2); font-size: var(--fs-xs); opacity: 0.8; max-width: 22ch; }

/* ---------- Responsif dashboard ---------- */
@media (max-width: 1600px) and (min-width: 1101px) { .hide-md { display: none; } }
@media (max-width: 720px) { .hide-md { display: none; } }
@media (max-width: 1280px) {
  .kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 1100px) {
  .dash { grid-template-columns: minmax(0, 1fr); }
  .dash > .span-2 { grid-column: auto; }
}
@media (max-width: 720px) {
  .kpis { gap: var(--sp-3); }
  .kpi { padding: var(--sp-3) var(--sp-4); min-height: 0; grid-template-columns: 1fr; }
  .kpi__icon { grid-row: auto; width: 34px; height: 34px; margin-bottom: var(--sp-2); }
  .kpi__value { font-size: var(--fs-xl); }
  .spark { width: 50%; height: 30px; }
  .perf { grid-template-columns: 1fr; }
  .hide-sm { display: none; }
  .pname__title, .pname__sub { max-width: 128px; }
  .pbar { min-width: 76px; }
  .pbar span { display: none; }
  .ptable td, .ptable th { padding-left: var(--sp-2); padding-right: var(--sp-2); }
  .pname__thumb { width: 32px; height: 32px; }
  .dash { gap: var(--sp-3); }
  .chipdate { height: 34px; font-size: var(--fs-xs); }
}

/* Tombol menu hanya untuk HP — di desktop sidebar selalu tampil. */
@media (min-width: 721px) { #menu-toggle { display: none !important; } }
