1. Home
  2. Pages
  3. Kurikulum 2026

Kurikulum 2026

Program Studi Bisnis Digital

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Peta Kurikulum Bisnis Digital 2025 - Elegant Interactive</title>
    <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
    <style>
        :root {
            /* Palette Elegant & Vibrant */
            --bg-dark: #0f172a;
            --bg-card: rgba(255, 255, 255, 0.9);
            --bg-card-hover: #ffffff;
            
            --text-main: #1e293b;
            --text-sub: #64748b;
            
            /* Warna PL (Gradient Base) */
            --pl1-grad: linear-gradient(135deg, #f43f5e 0%, #e11d48 100%); /* Pemrogram */
            --pl2-grad: linear-gradient(135deg, #10b981 0%, #059669 100%); /* Desainer */
            --pl3-grad: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); /* Analis */
            --pl4-grad: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%); /* Manajer */
            
            --pl1-color: #f43f5e;
            --pl2-color: #10b981;
            --pl3-color: #3b82f6;
            --pl4-color: #8b5cf6;

            --shadow-soft: 0 4px 20px rgba(0,0,0,0.05);
            --shadow-glow: 0 10px 30px rgba(0,0,0,0.12);
            --radius-lg: 16px;
        }

        * { box-sizing: border-box; margin: 0; padding: 0; font-family: 'Plus Jakarta Sans', sans-serif; }

        body {
            background-color: #f8fafc;
            background-image: 
                radial-gradient(at 0% 0%, rgba(59, 130, 246, 0.1) 0px, transparent 50%),
                radial-gradient(at 100% 0%, rgba(244, 63, 94, 0.1) 0px, transparent 50%),
                radial-gradient(at 100% 100%, rgba(16, 185, 129, 0.1) 0px, transparent 50%);
            background-attachment: fixed;
            color: var(--text-main);
            padding-bottom: 80px;
            min-height: 100vh;
        }

        /* --- HEADER & STATS --- */
        header {
            background: rgba(255, 255, 255, 0.8);
            backdrop-filter: blur(20px);
            border-bottom: 1px solid rgba(255,255,255,0.5);
            padding: 1rem 0;
            position: sticky;
            top: 0;
            z-index: 90;
            box-shadow: var(--shadow-soft);
        }

        .container { max-width: 1440px; margin: 0 auto; padding: 0 2rem; }

        .header-wrap {
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-wrap: wrap;
            gap: 20px;
        }

        .brand h1 {
            font-size: 1.5rem;
            font-weight: 800;
            letter-spacing: -0.5px;
            background: linear-gradient(90deg, #1e293b, #475569);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }

        .brand .subtitle { font-size: 0.9rem; color: var(--text-sub); font-weight: 500; }

        /* VISUAL STATS BAR */
        .stats-container {
            display: flex;
            align-items: center;
            gap: 24px;
            background: white;
            padding: 8px 24px;
            border-radius: 50px;
            box-shadow: 0 4px 15px rgba(0,0,0,0.05);
            border: 1px solid rgba(255,255,255,0.8);
        }

        .stat-bars-wrapper {
            display: flex;
            flex-direction: column;
            gap: 4px;
        }

        .stat-bars {
            display: flex;
            height: 10px;
            width: 200px;
            background: #e2e8f0;
            border-radius: 20px;
            overflow: hidden;
            box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
        }

        .stat-bar-segment {
            height: 100%;
            transition: width 1s cubic-bezier(0.4, 0, 0.2, 1);
            position: relative;
        }
        
        .stat-legend {
            display: flex;
            gap: 10px;
            font-size: 0.65rem;
            font-weight: 600;
            margin-top: 2px;
        }
        
        .legend-item { display: flex; align-items: center; gap: 4px; color: var(--text-sub); }
        .legend-dot { width: 6px; height: 6px; border-radius: 50%; }

        /* DYNAMIC STATS DISPLAY */
        .dynamic-stats {
            display: flex;
            flex-direction: column;
            align-items: flex-end;
            justify-content: center;
            border-left: 1px solid #e2e8f0;
            padding-left: 20px;
            min-width: 140px;
            text-align: right;
        }

        .ds-value {
            font-size: 1.5rem;
            font-weight: 800;
            color: var(--text-main);
            line-height: 1;
            font-feature-settings: "tnum";
            font-variant-numeric: tabular-nums;
        }

        .ds-label {
            font-size: 0.7rem;
            font-weight: 600;
            color: var(--text-sub);
            text-transform: uppercase;
            letter-spacing: 0.5px;
            margin-top: 2px;
        }

        .ds-pct {
            font-size: 0.8rem;
            font-weight: 700;
            color: var(--pl3-color);
            background: #eff6ff;
            padding: 2px 8px;
            border-radius: 12px;
            margin-top: 4px;
            display: inline-block;
            transition: all 0.3s ease;
        }

        /* --- FILTER BUTTONS --- */
        .filter-section {
            margin: 2rem 0;
            display: flex;
            justify-content: center;
            gap: 12px;
            flex-wrap: wrap;
        }

        .filter-btn {
            background: white;
            border: 1px solid #e2e8f0;
            padding: 10px 24px;
            border-radius: 12px;
            font-size: 0.9rem;
            font-weight: 600;
            color: var(--text-sub);
            cursor: pointer;
            transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
            display: flex;
            align-items: center;
            gap: 8px;
            box-shadow: var(--shadow-soft);
        }

        .filter-btn:hover { transform: translateY(-2px); box-shadow: var(--shadow-glow); color: var(--text-main); }
        
        .filter-btn.active {
            background: var(--text-main);
            color: white;
            border-color: var(--text-main);
            transform: scale(1.05);
        }

        /* --- MAIN GRID --- */
        .main-grid {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            gap: 2rem;
            perspective: 1000px;
        }
        
        @media (max-width: 1280px) { .main-grid { grid-template-columns: repeat(2, 1fr); } }
        @media (max-width: 640px) { .main-grid { grid-template-columns: 1fr; } }

        .semester-col {
            display: flex;
            flex-direction: column;
            gap: 1.2rem;
        }

        .sem-title {
            text-align: center;
            font-size: 0.85rem;
            font-weight: 800;
            text-transform: uppercase;
            letter-spacing: 1.5px;
            color: var(--text-sub);
            position: relative;
            padding-bottom: 10px;
            margin-bottom: 5px;
        }
        
        .sem-title::after {
            content: ''; position: absolute; bottom: 0; left: 50%; transform: translateX(-50%);
            width: 40px; height: 3px; background: #cbd5e1; border-radius: 2px;
        }

        /* --- COURSE CARD --- */
        .course-card {
            background: var(--bg-card);
            border-radius: var(--radius-lg);
            padding: 1.25rem;
            position: relative;
            transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
            border: 1px solid rgba(255,255,255,0.6);
            box-shadow: 0 4px 6px -1px rgba(0,0,0,0.05), 0 2px 4px -1px rgba(0,0,0,0.03);
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            min-height: 120px;
            overflow: hidden;
            cursor: pointer;
        }
        
        .card-top-bar {
            position: absolute;
            top: 0; left: 0; right: 0;
            height: 4px;
            background: #e2e8f0;
            transition: height 0.2s;
        }

        .course-card:hover {
            transform: translateY(-8px) scale(1.02);
            box-shadow: 0 20px 25px -5px rgba(0,0,0,0.1), 0 10px 10px -5px rgba(0,0,0,0.04);
            background: var(--bg-card-hover);
            z-index: 20;
        }
        
        .course-card:hover .card-top-bar { height: 6px; }

        .card-meta { display: flex; justify-content: space-between; margin-bottom: 0.75rem; align-items: center; }
        
        .code-pill {
            font-family: monospace; font-size: 0.7rem; color: var(--text-sub);
            background: #f1f5f9; padding: 2px 8px; border-radius: 6px; font-weight: 600;
        }
        
        .sks-pill {
            font-size: 0.7rem; font-weight: 700; color: white;
            background: var(--text-main); padding: 2px 8px; border-radius: 20px;
        }

        .card-name { font-size: 0.95rem; font-weight: 700; line-height: 1.4; color: var(--text-main); margin-bottom: 0.5rem; }

        .pl-indicators { display: flex; gap: 6px; margin-top: auto; padding-top: 10px; }
        .pl-dot { width: 8px; height: 8px; border-radius: 50%; opacity: 0.8; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }

        .bg-pl1 { background: var(--pl1-grad); }
        .bg-pl2 { background: var(--pl2-grad); }
        .bg-pl3 { background: var(--pl3-grad); }
        .bg-pl4 { background: var(--pl4-grad); }
        .bg-def { background: #cbd5e1; }

        .dimmed { opacity: 0.3; filter: grayscale(100%); pointer-events: none; transform: scale(0.95); }
        
        @keyframes pulse-glow {
            0% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.4); border-color: #f59e0b; }
            70% { box-shadow: 0 0 0 10px rgba(245, 158, 11, 0); border-color: #f59e0b; }
            100% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0); border-color: #f59e0b; }
        }

        .is-prereq {
            animation: pulse-glow 2s infinite;
            background: #fffbeb !important;
            border-color: #f59e0b !important;
            z-index: 10;
        }

        /* --- ELECTIVES DIVIDER --- */
        .electives-divider {
            grid-column: 1 / -1;
            margin-top: 4rem;
            margin-bottom: 2rem;
            text-align: center;
            position: relative;
        }
        
        .electives-divider h2 {
            display: inline-block;
            background: var(--text-main);
            color: white;
            padding: 8px 24px;
            border-radius: 50px;
            font-size: 1rem;
            font-weight: 700;
            position: relative;
            z-index: 2;
        }
        
        .electives-divider::before {
            content: ''; position: absolute; top: 50%; left: 0; width: 100%; height: 2px;
            background: #e2e8f0; z-index: 1;
        }

        /* --- TOOLTIP (HOVER) --- */
        #tooltip {
            position: fixed;
            display: none;
            width: 320px;
            background: rgba(15, 23, 42, 0.95);
            backdrop-filter: blur(12px);
            color: white;
            border-radius: 12px;
            padding: 16px;
            box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
            z-index: 200;
            pointer-events: none;
            font-size: 0.85rem;
            border: 1px solid rgba(255,255,255,0.1);
        }

        .tt-header { border-bottom: 1px solid rgba(255,255,255,0.1); padding-bottom: 12px; margin-bottom: 12px; }
        .tt-code { color: #94a3b8; font-family: monospace; font-size: 0.75rem; display: block; margin-bottom: 4px; }
        .tt-title { font-weight: 700; font-size: 1rem; color: white; line-height: 1.3; }
        .tt-tags { display: flex; flex-wrap: wrap; gap: 6px; }
        .tt-tag { font-size: 0.7rem; padding: 4px 10px; border-radius: 20px; font-weight: 600; color: white; }
        
        /* PERBAIKAN TATA LETAK TOOLTIP PRASYARAT */
        .tt-label { 
            font-size: 0.7rem; 
            text-transform: uppercase; 
            color: #64748b; 
            font-weight: 700; 
            display: block; 
            margin-bottom: 8px; /* Jarak ke bawah label */
            margin-top: 20px;   /* Jarak ke atas label diperbesar */
        }

        .prereq-list { 
            background: rgba(245, 158, 11, 0.1); 
            border-left: 3px solid #f59e0b; 
            padding: 12px 16px; /* Padding dalam diperbesar supaya tidak mepet */
            border-radius: 0 6px 6px 0; 
        }
        
        .prereq-item { 
            color: #fcd34d; 
            font-size: 0.85rem; 
            margin-bottom: 6px; /* Jarak antar item prasyarat ditambah */
            display: block; 
            line-height: 1.4; /* Jarak antar baris teks */
        }
        .prereq-item:last-child { margin-bottom: 0; }
        
        .ft-desc { font-style: italic; color: #cbd5e1; font-size: 0.85rem; margin-bottom: 10px; line-height: 1.5; }
        .ft-jobs { padding-left: 20px; color: #e2e8f0; font-size: 0.85rem; }
        .ft-jobs li { margin-bottom: 4px; }

        /* --- MODAL POPUP (CLICK) --- */
        .modal-overlay {
            position: fixed;
            top: 0; left: 0; width: 100%; height: 100%;
            background: rgba(15, 23, 42, 0.6);
            backdrop-filter: blur(8px);
            z-index: 1000;
            display: none;
            opacity: 0;
            transition: opacity 0.3s ease;
            justify-content: center;
            align-items: center;
            padding: 20px;
        }

        .modal-overlay.active { display: flex; opacity: 1; }

        .modal-card {
            background: #ffffff;
            width: 100%;
            max-width: 700px;
            max-height: 90vh;
            border-radius: 24px;
            box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25);
            display: flex;
            flex-direction: column;
            overflow: hidden;
            transform: translateY(20px) scale(0.95);
            transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
        }

        .modal-overlay.active .modal-card { transform: translateY(0) scale(1); }

        .modal-header {
            padding: 24px;
            background: #f8fafc;
            border-bottom: 1px solid #e2e8f0;
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
        }

        .m-code-badge { background: #0f172a; color: white; padding: 4px 10px; border-radius: 6px; font-family: monospace; font-size: 0.8rem; font-weight: 700; margin-bottom: 8px; display: inline-block; }
        .m-title { font-size: 1.5rem; font-weight: 800; color: #1e293b; line-height: 1.2; margin-bottom: 8px; }
        .m-subtitle { font-size: 0.9rem; color: #64748b; font-weight: 500; }

        .modal-close {
            background: transparent; border: none; cursor: pointer;
            width: 32px; height: 32px; border-radius: 50%;
            display: flex; align-items: center; justify-content: center;
            color: #94a3b8; transition: all 0.2s;
        }
        .modal-close:hover { background: #e2e8f0; color: #0f172a; }

        .modal-body { padding: 24px; overflow-y: auto; }

        .m-section { margin-bottom: 24px; }
        .m-section:last-child { margin-bottom: 0; }
        .m-label { text-transform: uppercase; font-size: 0.75rem; font-weight: 700; color: #94a3b8; letter-spacing: 1px; margin-bottom: 8px; display: block; }
        
        .m-text { font-size: 0.95rem; line-height: 1.6; color: #334155; }
        .m-text p { margin-bottom: 8px; }

        .m-tags { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }
        
        .m-footer {
            padding: 20px 24px;
            background: #f1f5f9;
            border-top: 1px solid #e2e8f0;
            font-size: 0.85rem;
            color: #475569;
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 16px;
        }

        .m-lecturer-box strong { display: block; color: #1e293b; margin-bottom: 2px; }

        footer {
            text-align: center; margin-top: 4rem; color: var(--text-sub); font-size: 0.85rem;
        }

    </style>
</head>
<body>

<header>
    <div class="container">
        <div class="header-wrap">
            <div class="brand">
                <h1>Kurikulum Bisnis Digital 2025</h1>
                <div class="subtitle">UPN "Veteran" Jawa Timur • Dashboard Interaktif</div>
            </div>
            
            <div class="stats-container">
                <div class="stat-bars-wrapper">
                    <div class="stat-bars" id="pl-composition-bar"></div>
                    <div class="stat-legend">
                        <div class="legend-item"><div class="legend-dot" style="background:var(--pl1-color)"></div>Pemrogram</div>
                        <div class="legend-item"><div class="legend-dot" style="background:var(--pl2-color)"></div>Desainer</div>
                        <div class="legend-item"><div class="legend-dot" style="background:var(--pl3-color)"></div>Analis</div>
                        <div class="legend-item"><div class="legend-dot" style="background:var(--pl4-color)"></div>Manajer</div>
                    </div>
                </div>
                <div class="dynamic-stats">
                    <div class="ds-value" id="stats-count">0</div>
                    <div class="ds-label" id="stats-label">Mata Kuliah</div>
                    <div class="ds-pct" id="stats-pct">100%</div>
                </div>
            </div>
        </div>
    </div>
</header>

<div class="container">
    <div class="filter-section">
        <button class="filter-btn active" onclick="filterData('all', this)">Semua</button>
        <button class="filter-btn" onclick="filterData('PL-1', this)" data-pl="PL-1">
            <div class="legend-dot" style="background:var(--pl1-color)"></div> Pemrogram
        </button>
        <button class="filter-btn" onclick="filterData('PL-2', this)" data-pl="PL-2">
            <div class="legend-dot" style="background:var(--pl2-color)"></div> Desainer
        </button>
        <button class="filter-btn" onclick="filterData('PL-3', this)" data-pl="PL-3">
            <div class="legend-dot" style="background:var(--pl3-color)"></div> Analis
        </button>
        <button class="filter-btn" onclick="filterData('PL-4', this)" data-pl="PL-4">
            <div class="legend-dot" style="background:var(--pl4-color)"></div> Manajer
        </button>
    </div>

    <div class="main-grid" id="curriculum-grid"></div>
</div>

<footer>
    &copy; 2025 Program Studi Bisnis Digital - UPN "Veteran" Jawa Timur.<br>
    Sistem Informasi Kurikulum Berbasis Capaian Pembelajaran Lulusan (CPL).
</footer>

<!-- TOOLTIP (Hover) -->
<div id="tooltip"></div>

<!-- MODAL (Click) -->
<div class="modal-overlay" id="course-modal" onclick="closeModal(event)">
    <div class="modal-card" onclick="event.stopPropagation()">
        <div class="modal-header">
            <div>
                <span class="m-code-badge" id="m-code">CODE</span>
                <div class="m-title" id="m-name">Course Name</div>
                <div class="m-subtitle" id="m-sks">3 SKS</div>
            </div>
            <button class="modal-close" onclick="closeModal()">
                <svg width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M6 18L18 6M6 6l12 12"></path></svg>
            </button>
        </div>
        <div class="modal-body">
            <div class="m-section">
                <span class="m-label">Profil Lulusan</span>
                <div class="m-tags" id="m-pl-tags"></div>
            </div>
            
            <div class="m-section">
                <span class="m-label">Deskripsi Mata Kuliah</span>
                <div class="m-text" id="m-desc"></div>
            </div>

            <div class="m-section" id="m-cpl-section">
                <span class="m-label">Capaian Pembelajaran Lulusan (CPL)</span>
                <div class="m-text" id="m-cpl" style="font-size:0.9rem; color:#475569;"></div>
            </div>

            <div class="m-section" id="m-cpmk-section">
                <span class="m-label">Capaian Pembelajaran Mata Kuliah (CPMK)</span>
                <div class="m-text" id="m-cpmk"></div>
            </div>

            <div class="m-section">
                <span class="m-label">Prasyarat</span>
                <div class="m-text" id="m-pre"></div>
            </div>
        </div>
        <div class="m-footer">
            <div class="m-lecturer-box">
                <span class="m-label" style="margin-bottom:4px;">PJMK</span>
                <div id="m-pjmk"></div>
            </div>
            <div class="m-lecturer-box">
                <span class="m-label" style="margin-bottom:4px;">Dosen Pengampu</span>
                <div id="m-dosen"></div>
            </div>
        </div>
    </div>
</div>

<script>
    // --- CPL DICTIONARY ---
    const CPL_DESC = {
        'CPL-1': 'Menguasai dasar-dasar ilmu komputer, rekayasa perangkat lunak, sains data, serta bisnis dan manajemen.',
        'CPL-2': 'Mampu merancang, mengembangkan, dan menguji perangkat lunak serta purwarupa solusi digital sesuai kebutuhan pengguna.',
        'CPL-3': 'Mampu menerapkan metode cerdas dan analitik data untuk mendukung pengambilan keputusan bisnis digital.',
        'CPL-4': 'Mampu mengelola proyek digital dan berkolaborasi lintas disiplin secara efektif.',
        'CPL-5': 'Mampu menggunakan perangkat komputasi dan teknologi digital untuk meningkatkan efisiensi proses bisnis.',
        'CPL-6': 'Menguasai metode riset dan mampu menghasilkan karya ilmiah atau inovasi berbasis teknologi bisnis digital.',
        'CPL-7': 'Memiliki integritas, profesionalitas, serta kepemimpinan dengan sikap kreatif, kritis, terbuka, dan berorientasi pada pembelajaran sepanjang hayat.',
        'CPL-8': 'Memiliki kepekaan sosial, kepedulian lingkungan, penghargaan terhadap keberagaman, serta semangat kontribusi bagi bangsa.'
    };

    // --- MAIN DATA ---
    const rawData = [
        {sem:1, code:'UV21007', name:'PANCASILA', sks:2, pl:['PL-1','PL-2','PL-3','PL-4'], pre:'N / A', cpl:[7,8]},
        {sem:1, code:'UV21010', name:'BAHASA INGGRIS', sks:3, pl:['PL-1','PL-2','PL-3','PL-4'], pre:'N / A', cpl:[7,8]},
        {sem:1, code:'UV21009', name:'BAHASA INDONESIA', sks:2, pl:['PL-1','PL-2','PL-3','PL-4'], pre:'N / A', cpl:[7,8]},
        {sem:1, code:'BD269001', name:'PENGANTAR MANAJEMEN BISNIS', sks:3, pl:['PL-2','PL-3'], pre:'Dasar Manajemen & Bisnis', cpl:[1,3,6]},
        {sem:1, code:'BD261102', name:'PENGANTAR TEKNOLOGI INFORMASI', sks:3, pl:['PL-2','PL-3'], pre:'N / A', cpl:[1,4,6]},
        {sem:1, code:'BD261103', name:'ALGORITMA DAN PEMROGRAMAN DASAR', sks:3, pl:['PL-1','PL-2','PL-3','PL-4'], pre:'N / A', cpl:[1,2,3,6]},
        {sem:1, code:'BD261101', name:'MATEMATIKA BISNIS', sks:3, pl:['PL-1','PL-4'], pre:'N / A', cpl:[1,3,4,5]},
        
        {sem:2, code:'UV21008', name:'KEWARGANEGARAAN', sks:3, pl:['PL-1','PL-2','PL-3','PL-4'], pre:'N / A', cpl:[7,8]},
        {sem:2, code:'UV21001', name:'PENDIDIKAN AGAMA', sks:2, pl:['PL-1','PL-2','PL-3','PL-4'], pre:'N / A', cpl:[7,8]},
        {sem:2, code:'BD269002', name:'START-UP FUNDING & VENTURE CAPITAL', sks:3, pl:['PL-2','PL-4'], pre:'N / A', cpl:[1,4]},
        {sem:2, code:'BD269003', name:'SISTEM INFORMASI BISNIS', sks:3, pl:['PL-1','PL-2','PL-4'], pre:'PENGANTAR TEKNOLOGI INFORMASI', cpl:[1,5]},
        {sem:2, code:'BD261106', name:'ALGORITMA DAN PEMROGRAMAN LANJUT', sks:3, pl:['PL-1','PL-2','PL-4'], pre:'ALGORITMA DAN PEMROGRAMAN DASAR', cpl:[1,2]},
        {sem:2, code:'BD261110', name:'STATISTIKA BISNIS', sks:3, pl:['PL-2','PL-3'], pre:'MATEMATIKA BISNIS', cpl:[1,3,6]},
        {sem:2, code:'BD261108', name:'SISTEM BASIS DATA', sks:3, pl:['PL-1','PL-2'], pre:'PENGANTAR TEKNOLOGI INFORMASI', cpl:[1,2,3]},
        
        {sem:3, code:'UV21011', name:'PENDIDIKAN BELA NEGARA', sks:3, pl:['PL-1','PL-2','PL-3','PL-4'], pre:'', cpl:[7,8]},
        {sem:3, code:'UV21012', name:'KEWIRAUSAHAAN', sks:3, pl:['PL-1','PL-3','PL-4'], pre:'N / A', cpl:[1,4,7]},
        {sem:3, code:'BD261111', name:'SISTEM PENGAMBILAN KEPUTUSAN', sks:3, pl:['PL-1','PL-2','PL-4'], pre:'MATEMATIKA BISNIS', cpl:[1,3,5]},
        {sem:3, code:'BD261112', name:'PERILAKU ORGANISASI DAN SDM', sks:3, pl:['PL-2','PL-3'], pre:'PENGANTAR MANAJEMEN BISNIS', cpl:[1,4]},
        {sem:3, code:'BD261113', name:'DIGITAL MARKETING', sks:3, pl:['PL-1','PL-2','PL-3','PL-4'], pre:'PENGANTAR TEKNOLOGI INFORMASI', cpl:[1,5]},
        {sem:3, code:'BD261122', name:'REKAYASA PERANGKAT LUNAK', sks:3, pl:['PL-1','PL-2','PL-4'], pre:'UI / UX', cpl:[1,2,4]},
        {sem:3, code:'BD261115', name:'UI / UX', sks:3, pl:['PL-2','PL-3'], pre:'PENGANTAR TEKNOLOGI INFORMASI', cpl:[1,2]},
        
        {sem:4, code:'BD261117', name:'PERILAKU KONSUMEN DAN PASAR', sks:3, pl:['PL-1','PL-3','PL-4'], pre:'DIGITAL MARKETING', cpl:[1,6]},
        {sem:4, code:'BD269004', name:'MULTIMEDIA DAN KONTEN KREATIF', sks:3, pl:['PL-2','PL-3','PL-4'], pre:'', cpl:[2,7]},
        {sem:4, code:'BD269005', name:'CREATIVE & INNOVATIVE THINKING', sks:3, pl:['PL-1','PL-2','PL-3','PL-4'], pre:'', cpl:[4,7]},
        {sem:4, code:'BD261124', name:'METODE PENELITIAN', sks:3, pl:['PL-1','PL-2','PL-4'], pre:'N / A', cpl:[6]},
        {sem:4, code:'BD269006', name:'FINANCIAL TECHNOLOGY', sks:3, pl:['PL-1','PL-2','PL-3','PL-5'], pre:'STATISTIKA BISNIS', cpl:[1,3,5]},
        {sem:4, code:'BD261114', name:'PEMROGRAMAN WEB DAN MOBILE', sks:3, pl:['PL-1','PL-2'], pre:'ALGORITMA DAN PEMROGRAMAN LANJUT | SISTEM BASIS DATA', cpl:[1,2,5]},
        {sem:4, code:'BD261116', name:'E-COMMERCE DAN MARKETPLACE', sks:3, pl:['PL-1','PL-2','PL-3','PL-4'], pre:'PEMROGRAMAN WEB DAN MOBILE | SISTEM BASIS DATA', cpl:[2,4,5]},

        {sem:5, code:'UV21013', name:'KEPEMIMPINAN', sks:2, pl:['PL-1','PL-2','PL-3','PL-4'], pre:'N / A', cpl:[4,7]},
        {sem:5, code:'BD261123', name:'PRAKTEK KERJA LAPANGAN', sks:2, pl:['PL-1'], pre:'N / A', cpl:[7,8]},
        {sem:5, code:'BD261120', name:'TEKNOLOGI KECERDASAN BISNIS', sks:3, pl:['PL-1','PL-2'], pre:'SISTEM PENGAMBILAN KEPUTUSAN', cpl:[3,5]},
        {sem:5, code:'BD261125', name:'STRATEGI NEGOSIASI DAN PITCHING', sks:3, pl:['PL-2','PL-3','PL-4'], pre:'PERILAKU KONSUMEN DAN PASAR', cpl:[4,7]},
        {sem:5, code:'BD261126', name:'MANAJEMEN RESIKO', sks:3, pl:['PL-2','PL-3','PL-4'], pre:'ANALISIS BISNIS DIGITAL', cpl:[1,3]},
        {sem:5, code:'BD261119', name:'ANALISIS BISNIS DIGITAL', sks:3, pl:['PL-1','PL-2','PL-3','PL-4'], pre:'', cpl:[1,3]},

        {sem:6, code:'BD261127', name:'KULIAH KERJA NYATA', sks:3, pl:[], pre:'N / A', cpl:[7,8]},
        {sem:6, code:'BD261128', name:'DATA MINING', sks:3, pl:['PL-1','PL-2','PL-4'], pre:'TEKNOLOGI KECERDASAN BISNIS', cpl:[3,6]},
        {sem:6, code:'BD261129', name:'MACHINE LEARNING & AI', sks:3, pl:['PL-1','PL-2','PL-4'], pre:'TEKNOLOGI KECERDASAN BISNIS', cpl:[2,3]},
        {sem:6, code:'BD261131', name:'STUDI KELAYAKAN BISNIS', sks:3, pl:['PL-1','PL-3','PL-4'], pre:'MANAJEMEN RESIKO', cpl:[1,4]},
        {sem:6, code:'BD269007', name:'AGILE & SCRUM', sks:3, pl:['PL-2','PL-3','PL-4'], pre:'', cpl:[4]},

        {sem:7, code:'BD261132', name:'MANAJEMEN PROYEK TEKNOLOGI INFORMASI', sks:3, pl:['PL-1','PL-2','PL-4','PL-5'], pre:'REKAYASA PERANGKAT LUNAK', cpl:[4,5]},
        {sem:7, code:'BD261133', name:'HUKUM DAN ETIKA BISNIS', sks:3, pl:['PL-1','PL-2','PL-3','PL-4'], pre:'STUDI KELAYAKAN BISNIS', cpl:[7,8]},

        {sem:8, code:'BD261134', name:'SKRIPSI', sks:6, pl:['PL-1','PL-2','PL-3','PL-4'], pre:'N / A', cpl:[6,7]},

        // PILIHAN
        {sem:'Pilihan V', code:'BD261201', name:'PENGALAMAN & PENERIMAAN PENGGUNA', sks:3, pl:['PL-3','PL-4'], pre:'REKAYASA PERANGKAT LUNAK', cpl:[2,6]},
        {sem:'Pilihan V', code:'BD261205', name:'TEXT MINING', sks:3, pl:['PL-2','PL-3'], pre:'TEKNOLOGI KECERDASAN BISNIS', cpl:[3]},
        {sem:'Pilihan V', code:'BD261209', name:'PEMROGRAMAN JARINGAN', sks:3, pl:['PL-1'], pre:'PEMROGRAMAN WEB DAN MOBILE | SISTEM BASIS DATA', cpl:[1,5]},
        {sem:'Pilihan V', code:'BD261216', name:'RISET PASAR', sks:3, pl:['PL-1','PL-4'], pre:'PERILAKU KONSUMEN DAN PASAR', cpl:[3,6]},
        {sem:'Pilihan V', code:'BD269008', name:'TEKNOLOGI TERAPAN & TRANSFORMASI DIGITAL', sks:3, pl:['PL-1'], pre:'', cpl:[5]},

        {sem:'Pilihan VI', code:'BD261202', name:'GIM DAN GAMIFIKASI UNTUK BISNIS', sks:3, pl:['PL-2','PL-4'], pre:'REKAYASA PERANGKAT LUNAK', cpl:[2,7]},
        {sem:'Pilihan VI', code:'BD261211', name:'KEAMANAN SISTEM & TEKNOLOGI INFORMASI', sks:3, pl:['PL-2','PL-3'], pre:'PEMROGRAMAN WEB DAN MOBILE | SISTEM BASIS DATA', cpl:[1,5]},
        {sem:'Pilihan VI', code:'BD261210', name:'UJI COBA DAN IMPLEMENTASI', sks:3, pl:['PL-2','PL-3'], pre:'PEMROGRAMAN WEB DAN MOBILE | SISTEM BASIS DATA', cpl:[2,4]},
        {sem:'Pilihan VI', code:'BD261215', name:'INVESTASI DIGITAL', sks:3, pl:['PL-1','PL-4'], pre:'PERILAKU KONSUMEN DAN PASAR', cpl:[1,3]},
        {sem:'Pilihan VI', code:'BD261208', name:'VISUALISASI DAN PENCERITAAN DATA', sks:3, pl:['PL-1','PL-4'], pre:'TEKNOLOGI KECERDASAN BISNIS', cpl:[3,4]},
        {sem:'Pilihan VI', code:'BD269009', name:'TAX ENGINEERING', sks:3, pl:['PL-3'], pre:'', cpl:[1,3]},
        {sem:'Pilihan VI', code:'BD269010', name:'BUSINESS INTELLIGENT', sks:3, pl:['PL-1','PL-3','PL-4'], pre:'', cpl:[3,5]},
        {sem:'Pilihan VI', code:'BD269011', name:'CRM', sks:3, pl:['PL-4'], pre:'', cpl:[4,5]},

        {sem:'Pilihan VII', code:'BD261203', name:'ANALISIS KEBUTUHAN PERANGKAT LUNAK', sks:3, pl:['PL-3','PL-4'], pre:'REKAYASA PERANGKAT LUNAK', cpl:[2,4]},
        {sem:'Pilihan VII', code:'BD261207', name:'DATA OFFICER', sks:3, pl:['PL-2','PL-4'], pre:'TEKNOLOGI KECERDASAN BISNIS', cpl:[3,4]},
        {sem:'Pilihan VII', code:'BD261214', name:'PROCESS MINING', sks:3, pl:['PL-2','PL-4'], pre:'TEKNOLOGI KECERDASAN BISNIS', cpl:[3,5]},
        {sem:'Pilihan VII', code:'BD261212', name:'PEMROGRAMAN FRONT-END', sks:3, pl:['PL-2','PL-3','PL-4'], pre:'', cpl:[2,5]},
        {sem:'Pilihan VII', code:'BD261213', name:'PEMROGRAMAN BACK-END', sks:3, pl:['PL-2','PL-3','PL-4'], pre:'PEMROGRAMAN WEB DAN MOBILE | SISTEM BASIS DATA', cpl:[2,5]},
        {sem:'Pilihan VII', code:'BD261217', name:'MANAJEMEN OPERASIONAL DIGITAL', sks:3, pl:['PL-1','PL-4'], pre:'PEMROGRAMAN WEB DAN MOBILE | SISTEM BASIS DATA', cpl:[4,5]},
        {sem:'Pilihan VII', code:'BD261218', name:'KOMERSIALISASI PRODUK', sks:3, pl:['PL-3','PL-4'], pre:'PERILAKU KONSUMEN DAN PASAR', cpl:[4,6]},
        {sem:'Pilihan VII', code:'BD269012', name:'GAME THEORY', sks:3, pl:['PL-2','PL-3'], pre:'PERILAKU KONSUMEN DAN PASAR', cpl:[1,3]},
        {sem:'Pilihan VII', code:'BD269013', name:'STRATEGI PLATFORM DAN INOVASI DIGITAL', sks:3, pl:['PL-1','PL-4','PL-5'], pre:'', cpl:[4,6]}
    ];

    // --- DETAILED DATA MAPPING (Simulating DB) ---
    // Maps Course Name to { desc, pjmk, dosen1, dosen2, cpmk }
    const courseDetails = {
        'PANCASILA': {
            desc: 'Mahasiswa mampu menjelaskan nilai – nilai Pancasila sehingga dapat menunjukkan sikap religius, menjunjung tinggi nilai kemanusiaan berdasarkan agama, moral dan etika. Selain itu, mata kuliah ini juga mendorong mahasiswa berkontribusi dalam peningkatan mutu kehidupan bermasyarakat, berbangsa, bernegara berdasarkan Pancasila.',
            pjmk: 'Dr. Taufikurraqman, S.Pd, M.Pd',
            dosen: ['Dr. Taufikurraqman, S.Pd, M.Pd'],
            cpmk: '1. Menganalisis urgensi Pendidikan Pancasila di Perguruan Tinggi.<br>2. Menganalisis alasan diperlukannya Pendidikan Pancasila di Perguruan Tinggi.<br>3. Menganalisis sumber historis, sosiologis, dan politis Pendidikan Pancasila.'
        },
        'BAHASA INGGRIS': {
            desc: 'Mata kuliah ini diselenggarakan untuk meningkatkan kemampuan Bahasa Inggris secara umum dan ilmiah, sehingga mahasiswa dapat berkomunikasi lisan maupun tulisan secara baik dan berterima untuk menunjang bidang keilmuannya dan meningkatkan kemampuan soft skill terutama dalam ranah team works dan public speaking.',
            pjmk: 'Dr. Wulan Retno W. M.Pd.',
            dosen: ['Tim MKU Universitas'],
            cpmk: '1. Mahasiswa mampu memahami teks akademik berbahasa Inggris.<br>2. Mahasiswa mampu menulis esai akademik sederhana.'
        },
        'BAHASA INDONESIA': {
            desc: 'Mata kuliah ini adalah mata kuliah umum yang bertujuan untuk membentuk keterampilan berbahasa Indonesia, baik secara lisan maupun tulis, dalam bidang ilmiah.',
            pjmk: 'Drs. Kusnarto, M.Si., M.Pd.',
            dosen: ['Tim MKU Universitas'],
            cpmk: 'Mahasiswa mampu menyusun karya ilmiah dengan menggunakan bahasa Indonesia yang baik dan benar.'
        },
        'PENGANTAR MANAJEMEN BISNIS': {
            desc: 'Memberikan pemahaman tentang konsep dasar manajemen dan bisnis, fungsi-fungsi manajemen, serta lingkungan bisnis modern.',
            pjmk: 'Dr. Muhadjir Anwar, SE, MM, CRP',
            dosen: ['Dr. Muhadjir Anwar, SE, MM, CRP', 'Prof. Dr. Yuniningsih, SE., MSi'],
            cpmk: 'Mahasiswa mampu menganalisis fungsi manajemen dalam organisasi bisnis.'
        },
        'PENGANTAR TEKNOLOGI INFORMASI': {
            desc: 'Membahas konsep dasar teknologi informasi, komponen sistem komputer, jaringan, dan dampaknya terhadap masyarakat.',
            pjmk: 'Hendra Maulana, S.Kom, M.Kom',
            dosen: ['Hendra Maulana, S.Kom, M.Kom', 'Sugiarto, S.Kom, M.Kom'],
            cpmk: 'Mahasiswa mampu menjelaskan komponen dan fungsi sistem komputer serta penerapannya.'
        },
        'ALGORITMA DAN PEMROGRAMAN DASAR': {
            desc: 'Mempelajari logika pemrograman, struktur data dasar, dan implementasi algoritma menggunakan bahasa pemrograman.',
            pjmk: 'Pratama Wirya Atmaja, S.Kom, M.Kom',
            dosen: ['Pratama Wirya Atmaja, S.Kom, M.Kom', 'Dhian Satria Yudha Kartika, S.Kom, M.Kom'],
            cpmk: 'Mahasiswa mampu membuat program sederhana untuk menyelesaikan masalah komputasi dasar.'
        },
        'MATEMATIKA BISNIS': {
            desc: 'Penerapan konsep matematika dalam pemecahan masalah ekonomi dan bisnis.',
            pjmk: 'Muhamad A. Burhanudin, S.Si., M.Sc.',
            dosen: ['Muhamad A. Burhanudin, S.Si., M.Sc.', 'Pratama Wirya Atmaja, S.Kom, M.Kom'],
            cpmk: 'Mahasiswa mampu menerapkan konsep fungsi dan kalkulus dalam analisis ekonomi.'
        },
        'SISTEM INFORMASI BISNIS': {
            desc: 'Konsep dasar sistem informasi dalam konteks organisasi dan bisnis digital.',
            pjmk: 'Sugiarto, S.Kom, M.Kom',
            dosen: ['Sugiarto, S.Kom, M.Kom', 'Iswanda F. Satibi, S.Hum., MCom.'],
            cpmk: 'Mampu menjelaskan peran sistem informasi dalam strategi bisnis.'
        },
        'ALGORITMA DAN PEMROGRAMAN LANJUT': {
            desc: 'Pendalaman struktur data kompleks, algoritma sorting/searching, dan pemrograman berorientasi objek.',
            pjmk: 'Dhian Satria Yudha Kartika, S.Kom, M.Kom',
            dosen: ['Dhian Satria Yudha Kartika, S.Kom, M.Kom'],
            cpmk: 'Mampu mengimplementasikan struktur data kompleks dalam pengembangan perangkat lunak.'
        },
        'PEMROGRAMAN WEB DAN MOBILE': {
            desc: 'Pengembangan aplikasi berbasis web dan mobile menggunakan teknologi terkini.',
            pjmk: 'Pratama Wirya Atmaja, S.Kom, M.Kom',
            dosen: ['Pratama Wirya Atmaja, S.Kom, M.Kom'],
            cpmk: 'Mampu membangun aplikasi web dan mobile fungsional.'
        },
        'DATA MINING': {
            desc: 'Konsep dan teknik penggalian data untuk menemukan pola yang berguna.',
            pjmk: 'Hendra Maulana, S.Kom, M.Kom',
            dosen: ['Hendra Maulana, S.Kom, M.Kom'],
            cpmk: 'Mampu menerapkan algoritma data mining untuk analisis data bisnis.'
        },
        'MANAJEMEN PROYEK TEKNOLOGI INFORMASI': {
            desc: 'Metodologi dan teknik pengelolaan proyek TI dari inisiasi hingga penutupan.',
            pjmk: 'Hendra Maulana, S.Kom, M.Kom',
            dosen: ['Hendra Maulana, S.Kom, M.Kom'],
            cpmk: 'Mampu menyusun rencana proyek TI yang komprehensif.'
        }
    };

    const plInfo = {
        'PL-1': { name: 'Pemrogram', color: 'var(--pl1-grad)', simpleColor: 'var(--pl1-color)', fullName: 'Pemrogram Bisnis Digital', desc: 'Merencanakan & mengembangkan aplikasi sesuai teknologi & bisnis.', jobs: ['Frontend/Backend Dev', 'Network Admin'] },
        'PL-2': { name: 'Desainer', color: 'var(--pl2-grad)', simpleColor: 'var(--pl2-color)', fullName: 'Desainer Bisnis Digital', desc: 'UI/UX, Multimedia, dan perancangan perangkat lunak.', jobs: ['App/Game Designer', 'Multimedia Producer'] },
        'PL-3': { name: 'Analis', color: 'var(--pl3-grad)', simpleColor: 'var(--pl3-color)', fullName: 'Analis Bisnis Digital', desc: 'Analisis kuantitatif & Big Data untuk keputusan manajerial.', jobs: ['Data Analyst', 'Data Admin'] },
        'PL-4': { name: 'Manajer', color: 'var(--pl4-grad)', simpleColor: 'var(--pl4-color)', fullName: 'Manajer Bisnis Digital', desc: 'Mengembangkan & menjalankan usaha rintisan (Startup).', jobs: ['Founder', 'COO', 'Venture Capitalist'] },
        'PL-5': { name: 'Umum', color: '#cbd5e1', simpleColor: '#cbd5e1', fullName:'Umum', desc:'', jobs:[] }
    };

    function getCourseName(code) {
        if(!code) return code;
        code = code.trim();
        const f = rawData.find(c => c.code === code);
        return f ? f.name : code;
    }

    // --- RENDER VISUAL STATS ---
    function renderStats() {
        const counts = { 'PL-1':0, 'PL-2':0, 'PL-3':0, 'PL-4':0 };
        rawData.forEach(item => {
            item.pl.forEach(p => { if(counts[p] !== undefined) counts[p]++; });
        });

        const container = document.getElementById('pl-composition-bar');
        container.innerHTML = '';
        const totalAssignments = counts['PL-1'] + counts['PL-2'] + counts['PL-3'] + counts['PL-4'];
        
        Object.keys(counts).forEach(key => {
            const count = counts[key];
            const pct = (count / totalAssignments) * 100;
            const bar = document.createElement('div');
            bar.className = 'stat-bar-segment';
            bar.style.width = pct + '%';
            bar.style.background = plInfo[key].color;
            container.appendChild(bar);
        });
        updateStatsUI('all');
    }

    // --- UPDATE HEADER DYNAMIC STATS ---
    function updateStatsUI(filter) {
        let count = 0;
        let total = rawData.length;
        let label = "Total Mata Kuliah";
        let pctColor = "#e2e8f0";
        let pctText = "100%";
        let pctBg = "#f1f5f9";

        if(filter === 'all') {
            count = total;
            label = "Total Kurikulum";
        } else {
            const items = rawData.filter(x => x.pl.includes(filter));
            count = items.length;
            const pct = ((count / total) * 100).toFixed(0);
            label = plInfo[filter].fullName;
            pctText = `${pct}% Kontribusi`;
            pctColor = plInfo[filter].simpleColor;
            pctBg = `${plInfo[filter].simpleColor}15`;
        }

        const countEl = document.getElementById('stats-count');
        const labelEl = document.getElementById('stats-label');
        const pctEl = document.getElementById('stats-pct');

        animateValue(countEl, parseInt(countEl.innerText), count, 800);
        labelEl.innerText = label;
        pctEl.innerText = pctText;
        if(filter !== 'all') {
            labelEl.style.color = pctColor;
            pctEl.style.color = pctColor;
            pctEl.style.background = pctBg;
        } else {
            labelEl.style.color = 'var(--text-sub)';
            pctEl.style.color = 'var(--text-main)';
            pctEl.style.background = '#e2e8f0';
        }
    }

    function animateValue(obj, start, end, duration) {
        let startTimestamp = null;
        const step = (timestamp) => {
            if (!startTimestamp) startTimestamp = timestamp;
            const progress = Math.min((timestamp - startTimestamp) / duration, 1);
            obj.innerHTML = Math.floor(progress * (end - start - 0) + start);
            if (progress < 1) window.requestAnimationFrame(step);
            else obj.innerHTML = end;
        };
        window.requestAnimationFrame(step);
    }

    // --- RENDER MAIN GRID ---
    function renderGrid(filter = 'all') {
        const grid = document.getElementById('curriculum-grid');
        grid.innerHTML = '';

        const semesters = [1,2,3,4,5,6,7,8];
        const electives = ['Pilihan V', 'Pilihan VI', 'Pilihan VII'];

        semesters.forEach(semId => {
            const col = document.createElement('div');
            col.className = 'semester-col';
            col.innerHTML = `<div class="sem-title">Semester ${semId}</div>`;
            const items = rawData.filter(x => x.sem == semId);
            items.forEach(item => col.appendChild(createCard(item, filter)));
            grid.appendChild(col);
        });

        const div = document.createElement('div');
        div.className = 'electives-divider';
        div.innerHTML = '<h2>Mata Kuliah Pilihan</h2>';
        grid.appendChild(div);

        electives.forEach(semId => {
            const col = document.createElement('div');
            col.className = 'semester-col';
            col.innerHTML = `<div class="sem-title">MK ${semId}</div>`;
            const items = rawData.filter(x => x.sem == semId);
            items.forEach(item => col.appendChild(createCard(item, filter)));
            grid.appendChild(col);
        });
    }

    function createCard(item, filter) {
        const card = document.createElement('div');
        card.className = 'course-card';
        card.setAttribute('data-name', item.name);
        card.id = `card-${item.code}`; 
        
        if(filter !== 'all' && !item.pl.includes(filter)) card.classList.add('dimmed');

        let barBg = '#e2e8f0';
        if(item.pl.length === 1 && plInfo[item.pl[0]]) barBg = plInfo[item.pl[0]].color;
        else if (item.pl.length > 1) {
            const c1 = plInfo[item.pl[0]] ? plInfo[item.pl[0]].simpleColor : '#ccc';
            const c2 = plInfo[item.pl[1]] ? plInfo[item.pl[1]].simpleColor : '#ccc';
            barBg = `linear-gradient(90deg, ${c1}, ${c2})`;
        }

        const bar = document.createElement('div');
        bar.className = 'card-top-bar';
        bar.style.background = barBg;
        card.appendChild(bar);

        const meta = document.createElement('div');
        meta.className = 'card-meta';
        meta.innerHTML = `<span class="code-pill">${item.code}</span><span class="sks-pill">${item.sks} SKS</span>`;
        card.appendChild(meta);

        const name = document.createElement('div');
        name.className = 'card-name';
        name.innerText = item.name;
        card.appendChild(name);

        const dots = document.createElement('div');
        dots.className = 'pl-indicators';
        item.pl.forEach(p => {
            if(plInfo[p]) {
                const dot = document.createElement('div');
                dot.className = 'pl-dot';
                dot.style.background = plInfo[p].color;
                dots.appendChild(dot);
            }
        });
        card.appendChild(dots);

        // Interaction
        card.addEventListener('mouseenter', (e) => {
            showTooltip(e, item, 'course');
            highlightPrereqs(item.pre);
        });
        card.addEventListener('mouseleave', () => {
            hideTooltip();
            clearHighlights();
        });
        card.addEventListener('mousemove', moveTooltip);
        
        // CLICK HANDLER FOR MODAL
        card.addEventListener('click', (e) => {
            e.stopPropagation(); // Prevent bubbling issues
            openModal(item);
        });

        return card;
    }

    // --- MODAL LOGIC ---
    function openModal(item) {
        const modal = document.getElementById('course-modal');
        const details = courseDetails[item.name] || { desc: 'Deskripsi mata kuliah belum tersedia.', pjmk: '-', dosen: ['-'], cpmk: 'Belum tersedia' };

        document.getElementById('m-code').innerText = item.code;
        document.getElementById('m-name').innerText = item.name;
        document.getElementById('m-sks').innerText = item.sks + " SKS";
        
        // PL Tags
        const tagContainer = document.getElementById('m-pl-tags');
        tagContainer.innerHTML = '';
        item.pl.forEach(p => {
            if(plInfo[p]) {
                const tag = document.createElement('span');
                tag.className = 'tt-tag';
                tag.style.background = plInfo[p].color;
                tag.innerText = plInfo[p].name;
                tagContainer.appendChild(tag);
            }
        });

        // Content
        document.getElementById('m-desc').innerText = details.desc;
        document.getElementById('m-cpmk').innerHTML = details.cpmk;
        document.getElementById('m-pjmk').innerHTML = `<strong>${details.pjmk}</strong>`;
        document.getElementById('m-dosen').innerHTML = details.dosen.map(d => `<div>${d}</div>`).join('');

        // CPL Logic
        const cplContainer = document.getElementById('m-cpl');
        if(item.cpl && item.cpl.length > 0) {
            cplContainer.innerHTML = item.cpl.map(num => `
                <div style="margin-bottom:6px;">
                    <span style="font-weight:700; color:#0f172a;">CPL ${num}:</span> ${CPL_DESC['CPL-'+num] || ''}
                </div>
            `).join('');
        } else {
            cplContainer.innerText = "-";
        }

        // Prereqs
        const preContainer = document.getElementById('m-pre');
        if(item.pre && item.pre !== 'N / A') {
            const names = item.pre.split('|');
            preContainer.innerHTML = names.map(n => `<span style="display:inline-block; background:#e0f2fe; color:#0369a1; padding:2px 8px; border-radius:4px; font-size:0.85rem; margin-right:6px; margin-bottom:4px;">${n}</span>`).join('');
        } else {
            preContainer.innerHTML = '<span style="color:#94a3b8; font-style:italic;">Tidak ada prasyarat</span>';
        }

        modal.classList.add('active');
    }

    function closeModal() {
        document.getElementById('course-modal').classList.remove('active');
    }

    // --- HIGHLIGHTING ---
    function highlightPrereqs(preString) {
        if(!preString || preString === 'N / A') return;
        const names = preString.split('|').map(s => s.trim());
        names.forEach(name => {
            const cards = document.querySelectorAll('.course-card');
            cards.forEach(card => {
                if(card.getAttribute('data-name') === name) card.classList.add('is-prereq');
            });
        });
    }

    function clearHighlights() {
        document.querySelectorAll('.is-prereq').forEach(el => el.classList.remove('is-prereq'));
    }

    // --- TOOLTIPS ---
    const tooltip = document.getElementById('tooltip');

    function showTooltip(e, data, type) {
        let html = '';
        if(type === 'course') {
            html += `<div class="tt-header">
                        <span class="tt-code">${data.code} • ${data.sks} SKS</span>
                        <div class="tt-title">${data.name}</div>
                     </div>`;
            html += `<div class="tt-tags">`;
            data.pl.forEach(p => {
                if(plInfo[p]) html += `<span class="tt-tag" style="background:${plInfo[p].color}">${plInfo[p].name}</span>`;
            });
            html += `</div>`;

            html += `<span class="tt-label">Prasyarat</span>`;
            if(data.pre && data.pre !== 'N / A') {
                const names = data.pre.split('|');
                html += `<div class="prereq-list">`;
                names.forEach(name => { html += `<span class="prereq-item">➥ ${name}</span>`; });
                html += `</div>`;
            } else {
                html += `<span style="color:#64748b; font-size:0.8rem; font-style:italic;">Tidak ada prasyarat</span>`;
            }
            html += `<div style="margin-top:10px; font-size:0.7rem; color:#fff; opacity:0.7; text-align:center;">(Klik untuk detail)</div>`;
        
        } else if (type === 'filter') {
            const info = plInfo[data];
            html += `<div class="tt-header" style="border-color:${info.simpleColor}">
                        <div class="tt-title" style="color:${info.simpleColor}">${info.fullName}</div>
                     </div>
                     <div class="ft-desc">${info.desc}</div>
                     <span class="tt-label">Prospek Karir</span>
                     <ul class="ft-jobs">
                        ${info.jobs.map(j => `<li>${j}</li>`).join('')}
                     </ul>`;
        }

        tooltip.innerHTML = html;
        tooltip.style.display = 'block';
        moveTooltip(e);
    }

    function moveTooltip(e) {
        const w = window.innerWidth;
        const h = window.innerHeight;
        let x = e.clientX + 20;
        let y = e.clientY + 20;
        if (x + 360 > w) x = e.clientX - 370;
        if (y + 300 > h) y = e.clientY - 300;
        tooltip.style.left = x + 'px';
        tooltip.style.top = y + 'px';
    }

    function hideTooltip() { tooltip.style.display = 'none'; }

    // --- FILTER EVENTS ---
    function filterData(filter, btn) {
        document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
        btn.classList.add('active');
        renderGrid(filter);
        updateStatsUI(filter);
    }

    document.querySelectorAll('.filter-btn').forEach(btn => {
        const pl = btn.getAttribute('data-pl');
        if(pl) {
            btn.addEventListener('mouseenter', (e) => showTooltip(e, pl, 'filter'));
            btn.addEventListener('mouseleave', hideTooltip);
            btn.addEventListener('mousemove', moveTooltip);
        }
    });

    window.onload = () => {
        renderStats();
        renderGrid('all');
    };

</script>
</body>
</html>

Category: