/* ============================================================
   Falcon Hub — Joko UI inspired theme
   DNA: Slate-900 base · Solid cards · Poppins · Falcon Red accent
   ============================================================ */
/* ============================================================
   FALCON HUB UTILITIES & GLASSMORPHISM -- digabung dari
   theme-utilities.css (v1.19.56). Dulu dimuat lewat @import
   yang memblokir render; sekarang satu file, satu request.
   ============================================================ */
:root {
  --glass-blur: blur(16px) saturate(180%);
}

/* Base Body Update for Glassmorphism */
body {
  background-image: 
    radial-gradient(circle at 15% 50%, rgba(249, 65, 68, 0.05), transparent 25%),
    radial-gradient(circle at 85% 30%, rgba(67, 97, 238, 0.05), transparent 25%);
  background-attachment: fixed;
}
[data-theme="light"] body {
  background-image: none;
}
[data-theme="forest"] body {
  background-image: 
    radial-gradient(circle at 15% 50%, rgba(16, 185, 129, 0.05), transparent 25%),
    radial-gradient(circle at 85% 30%, rgba(5, 150, 105, 0.05), transparent 25%);
}
[data-theme="midnight"] body {
  background-image: 
    radial-gradient(circle at 15% 50%, rgba(59, 130, 246, 0.05), transparent 25%),
    radial-gradient(circle at 85% 30%, rgba(99, 102, 241, 0.05), transparent 25%);
}

/* Utility Classes - Layout */
.fx-flex { display: flex; }
.fx-flex-col { display: flex; flex-direction: column; }
.fx-items-center { align-items: center; }
.fx-items-start { align-items: flex-start; }
.fx-items-end { align-items: flex-end; }
.fx-justify-center { justify-content: center; }
.fx-justify-between { justify-content: space-between; }
.fx-justify-start { justify-content: flex-start; }
.fx-justify-end { justify-content: flex-end; }
.fx-wrap { flex-wrap: wrap; }
.fx-flex-1 { flex: 1; }

.fx-grid { display: grid; }
.fx-grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.fx-grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.fx-grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* Utility Classes - Spacing */
.fx-gap-2 { gap: 2px; }
.fx-gap-4 { gap: 4px; }
.fx-gap-6 { gap: 6px; }
.fx-gap-8 { gap: 8px; }
.fx-gap-12 { gap: 12px; }
.fx-gap-16 { gap: 16px; }
.fx-gap-24 { gap: 24px; }
.fx-gap-32 { gap: 32px; }

.fx-m-0 { margin: 0; }
.fx-mt-0 { margin-top: 0; }
.fx-mt-4 { margin-top: 4px; }
.fx-mt-6 { margin-top: 6px; }
.fx-mt-8 { margin-top: 8px; }
.fx-mt-12 { margin-top: 12px; }
.fx-mt-16 { margin-top: 16px; }
.fx-mt-24 { margin-top: 24px; }

.fx-mb-0 { margin-bottom: 0; }
.fx-mb-4 { margin-bottom: 4px; }
.fx-mb-8 { margin-bottom: 8px; }
.fx-mb-12 { margin-bottom: 12px; }
.fx-mb-16 { margin-bottom: 16px; }
.fx-mb-24 { margin-bottom: 24px; }
.fx-mb-32 { margin-bottom: 32px; }

.fx-ml-4 { margin-left: 4px; }
.fx-ml-8 { margin-left: 8px; }
.fx-ml-auto { margin-left: auto; }
.fx-mr-4 { margin-right: 4px; }
.fx-mr-8 { margin-right: 8px; }
.fx-mr-auto { margin-right: auto; }

.fx-p-0 { padding: 0; }
.fx-p-4 { padding: 4px; }
.fx-p-8 { padding: 8px; }
.fx-p-12 { padding: 12px; }
.fx-p-16 { padding: 16px; }
.fx-p-24 { padding: 24px; }

.fx-px-8 { padding-left: 8px; padding-right: 8px; }
.fx-px-10 { padding-left: 10px; padding-right: 10px; }
.fx-px-12 { padding-left: 12px; padding-right: 12px; }
.fx-px-16 { padding-left: 16px; padding-right: 16px; }

.fx-py-4 { padding-top: 4px; padding-bottom: 4px; }
.fx-py-8 { padding-top: 8px; padding-bottom: 8px; }

/* Utility Classes - Typography */
.fx-text-xs { font-size: 11px; }
.fx-text-sm { font-size: 13px; }
.fx-text-base { font-size: 14px; }
.fx-text-lg { font-size: 16px; }
.fx-text-xl { font-size: 20px; }
.fx-text-2xl { font-size: 24px; }
.fx-text-3xl { font-size: 28px; }

.fx-font-normal { font-weight: 400; }
.fx-font-medium { font-weight: 500; }
.fx-font-semibold { font-weight: 600; }
.fx-font-bold { font-weight: 700; }
.fx-font-extrabold { font-weight: 800; }

.fx-text-center { text-align: center; }
.fx-text-right { text-align: right; }

.fx-text-primary { color: var(--text); }
.fx-text-secondary { color: var(--text-2); }
.fx-text-tertiary { color: var(--text-3); }
.fx-text-accent { color: var(--accent); }
.fx-text-info { color: var(--info); }
.fx-text-success { color: var(--success); }
.fx-text-warning { color: var(--warning); }
.fx-text-danger { color: var(--danger); }

/* Utility Classes - Miscellaneous */
.fx-w-full { width: 100%; }
.fx-w-auto { width: auto; }
.fx-h-full { height: 100%; }

.fx-rounded { border-radius: var(--radius); }
.fx-rounded-lg { border-radius: var(--radius-lg); }
.fx-rounded-xl { border-radius: var(--radius-xl); }
.fx-rounded-full { border-radius: 9999px; }

.fx-border { border: 1px solid var(--border); }
.fx-border-2 { border: 1px solid var(--border-2); }
.fx-border-none { border: none; }

.fx-bg-card { background: var(--card); backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur); }
.fx-bg-card-2 { background: var(--card-2); backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur); }
.fx-bg-card-3 { background: var(--card-3); backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur); }
.fx-bg-transparent { background: transparent; }
.fx-bg-glass { backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur); }

.fx-relative { position: relative; }
.fx-absolute { position: absolute; }
.fx-overflow-hidden { overflow: hidden; }
.fx-cursor-pointer { cursor: pointer; }

.fx-shadow-sm { box-shadow: var(--shadow-sm); }
.fx-shadow-md { box-shadow: var(--shadow-md); }
.fx-shadow-lg { box-shadow: var(--shadow-lg); }

/* Micro-Animations for Buttons and Cards */
.fx-btn, .fc-kpi-card, .theme-card, .fx-card, .fc-tab {
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.fx-card:hover, .fc-kpi-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

/* Make existing structural elements glassmorphic */
.fx-card, .fc-kpi-card, .theme-card {
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
}

:root {
  color-scheme: dark;
  /* ── Background (Deep Space / Glass) ───────────────────────── */
  --bg:         #0A0D14;   /* very deep black/gray */
  --bg-2:       #121620;   /* slightly lighter */
  --bg-3:       #1B2230;   /* elevated */

  /* ── Surface / Card — Glassmorphic ─────────────────────────── */
  --card:        rgba(18, 22, 32, 0.35);
  --card-2:      rgba(27, 34, 48, 0.5);
  --card-3:      rgba(38, 46, 64, 0.65);
  --card-solid:  #121620;

  /* ── Borders — Soft Glass ──────────────────────────────────── */
  --border:        rgba(255, 255, 255, 0.08);
  --border-2:      rgba(255, 255, 255, 0.15);
  --border-active: rgba(255, 255, 255, 0.25);

  /* ── Shadows & Glows ───────────────────────────────────────── */
  --shadow-sm:   0 4px 12px rgba(0, 0, 0, 0.5);
  --shadow-md:   0 12px 28px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.04);
  --shadow-lg:   0 24px 48px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.04);
  --glow-primary: 0 0 24px rgba(249, 65, 68, 0.35); /* Red glow */
  --glow-accent:  0 0 24px rgba(67, 97, 238, 0.35); /* Blue glow */

  /* ── Typography ────────────────────────────────────────────── */
  --text:   #F0F6FC;   /* crisp white */
  --text-2: #8B949E;   /* muted gray for secondary */
  --text-3: #757E89;   /* more muted gray */

  /* ── Brand Accents (Red/Orange & Blue) ───────────────────────── */
  --accent:        #F94144; /* Neon Red/Orange as primary */
  --accent-hover:  #FF5A5F;
  --accent-muted:  #8A252C;
  --accent-soft:   rgba(249, 65, 68, 0.15);
  --accent-ring:   rgba(249, 65, 68, 0.4);

  --accent-alt:    #4361EE; /* Neon Blue as secondary */

  /* ── Semantic ──────────────────────────────────────────────── */
  --success: #2DC653; /* Neon green */
  --warning: #F9C74F; /* Bright yellow */
  --danger:  #F94144; /* Neon red */
  --info:    #4361EE; /* Bright blue */

  /* ── Layout ────────────────────────────────────────────────── */
  --sidebar-w: 80px;  /* Collapsed sidebar by default for modern look */
  --sidebar-w-exp: 240px; /* Expanded width */
  --topbar-h:  70px;
  --radius:    12px;
  --radius-lg: 20px;
  --radius-xl: 28px;

  /* ── Fonts ─────────────────────────────────────────────────── */
  --font: 'Poppins', 'Inter', system-ui, -apple-system, sans-serif;
  --mono: 'JetBrains Mono', 'Cascadia Code', monospace;
  --accent-text: #0F172A;
  --accent-on-surface: #F94144;
  --brand-rgb:   249, 65, 68;
  --brand-2-rgb: 67, 97, 238;
  /* ── Token turunan semantik (anti-slop) ───────────────────────
     Dipakai gradient dua titik, glow tombol, dan latar modal.
     Sebelumnya view memakai hex Tailwind langsung (#3b82f6, #10b981,
     #ef4444, dst) yang tidak ikut berubah saat tema diganti sehingga
     gradient "nyangkut" di warna tema gelap. */
  --info-deep:     #3b82f6;
  --success-deep:  #10b981;
  --success-deeper:#047857;
  --warning-deep:  #f59e0b;
  --danger-deep:   #ef4444;
  --accent-deep:   #ef4444;
  --violet:        #a855f7;
  --osint:         #6366f1;
  --osint-deep:    #4338ca;

  /* Overlay latar modal — dulu 0.5 / 0.6 / 0.7 campur aduk antar modul. */
  --overlay: rgba(0, 0, 0, 0.72);

  /* Glow tombol aksi (shadow berwarna senada tombol). */
  --glow-info:    0 8px 16px rgba(59, 130, 246, 0.20);
  --glow-osint:   0 8px 16px rgba(99, 102, 241, 0.25);
  --glow-warning: 0 8px 16px rgba(234, 179, 8, 0.20);
  --glow-danger:  0 8px 16px rgba(239, 68, 68, 0.20);
  --glow-accent:  0 8px 16px rgba(249, 65, 68, 0.20);


}

/* ── Light Theme ────────────────────────────────────────────── */
[data-theme="light"] {
  color-scheme: light;
  --bg:         #f4f7f6;   /* off-white */
  --bg-2:       #ffffff;   /* solid white */
  --bg-3:       #eef2f5;   /* light gray */

  --card:        rgba(255, 255, 255, 1);
  --card-2:      #f8fafc;
  --card-3:      #f1f5f9;
  --card-solid:  #ffffff;

  --border:        #e2e8f0;
  --border-2:      #cbd5e1;
  --border-active: #94a3b8;

  --shadow-sm:   0 4px 12px rgba(0, 0, 0, 0.05);
  --shadow-md:   0 8px 24px rgba(0, 0, 0, 0.08);
  --shadow-lg:   0 16px 32px rgba(0, 0, 0, 0.1);

  --text:   #0f172a;   /* darkest slate */
  --text-2: #334155;   /* slate-700 */
  --text-3: #627188;   /* slate-500 */

  --accent-ring: rgba(249, 65, 68, 0.20);
  --accent-soft: rgba(249, 65, 68, 0.1);

  --success: #059669; /* green-600 */
  --warning: #d97706; /* amber-600 */
  --danger:  #dc2626; /* red-600 */
  --info:    #2563eb; /* blue-600 */
  --accent-text: #0F172A;
  --accent-on-surface: #B91C1C;
  --brand-rgb:   249, 65, 68;
  --brand-2-rgb: 67, 97, 238;
}

/* Token turunan yang perlu nilai berbeda di tema terang. */
[data-theme="light"] {
  --info-deep:    #2563eb;
  --warning-deep: #d97706;
  --danger-deep:  #dc2626;
  --accent-deep:  #dc2626;
  --overlay:      rgba(15, 23, 42, 0.55);
  --glow-info:    0 8px 16px rgba(37, 99, 235, 0.18);
  --glow-warning: 0 8px 16px rgba(217, 119, 6, 0.18);
  --glow-danger:  0 8px 16px rgba(220, 38, 38, 0.18);
  --glow-accent:  0 8px 16px rgba(249, 65, 68, 0.18);
}

/* ── Midnight Blue Theme ────────────────────────────────────────────── */
[data-theme="midnight"] {
  --bg:         #040814;   /* Very deep blue-black */
  --bg-2:       #0B1224;   /* Slightly lighter deep blue */
  --bg-3:       #131F3A;   /* Elevated blue */
  
  --card:       rgba(11, 18, 36, 0.4);
  --card-2:     rgba(19, 31, 58, 0.5);
  --card-3:     rgba(28, 45, 82, 0.65);
  --card-solid: #0B1224;
  
  --border:     rgba(59, 130, 246, 0.15);
  --border-2:   rgba(59, 130, 246, 0.35);
  --border-focus: #3b82f6; /* blue-500 */
  
  --accent:     #3b82f6; /* blue-500 */
  --accent-hover: #60a5fa; /* blue-400 */
  --accent-text: #0F172A;
  --accent-ring: rgba(59, 130, 246, 0.25);
  --accent-soft: rgba(59, 130, 246, 0.15);
  --text-3: #737C87;
  --accent-on-surface: #3B82F6;
  --brand-rgb:   59, 130, 246;
  --brand-2-rgb: 96, 165, 250;
}

/* ── Emerald Forest Theme ────────────────────────────────────────────── */
[data-theme="forest"] {
  --bg:         #010C07;   /* Extremely dark green-black */
  --bg-2:       #041D12;   /* Deep emerald */
  --bg-3:       #083321;   /* Elevated emerald */
  
  --card:       rgba(4, 29, 18, 0.4);
  --card-2:     rgba(8, 51, 33, 0.5);
  --card-3:     rgba(12, 74, 48, 0.65);
  --card-solid: #041D12;
  
  --border:     rgba(16, 185, 129, 0.15);
  --border-2:   rgba(16, 185, 129, 0.35);
  --border-focus: #10b981; /* emerald-500 */
  
  --accent:     #10b981; /* emerald-500 */
  --accent-hover: #34d399; /* emerald-400 */
  --accent-text: #0F172A;
  --accent-ring: rgba(16, 185, 129, 0.25);
  --accent-soft: rgba(16, 185, 129, 0.15);
  --text-3: #757D89;
  --accent-on-surface: #10B981;
  --brand-rgb:   16, 185, 129;
  --brand-2-rgb: 52, 211, 153;
}

/* ── Sunset Purple Theme ────────────────────────────────────────────── */
[data-theme="sunset"] {
  --bg:         #0A0512;   /* Extremely dark violet-black */
  --bg-2:       #160A29;   /* Deep violet */
  --bg-3:       #251245;   /* Elevated violet */
  
  --card:       rgba(22, 10, 41, 0.4);
  --card-2:     rgba(37, 18, 69, 0.5);
  --card-3:     rgba(54, 26, 100, 0.65);
  --card-solid: #160A29;
  
  --border:     rgba(168, 85, 247, 0.15);
  --border-2:   rgba(168, 85, 247, 0.35);
  --border-focus: #d946ef; /* fuchsia-500 */
  
  --accent:     #ec4899; /* pink-500 */
  --accent-hover: #f472b6; /* pink-400 */
  --accent-text: #0F172A;
  --accent-ring: rgba(236, 72, 153, 0.25);
  --accent-soft: rgba(236, 72, 153, 0.15);
  --text-3: #737B87;
  --accent-on-surface: #EC4899;
  --brand-rgb:   236, 72, 153;
  --brand-2-rgb: 168, 85, 247;
}

/* ── HMI — Hijau HMI + Hitam/Putih Bulan Bintang ── */
[data-theme="hmi"] {
  --bg:         #0B0F0D;
  --bg-2:       #151A17;
  --bg-3:       #1E2521;

  --card:       rgba(21, 26, 23, 0.4);
  --card-2:     rgba(30, 37, 33, 0.5);
  --card-3:     rgba(44, 54, 48, 0.65);
  --card-solid: #151A17;

  --border:       #2A332E;
  --border-2:     #506157;
  --border-focus: #16A34A;

  /* Primary */
  --accent:            #16A34A;
  --accent-hover:      #18B150;   /* palet: #15803D (lebih gelap) -> label gelap jd 3.3-4.4, gagal AA; dicerahkan */
  --accent-text:       #0F172A;
  --accent-soft:       rgba(22, 163, 74, 0.12);
  --accent-ring:       rgba(22, 163, 74, 0.25);
  --accent-on-surface: #16A34A;

  /* Secondary */
  --accent-2:            #18181B;
  --accent-2-hover:      #09090B;
  --accent-2-text:       #FFFFFF;
  --accent-2-soft:       rgba(24, 24, 27, 0.12);
  --accent-2-on-surface: #FAFAFA;

  /* Tertiary */
  --accent-3:            #475569;
  --accent-3-text:       #FFFFFF;
  --accent-3-soft:       rgba(71, 85, 105, 0.12);
  --accent-3-on-surface: #6C809C;

  /* Neutral accent (ring / outline) */
  --ring:      #FAFAFA;
  --ring-soft: rgba(250, 250, 250, 0.08);

  /* RGB mentah: dipakai glow halaman & fill transparan supaya ikut tema */
  --brand-rgb:    22, 163, 74;
  --brand-2-rgb:  24, 24, 27;
  --glow-primary: 0 0 24px rgba(22, 163, 74, 0.35);
  --glow-accent:  0 0 24px rgba(24, 24, 27, 0.35);

  --text:   #FFFFFF;
  --text-2: #94A3B8;
  --text-3: #6A7F9C;

  --success: #22C55E;
  --warning: #F59E0B;
  --danger:  #EF4444;
}

/* ── PMII — Biru Perisai + Kuning Mahkota ── */
[data-theme="pmii"] {
  --bg:         #0A0F16;
  --bg-2:       #131B26;
  --bg-3:       #1B2632;

  --card:       rgba(19, 27, 38, 0.4);
  --card-2:     rgba(27, 38, 50, 0.5);
  --card-3:     rgba(39, 55, 72, 0.65);
  --card-solid: #131B26;

  --border:       #22303F;
  --border-2:     #415B78;
  --border-focus: #0EA5E9;

  /* Primary */
  --accent:            #0EA5E9;
  --accent-hover:      #16ADF1;   /* palet: #0284C7 (lebih gelap) -> label gelap jd 3.3-4.4, gagal AA; dicerahkan */
  --accent-text:       #0F172A;
  --accent-soft:       rgba(14, 165, 233, 0.12);
  --accent-ring:       rgba(14, 165, 233, 0.25);
  --accent-on-surface: #0EA5E9;

  /* Secondary */
  --accent-2:            #FACC15;
  --accent-2-hover:      #EAB308;
  --accent-2-text:       #1E1B0E;
  --accent-2-soft:       rgba(250, 204, 21, 0.12);
  --accent-2-on-surface: #FACC15;

  /* Tertiary */
  --accent-3:            #312E81;
  --accent-3-text:       #FFFFFF;
  --accent-3-soft:       rgba(49, 46, 129, 0.12);
  --accent-3-on-surface: #7875CE;

  /* Neutral accent (ring / outline) */
  --ring:      #F1F5F9;
  --ring-soft: rgba(241, 245, 249, 0.08);

  /* RGB mentah: dipakai glow halaman & fill transparan supaya ikut tema */
  --brand-rgb:    14, 165, 233;
  --brand-2-rgb:  250, 204, 21;
  --glow-primary: 0 0 24px rgba(14, 165, 233, 0.35);
  --glow-accent:  0 0 24px rgba(250, 204, 21, 0.35);

  --text:   #FFFFFF;
  --text-2: #94A3B8;
  --text-3: #6B7F9D;

  --success: #22C55E;
  --warning: #F59E0B;
  --danger:  #EF4444;
}

/* ── IPM — Hijau Pita + Kuning + Merah ── */
[data-theme="ipm"] {
  --bg:         #0F0D08;
  --bg-2:       #1A1610;
  --bg-3:       #242015;

  --card:       rgba(26, 22, 16, 0.4);
  --card-2:     rgba(36, 32, 21, 0.5);
  --card-3:     rgba(52, 46, 30, 0.65);
  --card-solid: #1A1610;

  --border:       #332C1C;
  --border-2:     #615435;
  --border-focus: #059669;

  /* Primary */
  --accent:            #059669;
  --accent-hover:      #05A573;   /* palet: #047857 (lebih gelap) -> label gelap jd 3.3-4.4, gagal AA; dicerahkan */
  --accent-text:       #0F172A;
  --accent-soft:       rgba(5, 150, 105, 0.12);
  --accent-ring:       rgba(5, 150, 105, 0.25);
  --accent-on-surface: #059669;

  /* Secondary */
  --accent-2:            #EAB308;
  --accent-2-hover:      #CA8A04;
  --accent-2-text:       #1C1917;
  --accent-2-soft:       rgba(234, 179, 8, 0.12);
  --accent-2-on-surface: #EAB308;

  /* Tertiary */
  --accent-3:            #DC2626;
  --accent-3-text:       #FFFFFF;
  --accent-3-soft:       rgba(220, 38, 38, 0.12);
  --accent-3-on-surface: #E14444;

  /* Neutral accent (ring / outline) */
  --ring:      #18181B;
  --ring-soft: rgba(24, 24, 27, 0.08);

  /* RGB mentah: dipakai glow halaman & fill transparan supaya ikut tema */
  --brand-rgb:    5, 150, 105;
  --brand-2-rgb:  234, 179, 8;
  --glow-primary: 0 0 24px rgba(5, 150, 105, 0.35);
  --glow-accent:  0 0 24px rgba(234, 179, 8, 0.35);

  --text:   #FFFFFF;
  --text-2: #A8A29E;
  --text-3: #837B76;

  --success: #22C55E;
  --warning: #F59E0B;
  --danger:  #EF4444;
}

/* ── GMKI — Biru Perisai + Cobalt ── */
[data-theme="gmki"] {
  --bg:         #08090F;
  --bg-2:       #121526;
  --bg-3:       #1B1E38;

  --card:       rgba(18, 21, 38, 0.4);
  --card-2:     rgba(27, 30, 56, 0.5);
  --card-3:     rgba(39, 44, 81, 0.65);
  --card-solid: #121526;

  --border:       #25294A;
  --border-2:     #464E8D;
  --border-focus: #1E3A8A;

  /* Primary */
  --accent:            #1E3A8A;
  --accent-hover:      #1E2F73;
  --accent-text:       #FFFFFF;
  --accent-soft:       rgba(30, 58, 138, 0.12);
  --accent-ring:       rgba(30, 58, 138, 0.25);
  --accent-on-surface: #5477DA;

  /* Secondary */
  --accent-2:            #3B5BDB;
  --accent-2-hover:      #2F4BC0;
  --accent-2-text:       #FFFFFF;
  --accent-2-soft:       rgba(59, 91, 219, 0.12);
  --accent-2-on-surface: #5A75E1;

  /* Tertiary */
  --accent-3:            #64748B;
  --accent-3-text:       #FFFFFF;
  --accent-3-soft:       rgba(100, 116, 139, 0.12);
  --accent-3-on-surface: #6C7D96;

  /* Neutral accent (ring / outline) */
  --ring:      #F8FAFC;
  --ring-soft: rgba(248, 250, 252, 0.08);

  /* RGB mentah: dipakai glow halaman & fill transparan supaya ikut tema */
  --brand-rgb:    30, 58, 138;
  --brand-2-rgb:  59, 91, 219;
  --glow-primary: 0 0 24px rgba(30, 58, 138, 0.35);
  --glow-accent:  0 0 24px rgba(59, 91, 219, 0.35);

  --text:   #FFFFFF;
  --text-2: #94A3B8;
  --text-3: #687D9B;

  --success: #22C55E;
  --warning: #F59E0B;
  --danger:  #EF4444;
}

/* ── Golkar — Kuning Beringin + Hijau ── */
[data-theme="golkar"] {
  --bg:         #0F0E08;
  --bg-2:       #1A1810;
  --bg-3:       #242115;

  --card:       rgba(26, 24, 16, 0.4);
  --card-2:     rgba(36, 33, 21, 0.5);
  --card-3:     rgba(52, 48, 30, 0.65);
  --card-solid: #1A1810;

  --border:       #332E1C;
  --border-2:     #615735;
  --border-focus: #EAB308;

  /* Primary */
  --accent:            #EAB308;
  --accent-hover:      #CA8A04;
  --accent-text:       #1C1917;
  --accent-soft:       rgba(234, 179, 8, 0.12);
  --accent-ring:       rgba(234, 179, 8, 0.25);
  --accent-on-surface: #EAB308;

  /* Secondary */
  --accent-2:            #065F46;
  --accent-2-hover:      #064E3B;
  --accent-2-text:       #FFFFFF;
  --accent-2-soft:       rgba(6, 95, 70, 0.12);
  --accent-2-on-surface: #098F6A;

  /* Tertiary */
  --accent-3:            #D97706;
  --accent-3-text:       #1C1917;
  --accent-3-soft:       rgba(217, 119, 6, 0.12);
  --accent-3-on-surface: #D97706;

  /* Neutral accent (ring / outline) */
  --ring:      #18181B;
  --ring-soft: rgba(24, 24, 27, 0.08);

  /* RGB mentah: dipakai glow halaman & fill transparan supaya ikut tema */
  --brand-rgb:    234, 179, 8;
  --brand-2-rgb:  6, 95, 70;
  --glow-primary: 0 0 24px rgba(234, 179, 8, 0.35);
  --glow-accent:  0 0 24px rgba(6, 95, 70, 0.35);

  --text:   #FFFFFF;
  --text-2: #A8A29E;
  --text-3: #847C76;

  --success: #22C55E;
  --warning: #F59E0B;
  --danger:  #EF4444;
}

/* ── SOKSI — Merah Pentagon + Kuning Bintang ── */
[data-theme="soksi"] {
  --bg:         #0D0D0F;
  --bg-2:       #18181B;
  --bg-3:       #232224;

  --card:       rgba(24, 24, 27, 0.4);
  --card-2:     rgba(35, 34, 36, 0.5);
  --card-3:     rgba(51, 49, 52, 0.65);
  --card-solid: #18181B;

  --border:       #2C2A28;
  --border-2:     #54504C;
  --border-focus: #DC2626;

  /* Primary */
  --accent:            #DC2626;
  --accent-hover:      #B91C1C;
  --accent-text:       #FFFFFF;
  --accent-soft:       rgba(220, 38, 38, 0.12);
  --accent-ring:       rgba(220, 38, 38, 0.25);
  --accent-on-surface: #E14545;

  /* Secondary */
  --accent-2:            #EAB308;
  --accent-2-hover:      #CA8A04;
  --accent-2-text:       #1C1917;
  --accent-2-soft:       rgba(234, 179, 8, 0.12);
  --accent-2-on-surface: #EAB308;

  /* Tertiary */
  --accent-3:            #1D4ED8;
  --accent-3-text:       #FFFFFF;
  --accent-3-soft:       rgba(29, 78, 216, 0.12);
  --accent-3-on-surface: #5077E7;

  /* Neutral accent (ring / outline) */
  --ring:      #E4E4E7;
  --ring-soft: rgba(228, 228, 231, 0.08);

  /* RGB mentah: dipakai glow halaman & fill transparan supaya ikut tema */
  --brand-rgb:    220, 38, 38;
  --brand-2-rgb:  234, 179, 8;
  --glow-primary: 0 0 24px rgba(220, 38, 38, 0.35);
  --glow-accent:  0 0 24px rgba(234, 179, 8, 0.35);

  --text:   #FFFFFF;
  --text-2: #A1A1AA;
  --text-3: #7C7C89;

  --success: #22C55E;
  --warning: #F59E0B;
  --danger:  #EF4444;
}

/* .fx-badge-white dipakai sebagai warna tag kata kunci News Feed (lihat
   views/dashboard.html, opsi "Putih" di picker). Warnanya di-hardcode
   #f8fafc (nyaris putih) di definisi .fx-badge-white bawah karena didesain
   untuk kontras di atas kartu gelap (default theme) - persis kebalikan dari
   yang dibutuhkan di light theme (background sudah putih/nyaris putih, jadi
   teks putih di atasnya jadi tidak kelihatan sama sekali). Beda dengan
   fx-badge-success/warning/danger/info yang otomatis berubah gelap di light
   theme lewat CSS variable, fx-badge-white/gray/pink/orange pakai hex
   langsung tanpa varian tema - khusus "white" butuh override eksplisit di
   sini karena dia satu-satunya yang benar-benar terbalik kontrasnya
   (gray/pink/orange cukup kontras di kedua tema, tidak perlu di-override).
   */
[data-theme="light"] .fx-badge-white {
  color: #1e293b;
  border-color: rgba(15, 23, 42, .25);
  background: rgba(15, 23, 42, .06);
}

/* ── Reset ──────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html {
  transition: background-color 0.22s ease, color 0.22s ease;
}

html, body {
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  margin: 0;
}

body {
  font-family: var(--font);
  font-size: 13.5px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--text-2); text-decoration: none; transition: color 0.15s; }
a:hover { color: var(--text); }

/* ── Scrollbar ──────────────────────────────────────────────── */
::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 99px; }
::-webkit-scrollbar-thumb:hover { background: var(--border-active); }

/* ── Brand ──────────────────────────────────────────────────── */
.fx-brand { font-weight: 700; letter-spacing: 0.3px; font-size: 14px; }
.fx-brand .accent { color: var(--accent-on-surface); }

.fx-logo    { width: 68px; height: 68px; object-fit: contain; }
.fx-logo-sm { width: 22px; height: 22px; object-fit: contain; }

/* ── Shell ──────────────────────────────────────────────────── */
.fx-shell { display: flex; min-height: 100vh; }

/* ── Sidebar ────────────────────────────────────────────────── */
.fx-sidebar {
  width: var(--sidebar-w);
  background: rgba(12, 18, 34, 0.7);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0; bottom: 0; left: 0;
  z-index: 1040;
  transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.22s ease;
  overflow: hidden;
}

.fx-sidebar:hover {
  width: var(--sidebar-w-exp);
  box-shadow: var(--shadow-lg);
}

.fx-sidebar-head {
  height: var(--topbar-h);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 24px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  flex: 0 0 auto;
  white-space: nowrap;
}

.fx-sidebar-head .name { 
  font-size: 16px; 
  font-weight: 800; 
  letter-spacing: 0.5px; 
  opacity: 0;
  transition: opacity 0.2s;
}

.fx-sidebar:hover .fx-sidebar-head .name {
  opacity: 1;
}

/* ── Nav ────────────────────────────────────────────────────── */
.fx-nav { padding: 12px 10px; overflow-y: auto; flex: 1 1 auto; }

.fx-nav-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 1.1px;
  color: var(--text-3);
  padding: 0 10px 10px;
  font-weight: 700;
  opacity: 0;
  transition: opacity 0.2s;
  white-space: nowrap;
}

.fx-sidebar:hover .fx-nav-label {
  opacity: 1;
}

.fx-nav-item {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 14px;
  border-radius: var(--radius);
  color: var(--text-2);
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 4px;
  border: 1px solid transparent;
  transition: all 0.2s ease;
  position: relative;
  white-space: nowrap;
}

.fx-nav-item:hover {
  background: rgba(255, 255, 255, 0.05);
  color: var(--text);
}

.fx-nav-item.active {
  background: var(--accent-soft);
  color: var(--accent-hover);
  font-weight: 600;
  border: 1px solid var(--accent-ring);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05), var(--glow-primary);
}

.fx-nav-item.active::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 24px;
  background: var(--accent);
  border-radius: 0 4px 4px 0;
  box-shadow: var(--glow-primary);
}

.fx-nav-item span {
  opacity: 0;
  transition: opacity 0.2s, transform 0.2s;
  transform: translateX(-10px);
}

.fx-sidebar:hover .fx-nav-item span {
  opacity: 1;
  transform: translateX(0);
}

.fx-icon { flex: 0 0 auto; opacity: 0.65; transition: opacity 0.15s; }
.fx-nav-item:hover .fx-icon,
.fx-nav-item.active .fx-icon { opacity: 1; }

/* ── Sidebar footer ─────────────────────────────────────────── */
.fx-sidebar-foot {
  padding: 16px 14px;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  flex: 0 0 auto;
  white-space: nowrap;
  overflow: hidden;
}

/* ── Main ───────────────────────────────────────────────────── */
.fx-main {
  flex: 1 1 auto;
  margin-left: var(--sidebar-w);
  min-width: 0;
  display: flex;
  flex-direction: column;
  transition: margin-left 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* ── Topbar ─────────────────────────────────────────────────── */
.fx-topbar {
  height: var(--topbar-h);
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  background: rgba(12, 18, 34, 0.6);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 0 32px;
  position: sticky;
  top: 0;
  z-index: 1030;
}

/* min-width:0 WAJIB di sini -- flex item defaultnya nggak bisa menyusut di
   bawah lebar konten aslinya (min-width:auto bawaan browser), jadi tanpa ini
   judul panjang (mis. "Riwayat Unduhan & Job") malah numpuk jadi 3 baris dan
   tumpah ke luar/nutupin topbar yang tingginya fixed (--topbar-h), bukannya
   terpotong rapi dengan ellipsis. */
.fx-page-title {
  font-size: 20px; font-weight: 700; margin: 0;
  flex: 1 1 auto; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.fx-content { padding: 22px 26px; flex: 1 1 auto; }
.fx-content > .fx-container { max-width: 1340px; margin: 0 auto; }

/* ── Burger ─────────────────────────────────────────────────── */
.fx-burger {
  display: none;
  background: none;
  border: 1px solid var(--border);
  color: var(--text-2);
  border-radius: var(--radius);
  padding: 6px 9px;
  cursor: pointer;
  transition: all 0.15s;
}
.fx-burger:hover { background: var(--card); color: var(--text); }

.fx-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.6);
  z-index: 1035;
}

@media (max-width: 991px) {
  /* Sidebar mobile = off-canvas drawer beneran, dilepas total dari perilaku
     hover-expand versi desktop (yang butuh :hover, nggak pernah kepicu di
     layar sentuh). Di mobile, sidebar SELALU selebar versi ekspand
     (--sidebar-w-exp) begitu ke-render -- yang berubah cuma posisinya lewat
     `transform: translateX()`, jadi begitu drawer meluncur masuk dia langsung
     penuh dengan label/teks terlihat, bukan animasi dua tahap (lebar
     ngembang + geser) yang kelihatan patah-patah kayak sebelumnya. */
  .fx-sidebar {
    width: var(--sidebar-w-exp);
    transform: translateX(-100%);
    transition: transform 0.25s ease;
    box-shadow: var(--shadow-lg);
  }
  body.fx-sidebar-open .fx-sidebar { transform: translateX(0); }
  body.fx-sidebar-open .fx-backdrop { display: block; }
  .fx-main { margin-left: 0; }
  .fx-burger { display: inline-flex; }
  .fx-content { padding: 16px; }

  .fx-sidebar-head .name,
  .fx-nav-label,
  .fx-nav-item span,
  .fx-user .meta { opacity: 1; }
  .fx-nav-item span { transform: translateX(0); }

  /* Topbar mobile: judul kepotong parah walau cuma "Logbook" (7 huruf).
     Penyebabnya BUKAN .fx-page-title -- itu udah bener min-width:0. Yang
     salah: chip status "WFH 157.85.207.54" di sebelah kanan (#fxIpChip)
     punya white-space:nowrap tanpa max-width, jadi lebar minimalnya = lebar
     penuh teksnya sendiri, nggak pernah mau menyusut. Browser paksa penuhi
     itu dulu, sisa ruang yang jauh lebih kecil baru dikasih ke judul --
     makanya judul pendek pun keptotong. Padding topbar 32px kiri-kanan
     (ukuran desktop) juga kebesaran buat layar 390px. Fix: kecilin padding,
     dan IP-nya (span .fx-chip-ip, lihat layout.html) disembunyikan penuh di
     mobile -- cuma kata status (WFH/WFO/REMOTE) yang tetap kelihatan, jadi
     chip nggak makan banyak ruang sama sekali, nggak perlu ellipsis lagi. */
  .fx-topbar { padding: 0 14px; gap: 10px; }
  .fx-chip-ip { display: none; }
}

/* ── Light mode topbar & sidebar ───────────────────────────── */
[data-theme="light"] .fx-sidebar { background: #fff; }
[data-theme="light"] .fx-topbar  { background: #fff; }
[data-theme="light"] .fx-nav-item.active { color: var(--accent-muted); }

/* ── Avatar & User ──────────────────────────────────────────── */
.fx-avatar {
  width: 34px; height: 34px;
  border-radius: var(--radius);
  background: var(--accent-soft);
  border: 1px solid rgba(232,80,58,0.3);
  color: var(--accent-hover);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 12px;
  flex: 0 0 auto;
}

.fx-user {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--radius);
  background: var(--card);
  border: 1px solid var(--border);
  transition: border-color 0.15s;
}
.fx-user:hover { border-color: var(--border-active); }

.fx-user .meta .n { font-weight: 600; font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fx-user .meta .r { font-size: 11px; color: var(--text-3); font-weight: 500; }

/* ── Card ───────────────────────────────────────────────────── */
.fx-card {
  background: var(--card);
  backdrop-filter: blur(32px);
  -webkit-backdrop-filter: blur(32px);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 24px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05), var(--shadow-sm);
  transition: border-color 0.3s ease, box-shadow 0.3s ease, transform 0.3s ease;
}

.fx-card:hover { 
  border-color: var(--border-active); 
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), var(--shadow-md);
  transform: translateY(-2px);
}
.fx-card-tight { padding: 16px; }

.fx-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 20px;
}

.fx-card-title { font-size: 16px; font-weight: 700; margin: 0; letter-spacing: -0.2px; }
.fx-card-sub { font-size: 13px; color: var(--text-3); margin: 4px 0 0; }

/* ── Module Grid (dashboard "Tools") ───────────────────────────
   Ala app-grid mobile: cuma ikon + nama. Di layar sempit (mobile/tablet)
   dibiarkan wrap jadi beberapa baris seperti biasa (auto-fit). Di desktop
   lebar (>=1200px, lebar konten dashboard penuh) dipaksa muat SEMUA tool
   dalam SATU baris (lihat media query di bawah) -- kalau nama tool-nya
   panjang ("Comment Analysis"), yang boleh nambah adalah TINGGI kartunya
   (nama jadi 2 baris), bukan lebar kartunya melebar/nge-wrap ke baris baru.
   Breakpoint 1200px dipilih karena auto-fit di bawahnya sendiri sudah
   sering menghasilkan 1 baris juga (di lebar konten dashboard biasa
   ~1288px) -- media query ini jaring pengaman kalau suatu saat jumlah
   tool bertambah dan auto-fit mulai wrap duluan di lebar itu. */
.fx-mod-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 8px;
}

@media (min-width: 1200px) {
  .fx-mod-grid {
    /* auto-fit lama tetap bisa wrap ke baris ke-2 kalau jumlah tool
       bertambah di masa depan (mis. 10+ tool) -- grid-auto-flow:column
       dikombinasikan grid-template-rows:1fr disini MEMAKSA jadi 1 baris
       literal berapa pun jumlah tool-nya, kolom otomatis menyempit. */
    grid-auto-flow: column;
    grid-template-columns: none;
    grid-auto-columns: 1fr;
    grid-template-rows: 1fr;
  }
}

.fx-mod-card {
  /* Dulu pakai gradient rgba hardcoded (didesain asumsi background gelap) --
     bikin card ini keliatan abu-abu/beda sendiri dibanding card lain
     (fx-card, fc-kpi-card) begitu ganti ke tema light, karena gradient-nya
     nggak baca variable tema sama sekali. Sekarang pakai var(--card) biar
     seragam persis sama card lain di tiap tema (termasuk solid putih di
     tema light). */
  position: relative;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
  background: var(--card);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 10px 12px;
  color: var(--text-2);
  text-decoration: none;
  transition: transform 0.25s cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 0.25s ease, border-color 0.25s ease;
  overflow: hidden;
}

.fx-mod-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg), var(--glow-primary);
  border-color: var(--border-active);
  color: var(--text);
}

.fx-mod-icon {
  flex: none;
  width: 36px; height: 36px;
  border-radius: 11px;
  background: rgba(var(--brand-rgb), 0.12);
  color: var(--accent-on-surface);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);
  border: 1px solid rgba(var(--brand-rgb), 0.25);
  box-shadow: inset 0 2px 10px rgba(255,255,255,0.05);
}

.fx-mod-card:hover .fx-mod-icon {
  background: linear-gradient(135deg, var(--accent), #00F5D4);
  color: #fff;
  border-color: transparent;
  transform: scale(1.08);
  box-shadow: 0 6px 14px rgba(var(--brand-rgb), 0.4);
}

.fx-mod-card h3 {
  flex: 1 1 auto;
  min-width: 0; /* wajib -- tanpa ini flex item default min-width:auto bikin
                   teks meluber keluar kartu alih-alih wrap saat kolom sempit */
  font-size: 13px;
  font-weight: 700;
  margin: 0;
  color: var(--text);
  letter-spacing: 0px;
  line-height: 1.25;
  /* Sengaja BOLEH wrap ke 2 baris (beda dari versi sebelumnya yang
     nowrap+ellipsis) -- yang wajib satu baris itu TOOL-nya (lihat
     .fx-mod-grid di atas), bukan nama tool-nya. Dibatasi 2 baris (bukan
     bebas) supaya kartu tidak jadi terlalu tinggi kalau ada nama yang
     sangat panjang. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: break-word; /* cuma jaga-jaga kalau ada 1 kata super panjang
                                 yang benar-benar tidak muat -- normalnya wrap
                                 di spasi antar kata, bukan di tengah kata */
}

/* ── Stat ───────────────────────────────────────────────────── */
.fx-stat { display: flex; flex-direction: column; gap: 4px; }
.fx-stat .label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.9px;
  color: var(--text-3);
  font-weight: 600;
}
.fx-stat .value {
  font-size: 36px;
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -1px;
  color: var(--text);
}
.fx-stat .delta { font-size: 12px; color: var(--text-3); }

/* ── Chip / Badge ───────────────────────────────────────────── */
.fx-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--mono);
  font-size: 11px;
  border-radius: 6px;
  padding: 3px 9px;
  color: var(--accent-hover);
  background: var(--accent-soft);
  border: 1px solid rgba(232,80,58,0.3);
  white-space: nowrap;
}

.fx-chip-office  { color: var(--success); background: rgba(34,197,94,.10);  border-color: rgba(34,197,94,.3); }
.fx-chip-off     { color: var(--warning); background: rgba(245,158,11,.10); border-color: rgba(245,158,11,.3); }
.fx-chip-remote  { color: var(--info);    background: rgba(56,189,248,.10);  border-color: rgba(56,189,248,.3); }
.fx-chip-local   { color: var(--text-3);  background: transparent;          border-color: var(--border-2); }
.fx-badge {
  display: inline-block;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.2px;
  border-radius: 5px;
  padding: 2px 7px;
  background: var(--card-3);
  color: var(--text-3);
  border: 1px solid var(--border);
}

.fx-badge-success { color: var(--success); border-color: rgba(34,197,94,.35);  background: rgba(34,197,94,.10); }
.fx-badge-warning { color: var(--warning); border-color: rgba(245,158,11,.35); background: rgba(245,158,11,.10); }
.fx-badge-danger  { color: var(--danger);  border-color: rgba(239,68,68,.35);  background: rgba(239,68,68,.10); }
.fx-badge-info    { color: var(--info);    border-color: rgba(56,189,248,.35);  background: rgba(56,189,248,.10); }
.fx-badge-white   { color: #f8fafc;        border-color: rgba(248,250,252,.35); background: rgba(248,250,252,.10); }
.fx-badge-gray    { color: #94a3b8;        border-color: rgba(148,163,184,.35); background: rgba(148,163,184,.10); }
.fx-badge-pink    { color: #ec4899;        border-color: rgba(236,72,153,.35);  background: rgba(236,72,153,.10); }
.fx-badge-orange  { color: #f97316;        border-color: rgba(249,115,22,.35);  background: rgba(249,115,22,.10); }

/* ── Form ───────────────────────────────────────────────────── */
.fx-label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-3);
  margin-bottom: 6px;
  letter-spacing: 0.2px;
}

.fx-input, .fx-select, .fx-textarea {
  width: 100%;
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius);
  padding: 9px 13px;
  font-size: 13.5px;
  font-family: var(--font);
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.fx-textarea { resize: vertical; min-height: 92px; line-height: 1.55; }

.fx-input:focus, .fx-select:focus, .fx-textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

.fx-input::placeholder, .fx-textarea::placeholder { color: var(--text-3); }

.fx-select {
  appearance: none;
  color-scheme: dark;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2.5'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 13px center;
  padding-right: 36px;
  cursor: pointer;
}


[data-theme="light"] .fx-input,
[data-theme="light"] .fx-select,
[data-theme="light"] .fx-textarea {
  background: #fff;
  border-color: var(--border);
}
[data-theme="light"] .fx-select { color-scheme: light; }

/* ── Button ─────────────────────────────────────────────────── */
.fx-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  border: 1px solid var(--border-2);
  background: var(--card-2);
  color: var(--text-2);
  border-radius: var(--radius);
  padding: 8px 16px;
  font-size: 13px;
  font-weight: 600;
  font-family: var(--font);
  cursor: pointer;
  transition: all 0.15s ease;
  text-decoration: none;
}

.fx-btn:hover {
  background: var(--card-3);
  border-color: var(--border-active);
  color: var(--text);
}
.fx-btn:active { transform: scale(0.96); }
.fx-btn:disabled { opacity: 0.45; cursor: not-allowed; }

.fx-btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-text);
}
.fx-btn-primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  color: var(--accent-text);
  box-shadow: 0 4px 16px var(--accent-ring);
}

.fx-btn-ghost { background: transparent; border-color: transparent; color: var(--text-3); }
.fx-btn-ghost:hover { background: var(--card); border-color: var(--border); color: var(--text-2); }

.fx-btn-danger { color: var(--danger); border-color: rgba(239,68,68,.3); background: rgba(239,68,68,.08); }
.fx-btn-danger:hover { background: rgba(239,68,68,.15); }

.fx-btn-sm { padding: 5px 11px; font-size: 12px; border-radius: 6px; }
.fx-btn-block { width: 100%; }

/* Light mode buttons */
[data-theme="light"] .fx-btn { background: #f8fafc; border-color: var(--border); color: var(--text-2); }
[data-theme="light"] .fx-btn:hover { background: #f1f5f9; color: var(--text); }
[data-theme="light"] .fx-btn-primary { background: var(--accent) !important; border-color: var(--accent) !important; color: var(--accent-text) !important; }
[data-theme="light"] .fx-btn-primary:hover { background: var(--accent-hover) !important; border-color: var(--accent-hover) !important; color: var(--accent-text) !important; }
[data-theme="light"] .fx-btn-ghost { background: transparent; border-color: transparent; }
[data-theme="light"] .fx-btn-ghost:hover { background: #f8fafc; border-color: var(--border); }

/* ── Table ──────────────────────────────────────────────────── */
.fx-table-wrap { overflow-x: auto; border-radius: var(--radius-lg); border: 1px solid var(--border); }

.fx-table { width: 100%; border-collapse: collapse; font-size: 13px; }

.fx-table th {
  text-align: left;
  padding: 10px 14px;
  background: var(--card-2);
  color: var(--text-3);
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  font-weight: 700;
  white-space: nowrap;
  border-bottom: 1px solid var(--border);
}

.fx-table td { padding: 11px 14px; border-bottom: 1px solid var(--border); vertical-align: top; color: var(--text-2); }
.fx-table tbody tr:last-child td { border-bottom: none; }
.fx-table tbody tr:hover { background: var(--card-2); }

/* ── Text clamp ─────────────────────────────────────────────────
   Buat teks panjang di sel tabel (mis. kolom "Pekerjaan" di Rekap Tim /
   Riwayat Logbook Saya) supaya nggak ditampilkan mentah-mentah tanpa batas
   -- 1 entri logbook yang panjang bisa bikin 1 baris tabel makan seluruh
   layar. Dibatasi 3 baris dulu, ada tombol buat lihat penuh (lihat
   fx-clamp-toggle di shell.js). */
.fx-clamp-3 {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.fx-clamp-3.fx-clamp-expanded {
  display: block;
  -webkit-line-clamp: unset;
  overflow: visible;
}
.fx-clamp-toggle {
  display: inline-block;
  margin-top: 4px;
  font-size: 11px;
  font-weight: 700;
  color: var(--accent-on-surface);
  cursor: pointer;
  user-select: none;
}
.fx-clamp-toggle:hover { text-decoration: underline; }

/* ── Alert ──────────────────────────────────────────────────── */
.fx-alert {
  border-radius: var(--radius);
  padding: 11px 14px;
  font-size: 13px;
  border: 1px solid var(--border);
  background: var(--card-2);
  margin-bottom: 14px;
  line-height: 1.5;
}

.fx-alert-danger  { color: #fca5a5; background: rgba(239,68,68,.10);   border-color: rgba(239,68,68,.30); }
.fx-alert-success { color: #86efac; background: rgba(34,197,94,.10);   border-color: rgba(34,197,94,.30); }
.fx-alert-warning { color: #fde68a; background: rgba(245,158,11,.10);  border-color: rgba(245,158,11,.30); }
/* ── Progress ───────────────────────────────────────────────── */
.fx-progress {
  height: 6px;
  background: var(--card-3);
  border-radius: 999px;
  overflow: hidden;
}

.fx-progress > div {
  height: 100%;
  background: linear-gradient(90deg, var(--accent), var(--accent-hover));
  width: 0%;
  transition: width 0.3s ease;
}

/* ── Console ────────────────────────────────────────────────── */
.fx-console {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.65;
  max-height: 280px;
  overflow-y: auto;
  color: var(--text-3);
  white-space: pre-wrap;
  word-break: break-word;
}

.fx-console .t-ERROR { color: var(--danger); }
.fx-console .t-WARN  { color: var(--warning); }
.fx-console .t-OK    { color: var(--success); }
.fx-console .t-tag   { color: var(--accent-hover); }

/* ── Grid ───────────────────────────────────────────────────── */
.fx-grid   { display: grid; gap: 16px; }
.fx-grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.fx-grid-3 { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.fx-grid-4 { grid-template-columns: repeat(auto-fit, minmax(195px, 1fr)); }

.fx-row { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; }
.fx-row > .grow { flex: 1 1 220px; min-width: 0; }

/* ── Toolbar action button (Unduh Video, Analisis Komentar, Cari Berita,
   Social Network Analysis) ────────────────────────────────────
   Dipakai buat div pembungkus tombol aksi utama ("CEK VIDEO",
   "ANALISIS SEKARANG", "MULAI PENCARIAN", "ANALISIS") di sebelah kanan
   field input/select, di dalam .fx-row yang align-items:flex-end.
   Sebelumnya tombol itu cuma div polos tanpa label -- sejajarnya sama
   input di sampingnya CUMA KEBETULAN (tinggi label field ~27px vs sisa
   ruang buat tombol dari flex-end ~29px, dua angka beda tipis yang di
   Linux/Chromium keliatan mepet tapi nggak dijamin sama persis di semua
   browser/OS -- terutama <select> native yang tinggi render-nya bisa
   beda dikit di Windows/Chrome dibanding di sini). Sekarang dikasih
   spacer label TAK KELIHATAN (.fx-label-spacer, visibility:hidden) yang
   tingginya persis sama kaya label asli, plus tombolnya dikasih tinggi
   fix SAMA PERSIS kaya input/select di sampingnya (lihat height:54px
   yang ditambahkan ke masing-masing field di views/vd.html, csa.html,
   ns.html, sna.html) -- jadi sejajar & seukurannya dijamin oleh CSS,
   bukan kebetulan lagi.
   Tinggi 54px (naik dari 47px) + padding tombol lebih lega dipilih atas
   permintaan user langsung ("tombolnya kekecilan, mau dibikin lebih
   besar") -- baris input/select di sampingnya ikut dinaikkan ke 54px
   juga (bukan cuma tombolnya sendiri) supaya tetap sejajar persis,
   bukan tombol doang yang membesar sendirian lalu nabrak alignment. */
.fx-toolbar-action { display: flex; flex-direction: column; }
.fx-toolbar-action .fx-label-spacer {
  visibility: hidden;
  display: block;
  margin-bottom: 8px;
  font-size: 11px;
  font-weight: 800;
  line-height: 1.3;
}
.fx-toolbar-action .fx-btn { height: 54px; }

.fx-stack { display: flex; flex-direction: column; gap: 16px; }

/* ── Utility ────────────────────────────────────────────────── */
.fx-muted    { color: var(--text-3); }
.fx-small    { font-size: 12px; }
.fx-mono     { font-family: var(--mono); }
.fx-hidden   { display: none !important; }
.fx-center   { text-align: center; }
.fx-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fx-mt       { margin-top: 16px; }
.fx-mb       { margin-bottom: 16px; }
@keyframes pulseGlow {
  0% { opacity: 0.5; transform: scale(1) translate(-50%, -50%); }
  50% { opacity: 0.8; transform: scale(1.1) translate(-45%, -45%); }
  100% { opacity: 0.5; transform: scale(1) translate(-50%, -50%); }
}

.fx-glow-red {
  position: absolute;
  width: 300px;
  height: 300px;
  background: radial-gradient(circle, rgba(var(--brand-rgb), 0.25) 0%, rgba(var(--brand-rgb), 0) 70%);
  border-radius: 50%;
  pointer-events: none;
  z-index: 0;
  transform: translate(-50%, -50%);
  animation: pulseGlow 12s ease-in-out infinite alternate;
}

.fx-glow-blue {
  position: absolute;
  width: 300px;
  height: 300px;
  background: radial-gradient(circle, rgba(var(--brand-2-rgb), 0.25) 0%, rgba(var(--brand-2-rgb), 0) 70%);
  border-radius: 50%;
  pointer-events: none;
  z-index: 0;
  transform: translate(-50%, -50%);
  animation: pulseGlow 14s ease-in-out infinite alternate-reverse;
}

.fx-empty {
  text-align: center;
  color: var(--text-3);
  padding: 36px 18px;
  font-size: 13px;
}

/* ── Auth page ──────────────────────────────────────────────── */
.fx-auth {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background:
    radial-gradient(ellipse 70% 50% at 50% -10%, rgba(232, 80, 58, 0.12), transparent),
    var(--bg);
}

.fx-auth-card { width: 100%; max-width: 420px; }

/* ── Tabs ───────────────────────────────────────────────────── */
/* Dibikin sama persis gaya pill .fc-tab-group yang dipakai di Board/Logbook
   (1 kontainer bulat dengan background, tab di dalamnya nggak punya border
   sendiri-sendiri) -- sebelumnya .fx-tabs/.fx-tab (cuma dipakai di halaman
   Admin) tampilannya beda sendiri: tiap tombol punya border bulat sendiri
   yang lepas-lepas, bukan 1 kesatuan pill. Class name TETAP fx-tabs/fx-tab
   (bukan diganti fc-tab-group/fc-tab) karena helper JS `fxTabs()` di
   shell.js hardcode nyari `.fx-tab` -- ganti nama class bakal matiin klik
   tab-nya. Cukup CSS-nya yang disamain. */
.fx-tabs {
  display: inline-flex;
  background: var(--bg-3);
  border-radius: 20px;
  padding: 4px;
  margin-bottom: 20px;
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.fx-tabs::-webkit-scrollbar { display: none; }

.fx-tab {
  padding: 6px 16px;
  border-radius: 16px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-3);
  background: transparent;
  border: none;
  cursor: pointer;
  transition: all 0.2s;
  white-space: nowrap;
  flex-shrink: 0;
}

.fx-tab.active {
  background: var(--accent);
  color: #fff;
}

/* ── Inline Segmented Tabs (Tab Group) ──────────────────────── */
.fx-segmented-tabs {
  display: inline-flex;
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--card-2);
}

.fx-segmented-tabs .fx-btn {
  border: none;
  border-radius: 0;
  background: transparent;
  color: var(--text-2);
}

.fx-segmented-tabs .fx-btn.fx-btn-primary {
  background: var(--accent) !important;
  color: #fff !important;
}

/* ── Spinner ────────────────────────────────────────────────── */
.fx-spinner {
  width: 15px; height: 15px;
  border: 2px solid rgba(255,255,255,0.15);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: fx-spin 0.65s linear infinite;
  display: inline-block;
}

@keyframes fx-spin { to { transform: rotate(360deg); } }

/* ── Toast ──────────────────────────────────────────────────── */
#fxToast {
  position: fixed;
  right: 18px; bottom: 18px;
  z-index: 10000;
  display: flex;
  flex-direction: column;
  gap: 9px;
  max-width: min(380px, calc(100vw - 36px));
}

.fx-toast {
  background: var(--card);
  border: 1px solid var(--border-2);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  padding: 11px 15px;
  font-size: 13px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.35);
  animation: fx-slide-up 0.2s ease;
  color: var(--text-2);
}

.fx-toast.ok  { border-left-color: var(--success); }
.fx-toast.err { border-left-color: var(--danger); }

@keyframes fx-slide-up { from { opacity: 0; transform: translateY(8px); } }

/* Tombol toggle tema cepat di topbar (matahari/bulan) sudah dihapus --
   Pengaturan > Personalisasi sudah ada pemilih tema lengkap (5 pilihan:
   dark/light/midnight/forest/sunset), jadi tombol ini di topbar cuma
   duplikat sekaligus makan ruang topbar yang sudah sempit di mobile. CSS-nya
   dibuang juga di sini supaya nggak jadi dead code. */

/* --- NEW PREMIUM UI ADDITIONS --- */
.fc-card-premium {
  background: var(--card);
  backdrop-filter: blur(32px);
  -webkit-backdrop-filter: blur(32px);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  overflow: hidden;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05), var(--shadow-sm);
  transition: border-color 0.3s ease, box-shadow 0.3s ease, transform 0.3s ease;
}
.fc-card-premium:hover {
  border-color: var(--border-active);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), var(--shadow-lg);
  transform: translateY(-4px);
}
.fc-header-title {
  font-size: 24px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 2px;
  text-align: center;
  margin-bottom: 4px;
  color: var(--text);
}
.fc-header-sub {
  font-size: 11px;
  letter-spacing: 1.5px;
  text-align: center;
  color: var(--text-3);
  text-transform: uppercase;
  margin-bottom: 24px;
}
.fc-gauge-wrap {
  position: relative;
  width: 80px;
  height: 40px;
  overflow: hidden;
  margin: 0 auto;
}
.fc-gauge-bg, .fc-gauge-fill {
  position: absolute;
  top: 0; left: 0;
  width: 80px; height: 80px;
  border-radius: 50%;
  border: 8px solid var(--border-2);
  box-sizing: border-box;
}
.fc-gauge-fill {
  border-color: #f59e0b; /* Orange for health */
  border-bottom-color: transparent;
  border-right-color: transparent;
  transform: rotate(-45deg); /* Base rotation */
}
.fc-table-premium {
  width: 100%;
  border-collapse: collapse;
}
.fc-table-premium th, .fc-table-premium td {
  padding: 12px 16px;
  text-align: center;
  border-bottom: 1px solid var(--border);
  border-right: 1px solid var(--border);
}
.fc-table-premium th:last-child, .fc-table-premium td:last-child {
  border-right: none;
}
.fc-table-premium th {
  background: var(--bg-3);
  color: var(--text-3);
  font-size: 12px;
  font-weight: 600;
}
.fc-table-premium td {
  font-family: 'JetBrains Mono', Consolas, monospace;
  font-size: 13px;
  color: var(--text-2);
}
.fc-post-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.fc-post-thumb {
  position: relative;
  border-radius: 6px;
  overflow: hidden;
  aspect-ratio: 1;
  background: var(--bg);
}
.fc-post-thumb img { width: 100%; height: 100%; object-fit: cover; opacity: 0.8; }
.fc-post-overlay {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  padding: 8px;
  background: linear-gradient(transparent, rgba(0,0,0,0.8));
  font-size: 10px;
  color: #fff;
  display: flex;
  justify-content: space-between;
}
/* max-width + overflow-x:auto -- .fc-tab-group dipakai buat tab pill (mis.
   "Isi Logbook/Riwayat Saya/Rekap Tim/Kelola Instruksi", "Semua Akun/
   Leaderboard/Alerts/Riwayat Fetch") yang sengaja dirender sebagai satu
   pill utuh, bukan tombol lepas -- kalau di-wrap ke baris baru bentuk
   pill-nya bakal patah/aneh. Sebelum ini nggak ada overflow handling sama
   sekali, jadi di layar sempit tab yang nggak muat (mis. "Kelola
   Instruksi") kepotong abis di luar layar, nggak kelihatan & nggak bisa
   diklik. Sekarang boleh discroll horizontal (swipe) tanpa merusak bentuk
   pill-nya, scrollbar-nya disembunyikan biar tetep rapi.*/
.fc-tab-group {
  display: inline-flex;
  background: var(--bg-3);
  border-radius: 20px;
  padding: 4px;
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.fc-tab-group::-webkit-scrollbar { display: none; }
/* Kelas ini di-toggle dari shell.js (cuma kalau isinya beneran melebihi
   lebar kontainer) -- indikator sederhana biar user tau pill ini bisa
   di-swipe, bukan cuma mentok diam di tempat kalau tab terakhir kepotong. */
.fc-tab-group--scrollable {
  box-shadow: inset -14px 0 10px -10px rgba(0, 0, 0, 0.35);
}
[data-theme="light"] .fc-tab-group--scrollable {
  box-shadow: inset -14px 0 10px -10px rgba(0, 0, 0, 0.15);
}
.fc-tab {
  padding: 6px 16px;
  border-radius: 16px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-3);
  cursor: pointer;
  flex-shrink: 0;
  white-space: nowrap;
}
.fc-tab.active {
  background: var(--accent);
  /* Dulu hardcode #fff -- di tema dengan aksen terang (Golkar/kuning, HMI,
     IPM) teks putih di atas kuning nyaris tidak terbaca (kontras rendah).
     --accent-text sudah didefinisikan per-tema persis untuk kasus ini
     (dipakai fx-btn-primary sejak v1.18.1) -- Golkar set ini ke warna
     gelap (#1C1917), tema lain yang aksennya gelap tetap #fff. */
  color: var(--accent-text);
}

/* --- DASHBOARD PREMIUM UI ADDITIONS --- */
.fc-kpi-card {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 24px;
  border-radius: var(--radius-xl);
  position: relative;
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--card);
  backdrop-filter: blur(32px);
  -webkit-backdrop-filter: blur(32px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05), var(--shadow-sm);
  transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 0.3s ease, border-color 0.3s ease;
}
.fc-kpi-card:hover {
  transform: translateY(-6px) scale(1.02);
  border-color: var(--border-active);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), var(--shadow-lg);
}
.fc-kpi-card .val { font-size: 32px; font-weight: 800; color: var(--text); z-index: 1; letter-spacing: -0.5px; }
.fc-kpi-card .lbl { font-size: 13px; font-weight: 700; color: var(--text-3); text-transform: uppercase; letter-spacing: 1px; z-index: 1; margin-bottom: 6px; }
.fc-kpi-card .sub { font-size: 12px; font-weight: 500; color: var(--text-3); z-index: 1; margin-top: 6px; }
.fc-kpi-card .sub .trend { font-weight: 700; color: var(--text-2); }
.fc-kpi-card .icon-bg {
  position: absolute;
  right: -10px;
  bottom: -10px;
  opacity: 0.15;
  width: 100px;
  height: 100px;
  transform: rotate(-10deg);
  z-index: 0;
  transition: transform 0.5s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.5s ease;
}

.fc-kpi-card:hover .icon-bg {
  transform: rotate(0deg) scale(1.1);
  opacity: 0.25;
}

/* Kpi Variants */
.fc-kpi-blue { border-bottom: 2px solid var(--info); }
.fc-kpi-blue .icon-bg { color: var(--info); }
.fc-kpi-purple { border-bottom: 2px solid #8338ec; }
.fc-kpi-purple .icon-bg { color: #8338ec; }
.fc-kpi-green { border-bottom: 2px solid var(--success); }
.fc-kpi-green .icon-bg { color: var(--success); }
.fc-kpi-orange { border-bottom: 2px solid var(--accent); }
.fc-kpi-orange .icon-bg { color: var(--accent-on-surface); }
.fc-kpi-slate { border-bottom: 2px solid var(--border-active); }
.fc-kpi-slate .icon-bg { color: var(--text-2); }

[data-theme="light"] .fc-kpi-blue, [data-theme="light"] .fc-kpi-purple, [data-theme="light"] .fc-kpi-green, [data-theme="light"] .fc-kpi-orange {
  background: #fff;
  border-color: var(--border-2);
}

/* --- TIMELINE --- */
.fc-timeline {
  display: flex;
  flex-direction: column;
  padding: 8px 12px;
}
.fc-timeline-item {
  display: flex;
  gap: 16px;
  position: relative;
  padding-bottom: 24px;
}
.fc-timeline-item:last-child { padding-bottom: 0; }
.fc-timeline-item::before {
  content: '';
  position: absolute;
  left: 64px; 
  top: 6px;
  bottom: -6px;
  width: 1px;
  background: var(--border-2);
}
.fc-timeline-item:last-child::before { display: none; }

.fc-timeline-time {
  flex: 0 0 45px;
  font-size: 11.5px;
  color: var(--text-3);
  font-weight: 600;
  text-align: right;
  padding-top: 2px;
}
.fc-timeline-dot {
  flex: 0 0 10px;
  height: 10px;
  width: 10px;
  border-radius: 50%;
  margin-top: 6px;
  z-index: 1;
  background: var(--text-3);
  box-shadow: 0 0 0 4px var(--card);
}
/* min-width:0 WAJIB -- tanpa ini flex item nggak bisa menyusut di bawah
   lebar konten aslinya. Detail aktivitas sering berisi URL panjang tanpa
   spasi (link Instagram/TikTok hasil download) yang nggak ada titik potong
   alami, jadi tanpa min-width:0 + overflow-wrap di .fc-timeline-desc URL itu
   maksa .fc-timeline-content (dan ujung-ujungnya seluruh card/halaman) jadi
   lebih lebar dari viewport -- itu yang bikin card "Aktivitas terakhir kamu"
   kelihatan overhang/geser ke kiri di HP. */
.fc-timeline-content {
  flex: 1;
  min-width: 0;
}
.fc-timeline-title {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 2px;
  display: flex;
  gap: 8px;
  align-items: center;
}
.fc-timeline-desc {
  font-size: 12px;
  color: var(--text-2);
  line-height: 1.5;
  overflow-wrap: anywhere;
}

/* ── Riwayat Unduhan & Job (history.html) ──────────────────────
   Layout dipindah dari inline style ke sini supaya bisa dibikin beda di
   mobile -- di layar sempit, badge+judul+tombol yang tadinya dipaksa
   sejajar 1 baris (align-items:center) kelihatan bertumpuk/sempit karena
   judul kepotong ellipsis dan tombol "Lihat/Unduh" ketiban sisa ruang yang
   udah kecil. Di mobile, konten & tombol ditumpuk vertikal (lebih lapang,
   judul nggak perlu terlalu kepotong) alih-alih dipaksa 1 baris. */
.fx-history-item {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px;
  background: var(--bg-2);
  border: 1px solid var(--border-2);
  border-radius: 12px;
  transition: transform 0.2s, box-shadow 0.2s;
  /* 2026-08-28: jarak antar item riwayat (sebelumnya menempel) */
  margin-bottom: 22px;
}
.fx-history-item:last-child { margin-bottom: 0; }
.fx-history-item-bar { width: 4px; height: 32px; border-radius: 4px; flex-shrink: 0; }
.fx-history-item-body { flex: 1; min-width: 0; }
.fx-history-item-action { flex: 0 0 auto; }

@media (max-width: 600px) {
  .fx-history-item { flex-wrap: wrap; row-gap: 14px; padding: 16px; }
  .fx-history-item-bar { display: none; } /* warna badge di body udah cukup nunjukin modulnya */
  .fx-history-item-body { flex-basis: 100%; }
  /* 2026-08-28: beri napas antara teks riwayat & tombol aksi di mobile */
  .fx-history-item-action { flex-basis: 100%; margin-top: 10px; }
  .fx-history-item-action .fx-btn {
    width: 100%;
    justify-content: center;
    white-space: normal;
    line-height: 1.4;
    padding: 9px 12px;
  }
  .fx-history-item-body > div:first-child { margin-bottom: 6px; }
}

/* Dot colors */
.dot-success { background: var(--success); }
.dot-warning { background: var(--warning); }
.dot-danger { background: var(--danger); }
.dot-info { background: var(--info); }
.dot-default { background: var(--text-3); }

/* --- QUICK ACTION --- */
.fc-quick-action {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: rgba(var(--brand-rgb), 0.12);
  color: var(--accent-on-surface);
  border: 1px solid rgba(var(--brand-rgb), 0.3);
  padding: 8px 20px;
  border-radius: 99px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(var(--brand-rgb), 0.15);
  transition: all 0.2s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.fc-quick-action:hover { 
  transform: translateY(-2px);
  background: rgba(var(--brand-rgb), 0.22);
  border-color: rgba(var(--brand-rgb), 0.5);
  box-shadow: var(--glow-primary); 
}

/* ============================================================
   Chat internal (widget mengambang, muncul di semua halaman)
   ============================================================ */
/* env(safe-area-inset-*) -- jaga-jaga buat browser mobile yang area bawah
   layarnya ketutupan home-indicator/toolbar (notch, gesture bar iPhone,
   dsb.) supaya FAB chat ini nggak collision sama itu. Elemen ini SUDAH
   position:fixed dengan z-index tinggi & tanpa ancestor ber-transform (dicek
   manual), jadi harusnya selalu nempel di posisi ini dari awal load, nggak
   perlu scroll dulu -- kalau di HP tertentu masih kelihatan "nunggu scroll",
   kemungkinan itu perilaku address bar dinamis browser mobile itu sendiri
   (bukan sesuatu yang CSS bisa kontrol penuh), bukan salah kode di sini. */
.fx-chat {
  position: fixed;
  right: max(20px, env(safe-area-inset-right));
  bottom: max(20px, env(safe-area-inset-bottom));
  z-index: 9500;
}

/* PENTING: beberapa elemen widget (panel, body pesan, form) di-set
   `display: flex` secara eksplisit di bawah supaya layoutnya flex-column.
   Tanpa override ini, atribut `hidden` yang dipasang lewat JS TIDAK ngefek
   sama sekali - aturan `[hidden]{display:none}` bawaan browser kalah sama
   `display: flex` dari class kita sendiri (author style selalu menang atas
   UA stylesheet meski specificity-nya setara). Akibatnya panel/area
   pesan/form yang seharusnya disembunyikan (mis. saat pindah ke tab
   Personal sebelum pilih orang) tetap kelihatan & tetap bisa dipakai. */
#fxChat [hidden] { display: none !important; }

.fx-chat-toggle {
  width: 52px; height: 52px; border-radius: 50%;
  background: var(--accent); color: #fff; border: none;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; box-shadow: 0 8px 20px rgba(0,0,0,.35);
  transition: transform .15s, background .15s;
  position: relative;
}
.fx-chat-toggle:hover { background: var(--accent-hover); transform: translateY(-2px); }

.fx-chat-badge {
  position: absolute; top: -4px; right: -4px;
  background: var(--danger); color: #fff;
  font-size: 11px; font-weight: 800; line-height: 1;
  min-width: 20px; height: 20px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  padding: 0 5px; border: 2px solid var(--bg);
}

/* Seluruh warna widget chat di bawah ini SENGAJA pakai CSS variable tema
   (bukan hex langsung seperti #212121/#8774e1 dari desain "Telegram dark"
   sebelumnya) supaya ikut berubah saat user toggle light/dark theme -
   sebelumnya hardcode, jadi chat tetap gelap ala Telegram walau app-nya
   sudah di light theme (teks putih di atas bubble gelap yang seharusnya
   sudah terang, dst). Aksen ungu Telegram (#8774e1) diganti var(--accent)
   (biru, warna brand asli app) supaya konsisten dengan tombol/badge lain,
   bukan sekadar supaya kontras. */
.fx-chat-panel.telegram-style {
  position: absolute; right: 0; bottom: 66px;
  width: 760px; max-width: calc(100vw - 32px);
  height: 540px; max-height: calc(100vh - 120px);
  background: var(--card-solid); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: 0 20px 50px rgba(0,0,0,.5);
  display: flex; flex-direction: row; overflow: hidden;
  /* Resize dari pojok kiri atas - panel muncul dari kanan bawah */
  resize: none;
  transform-origin: bottom right;
}

/* Kiri: Sidebar */
.fx-chat-sidebar {
  width: 280px; border-right: 1px solid var(--border);
  display: flex; flex-direction: column; background: var(--card-2);
  flex-shrink: 0; position: relative;
}
.fx-chat-head {
  padding: 12px; border-bottom: 1px solid var(--border);
}
.fx-chat-tab {
  background: var(--card-3); border: none; color: var(--text-3);
  font-size: 12px; font-weight: 600; cursor: pointer;
  padding: 8px 12px; border-radius: 16px; flex: 1; transition: 0.2s;
}
.fx-chat-tab.active { background: var(--accent); color: #fff; }
.fx-chat-users { flex: 1; overflow-y: auto; padding: 8px; }
.fx-chat-user-row { display: flex; align-items: center; gap: 10px; padding: 10px; border-radius: 8px; cursor: pointer; transition: background 0.15s; }
.fx-chat-user-row:hover { background: var(--card-3); }
.fx-chat-user-row.active { background: var(--accent); }
.fx-chat-user-row .n { font-size: 13px; font-weight: 400; color: var(--text-3); flex: 1; }
.fx-chat-user-row .r { font-size: 11px; color: var(--text-3); opacity: 0.7; }
.fx-chat-user-row.online .n { font-weight: 600; color: var(--text); }
.fx-chat-user-row.online .r { opacity: 1; }
.fx-chat-user-row.active .n, .fx-chat-user-row.active .r { color: #fff; }

/* Baris kontak Faline AI (virtual, di atas daftar user) */
.fx-chat-user-row.ai { border: 1px solid rgba(var(--brand-rgb), 0.28); background: rgba(var(--brand-rgb), 0.07); margin-bottom: 6px; }
.fx-chat-user-row.ai:hover { background: rgba(var(--brand-rgb), 0.14); }
.fx-chat-user-row.ai.active { background: var(--accent); border-color: var(--accent); }
.fx-chat-user-row.ai.busy { opacity: 0.7; }
.fx-chat-user-row.ai .r { color: var(--accent); font-weight: 700; opacity: 1; }
.fx-chat-user-row.ai.active .r { color: #fff; }
.fx-ai-avatar {
  width: 24px; height: 24px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--brand, #e63946), var(--accent, #b3123a));
  color: #fff;
}

/* FAB Pensil */
/* Online dot */
.fx-online-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-3); flex-shrink: 0; }
.fx-online-dot.on { background: #4cd964; box-shadow: 0 0 0 2px var(--card-2); }
.fx-chat-user-row.active .fx-online-dot.on { box-shadow: none; }

/* Kanan: Main Chat */
.fx-chat-main {
  flex: 1; display: flex; flex-direction: column; position: relative; min-width: 0;
}
.fx-chat-main-bg {
  position: absolute; top: 0; left: 0; right: 0; bottom: 0;
  opacity: 0.05; background-image: radial-gradient(var(--text) 1px, transparent 1px);
  background-size: 20px 20px; pointer-events: none;
}

.fx-chat-main-head {
  padding: 12px 16px; border-bottom: 1px solid var(--border);
  background: var(--card-2); display: flex; align-items: center; justify-content: space-between; z-index: 10;
}
.fx-chat-thread-title { display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 700; color: var(--text); }
.fx-chat-close { background: none; border: none; color: var(--text-3); font-size: 22px; cursor: pointer; line-height: 1; }
.fx-chat-close:hover { color: var(--text); }

.fx-chat-body { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 16px; z-index: 5; scroll-behavior: smooth; min-width: 0; min-height: 0; }
.fx-chat-messages { display: flex; flex-direction: column; gap: 8px; }
.fx-chat-empty { text-align: center; color: var(--text-3); font-size: 13px; margin: auto; padding: 20px; }

.fx-msg { max-width: 75%; display: flex; flex-direction: column; align-self: flex-start; }
.fx-msg.me { align-self: flex-end; }
.fx-msg-author { font-size: 12px; font-weight: 600; color: var(--accent-on-surface); margin-bottom: 2px; }
.fx-msg.me .fx-msg-author { display: none; }
.fx-msg-bubble {
  background: var(--card-3); color: var(--text); padding: 8px 12px; border-radius: 12px 12px 12px 4px; font-size: 13px; line-height: 1.4; word-break: break-word; box-shadow: 0 1px 2px rgba(0,0,0,0.2);
}
.fx-msg.me .fx-msg-bubble { background: var(--accent); color: #fff; border-radius: 12px 12px 4px 12px; }

/* Bubble Faline AI — aksen berbeda dari bubble user lain */
.fx-msg.ai { max-width: 85%; }
.fx-msg.ai .fx-msg-bubble {
  background: linear-gradient(135deg, rgba(var(--brand-rgb), 0.14), rgba(var(--accent-rgb, 179, 18, 58), 0.08));
  border: 1px solid rgba(var(--brand-rgb), 0.25);
  border-radius: 12px 12px 12px 4px;
  font-size: 13px; line-height: 1.5;
}
.fx-msg.ai .fx-msg-author { color: var(--accent); }
.fx-msg-bubble.ai code {
  background: rgba(128,128,128,0.2); border-radius: 4px; padding: 1px 5px; font-size: 12px;
  font-family: ui-monospace, 'Cascadia Code', Consolas, monospace;
}
.fx-msg-bubble.ai strong { font-weight: 700; }
.fx-msg-bubble.ai em { font-style: italic; }
.fx-msg-bubble.ai a { color: var(--accent); text-decoration: underline; }
.fx-msg-bubble.ai { white-space: normal; }
.fx-msg-bubble.ai br { content: ''; }

/* Caret berkedip saat Faline mengetik (streaming) */
.fx-ai-caret {
  display: inline-block; width: 7px; height: 14px; margin-left: 2px; vertical-align: text-bottom;
  background: var(--accent); border-radius: 1px;
  animation: fx-caret-blink 0.9s step-end infinite;
}
@keyframes fx-caret-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
.fx-msg-time { font-size: 10px; color: var(--text-3); margin-top: 4px; text-align: left; }
.fx-msg.me .fx-msg-time { text-align: right; }

.fx-msg { position: relative; }
.fx-reply-block { background: rgba(128,128,128,0.15); border-left: 3px solid var(--accent); padding: 5px 10px; border-radius: 4px 8px 8px 4px; margin-bottom: 6px; font-size: 12px; overflow: hidden; }
.fx-msg.me .fx-reply-block { background: rgba(255,255,255,0.2); border-left-color: rgba(255,255,255,0.7); }
.fx-reply-author { font-weight: 600; margin-bottom: 2px; color: var(--accent-on-surface); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fx-msg.me .fx-reply-author { color: #fff; }
.fx-reply-text { opacity: 0.85; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; max-width: 260px; line-height: 1.4; white-space: pre-wrap; word-break: break-word; }
.fx-msg-actions { position: absolute; top: 50%; transform: translateY(-50%); opacity: 0; transition: opacity 0.2s; display: flex; gap: 4px; }
.fx-msg:hover .fx-msg-actions { opacity: 1; }
.fx-msg:not(.me) .fx-msg-actions { right: -36px; }
.fx-msg.me .fx-msg-actions { left: -36px; }
.fx-msg-action-btn { background: var(--card-3); border: 1px solid var(--border); color: var(--text-3); border-radius: 50%; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: 0 1px 2px rgba(0,0,0,0.1); padding: 0; }
.fx-msg-action-btn:hover { color: var(--accent-on-surface); }

/* Form */
.fx-chat-form {
  display: flex; align-items: center; gap: 10px; padding: 12px 16px; z-index: 10;
}
.fx-chat-input-wrapper {
  flex: 1; display: flex; align-items: center; background: var(--card-3); border-radius: 20px; padding: 4px 12px;
}
.fx-chat-input-wrapper input, .fx-chat-input-wrapper textarea {
  flex: 1; background: transparent; border: none; color: var(--text); padding: 8px 8px; font-size: 14px; font-family: var(--font);
}
.fx-chat-input-wrapper textarea { resize: none; overflow-y: auto; max-height: 80px; min-height: 20px; line-height: 1.4; }
.fx-chat-input-wrapper input:focus, .fx-chat-input-wrapper textarea:focus { outline: none; }
.fx-chat-icon-btn { background: none; border: none; color: var(--text-3); cursor: pointer; padding: 4px; display: flex; align-items: center; }
.fx-chat-icon-btn:hover { color: var(--text); }
@media (max-width: 600px) {
  .fx-chat {
    right: max(12px, env(safe-area-inset-right));
    bottom: max(12px, env(safe-area-inset-bottom));
  }
  .fx-chat-panel.telegram-style { flex-direction: column; width: calc(100vw - 24px); height: calc(100vh - 80px); }
  .fx-chat-sidebar { width: 100%; flex: 1; }
  .fx-chat-main { display: none; flex: 1; }
  .fx-chat-panel.telegram-style.show-chat .fx-chat-sidebar { display: none; }
  .fx-chat-panel.telegram-style.show-chat .fx-chat-main { display: flex; }
}
.fc-quick-action svg { width: 14px; height: 14px; }

/* ===================== Modul SNA — panel insight ala Drone Emprit ===================== */
.sna-stat-box { background: var(--bg-3); border: 1px solid var(--border-2); border-radius: 10px; padding: 10px 12px; }
.sna-stat-val { font-size: 18px; font-weight: 800; color: var(--text); line-height: 1.2; }
.sna-stat-lbl { font-size: 10px; font-weight: 700; color: var(--text-3); text-transform: uppercase; letter-spacing: .5px; margin-top: 2px; }

.sna-legend-row { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text-2, var(--text-3)); }
.sna-legend-dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
.sna-legend-name { flex: 1; font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sna-legend-pct { font-weight: 700; color: var(--text-3); font-variant-numeric: tabular-nums; }

.sna-node-row { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: 8px; cursor: pointer; font-size: 12px; border: 1px solid transparent; }
.sna-node-row:hover { background: var(--card-3); }
.sna-node-row.active { background: var(--accent-soft, var(--card-3)); border-color: var(--accent); }
.sna-node-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.sna-node-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); font-weight: 600; }
.sna-node-deg { font-size: 11px; font-weight: 700; color: var(--text-3); font-variant-numeric: tabular-nums; }

.sna-insight-name { font-size: 14px; font-weight: 800; color: var(--text); margin-bottom: 6px; word-break: break-word; }
.sna-insight-row { display: flex; justify-content: space-between; font-size: 12px; color: var(--text-3); padding: 3px 0; }
.sna-insight-row strong { color: var(--text); font-weight: 700; }
.sna-insight-neighbors { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 6px; }
.sna-insight-chip { font-size: 11px; font-weight: 600; padding: 3px 8px; border-radius: 99px; background: var(--bg-3); border: 1px solid var(--border-2); color: var(--text-2, var(--text-3)); }

.sna-mode-btn.active { background: var(--accent); color: #fff !important; }

.sna-insight-comments-title { font-size: 10px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase; color: var(--text-3); margin: 14px 0 8px; }
.sna-insight-comments { display: flex; flex-direction: column; gap: 6px; max-height: 260px; overflow-y: auto; }
.sna-insight-comment-item { display: flex; align-items: flex-start; gap: 8px; padding: 8px 10px; border-radius: 8px; background: var(--bg-3); border: 1px solid var(--border-2); }
.sna-insight-comment-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; margin-top: 4px; }
.sna-insight-comment-text { font-size: 12px; line-height: 1.45; color: var(--text-2, var(--text)); word-break: break-word; white-space: pre-wrap; }

/* ===================== Modul VD — grid thumbnail carousel/playlist ===================== */
.vd-playlist-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 8px; max-height: 280px; overflow-y: auto; padding: 4px; }
.vd-pl-item { position: relative; display: block; border-radius: 10px; overflow: hidden; border: 2px solid var(--border-2); cursor: pointer; aspect-ratio: 1 / 1; background: var(--bg-3); transition: opacity .15s, border-color .15s; }
.vd-pl-item.selected { border-color: var(--accent); }
.vd-pl-item:not(.selected) { opacity: .4; }
.vd-pl-item img { width: 100%; height: 100%; object-fit: cover; display: block; }
.vd-pl-item .pl-check { position: absolute; top: 6px; left: 6px; width: 16px; height: 16px; z-index: 2; accent-color: var(--accent); cursor: pointer; }
.vd-pl-badge { position: absolute; bottom: 4px; right: 4px; font-size: 9px; font-weight: 800; padding: 2px 5px; border-radius: 4px; background: rgba(0,0,0,.65); color: #fff; letter-spacing: .3px; }
.vd-pl-index { position: absolute; bottom: 4px; left: 4px; font-size: 9px; font-weight: 800; padding: 2px 5px; border-radius: 4px; background: rgba(0,0,0,.5); color: #fff; }

@media (max-width: 991px) {
  .sna-layout { flex-direction: column; height: auto !important; }
  .sna-sidebar { flex: 1 1 auto !important; max-width: none !important; height: auto !important; border-left: none !important; border-top: 1px solid var(--border-2); }
  #networkCanvas { height: 420px !important; }
}

/* ===================== Superapp Command Palette (Ctrl+K) ===================== */
.fx-cmd-trigger {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--card-2);
  border: 1px solid var(--border);
  color: var(--text-2);
  border-radius: 8px;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s ease;
  user-select: none;
}
.fx-cmd-trigger:hover {
  background: var(--card-3);
  border-color: var(--border-2);
  color: var(--text);
}
.fx-cmd-trigger-text {
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fx-cmd-kbd {
  font-family: var(--font);
  font-size: 10px;
  font-weight: 700;
  background: var(--bg-3);
  border: 1px solid var(--border-2);
  border-radius: 4px;
  padding: 2px 6px;
  color: var(--text-3);
  line-height: 1;
}
@media (max-width: 640px) {
  .fx-cmd-trigger-text { display: none; }
  .fx-cmd-trigger { padding: 6px 8px; }
}

.fx-cmd-overlay {
  position: fixed;
  inset: 0;
  background: rgba(4, 7, 13, 0.75);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  z-index: 100000;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 10vh 16px 20px;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.18s ease-out, visibility 0.18s ease-out;
}
.fx-cmd-overlay.is-open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.fx-cmd-dialog {
  background: var(--bg-2);
  border: 1px solid var(--border-2);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.75), 0 0 0 1px rgba(255, 255, 255, 0.05);
  border-radius: 16px;
  width: 100%;
  max-width: 620px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transform: scale(0.96) translateY(-8px);
  transition: transform 0.18s cubic-bezier(0.16, 1, 0.3, 1);
}
.fx-cmd-overlay.is-open .fx-cmd-dialog {
  transform: scale(1) translateY(0);
}

.fx-cmd-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-3);
}
.fx-cmd-head .fx-cmd-icon {
  color: var(--accent);
  flex-shrink: 0;
}
.fx-cmd-input {
  background: transparent;
  border: none;
  outline: none;
  font-family: var(--font);
  font-size: 15px;
  font-weight: 500;
  color: var(--text);
  flex: 1;
  min-width: 0;
}
.fx-cmd-input::placeholder {
  color: var(--text-3);
}
.fx-cmd-esc-hint kbd {
  font-family: var(--font);
  font-size: 10px;
  font-weight: 700;
  background: var(--card-2);
  border: 1px solid var(--border-2);
  border-radius: 4px;
  padding: 3px 6px;
  color: var(--text-3);
}

.fx-cmd-body {
  max-height: 400px;
  overflow-y: auto;
  padding: 8px;
}
.fx-cmd-group-title {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--text-3);
  padding: 10px 12px 4px;
}
.fx-cmd-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-radius: 10px;
  cursor: pointer;
  transition: background 0.1s, transform 0.08s;
  text-decoration: none;
  color: inherit;
  user-select: none;
  border: 1px solid transparent;
}
.fx-cmd-item.is-selected,
.fx-cmd-item:hover {
  background: rgba(var(--brand-rgb), 0.12);
  border-color: rgba(var(--brand-rgb), 0.25);
}
.fx-cmd-item.is-selected .fx-cmd-item-title,
.fx-cmd-item:hover .fx-cmd-item-title {
  color: #fff;
}
.fx-cmd-item-icon {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: var(--card-3);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--accent);
}
.fx-cmd-item-main {
  flex: 1;
  min-width: 0;
}
.fx-cmd-item-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 8px;
}
.fx-cmd-item-desc {
  font-size: 11px;
  color: var(--text-3);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fx-cmd-item-badge {
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  background: var(--card-2);
  color: var(--text-2);
  padding: 2px 6px;
  border-radius: 4px;
  border: 1px solid var(--border);
  letter-spacing: 0.3px;
}
.fx-cmd-empty {
  padding: 32px 16px;
  text-align: center;
  color: var(--text-3);
  font-size: 13px;
}
.fx-cmd-foot {
  padding: 10px 18px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 11px;
  color: var(--text-3);
  background: var(--bg-3);
}
.fx-cmd-hints {
  display: flex;
  align-items: center;
  gap: 12px;
}
.fx-cmd-hints kbd {
  font-family: var(--font);
  font-size: 9px;
  font-weight: 700;
  background: var(--card-2);
  border: 1px solid var(--border-2);
  border-radius: 3px;
  padding: 1px 4px;
  margin-right: 2px;
  color: var(--text-2);
}
.fx-cmd-branding {
  font-weight: 800;
  letter-spacing: 1px;
  font-size: 10px;
}
.fx-cmd-branding span {
  color: var(--accent);
}

/* ============================================================
   ANTI-SLOP FOUNDATION (v1.19.56)
   Keyframes yang hilang + utility yang dipakai tapi belum ada
   + class komponen semantik (hasil ekstraksi inline style).
   ============================================================ */

/* -- 1. Keyframes hilang ---------------------------------------
   fx-fade-in & fx-pop-in dipakai lewat `animation:` di modal
   dashboard, history, dan shell.js -- tapi keyframes-nya tidak
   pernah ada. Akibatnya modal muncul tanpa animasi, dan karena
   animation-fill-mode tak pernah dieksekusi, kartu modal tertahan
   di inline transform:scale(0.95) selamanya (5% mengecil). */
@keyframes fx-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes fx-pop-in {
  from { opacity: 0; transform: scale(0.95); }
  to   { opacity: 1; transform: scale(1); }
}

/* Hormati preferensi aksesibilitas: matikan animasi dekoratif. */
@media (prefers-reduced-motion: reduce) {
  .fx-fade-in, .fx-pop-in {
    animation: none !important;
    transform: none !important;
  }
}

/* -- 2. Utility yang hilang ------------------------------------ */
.fx-my-4  { margin-top: 4px;  margin-bottom: 4px; }
.fx-my-24 { margin-top: 24px; margin-bottom: 24px; }

.fx-mt-20 { margin-top: 20px; }
.fx-mb-14 { margin-bottom: 14px; }

.fx-p-20  { padding: 20px; }
.fx-p-32  { padding: 32px; }
.fx-pb-24 { padding-bottom: 24px; }

.fx-gap-10 { gap: 10px; }
/* -- 3. Tombol outline -----------------------------------------
   Dipakai tombol "Batal" di modal dashboard/history/shell.js,
   tapi definisinya tidak ada -> tombol jatuh ke style .fx-btn
   polos dan tidak terbaca sebagai aksi sekunder. */
.fx-btn-outline {
  background: transparent;
  border-color: var(--border-2);
  color: var(--text-2);
}
.fx-btn-outline:hover {
  background: var(--card-2);
  border-color: var(--border-active);
  color: var(--text);
}

/* -- 4. Input ukuran kecil ------------------------------------ */
.fx-input-sm {
  height: 34px;
  padding: 6px 10px;
  font-size: 12px;
  border-radius: 8px;
}

/* -- 5. Class komponen semantik -------------------------------
   Menggantikan inline style yang diulang puluhan kali di 16 view,
   supaya spacing & hierarki tipografi konsisten antar modul. */

/* Label kecil huruf kapital di atas field (dipakai ~28x). */
.fc-label {
  display: block;
  margin-bottom: 8px;
  color: var(--text-3);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
}
/* Versi ringkas tanpa margin bawah. */
.fc-label-inline {
  color: var(--text-3);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
}

/* Teks keterangan abu-abu 12px (dipakai ~18x). */
.fc-sub {
  margin: 0;
  color: var(--text-3);
  font-size: 12px;
  font-weight: 600;
}

/* Judul kartu + slot ikon (dipakai ~13x). */
.fc-card-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 4px 0;
  color: var(--text);
  font-size: 20px;
  font-weight: 800;
}

/* Kepala kartu: judul kiri-kanan + garis pemisah (dipakai ~12x). */
.fc-card-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 24px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--border-2);
}
/* Varian tanpa margin atas, hanya garis batas bawah. */
.fc-divider-b {
  margin-bottom: 24px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--border-2);
}

/* Ikon aksen persegi di dalam judul kartu. */
.fc-title-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  color: #fff;
  flex: 0 0 auto;
}

/* Pill kecil label/status (dipakai ~6x). */
.fc-tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--card);
  border: 1px solid var(--border-2);
  font-weight: 700;
}


/* ANTI-SLOP FIX: spesifisitas tombol outline di tema terang.
   [data-theme="light"] .fx-btn = (0,2,0) mengalahkan .fx-btn-outline = (0,1,0),
   jadi tanpa aturan ini tombol "Batal" kembali jadi gaya .fx-btn biasa
   tepat di tema yang paling butuh pembedaannya. */
[data-theme="light"] .fx-btn-outline {
  background: transparent;
  border-color: var(--border-2);
  color: var(--text-2);
}
[data-theme="light"] .fx-btn-outline:hover {
  background: #f1f5f9;
  border-color: var(--border-active);
  color: var(--text);
}

.fx-mt-2 { margin-top: 2px; }
.fx-mb-18 { margin-bottom: 18px; }


/* ── Override layer (anti-slop batch 2) ────────────────────────
   Inline style menang atas class apa pun. Ketika inline dipindahkan
   ke class, class penggantinya harus ikut menang — tapi class utility
   tinggal di awal file (dulu theme-utilities.css dimuat lewat @import
   di baris 5), sementara class komponen menyusul, jadi komponen yang
   menang. Uji otomatis menemukan 3 pasangan yang tampilannya berubah:

     .fx-stack     gap:16px  vs .fx-gap-24  -> 8 tempat
     .fx-grid      gap:16px  vs .fx-gap-24  -> 1 tempat
     .fx-card-head margin-b 20px vs .fx-mb-16 -> 1 tempat

   Blok ini hanya mengembalikan prioritas pada pasangan tersebut, bukan
   memindahkan seluruh skala utility ke akhir file — itu akan mengubah
   pula elemen lama yang selama ini memang dikalahkan komponen. */
.fx-stack.fx-gap-24,
.fx-grid.fx-gap-24   { gap: 24px; }
.fx-card-head.fx-mb-16 { margin-bottom: 16px; }
.fx-empty.fx-text-success { color: var(--success); }
.fx-empty.fx-text-danger  { color: var(--danger); }
.fx-btn-ghost.fx-text-danger,
.fx-btn-ghost.fx-text-success,
.fx-btn-ghost.fx-text-info,
.fx-btn-ghost.fx-text-warning { color: inherit; }
.fx-btn-ghost.fx-text-danger  { color: var(--danger); }
.fx-btn-ghost.fx-text-success { color: var(--success); }


/* ============================================================
   ANTI-SLOP BATCH 3 (v1.19.61)
   Komponen modal overlay, progress track, metrics & utility
   ============================================================ */

/* ── Modal Components ── */
.fc-modal-overlay {
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: var(--overlay);
  z-index: 10000;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(4px);
}
.fc-modal-close-btn {
  position: absolute;
  top: 20px;
  right: 20px;
  background: var(--bg-3);
  border: 1px solid var(--border);
  border-radius: 50%;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text);
  cursor: pointer;
  z-index: 5;
  transition: all 0.15s ease;
}
.fc-modal-close-btn:hover {
  background: var(--border);
}

/* ── Metrics & Progress ── */
.fc-mono-metric {
  font-size: 20px;
  font-weight: 800;
  color: var(--text);
  font-family: var(--mono);
}
.fc-progress-track {
  height: 12px;
  background: var(--bg-3);
  border-radius: 12px;
  overflow: hidden;
  position: relative;
  margin-bottom: 24px;
}
.fc-card-pad-xl-split {
  padding: 24px 32px;
  border-bottom: 1px solid var(--border-2);
}

/* ── Title Icons ── */
.fc-title-icon-info {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: linear-gradient(135deg, var(--info) 0%, var(--info-deep) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  flex: 0 0 auto;
}
.fc-title-icon-danger {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: linear-gradient(135deg, var(--danger) 0%, var(--danger-deep) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  flex: 0 0 auto;
}
.fc-title-icon-warning {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: linear-gradient(135deg, var(--warning) 0%, var(--warning-deep) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  flex: 0 0 auto;
}

/* ── Utility Batch 3 ── */
.fx-p-12-16        { padding: 12px 16px; }
.fx-icon-inline     { vertical-align: middle; margin-right: 6px; }
.fx-rounded-700     { border-radius: 8px; font-weight: 700; }
.fx-font-600        { font-weight: 600; }
.fx-text-primary-700{ font-weight: 700; color: var(--text); }
.fx-text-info-800   { font-weight: 800; color: var(--info); }
.fx-border-b-2      { border-bottom: 1px solid var(--border-2); }
.fx-bg-3            { background: var(--bg-3); }
.fx-flex-row-4      { display: flex; align-items: center; gap: 4px; }
.fx-flex-baseline-8 { display: flex; align-items: baseline; gap: 8px; }
.fx-w-110           { width: 110px; }


/* ── Batch 3 lanjutan ── */
.fc-row-2     { padding: 16px 24px; text-align: left; }
.fc-row-3     { padding-top: 14px; vertical-align: top; }
.fc-row-4     { padding-top: 100px; text-align: center; }
.fc-row-5     { align-items: start; gap: 24px; }
.fc-row-6     { align-items: flex-end; gap: 16px; }
.fc-label-xs  { font-size: 11px; font-weight: 700; text-decoration: none; }
.fc-ss-upper  { letter-spacing: 1px; text-transform: uppercase; }
.fc-note      { color: var(--text-3); font-size: 12px; margin: 0; }
.fc-track-sm  { background: var(--bg-3); border-radius: 6px; height: 6px; overflow: hidden; }
.fc-input-lg  { background: var(--bg-3); border-radius: 12px; font-size: 14px; height: 54px; padding: 12px 16px; width: 100%; }
.fc-radius-8  { border-radius: 8px; }
.fc-lh-1      { line-height: 1; }
.fc-pre-wrap  { white-space: pre-wrap; }
.fx-w-80      { width: 80px; }
/* anti-slop foundation end */

/* ============================================================
   ANTI-SLOP BATCH 2 (v1.19.60)
   Migrasi inline style layout, animasi shell, chat, dropdown & komponen
   ============================================================ */

/* ── Animasi Shell & Splash (sebelumnya inline style di layout.html) ── */
@keyframes fx-splash-pulse {
  0%   { transform: scale(0.95); opacity: 0.8; filter: drop-shadow(0 0 10px rgba(var(--brand-rgb), 0.2)); }
  50%  { transform: scale(1.05); opacity: 1; filter: drop-shadow(0 0 20px rgba(var(--brand-rgb), 0.6)); }
  100% { transform: scale(0.95); opacity: 0.8; filter: drop-shadow(0 0 10px rgba(var(--brand-rgb), 0.2)); }
}

@keyframes fx-logo-pulse-load {
  0%   { transform: scale(0.9); opacity: 0.6; }
  50%  { transform: scale(1.1); opacity: 1; filter: drop-shadow(0 0 8px rgba(var(--brand-rgb), 0.5)); }
  100% { transform: scale(0.9); opacity: 0.6; }
}

.is-loading-logo {
  animation: fx-logo-pulse-load 1s ease-in-out infinite;
}

/* User avatar visibility toggling */
.fx-user-avatar-wrap[data-has-avatar="false"] .avatar-img { display: none !important; }
.fx-user-avatar-wrap[data-has-avatar="true"] .avatar-initials { display: none !important; }
.fx-sidebar:hover .fx-user .meta { opacity: 1 !important; }

/* ── Dropdown System ── */
.fx-dropdown {
  position: relative;
}
.fx-dropdown-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  /* background: var(--surface) di markup aslinya TIDAK SAH -- variabel itu
     tidak pernah didefinisikan di theme.css, jadi browsernya memakai nilai
     awal (transparent) dan isi halaman menembus menu. Diganti token yang
     benar; sisanya dikembalikan persis seperti inline aslinya. */
  background: var(--card-solid);
  border: 1px solid var(--border);
  border-radius: 8px;
  width: 280px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  z-index: 100;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
  transition: all 0.2s;
  pointer-events: none;
}
.fx-dropdown-menu.active,
.fx-dropdown.active .fx-dropdown-menu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  pointer-events: auto;
}

/* ── Chat Components ── */
.fx-chat-sidebar-bottom {
  padding: 16px;
}

/* ── Batch 2 Semantic Components ── */
.fc-card-sub {
  margin: 0 0 4px 0;
  font-size: 16px;
  font-weight: 800;
  color: var(--text);
}
/* Varian tanpa margin — pasangan dari `margin:0; font-size:16px; ...`,
   dipisah dari .fc-card-sub yang punya margin bawah 4px. */
.fc-card-sub-flush {
  margin: 0;
  font-size: 16px;
  font-weight: 800;
  color: var(--text);
}
.fc-card-sub-sm {
  margin: 0;
  font-size: 14px;
  font-weight: 800;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 8px;
}
.fc-tag-label {
  font-size: 10px;
  font-weight: 800;
  color: var(--text-3);
  text-transform: uppercase;
  letter-spacing: 1px;
  margin-bottom: 4px;
}
.fc-head-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}
.fc-ellipsis-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 420px;
}
.fc-cover-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.fc-card-pad-lg {
  padding: 20px 32px;
}
.fc-card-pad-xl {
  padding: 24px 32px;
}
.fc-card-pad-split {
  padding: 20px 32px;
  border-bottom: 1px solid var(--border-2);
}

/* ── Utility Spacing & Flex ── */
.fx-flex-col-4   { display: flex; flex-direction: column; gap: 4px; }
.fx-flex-row-center { display: inline-flex; align-items: center; gap: 6px; }
.fx-text-left    { text-align: left; }
.fx-text-muted-12 { font-size: 12px; color: var(--text-3); }
.fx-text-muted-11 { font-size: 11px; color: var(--text-3); }
.fx-flex-none    { flex: 0 0 auto; }
.fx-overflow-x   { overflow-x: auto; }
.fx-card-clip    { padding: 0; overflow: hidden; }

