
/* Menahan template yang belum terkompilasi.

   Vue global build tanpa build step berarti template hidup sebagai HTML biasa
   sampai Vue mount. Tanpa aturan ini, kurung kurawal ganda terlihat mentah di
   layar setiap kali halaman dimuat -- yang terbaca seperti kerusakan, bukan
   seperti sedang memuat.

   Pasangannya ada di data.js: kalau mount tidak pernah terjadi, atribut ini
   dilepas paksa setelah beberapa detik. Tanpa pelepasan itu, halaman yang
   gagal mount akan berakhir putih total -- menyembunyikan kegagalan alih-alih
   menampilkannya, kebalikan dari yang kita mau. */
[v-cloak] { display: none !important; }
/* ============================================================================
   console.css — Gateway Console
   Krom netral (slate). Warna DIKUNCI untuk status saja: begitu warna merek ikut
   hijau/merah, sinyal status jadi tumpul di layar yang tugasnya memberi sinyal.
   Terang dulu; token disusun supaya gelap kelak tinggal penukaran nilai.
   ========================================================================== */

:root {
  --bg: #f1f5f9;
  --surface: #ffffff;
  --surface-2: #f8fafc;
  --surface-3: #f1f5f9;
  --border: #e2e8f0;
  --border-strong: #cbd5e1;

  --text: #0f172a;
  --text-muted: #64748b;
  --text-faint: #94a3b8;

  --chrome: #1e293b;
  --chrome-2: #334155;
  --chrome-text: #cbd5e1;
  --chrome-text-dim: #94a3b8;

  --ring: #475569;

  /* status — satu-satunya tempat warna berbicara */
  --st-delivered: #15803d;  --st-delivered-bg: #dcfce7;
  --st-routed: #1d4ed8;     --st-routed-bg: #dbeafe;
  --st-held: #b45309;       --st-held-bg: #fef3c7;
  --st-dead: #b91c1c;       --st-dead-bg: #fee2e2;
  --st-rejected: #6d28d9;   --st-rejected-bg: #ede9fe;
  /* `unrouted` sengaja TIDAK memakai warna dead/rejected: tindakannya berbeda
     dari keduanya (DEC-027), dan warna yang sama akan mengajari mata bahwa
     tombolnya sama. */
  --st-unrouted: #0e7490;   --st-unrouted-bg: #cffafe;

  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 24px; --sp-6: 32px;
  --r: 6px; --r-lg: 10px;
  --sidebar-w: 216px;
  --font: Inter, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg); color: var(--text);
  font-family: var(--font); font-size: 14px; line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; }
button { font: inherit; cursor: pointer; }
[hidden] { display: none !important; }

/* ---------- kerangka ------------------------------------------------------ */
.layout { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-w); flex: 0 0 var(--sidebar-w);
  background: var(--chrome); color: var(--chrome-text);
  display: flex; flex-direction: column; position: sticky; top: 0; height: 100vh;
}
.brand {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-4); border-bottom: 1px solid var(--chrome-2);
}
.brand-mark {
  width: 28px; height: 28px; border-radius: var(--r); background: var(--chrome-2);
  display: grid; place-items: center; color: #fff; flex: 0 0 28px;
}
.brand-name { font-weight: 600; color: #fff; line-height: 1.2; }
.brand-sub { font-size: 11px; color: var(--chrome-text-dim); letter-spacing: .04em; text-transform: uppercase; }

.nav { padding: var(--sp-3) var(--sp-2); display: flex; flex-direction: column; gap: 2px; }
.nav-label {
  font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--chrome-text-dim); padding: var(--sp-3) var(--sp-3) var(--sp-1);
}
.nav-item {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 8px var(--sp-3); border-radius: var(--r);
  color: var(--chrome-text); text-decoration: none; font-size: 13.5px;
  transition: background 160ms ease, color 160ms ease;
}
.nav-item:hover { background: var(--chrome-2); color: #fff; }
.nav-item.is-active { background: var(--chrome-2); color: #fff; font-weight: 500; }
.nav-badge {
  margin-left: auto; background: var(--st-dead); color: #fff;
  font-size: 11px; font-weight: 600; padding: 1px 6px; border-radius: 999px;
}
.sidebar-foot {
  margin-top: auto; padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--chrome-2); font-size: 11.5px; color: var(--chrome-text-dim);
}

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.topbar {
  background: var(--surface); border-bottom: 1px solid var(--border);
  padding: var(--sp-4) var(--sp-5); display: flex; align-items: baseline; gap: var(--sp-3);
  position: sticky; top: 0; z-index: 5;
}
.topbar h1 { margin: 0; font-size: 17px; font-weight: 600; letter-spacing: -.01em; }
.topbar .sub { color: var(--text-muted); font-size: 13px; }
.content { padding: var(--sp-5); display: flex; flex-direction: column; gap: var(--sp-5); }

/* ---------- pernyataan keadaan ------------------------------------------- */
.state {
  display: flex; align-items: center; gap: var(--sp-3);
  background: var(--surface); border: 1px solid var(--border);
  border-left: 3px solid var(--st-delivered);
  border-radius: var(--r-lg); padding: var(--sp-4) var(--sp-5);
}
.state.is-alert { border-left-color: var(--st-dead); }
.state-icon { color: var(--st-delivered); display: grid; place-items: center; }
.state.is-alert .state-icon { color: var(--st-dead); }
.state-text { font-size: 15px; font-weight: 500; }
.state-text small { display: block; font-weight: 400; font-size: 13px; color: var(--text-muted); margin-top: 2px; }

/* ---------- kartu tindakan ------------------------------------------------ */
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--sp-4); }
.card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  padding: var(--sp-4); text-align: left; display: flex; flex-direction: column; gap: var(--sp-2);
  transition: border-color 160ms ease, transform 160ms ease;
}
button.card:hover { border-color: var(--border-strong); transform: translateY(-1px); }
button.card:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.card-head { display: flex; align-items: center; gap: var(--sp-2); font-size: 13px; color: var(--text-muted); }
.card-num { font-size: 30px; font-weight: 650; letter-spacing: -.02em; line-height: 1; }
.card-num.is-zero { color: var(--text-faint); }
.card-note { font-size: 12.5px; color: var(--text-muted); }

.metrics { display: flex; flex-wrap: wrap; gap: var(--sp-5); padding: var(--sp-4) var(--sp-5);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); }
.metric-label { font-size: 12px; color: var(--text-muted); }
.metric-value { font-size: 17px; font-weight: 600; }

/* ---------- panel & tabel ------------------------------------------------- */
.panel { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden; }
.panel-head {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border); background: var(--surface-2);
}
.panel-title { font-weight: 600; font-size: 13.5px; }
.panel-title small { font-weight: 400; color: var(--text-muted); margin-left: var(--sp-2); }
.panel-body { padding: var(--sp-4); }

.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th {
  text-align: left; font-weight: 600; font-size: 11.5px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-muted); padding: var(--sp-2) var(--sp-4); border-bottom: 1px solid var(--border);
  white-space: nowrap; background: var(--surface-2);
}
td { padding: 9px var(--sp-4); border-bottom: 1px solid var(--border); vertical-align: middle; }
tbody tr { cursor: pointer; }
tbody tr:hover { background: var(--surface-2); }
tbody tr:last-child td { border-bottom: 0; }
tbody tr.is-selected { background: var(--surface-3); }
.num { font-variant-numeric: tabular-nums; }
.mono { font-family: var(--mono); font-size: 12.5px; }
.muted { color: var(--text-muted); }
.faint { color: var(--text-faint); }
.nowrap { white-space: nowrap; }

/* amplop kode domain disorot — "kenapa gagal" jadi pengamatan, bukan penyelidikan */
.env-prefix { background: var(--surface-3); border-radius: 3px; padding: 1px 3px; font-weight: 600; color: var(--text); }
.env-rest { color: var(--text-muted); }
.env-none { color: var(--st-dead); font-weight: 600; }

/* ---------- pil status ---------------------------------------------------- */
.pill {
  display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
  font-size: 11.5px; font-weight: 600; padding: 2px 8px; border-radius: 999px;
}
.pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.pill-delivered { color: var(--st-delivered); background: var(--st-delivered-bg); }
.pill-routed { color: var(--st-routed); background: var(--st-routed-bg); }
.pill-held { color: var(--st-held); background: var(--st-held-bg); }
.pill-dead_letter { color: var(--st-dead); background: var(--st-dead-bg); }
.pill-rejected { color: var(--st-rejected); background: var(--st-rejected-bg); }
.pill-unrouted { color: var(--st-unrouted); background: var(--st-unrouted-bg); }

/* ---------- kendali ------------------------------------------------------- */
.filters { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; }
select, input[type=text], input[type=url] {
  font: inherit; font-size: 13px; padding: 6px 10px; border-radius: var(--r);
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text);
}
select:focus, input:focus { outline: 2px solid var(--ring); outline-offset: -1px; }
.search { position: relative; display: flex; align-items: center; }
.search svg { position: absolute; left: 8px; color: var(--text-faint); pointer-events: none; }
.search input { padding-left: 30px; min-width: 260px; }

.btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: var(--r); font-size: 13px; font-weight: 500;
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text);
  transition: background 160ms ease, border-color 160ms ease;
}
.btn:hover { background: var(--surface-2); border-color: var(--text-faint); }
.btn:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.btn-primary { background: var(--chrome); border-color: var(--chrome); color: #fff; }
.btn-primary:hover { background: var(--chrome-2); border-color: var(--chrome-2); }
.btn-danger { background: var(--st-dead); border-color: var(--st-dead); color: #fff; }
.btn-danger:hover { background: #991b1b; border-color: #991b1b; }
.btn-ghost { border-color: transparent; background: transparent; color: var(--text-muted); }
.btn-ghost:hover { background: var(--surface-3); color: var(--text); }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.spacer { margin-left: auto; }

/* ---------- laci detail --------------------------------------------------- */
.scrim { position: fixed; inset: 0; background: rgba(15, 23, 42, .32); z-index: 20; }
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(560px, 92vw);
  background: var(--surface); border-left: 1px solid var(--border); z-index: 21;
  display: flex; flex-direction: column; box-shadow: -12px 0 32px rgba(15, 23, 42, .10);
}
.drawer-head {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5); border-bottom: 1px solid var(--border);
}
.drawer-title { font-weight: 600; }
.drawer-body { overflow-y: auto; padding: var(--sp-5); display: flex; flex-direction: column; gap: var(--sp-5); }
.section-title {
  font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-muted); font-weight: 600; margin-bottom: var(--sp-2);
}
.kv { display: grid; grid-template-columns: 128px 1fr; gap: 6px var(--sp-3); font-size: 13px; }
.kv dt { color: var(--text-muted); }
.kv dd { margin: 0; word-break: break-all; }

.locked {
  border: 1px dashed var(--border-strong); border-radius: var(--r);
  padding: var(--sp-4); text-align: center; background: var(--surface-2);
}
.locked p { margin: 0 0 var(--sp-3); font-size: 12.5px; color: var(--text-muted); }
pre.raw {
  margin: 0; background: var(--chrome); color: #e2e8f0; border-radius: var(--r);
  padding: var(--sp-3); font-family: var(--mono); font-size: 12px; line-height: 1.55;
  overflow-x: auto; max-height: 320px;
  /* Badan non-JSON kerap satu baris sangat panjang (form-encoded). Gulir
     mendatar menyembunyikan ekornya; bungkus supaya seluruh byte terbaca. */
  white-space: pre-wrap; overflow-wrap: anywhere;
}

.timeline { display: flex; flex-direction: column; gap: 0; }
.tl-item { display: flex; gap: var(--sp-3); padding: var(--sp-2) 0; border-bottom: 1px dashed var(--border); font-size: 13px; }
.tl-item:last-child { border-bottom: 0; }
.tl-no {
  flex: 0 0 22px; height: 22px; border-radius: 50%; background: var(--surface-3);
  display: grid; place-items: center; font-size: 11px; font-weight: 600; color: var(--text-muted);
}

.note {
  border-left: 3px solid var(--border-strong); background: var(--surface-2);
  padding: var(--sp-3) var(--sp-4); border-radius: 0 var(--r) var(--r) 0;
  font-size: 12.5px; color: var(--text-muted);
}
.note strong { color: var(--text); }

.toast {
  position: fixed; bottom: var(--sp-5); left: 50%; transform: translateX(-50%);
  background: var(--chrome); color: #fff; padding: 10px var(--sp-4); border-radius: var(--r);
  font-size: 13px; z-index: 40; box-shadow: 0 8px 24px rgba(15, 23, 42, .24);
}
.toast.is-error { background: var(--st-dead); }

.empty { padding: var(--sp-6); text-align: center; color: var(--text-muted); }
.empty svg { color: var(--text-faint); margin-bottom: var(--sp-2); }

/* ---------- form config --------------------------------------------------- */
.form-grid { display: grid; grid-template-columns: 180px 1fr; gap: var(--sp-3) var(--sp-4); align-items: center; }
.form-grid label { font-size: 13px; color: var(--text-muted); }
.field-err {
  color: var(--st-dead); font-size: 12.5px; margin-top: 4px;
  display: flex; align-items: flex-start; gap: 5px;
}
/* Ditandai hanya setelah kolom disentuh atau setelah tombol simpan ditekan —
   memerahi form yang belum sempat diisi adalah menghukum orang karena belum mengetik. */
input.is-invalid, select.is-invalid { border-color: var(--st-dead); }
input.is-invalid:focus, select.is-invalid:focus { outline-color: var(--st-dead); }
input.is-valid, select.is-valid { border-color: var(--st-delivered); }
.field-ok { color: var(--st-delivered); font-size: 12.5px; margin-top: 4px;
  display: flex; align-items: center; gap: 5px; }
.field-hint { color: var(--text-muted); font-size: 12px; margin-top: 4px; }
.secret-set { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--st-delivered); }
.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border); }
.tab {
  padding: 8px var(--sp-4); font-size: 13px; border: 0; background: transparent;
  color: var(--text-muted); border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.tab.is-active { color: var(--text); border-bottom-color: var(--chrome); font-weight: 600; }
.chip {
  display: inline-block; font-size: 11.5px; padding: 1px 7px; border-radius: 999px;
  background: var(--surface-3); color: var(--text-muted); border: 1px solid var(--border);
}
.chip-off { background: var(--st-held-bg); color: var(--st-held); border-color: transparent; }

/* ---------- sidebar bisa diciutkan ---------------------------------------- */
.sidebar { transition: width 180ms ease, flex-basis 180ms ease; }
.layout.is-collapsed .sidebar { width: 56px; flex-basis: 56px; }
.layout.is-collapsed .brand-text,
.layout.is-collapsed .nav-label,
.layout.is-collapsed .nav-item span.label,
.layout.is-collapsed .sidebar-foot,
.layout.is-collapsed .lang-switch .label { display: none; }
.layout.is-collapsed .brand { padding: var(--sp-3) 0; justify-content: center; }
.layout.is-collapsed .nav-item { justify-content: center; padding: 8px 0; }
.layout.is-collapsed .nav-badge {
  margin: 0; position: absolute; top: 2px; right: 6px; font-size: 9px; padding: 0 4px;
}
.layout.is-collapsed .nav-item { position: relative; }
.layout.is-collapsed .sidebar-user { justify-content: center; }
.layout.is-collapsed .sidebar-user .who { display: none; }

.nav-toggle {
  margin-left: auto; background: transparent; border: 0; color: var(--chrome-text-dim);
  padding: 4px; border-radius: var(--r); display: grid; place-items: center;
}
.nav-toggle:hover { background: var(--chrome-2); color: #fff; }
.nav-toggle:focus-visible { outline: 2px solid var(--chrome-text); outline-offset: 1px; }
.layout.is-collapsed .nav-toggle { margin: 0; }
.layout.is-collapsed .nav-toggle svg { transform: rotate(180deg); }

.sidebar-user {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3); border-top: 1px solid var(--chrome-2); margin-top: auto;
}
.avatar {
  width: 28px; height: 28px; border-radius: 50%; background: var(--chrome-2); color: #fff;
  display: grid; place-items: center; font-size: 11.5px; font-weight: 600; flex: 0 0 28px;
}
.sidebar-user .who { min-width: 0; line-height: 1.25; }
.sidebar-user .who b { display: block; color: #fff; font-size: 12.5px; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-user .who small { color: var(--chrome-text-dim); font-size: 11px; }
.sidebar-user .out { margin-left: auto; }

/* menu profil — bahasa & kata sandi hidup di sini, bukan sebagai baris sendiri */
.sidebar-user { position: relative; }
.profile-btn {
  display: flex; align-items: center; gap: var(--sp-2); flex: 1; min-width: 0;
  background: transparent; border: 0; color: inherit; padding: 2px; border-radius: var(--r);
  text-align: left;
}
.profile-btn:hover { background: var(--chrome-2); }
.profile-menu {
  position: absolute; bottom: calc(100% + 6px); left: var(--sp-2); right: var(--sp-2);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: 0 12px 32px rgba(2, 6, 23, .32); padding: var(--sp-2); z-index: 30;
}
.layout.is-collapsed .profile-menu { left: calc(100% + 6px); right: auto; width: 210px; }
.pm-label {
  font-size: 10.5px; letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-muted); padding: var(--sp-2) var(--sp-2) var(--sp-1);
}
.pm-item {
  display: flex; align-items: center; gap: var(--sp-2); width: 100%;
  padding: 7px var(--sp-2); border: 0; background: transparent; color: var(--text);
  border-radius: var(--r); font-size: 13px; text-align: left;
}
.pm-item:hover { background: var(--surface-3); }
.pm-item .tick { margin-left: auto; color: var(--st-delivered); }
.pm-sep { height: 1px; background: var(--border); margin: var(--sp-2) 0; }
.pm-who { padding: var(--sp-2); border-bottom: 1px solid var(--border); margin-bottom: var(--sp-2); }
.pm-who b { display: block; font-size: 13px; }
.pm-who small { color: var(--text-muted); font-size: 11.5px; }

/* modal kecil */
.modal-card {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: min(420px, 92vw); background: var(--surface); border-radius: var(--r-lg);
  box-shadow: 0 24px 60px rgba(2, 6, 23, .35); z-index: 31; padding: var(--sp-5);
}
.modal-card h2 { margin: 0 0 var(--sp-4); font-size: 16px; }

.lang-switch { display: flex; gap: 2px; padding: var(--sp-2) var(--sp-3); }
.lang-btn {
  flex: 1; background: transparent; border: 1px solid transparent; color: var(--chrome-text-dim);
  font-size: 11.5px; padding: 4px 6px; border-radius: var(--r);
}
.lang-btn:hover { background: var(--chrome-2); color: #fff; }
.lang-btn.is-active { background: var(--chrome-2); color: #fff; border-color: var(--chrome-text-dim); }

/* ---------- pagination ----------------------------------------------------- */
.pager {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4); border-top: 1px solid var(--border); background: var(--surface-2);
  font-size: 12.5px; color: var(--text-muted); flex-wrap: wrap;
}
.pager .pages { display: flex; gap: 2px; margin-left: auto; }
.page-btn {
  min-width: 28px; height: 28px; padding: 0 6px; border-radius: var(--r);
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text);
  font-size: 12.5px; display: inline-grid; place-items: center;
}
.page-btn:hover:not(:disabled) { background: var(--surface-3); }
.page-btn:disabled { opacity: .45; cursor: not-allowed; }
.page-btn.is-active { background: var(--chrome); border-color: var(--chrome); color: #fff; font-weight: 600; }
.pager select { padding: 3px 6px; font-size: 12.5px; }

/* ---------- halaman masuk -------------------------------------------------- */
.login-page {
  min-height: 100vh; display: grid; place-items: center; padding: var(--sp-5);
  background: var(--chrome);
}
.login-card {
  width: min(400px, 100%); background: var(--surface); border-radius: var(--r-lg);
  padding: var(--sp-6); box-shadow: 0 20px 48px rgba(2, 6, 23, .35);
}
.login-brand { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-5); }
.login-brand .brand-mark { background: var(--chrome); }
.login-title { font-size: 18px; font-weight: 650; letter-spacing: -.01em; }
.login-sub { font-size: 13px; color: var(--text-muted); }
.login-field { margin-bottom: var(--sp-4); }
.login-field label { display: block; font-size: 12.5px; color: var(--text-muted); margin-bottom: 4px; }
.login-field input { width: 100%; padding: 9px 11px; }
.login-btn { width: 100%; justify-content: center; padding: 10px; font-size: 14px; }
.login-err {
  background: var(--st-dead-bg); color: var(--st-dead); border-radius: var(--r);
  padding: 8px 12px; font-size: 12.5px; margin-bottom: var(--sp-4);
}
.login-hint { font-size: 12px; color: var(--text-muted); margin-top: var(--sp-4); line-height: 1.5; }
.login-lang { display: flex; gap: 4px; justify-content: center; margin-top: var(--sp-4); }
.login-lang .lang-btn { flex: 0 0 auto; color: var(--text-muted); border-color: var(--border); }
.login-lang .lang-btn.is-active { background: var(--surface-3); color: var(--text); }

/* ---------- peran & aksi pengguna ------------------------------------------ */
.role { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600; }
.role-super { color: var(--st-rejected); }
.role-operator { color: var(--text); }
.role-domain { color: var(--text-muted); }
.row-actions { display: flex; gap: 4px; justify-content: flex-end; }
.locked-hint { display: inline-flex; align-items: center; gap: 5px; color: var(--text-faint); font-size: 12px; }

/* ---------- keadaan memuat ------------------------------------------------- */
/* Tanpa ini orang tak bisa membedakan "sedang diambil" dari "memang kosong",
   dan satu-satunya petunjuk tersisa adalah indikator peramban. */

.progress-top {
  position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 60;
  background: transparent; overflow: hidden;
}
.progress-top::after {
  content: ""; position: absolute; inset: 0; width: 40%;
  background: linear-gradient(90deg, transparent, var(--st-routed), transparent);
  animation: geser 1s linear infinite;
}
@keyframes geser { from { transform: translateX(-100%); } to { transform: translateX(320%); } }

.skeleton {
  background: linear-gradient(90deg, var(--surface-3) 25%, var(--surface-2) 37%, var(--surface-3) 63%);
  background-size: 400% 100%; animation: kilau 1.3s ease infinite;
  border-radius: 4px; height: 11px; display: inline-block; width: 100%;
}
@keyframes kilau { from { background-position: 100% 50%; } to { background-position: 0 50%; } }
.sk-sm { width: 45%; } .sk-md { width: 70%; } .sk-lg { width: 90%; }

.spinner {
  width: 14px; height: 14px; border-radius: 50%; display: inline-block;
  border: 2px solid currentColor; border-right-color: transparent;
  animation: putar .7s linear infinite; vertical-align: -2px;
}
@keyframes putar { to { transform: rotate(360deg); } }
.btn.is-loading { pointer-events: none; opacity: .75; }

.loading-note {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-4); color: var(--text-muted); font-size: 13px;
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
  .skeleton, .progress-top::after, .spinner { animation: none; }
  .skeleton { background: var(--surface-3); }
}
@media (max-width: 900px) {
  .sidebar { display: none; }
  .content { padding: var(--sp-4); }
  .kv { grid-template-columns: 1fr; }
  .form-grid { grid-template-columns: 1fr; }
}

/* Respons yang dikembalikan domain pada tiap percobaan kirim. Tanpa ini operator
   hanya tahu "gagal", bukan alasan yang domain sendiri berikan. */
.respons {
  margin-top: 4px; background: var(--surface-3); border-radius: 4px;
  padding: 4px 6px; font-family: var(--mono); font-size: 11.5px;
  color: var(--text-muted); overflow-x: auto; white-space: nowrap;
}

/* ============================================================================
   Perbaikan hasil audit aksesibilitas (ui-ux-pro-max §1 & §2)
   ========================================================================== */

/* focus-states — sebelumnya hanya .btn, .card, dan input yang punya cincin
   fokus. Tab, pager, item menu profil, dan baris tabel tak punya sama sekali,
   jadi pengguna papan-ketik kehilangan jejak posisinya. */
.tab:focus-visible,
.page-btn:focus-visible,
.pm-item:focus-visible,
.profile-btn:focus-visible,
.lang-btn:focus-visible,
.nav-item:focus-visible,
tbody tr:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: -2px;
  border-radius: var(--r);
}
.nav-item:focus-visible, .profile-btn:focus-visible, .lang-btn:focus-visible {
  outline-color: var(--chrome-text);
}

/* keyboard-nav — baris tabel bisa diklik tapi dulu tak bisa dicapai papan-ketik
   sama sekali. Sekarang fokusabel, dan Enter/Spasi menjalankan aksi barisnya. */
tbody tr[tabindex] { outline-offset: -2px; }
tbody tr:focus-visible { background: var(--surface-2); }

/* touch-target-size — pedoman 44px untuk sentuh; konsol ini alat papan-ketik
   dan tetikus di meja, jadi 32px dipilih sebagai kompromi sadar: cukup besar
   untuk tetikus, tanpa membuat baris tabel padat jadi renggang. */
.btn, .page-btn, .tab { min-height: 32px; }


/* ============================================================================
   HOP — perjalanan event dibaca sebagai dua ruas terpisah (FR-084)
   Ruas yang tergabung membuat kegagalan hop 1 dan hop 2 terbaca sama, padahal
   penanganannya berlawanan. Batas kotak di sini bukan hiasan.
   ========================================================================== */
.hop {
  border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--surface); overflow: hidden;
}
.hop + .hop { margin-top: var(--sp-4); }
.hop-head {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: 10px var(--sp-4); background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}
.hop-no {
  flex: none; width: 20px; height: 20px; border-radius: 999px;
  background: var(--chrome); color: #fff; font-size: 11.5px; font-weight: 700;
  display: grid; place-items: center;
}
.hop-arah { font-size: 12.5px; color: var(--text); font-weight: 600; }
.hop-verdict {
  margin-left: auto; font-size: 11.5px; padding: 1px 8px; border-radius: 999px;
  background: var(--surface-3); color: var(--text-muted);
}
.hop-verdict.is-ok { background: var(--st-delivered-bg); color: var(--st-delivered); }
.hop-verdict.is-bad { background: var(--st-dead-bg); color: var(--st-dead); }
.hop-verdict.is-mati { background: var(--surface-3); color: var(--text-faint); }
.hop-body { padding: var(--sp-4); }
.hop-body .section-title { margin-top: var(--sp-4); }
.hop-body > .section-title:first-child { margin-top: 0; }
/* Hop yang tak pernah dijalankan diredupkan — bukan disembunyikan. Operator
   tetap perlu melihat bahwa ruas itu ADA dan sengaja kosong. */
.hop.is-mati { opacity: .72; }

.teks-ok { color: var(--st-delivered); font-weight: 600; }
.teks-bad { color: var(--st-dead); font-weight: 600; }

/* Header korelasi disorot: inilah satu nilai yang menyatukan dua log. */
.hdr-korelasi { color: var(--st-routed); font-weight: 700; }
.btn-mini {
  padding: 0 6px; height: 20px; font-size: 11px; margin-left: 6px;
  vertical-align: middle;
}

/* ---------- badan mentah (FR-085) ------------------------------------------ */
.note-milik { border-left-color: var(--st-routed); margin-bottom: var(--sp-3); }
.badan-meta {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: 12px; color: var(--text-muted); margin-bottom: 6px;
}
.chip-warn { background: var(--st-held-bg); color: var(--st-held); border-color: transparent; }
/* Karakter kendali DITAMPILKAN sebagai \xNN, tidak diserahkan ke peramban.
   Tanpa penanda ini NUL dan BEL hilang tanpa jejak, dan CR telanjang memecah
   tata letak — dua-duanya membuat layar berbohong soal byte yang sebenarnya. */
.ctl {
  background: var(--st-dead); color: #fff; border-radius: 3px;
  padding: 0 3px; font-weight: 700;
}
.badan-potong {
  margin-top: 6px; font-size: 12px; color: var(--st-held);
  display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
}

/* ---------- legenda status (FR-086) ---------------------------------------- */
.legend { margin: 0 var(--sp-4) var(--sp-3); }
.legend-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  background: none; border: 0; padding: 2px 0;
  font-size: 12.5px; color: var(--text-muted);
}
.legend-toggle:hover { color: var(--text); }
.legend-body {
  margin-top: var(--sp-2); border: 1px solid var(--border); border-radius: var(--r);
  background: var(--surface-2); padding: var(--sp-3);
}
.legend-row {
  display: grid; grid-template-columns: 104px 1fr; gap: var(--sp-3);
  align-items: start; font-size: 12.5px; color: var(--text-muted);
}
.legend-row + .legend-row { margin-top: 6px; }
.legend-note {
  margin: var(--sp-3) 0 0; padding-top: var(--sp-2);
  border-top: 1px solid var(--border);
  font-size: 12px; color: var(--text-muted);
}
.rot-90 { transform: rotate(-90deg); }
.rot-180 { transform: rotate(0deg); }

/* ---------- kesehatan vendor ------------------------------------------------ */
.sehat-baris {
  display: grid; grid-template-columns: 8px 52px 1fr; align-items: baseline;
  gap: var(--sp-2); font-size: 12.5px;
}
.sehat-arah { color: var(--text-faint); font-size: 11.5px; }
.sehat-sub {
  padding-left: 68px; color: var(--text-faint); font-size: 11.5px; line-height: 1.45;
}
.dot {
  width: 8px; height: 8px; border-radius: 999px; flex: none;
  background: var(--text-faint); position: relative; top: -1px;
}
.dot-ok { background: var(--st-delivered); }
.dot-warn { background: var(--st-held); }
.dot-bad { background: var(--st-dead); }
.dot-off { background: var(--border-strong); }
.sehat-waktu { color: var(--text-faint); font-size: 11.5px; }
.spin { animation: putar 900ms linear infinite; }
@keyframes putar { to { transform: rotate(360deg); } }

/* ---------- katalog vendor sebagai kartu ------------------------------------ */
.vendor-grid {
  display: grid; gap: var(--sp-4); margin-top: var(--sp-4);
  grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
}
.vendor-card {
  border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--surface); display: flex; flex-direction: column;
}
.vc-head {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: 10px var(--sp-4); background: var(--surface-2);
  border-bottom: 1px solid var(--border); border-radius: var(--r-lg) var(--r-lg) 0 0;
}
.vc-nama { font-weight: 600; }
.vc-kode {
  font-size: 11.5px; color: var(--text-muted);
  background: var(--surface-3); padding: 1px 7px; border-radius: 999px;
}
.vc-sehat {
  padding: var(--sp-3) var(--sp-4); display: grid; gap: 3px;
  border-bottom: 1px solid var(--border);
}
.vc-kv { padding: var(--sp-3) var(--sp-4) 0; grid-template-columns: 108px 1fr; }
.vc-catatan { padding: var(--sp-2) var(--sp-4) 0; }
.vc-riwayat { margin: var(--sp-3) var(--sp-4) var(--sp-4); align-self: flex-start; }

/* ---------- penanda mode ----------------------------------------------------
   Bukan hiasan: satu-satunya pembeda visual antara konsol yang menyentuh uang
   sungguhan dan yang tidak. Sengaja tak bisa ditutup. -------------------------- */
/* Penanda mode melekat pada DOMAIN, bukan pada portal: satu penanda global
   akan berbohong begitu sebagian tenant live dan sebagian lagi menguji. */
.mode-strip {
  display: flex; align-items: center; gap: 6px;
  padding: 8px var(--sp-4); border-radius: var(--r);
  background: var(--st-held-bg); color: var(--st-held);
  font-size: 12.5px; font-weight: 600;
}
.chip-sandbox { background: var(--st-held-bg); color: var(--st-held); border-color: transparent; }
.chip-campuran { background: var(--st-routed-bg); color: var(--st-routed); border-color: transparent; }

.chip-prod { background: var(--st-delivered-bg); color: var(--st-delivered); border-color: transparent; }
.chip-bad { background: var(--st-dead-bg); color: var(--st-dead); border-color: transparent; }
