Files
edukarsa/documentation.html

1292 lines
79 KiB
HTML

<!DOCTYPE html>
<html lang="id" class="scroll-smooth">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>EduKarsa - Native WordPress Theme Documentation & Architecture Explorer</title>
<!-- Tailwind CSS CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Chart.js CDN -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
brand: {
50: '#f0f7ff',
100: '#e0effe',
600: '#1a73e8',
800: '#0b4a8e',
900: '#0a3a6f',
},
accent: {
500: '#f59e0b',
600: '#d97706',
}
}
}
}
}
</script>
<style>
.chart-container {
position: relative;
width: 100%;
max-width: 600px;
margin-left: auto;
margin-right: auto;
height: 300px;
max-height: 400px;
}
@media (min-width: 768px) {
.chart-container {
height: 340px;
}
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: #f1f5f9;
}
::-webkit-scrollbar-thumb {
background: #cbd5e1;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #94a3b8;
}
/* High contrast mode simulation class */
.a11y-high-contrast {
filter: contrast(175%) !important;
background-color: #000000 !important;
color: #ffff00 !important;
}
.a11y-high-contrast * {
border-color: #ffff00 !important;
}
</style>
</head>
<body class="bg-slate-50 text-slate-800 font-sans antialiased min-h-screen flex flex-col transition-all duration-300" id="app-body">
<!-- Chosen Palette: Warm Institutional Slate (Primary: #0b4a8e, Secondary: #1a73e8, Warm Amber Accent: #f59e0b, Neutral Light BG: #f8fafc) -->
<!-- Application Structure Plan:
1. Sticky Navigation & Live Search Header: Seamless section switching, global search across functions, CPTs, asset guidelines, and configuration options.
2. Dashboard Hero & Performance Metric Center: Highlighting the key technical specs, 0-plugin native WP core philosophy, and interactive Chart.js benchmark comparisons (EduKarsa vs Heavy Plugin Themes).
3. 7 Architectural & Security Pillars: Interactive cards with code insights + live WCAG 2.1 accessibility simulator widget.
4. Asset Dimension Calculator & Ratio Visualizer: Interactive selector for all 6 media assets with dynamic specs and HTML5 Canvas proportional visualizer.
5. Modular Code Explorer (File Tree): Interactive filterable tree view of theme root files and inc/ modules with detailed hook & functionality descriptions.
6. Native Layout Builder Simulator: Drag-and-drop / order manipulator simulating backend jQuery UI sortable with live wireframe representation.
7. Interactive Quick Start Guide & Setup Checklist: Interactive workflow tracker with dynamic progress calculation.
RATIONALE: Designed to transform static text/table technical documentation into an intuitive visual and operational experience for school IT admins, developers, and institution decision-makers.
-->
<!-- Visualization & Content Choices:
- Performance Benchmark: Chart.js Bar Chart (Compares Load Time, DB Queries, HTTP Requests, Asset Size). Goal: Compare efficiency.
- Architecture Codebase Breakdown: Chart.js Donut Chart (Shows proportions of Security, CPTs, Admin Settings, SEO, i18n, Core Templates). Goal: Inform code structure.
- Asset Recommended Size Limits: Chart.js Horizontal Bar (Visualizes max file sizes for assets). Goal: Guideline clarity.
- Asset Canvas Preview: Custom HTML5 Canvas rendering exact proportional ratios. Goal: Immediate visual feedback.
- Layout Builder: Interactive JS reordering list + dynamic HTML/CSS wireframe builder. Goal: Process simulation.
- WCAG Simulation: JS Web Speech API + CSS scale/contrast toggles. Goal: Interactive feature proofing.
- NO SVG used anywhere. All icons rendered via structured HTML badges, CSS styling, Canvas, or standard Unicode characters. NO Mermaid JS used.
-->
<!-- CONFIRMATION: NO SVG graphics used. NO Mermaid JS used. -->
<!-- HEADER / NAVIGATION -->
<header class="sticky top-0 z-50 bg-brand-800 text-white shadow-md border-b border-brand-900">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-16">
<!-- Brand Title -->
<div class="flex items-center gap-3">
<div class="w-10 h-10 rounded-lg bg-accent-500 text-slate-900 font-black text-xl flex items-center justify-center shadow-inner">
EK
</div>
<div>
<h1 class="font-bold text-lg leading-tight tracking-tight text-white">EduKarsa</h1>
<p class="text-xs text-brand-100 font-medium hidden sm:block">Native WordPress Theme Explorer & Architecture Docs</p>
</div>
</div>
<!-- Desktop Nav Tabs -->
<nav class="hidden md:flex items-center space-x-1 font-medium text-sm">
<button onclick="scrollToSection('overview')" class="nav-btn px-3 py-2 rounded-md text-brand-100 hover:text-white hover:bg-brand-900 transition-colors">Ringkasan</button>
<button onclick="scrollToSection('architecture')" class="nav-btn px-3 py-2 rounded-md text-brand-100 hover:text-white hover:bg-brand-900 transition-colors">Pilar & Keamanan</button>
<button onclick="scrollToSection('assets')" class="nav-btn px-3 py-2 rounded-md text-brand-100 hover:text-white hover:bg-brand-900 transition-colors">Dimensi Aset</button>
<button onclick="scrollToSection('code-tree')" class="nav-btn px-3 py-2 rounded-md text-brand-100 hover:text-white hover:bg-brand-900 transition-colors">Struktur Kode</button>
<button onclick="scrollToSection('layout-simulator')" class="nav-btn px-3 py-2 rounded-md text-brand-100 hover:text-white hover:bg-brand-900 transition-colors">Simulator Builder</button>
<button onclick="scrollToSection('quick-start')" class="nav-btn px-3 py-2 rounded-md text-brand-100 hover:text-white hover:bg-brand-900 transition-colors">Panduan Setup</button>
</nav>
<!-- Search & Status -->
<div class="flex items-center gap-2">
<div class="relative">
<input type="text" id="globalSearchInput" oninput="handleGlobalSearch()" placeholder="Cari fitur, file, aset..." class="w-36 sm:w-48 px-3 py-1.5 text-xs rounded-full bg-brand-900 text-white placeholder-brand-100 border border-brand-600 focus:outline-none focus:ring-2 focus:ring-accent-500">
</div>
<span class="bg-emerald-500 text-slate-950 font-bold text-[10px] uppercase px-2 py-1 rounded-md tracking-wider">v1.0 Native</span>
</div>
</div>
</div>
<!-- Mobile Nav bar -->
<div class="md:hidden flex overflow-x-auto bg-brand-900 px-4 py-2 text-xs border-t border-brand-800 gap-3">
<button onclick="scrollToSection('overview')" class="text-white whitespace-nowrap">Ringkasan</button>
<button onclick="scrollToSection('architecture')" class="text-white whitespace-nowrap">Pilar & Keamanan</button>
<button onclick="scrollToSection('assets')" class="text-white whitespace-nowrap">Dimensi Aset</button>
<button onclick="scrollToSection('code-tree')" class="text-white whitespace-nowrap">Struktur Kode</button>
<button onclick="scrollToSection('layout-simulator')" class="text-white whitespace-nowrap">Simulator</button>
<button onclick="scrollToSection('quick-start')" class="text-white whitespace-nowrap">Setup</button>
</div>
</header>
<!-- SEARCH RESULTS MODAL / NOTIFICATION -->
<div id="searchResultsBox" class="hidden fixed inset-x-0 top-16 z-40 bg-white border-b border-slate-200 shadow-2xl max-w-4xl mx-auto p-4 rounded-b-xl max-h-96 overflow-y-auto">
<div class="flex justify-between items-center mb-2 pb-2 border-b border-slate-100">
<h3 class="text-xs font-bold uppercase tracking-wider text-slate-500">Hasil Pencarian Interaktif</h3>
<button onclick="closeSearchBox()" class="text-slate-400 hover:text-slate-600 font-bold text-sm">✕ Tutup</button>
</div>
<div id="searchResultsList" class="space-y-2 text-sm"></div>
</div>
<!-- MAIN CONTENT AREA -->
<main class="flex-grow max-w-7xl w-full mx-auto px-4 sm:px-6 lg:px-8 py-8 space-y-12">
<!-- SECTION 1: OVERVIEW & PERFORMANCE DASHBOARD -->
<section id="overview" class="space-y-6 scroll-mt-20">
<!-- Section Introductory Paragraph -->
<div class="bg-white p-6 sm:p-8 rounded-2xl border border-slate-200 shadow-sm relative overflow-hidden">
<div class="absolute top-0 right-0 w-64 h-64 bg-brand-50 rounded-full blur-3xl -z-10 opacity-70"></div>
<div class="max-w-3xl space-y-3">
<span class="inline-block bg-brand-100 text-brand-800 text-xs font-bold px-3 py-1 rounded-full uppercase tracking-wider">
Enterprise-Grade Educational Theme Architecture
</span>
<h2 class="text-2xl sm:text-3xl font-extrabold text-slate-900 tracking-tight">
Dokumentasi Arsitektur & Portal Eksplorasi EduKarsa
</h2>
<p class="text-slate-600 leading-relaxed text-sm sm:text-base">
EduKarsa didesain khusus untuk portal resmi sekolah, madrasah, pesantren, dan perguruan tinggi dengan filosofi <strong>100% Native & Zero Plugin</strong>. Aplikasi dokumentasi interaktif ini memungkinkan Anda mengeksplorasi metrik kinerja, struktur modular file, aturan dimensi media, fitur keamanan native, hingga mensimulasikan tata letak beranda secara langsung.
</p>
<div class="flex flex-wrap gap-4 pt-2">
<a href="https://edukarsa.masbudi.my.id" target="_blank" class="inline-flex items-center gap-2 bg-brand-800 hover:bg-brand-900 text-white text-xs font-bold px-4 py-2.5 rounded-lg shadow-sm transition-all">
<span>🌐 Live Demo Situs</span>
</a>
<a href="https://apps.masbudi.my.id/edukarsa" target="_blank" class="inline-flex items-center gap-2 bg-slate-100 hover:bg-slate-200 text-slate-800 text-xs font-bold px-4 py-2.5 rounded-lg border border-slate-300 transition-all">
<span>📦 Portal Aplikasi</span>
</a>
<a href="https://donate.masbudi.my.id/edukarsa" target="_blank" class="inline-flex items-center gap-2 bg-amber-500 hover:bg-amber-600 text-slate-950 text-xs font-bold px-4 py-2.5 rounded-lg shadow-sm transition-all">
<span>☕ Dukung Pengembang</span>
</a>
</div>
</div>
</div>
<!-- KPI Metric Cards Grid -->
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<div class="bg-white p-5 rounded-xl border border-slate-200 shadow-sm hover:border-brand-600 transition-all">
<div class="text-2xl font-black text-brand-800 mb-1">0 Plugin</div>
<div class="text-xs font-bold uppercase tracking-wider text-slate-500">Dependensi Pihak Ke-3</div>
<p class="text-xs text-slate-600 mt-2">Bebas Elementor, ACF, atau plugin galeri. Lebih hemat lisensi & aman.</p>
</div>
<div class="bg-white p-5 rounded-xl border border-slate-200 shadow-sm hover:border-brand-600 transition-all">
<div class="text-2xl font-black text-emerald-600 mb-1">&lt; 300 ms</div>
<div class="text-xs font-bold uppercase tracking-wider text-slate-500">Waktu Muat Rata-Rata</div>
<p class="text-xs text-slate-600 mt-2">Eksekusi kode native tanpa overhead query plugin tambahan.</p>
</div>
<div class="bg-white p-5 rounded-xl border border-slate-200 shadow-sm hover:border-brand-600 transition-all">
<div class="text-2xl font-black text-amber-500 mb-1">WCAG 2.1</div>
<div class="text-xs font-bold uppercase tracking-wider text-slate-500">Standar Aksesibilitas</div>
<p class="text-xs text-slate-600 mt-2">Pustaka ramah disabilitas dengan pembaca suara & mode kontras tinggi.</p>
</div>
<div class="bg-white p-5 rounded-xl border border-slate-200 shadow-sm hover:border-brand-600 transition-all">
<div class="text-2xl font-black text-indigo-600 mb-1">5 Bahasa</div>
<div class="text-xs font-bold uppercase tracking-wider text-slate-500">Frontend Multilingual</div>
<p class="text-xs text-slate-600 mt-2">Dukungan bawaan Bahasa Indonesia, English, Arabic, Chinese, & Japanese.</p>
</div>
</div>
<!-- Visualizations Container Grid -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- Chart 1: Benchmark Performance Comparison -->
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm flex flex-col justify-between">
<div>
<div class="flex justify-between items-start mb-2">
<div>
<h3 class="font-bold text-slate-900 text-base">Komparasi Performa Native vs Plugin Heavy</h3>
<p class="text-xs text-slate-500">Metrik komparatifEduKarsa dibandingkan tema sekolah berbasis 15+ plugin.</p>
</div>
<span class="text-[10px] bg-brand-50 text-brand-800 font-bold px-2 py-1 rounded">Chart.js Live</span>
</div>
<p class="text-xs text-slate-600 mb-4">
Grafik ini menggambarkan efisiensi sumber daya sistem. EduKarsa secara signifikan memangkas waktu muat (*load time*), kueri database, serta beban payload halaman web sekolah Anda.
</p>
</div>
<div class="chart-container">
<canvas id="benchmarkChart"></canvas>
</div>
<div class="mt-4 pt-3 border-t border-slate-100 text-xs text-slate-500 flex justify-between items-center">
<span>💡 Sumber: Hasil pengujian lingkungan WordPress 6.x standar</span>
<button onclick="toggleChartMetric()" class="text-brand-600 font-bold hover:underline">Ganti Mode Tampilan</button>
</div>
</div>
<!-- Chart 2: Codebase Modular Distribution -->
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm flex flex-col justify-between">
<div>
<div class="flex justify-between items-start mb-2">
<div>
<h3 class="font-bold text-slate-900 text-base">Distribusi Modul Kode (`inc/` Architecture)</h3>
<p class="text-xs text-slate-500">Persentase porsi tanggung jawab fungsi pada arsitektur terisolasi EduKarsa.</p>
</div>
<span class="text-[10px] bg-brand-50 text-brand-800 font-bold px-2 py-1 rounded">Donut View</span>
</div>
<p class="text-xs text-slate-600 mb-4">
Tampilan lingkaran ini menunjukkan pemisahan tugas (*separation of concerns*) di mana berkas `functions.php` hanya bertindak sebagai pemuat, sementara logika bisnis diisolasi dalam direktori `inc/`.
</p>
</div>
<div class="chart-container">
<canvas id="architectureChart"></canvas>
</div>
<div class="mt-4 pt-3 border-t border-slate-100 text-xs text-slate-500 flex justify-between items-center">
<span>🧩 Arsitektur terisolasi memudahkan pemeliharaan tanpa efek samping</span>
</div>
</div>
</div>
</section>
<!-- SECTION 2: ARCHITECTURE & SECURITY PILLARS + ACCESSIBILITY DEMO -->
<section id="architecture" class="space-y-6 scroll-mt-20">
<!-- Section Intro -->
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm">
<span class="text-xs font-bold text-brand-600 uppercase tracking-wider">7 Pilar Inti Arsitektur & Keamanan</span>
<h2 class="text-xl sm:text-2xl font-bold text-slate-900 mt-1">Struktur Andal, Aman, & Ramah Aksesibilitas</h2>
<p class="text-xs sm:text-sm text-slate-600 mt-2">
EduKarsa dibangun dengan standar keamanan enterprise dan prinsip aksesibilitas publik (WCAG 2.1). Pilih salah satu pilar di bawah ini untuk melihat detail teknis, proteksi native, serta cara kerjanya.
</p>
</div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- 7 Pillars Selector List (1 Column) -->
<div class="bg-white p-4 rounded-2xl border border-slate-200 shadow-sm space-y-2 lg:col-span-1">
<h3 class="text-xs font-bold uppercase tracking-wider text-slate-400 px-3 py-1">Daftar Pilar Arsitektur</h3>
<div id="pillarButtonsContainer" class="space-y-1">
<!-- Dynamic Buttons inserted by JS -->
</div>
</div>
<!-- Pillar Detail Card + Interactive WCAG Tool (2 Columns) -->
<div class="lg:col-span-2 space-y-6">
<!-- Selected Pillar Detail Pane -->
<div id="pillarDetailPane" class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-4">
<!-- Populated dynamically via JS -->
</div>
<!-- WCAG 2.1 Live Accessibility Toolbar Simulator -->
<div class="bg-slate-900 text-white p-6 rounded-2xl shadow-md border border-slate-800 space-y-4">
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-2 pb-3 border-b border-slate-800">
<div>
<span class="bg-amber-500 text-slate-950 text-[10px] font-black uppercase px-2 py-0.5 rounded">Simulasi Toolbar Aksesibilitas</span>
<h3 class="font-bold text-base text-white mt-1">Uji Coba Toolbar Aksesibilitas WCAG 2.1 Native</h3>
</div>
<span class="text-xs text-slate-400">Web Speech API & CSS Scaler Integration</span>
</div>
<p class="text-xs text-slate-300 leading-relaxed">
Di situs EduKarsa, pengguna disabilitas visual dapat mengaktifkan toolbar melayang bawaan tanpa memerlukan plugin tambahan. Silakan coba fitur pengujian interaktif di bawah ini:
</p>
<!-- Controls -->
<div class="flex flex-wrap items-center gap-3 pt-2">
<button onclick="simulateHighContrast()" id="btnContrastSim" class="bg-slate-800 hover:bg-slate-700 text-amber-400 font-bold text-xs px-3 py-2 rounded-lg border border-slate-700 transition-all">
👁️ Toggle Kontras Tinggi
</button>
<div class="flex items-center gap-1 bg-slate-800 p-1 rounded-lg border border-slate-700">
<span class="text-xs text-slate-400 px-2 font-medium">Ukuran Teks:</span>
<button onclick="changeSimFontSize(-2)" class="px-2 py-1 bg-slate-700 hover:bg-slate-600 text-white rounded text-xs font-bold">-</button>
<span id="simFontLabel" class="text-xs font-mono font-bold px-2 text-amber-400">100%</span>
<button onclick="changeSimFontSize(2)" class="px-2 py-1 bg-slate-700 hover:bg-slate-600 text-white rounded text-xs font-bold">+</button>
</div>
<button onclick="simulateScreenReader()" class="bg-brand-600 hover:bg-brand-700 text-white font-bold text-xs px-3 py-2 rounded-lg transition-all flex items-center gap-1">
🔊 Tes Pembaca Suara (Text-to-Speech)
</button>
</div>
<!-- Sample Test Paragraph Box -->
<div id="a11yTestTarget" class="bg-slate-800/80 p-4 rounded-xl border border-slate-700 text-slate-200 text-sm leading-relaxed transition-all">
<strong class="text-amber-400">Teks Pengujian Aksesibilitas:</strong>
<p id="a11yTextSample" class="mt-1">
"Selamat datang di Portal Resmi EduKarsa. Tema ini dirancang agar dapat diakses secara inklusif oleh seluruh lapisan masyarakat, termasuk penyandang disabilitas penglihatan melalui teknologi pembaca layar bawaan."
</p>
</div>
</div>
</div>
</div>
</section>
<!-- SECTION 3: ASSET DIMENSION RECOMMENDATIONS & SPEC TOOL -->
<section id="assets" class="space-y-6 scroll-mt-20">
<!-- Section Intro -->
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm">
<span class="text-xs font-bold text-brand-600 uppercase tracking-wider">Rekomendasi Dimensi Aset Media</span>
<h2 class="text-xl sm:text-2xl font-bold text-slate-900 mt-1">Panduan Proporsi & Kalkulator Visual Aset</h2>
<p class="text-xs sm:text-sm text-slate-600 mt-2">
Untuk memastikan tampilan web sekolah tajam, tidak terpotong secara tidak profesional, serta cepat saat diunggah, ikuti panduan dimensi dan rasio gambar bawaan EduKarsa berikut.
</p>
</div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- Asset Selector Buttons & Spec Sheet (2 Columns) -->
<div class="lg:col-span-2 bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-6">
<div>
<h3 class="text-xs font-bold uppercase tracking-wider text-slate-400 mb-3">Pilih Jenis Aset Media</h3>
<div id="assetSelectorGrid" class="grid grid-cols-2 sm:grid-cols-3 gap-2">
<!-- Populated dynamically by JS -->
</div>
</div>
<!-- Selected Asset Specs Detail -->
<div id="assetSpecBox" class="bg-slate-50 p-5 rounded-xl border border-slate-200 space-y-3">
<!-- Populated dynamically by JS -->
</div>
<!-- Max File Size Chart (Chart 3) -->
<div class="pt-4 border-t border-slate-100">
<div class="flex justify-between items-center mb-2">
<h4 class="font-bold text-slate-800 text-xs uppercase tracking-wider">Batas Maksimal Ukuran Berkas Rekomendasi (KB)</h4>
<span class="text-[10px] text-slate-400">Format Ideal: WebP / JPG</span>
</div>
<div class="chart-container" style="height: 220px; max-height: 250px;">
<canvas id="assetSizeChart"></canvas>
</div>
</div>
</div>
<!-- Live Canvas Aspect Ratio Visualizer (1 Column) -->
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm flex flex-col justify-between">
<div>
<div class="flex items-center justify-between mb-2">
<h3 class="font-bold text-slate-900 text-sm">Visualisator Rasio Canvas</h3>
<span id="canvasRatioBadge" class="bg-brand-100 text-brand-800 font-bold text-[10px] px-2 py-0.5 rounded">16:9</span>
</div>
<p class="text-xs text-slate-500 mb-4">
Kanvas interaktif di bawah menggambarkan orientasi dan perbandingan proporsi gambar aktual dibandingkan ruang tampilan layout.
</p>
</div>
<!-- HTML5 Canvas Preview Container -->
<div class="w-full bg-slate-100 rounded-xl p-4 flex items-center justify-center border border-slate-200 min-h-[220px]">
<canvas id="ratioPreviewCanvas" width="300" height="200" class="max-w-full rounded shadow-sm border border-slate-300 bg-white"></canvas>
</div>
<div class="mt-4 pt-3 border-t border-slate-100 text-[11px] text-slate-500 space-y-1">
<div class="flex justify-between">
<span>Format Direkomendasikan:</span>
<strong id="canvasFormatText" class="text-slate-700">WebP / JPG</strong>
</div>
<div class="flex justify-between">
<span>Target Kompresi:</span>
<strong id="canvasSizeText" class="text-emerald-600">&lt; 300 KB</strong>
</div>
</div>
</div>
</div>
</section>
<!-- SECTION 4: THEME FILE STRUCTURE & CODE MAP (TREE VIEW) -->
<section id="code-tree" class="space-y-6 scroll-mt-20">
<!-- Section Intro -->
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm">
<span class="text-xs font-bold text-brand-600 uppercase tracking-wider">Arsitektur Berkas & Peta Kode</span>
<h2 class="text-xl sm:text-2xl font-bold text-slate-900 mt-1">Eksplorasi Direktori Terisolasi `inc/`</h2>
<p class="text-xs sm:text-sm text-slate-600 mt-2">
EduKarsa menerapkan pola modul terpisah. Berkas `functions.php` bersih dan hanya berfungsi sebagai pemuat (*loader*). Pilih file di bawah untuk mempelajari fungsi, hook WordPress yang digunakan, serta tanggung jawab kodenya.
</p>
</div>
<!-- Filter Buttons & Search -->
<div class="flex flex-wrap items-center justify-between gap-3 bg-white p-4 rounded-xl border border-slate-200 shadow-sm">
<div class="flex flex-wrap gap-2 text-xs font-semibold" id="fileFilterButtons">
<button onclick="filterFileList('all')" class="filter-file-btn bg-brand-800 text-white px-3 py-1.5 rounded-lg">Semua Berkas</button>
<button onclick="filterFileList('core')" class="filter-file-btn bg-slate-100 text-slate-700 hover:bg-slate-200 px-3 py-1.5 rounded-lg">Core & Loader</button>
<button onclick="filterFileList('inc')" class="filter-file-btn bg-slate-100 text-slate-700 hover:bg-slate-200 px-3 py-1.5 rounded-lg">Modul `inc/`</button>
<button onclick="filterFileList('template')" class="filter-file-btn bg-slate-100 text-slate-700 hover:bg-slate-200 px-3 py-1.5 rounded-lg">Template Halaman</button>
</div>
<span id="fileCountBadge" class="text-xs text-slate-500 font-medium">17 Berkas Terdaftar</span>
</div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- File Tree Navigator List (1 Column) -->
<div class="bg-white p-4 rounded-2xl border border-slate-200 shadow-sm max-h-[500px] overflow-y-auto space-y-1">
<div class="text-xs font-bold uppercase tracking-wider text-slate-400 px-3 py-2 border-b border-slate-100 mb-2">
edukarsa/ (Struktur Tema)
</div>
<div id="fileTreeItems" class="space-y-1">
<!-- File items populated dynamically by JS -->
</div>
</div>
<!-- Selected File Inspector Card (2 Columns) -->
<div id="fileInspectorPane" class="lg:col-span-2 bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-4">
<!-- Populated dynamically by JS -->
</div>
</div>
</section>
<!-- SECTION 5: INTERACTIVE HOMEPAGE LAYOUT BUILDER SIMULATOR -->
<section id="layout-simulator" class="space-y-6 scroll-mt-20">
<!-- Section Intro -->
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm">
<span class="text-xs font-bold text-brand-600 uppercase tracking-wider">Simulator Builder Tata Letak Native</span>
<h2 class="text-xl sm:text-2xl font-bold text-slate-900 mt-1">Uji Coba Pengaturan Urutan Seksi Beranda</h2>
<p class="text-xs sm:text-sm text-slate-600 mt-2">
EduKarsa memiliki UI builder bawaan di menu <strong>EduKarsa &gt; 🏗️ Tata Letak</strong> menggunakan pustaka bawaan WordPress (`jQuery UI Sortable`). Ubah urutan atau aktifkan/nonaktifkan seksi di bawah ini untuk melihat pratinjau struktur wireframe beranda secara langsung.
</p>
</div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- Control Panel List (1 Column) -->
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-4">
<div class="flex items-center justify-between border-b border-slate-100 pb-3">
<h3 class="font-bold text-slate-900 text-sm">Urutan Seksi Beranda</h3>
<button onclick="resetLayoutOrder()" class="text-xs text-brand-600 hover:underline font-bold">Reset Default</button>
</div>
<p class="text-xs text-slate-500">Gunakan tombol ⬆️ Naik, ⬇️ Turun, atau centang untuk menyembunyikan seksi.</p>
<div id="layoutBuilderControls" class="space-y-2">
<!-- Dynamic Section controls inserted via JS -->
</div>
</div>
<!-- Live Wireframe Canvas / Visualizer (2 Columns) -->
<div class="lg:col-span-2 bg-slate-900 p-6 rounded-2xl shadow-xl border border-slate-800 space-y-4 flex flex-col justify-between">
<div>
<div class="flex items-center justify-between pb-3 border-b border-slate-800">
<div>
<span class="bg-emerald-500 text-slate-950 text-[10px] font-black uppercase px-2 py-0.5 rounded">Pratinjau Wireframe Live</span>
<h3 class="font-bold text-base text-white mt-1">Struktur Beranda Aktif (`front-page.php`)</h3>
</div>
<button onclick="copyLayoutConfig()" class="bg-slate-800 hover:bg-slate-700 text-slate-200 text-xs px-3 py-1.5 rounded border border-slate-700 font-medium">
📋 Salin Ringkasan Layout
</button>
</div>
<!-- Live Rendered Wireframe Box -->
<div id="wireframeContainer" class="mt-4 space-y-3 max-h-[500px] overflow-y-auto pr-2">
<!-- Dynamically updated wireframe blocks via JS -->
</div>
</div>
<div class="pt-3 border-t border-slate-800 text-xs text-slate-400 flex justify-between items-center">
<span>💡 Pengaturan ini disimpan langsung di `wp_options` via WordPress Settings API.</span>
</div>
</div>
</div>
</section>
<!-- SECTION 6: QUICK START GUIDE & SETUP CHECKLIST -->
<section id="quick-start" class="space-y-6 scroll-mt-20">
<!-- Section Intro -->
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm">
<span class="text-xs font-bold text-brand-600 uppercase tracking-wider">Petunjuk Penggunaan & Workflow</span>
<h2 class="text-xl sm:text-2xl font-bold text-slate-900 mt-1">Checklist Peluncuran Tema EduKarsa</h2>
<p class="text-xs sm:text-sm text-slate-600 mt-2">
Ikuti 4 langkah taktis berikut untuk mengonfigurasi situs web sekolah Anda dari nol hingga siap dipublikasikan. Centang setiap tugas yang selesai untuk memantau progres peluncuran.
</p>
</div>
<!-- Progress Bar -->
<div class="bg-white p-5 rounded-2xl border border-slate-200 shadow-sm space-y-2">
<div class="flex justify-between items-center text-xs font-bold">
<span class="text-slate-700">Progres Kesiapan Situs Web Sekolah:</span>
<span id="setupProgressPercent" class="text-brand-800 text-sm">0% Selesai</span>
</div>
<div class="w-full bg-slate-100 rounded-full h-3 overflow-hidden border border-slate-200">
<div id="setupProgressBar" class="bg-brand-600 h-full w-0 transition-all duration-500"></div>
</div>
</div>
<!-- Workflow Cards Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Step 1 -->
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-3">
<div class="flex items-center gap-3">
<span class="w-8 h-8 rounded-full bg-brand-800 text-white font-black text-sm flex items-center justify-center">1</span>
<h3 class="font-bold text-slate-900 text-base">Pengaturan Identitas & Kontak</h3>
</div>
<p class="text-xs text-slate-600 leading-relaxed">
Masuk ke menu <strong>EduKarsa &gt; ⚙️ Pengaturan Utama</strong> di Dasbor WordPress Anda.
</p>
<ul class="space-y-2 text-xs text-slate-700 pt-2">
<li class="flex items-start gap-2">
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
<span>Unggah Logo Header (PNG Transparan / WebP, tinggi 110px).</span>
</li>
<li class="flex items-start gap-2">
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
<span>Isi profil sekolah, alamat lengkap, nomor telepon, & email resmi.</span>
</li>
<li class="flex items-start gap-2">
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
<span>Tautkan URL media sosial resmi (Facebook, Instagram, YouTube).</span>
</li>
</ul>
</div>
<!-- Step 2 -->
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-3">
<div class="flex items-center gap-3">
<span class="w-8 h-8 rounded-full bg-brand-800 text-white font-black text-sm flex items-center justify-center">2</span>
<h3 class="font-bold text-slate-900 text-base">Menyusun Tata Letak Beranda</h3>
</div>
<p class="text-xs text-slate-600 leading-relaxed">
Atur struktur tampilan utama agar sesuai dengan kebutuhan informasi calon siswa & wali murid.
</p>
<ul class="space-y-2 text-xs text-slate-700 pt-2">
<li class="flex items-start gap-2">
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
<span>Buka <strong>EduKarsa &gt; 🏗️ Tata Letak</strong>.</span>
</li>
<li class="flex items-start gap-2">
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
<span>Geser (*drag and drop*) urutan seksi hero, statistik, program, & berita.</span>
</li>
<li class="flex items-start gap-2">
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
<span>Simpan susunan urutan tata letak.</span>
</li>
</ul>
</div>
<!-- Step 3 -->
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-3">
<div class="flex items-center gap-3">
<span class="w-8 h-8 rounded-full bg-brand-800 text-white font-black text-sm flex items-center justify-center">3</span>
<h3 class="font-bold text-slate-900 text-base">Membuat Halaman Galeri & Fasilitas</h3>
</div>
<p class="text-xs text-slate-600 leading-relaxed">
Tampilkan dokumentasi laboratorium, ruang kelas, perpustakaan, dan kegiatan kampus.
</p>
<ul class="space-y-2 text-xs text-slate-700 pt-2">
<li class="flex items-start gap-2">
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
<span>Tambahkan foto di <strong>EduKarsa &gt; 📸 Galeri Fasilitas</strong>.</span>
</li>
<li class="flex items-start gap-2">
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
<span>Buat Laman baru (**Laman &gt; Tambah Baru**).</span>
</li>
<li class="flex items-start gap-2">
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
<span>Pilih atribut template <strong>Galeri & Fasilitas</strong>, lalu terbitkan.</span>
</li>
</ul>
</div>
<!-- Step 4 -->
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-3">
<div class="flex items-center gap-3">
<span class="w-8 h-8 rounded-full bg-brand-800 text-white font-black text-sm flex items-center justify-center">4</span>
<h3 class="font-bold text-slate-900 text-base">Pengumuman & Pop-up Flyer PPDB</h3>
</div>
<p class="text-xs text-slate-600 leading-relaxed">
Aktifkan dialog pop-up promosi pendaftaran penerimaan siswa baru secara otomatis.
</p>
<ul class="space-y-2 text-xs text-slate-700 pt-2">
<li class="flex items-start gap-2">
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
<span>Buka panel <strong>🪟 8. Pop-up Flyer & Pengumuman</strong>.</span>
</li>
<li class="flex items-start gap-2">
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
<span>Aktifkan sakelar dan unggah flyer poster (min 800x800 px).</span>
</li>
<li class="flex items-start gap-2">
<input type="checkbox" onchange="updateSetupProgress()" class="setup-chk mt-0.5 rounded text-brand-600">
<span>Masukkan tautan tujuan pendaftaran online (PPDB), lalu simpan.</span>
</li>
</ul>
</div>
</div>
</section>
</main>
<!-- FOOTER -->
<footer class="bg-slate-900 text-white border-t border-slate-800 py-8 mt-12 text-xs">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex flex-col sm:flex-row justify-between items-center gap-4 text-center sm:text-left">
<div>
<p class="font-bold text-white">EduKarsa - Enterprise Native WordPress Theme</p>
<p class="text-slate-400 mt-0.5">Dirancang dan dikembangkan secara independen oleh <strong>Mas Budi Kusuma</strong>.</p>
</div>
<div class="flex items-center gap-4 text-slate-400">
<a href="https://masbudi.my.id" target="_blank" class="hover:text-white transition-colors">masbudi.my.id</a>
<span>•</span>
<a href="mailto:[email protected]" class="hover:text-white transition-colors">[email protected]</a>
<span>•</span>
<span class="bg-slate-800 text-amber-400 px-2 py-1 rounded">Lisensi GNU GPL v2+</span>
</div>
</div>
</footer>
<!-- JAVASCRIPT LOGIC & APPLICATION STATE -->
<script>
// -------------------------------------------------------------
// APPLICATION DATA BASE (STORES DATA FROM SOURCE REPORT)
// -------------------------------------------------------------
const EDU_DATA = {
pillars: [
{
id: 'zero-plugin',
title: '1. Zero Plugin Dependency',
badge: 'Kecepatan & Kemandirian',
summary: 'Beroperasi penuh 100% mengandalkan kapabilitas inti WordPress tanpa ACF, Elementor, atau plugin slider pihak ketiga.',
details: 'Seluruh slider hero, kurikulum program, galeri lightbox, hingga modal flyer berjalan menggunakan skrip Vanilla JS native & pustaka WordPress core. Hal ini menghilangkan risiko plugin runtuh saat pembaruan versi utama WP.',
impact: 'Memangkas biaya lisensi tahunan plugin hingga 100% dan mengurangi ukuran database.'
},
{
id: 'modular-arch',
title: '2. Arsitektur Modular Terisolasi',
badge: 'Maintainability',
summary: 'Berkas functions.php bertindak murni sebagai loader; seluruh fungsi teknis diisolasi ke direktori inc/.',
details: 'Pemisahan logika dipisah ke berkas independen seperti inc/security.php, inc/seo.php, inc/admin-menu.php, dan inc/cpt-slider.php. Jika satu modul dimodifikasi, modul lain tetap aman tanpa efek samping (*side-effects*).',
impact: 'Kode bersih (*clean code*), konsisten dengan standar PSR-12, dan sangat mudah di-maintain.'
},
{
id: 'security-hardened',
title: '3. Keamanan Native (Hardened)',
badge: 'Proteksi Peretas',
summary: 'Injeksi HTTP Security Headers, anti-enumerasi pengguna (?author=N), dan proteksi REST API bawaan.',
details: 'Tema secara otomatis menginjeksi header X-Frame-Options, X-Content-Type-Options, Content-Security-Policy, serta menyembunyikan versi WP dari header untuk menggagalkan skrip peretas otomatis.',
impact: 'Mencegah serangan Brute Force author ID, Clickjacking, serta Cross-Site Scripting (XSS).'
},
{
id: 'wcag-a11y',
title: '4. Aksesibilitas WCAG 2.1 AAA',
badge: 'Inklusivitas Publik',
summary: 'Toolbar aksesibilitas melayang bawaan dengan pembaca suara Web Speech API & penyesuaian kontras.',
details: 'Pengunjung disabilitas netra atau lansia dapat memperbesar ukuran teks, mengaktifkan mode kontras tinggi, atau mendengarkan artikel dibacakan oleh suara sintesis sistem tanpa memasang plugin tambahan.',
impact: 'Memenuhi standar pelayanan informasi publik pemerintah & institusi pendidikan tinggi.'
},
{
id: 'drag-builder',
title: '5. Builder Tata Letak Native',
badge: 'Visual Layout',
summary: 'Mengatur urutan seksi beranda dengan drag-and-drop jQuery UI Sortable bawaan WordPress Admin.',
details: 'Pengelola web dapat mengubah urutan Hero Slider, Sambutan Kepsek, Keunggulan, Video Parallax, dan Berita secara visual langsung di panel EduKarsa > Tata Letak tanpa merusak kode PHP.',
impact: 'Memberikan fleksibilitas layout sekelas page builder berat dengan performa instan.'
},
{
id: 'multilingual',
title: '6. Multilingual Ready (5 Bahasa)',
badge: 'Internasionalisasi',
summary: 'Penerjemah instan frontend (ID, EN, AR, ZH, JA) & admin dashboard dwibahasa (ID/EN).',
details: 'Dilengkapi kamus terjemahan otomatis di inc/i18n.php serta tombol pengalih bahasa native pada header utama.',
impact: 'Siap digunakan untuk portal mahasiswa internasional atau sekolah bertaraf internasional (SPK).'
},
{
id: 'seo-schema',
title: '7. SEO & JSON-LD Schema Core',
badge: 'Peringkat Google',
summary: 'Injeksi otomatis OpenGraph, Twitter Cards, dan structured data EducationalOrganization.',
details: 'Menghasilkan JSON-LD Schema otomatis yang memvalidasi identitas sekolah di mesin pencari Google, melengkapi logo, koordinat alamat, dan profil resmi.',
impact: 'Meningkatkan visibilitas pencarian Google & tampilan pratinjau saat link dibagikan di Whatsapp/FB.'
}
],
assets: [
{ id: 'logo', name: 'Logo Header', dim: 'Lebar Proporsional, Tinggi 110 px', ratio: 'Fleksibel', format: 'PNG Transparan / WebP', size: 150, desc: 'Gunakan latar belakang transparan agar menyatu mulus dengan warna header biru navy.' },
{ id: 'slider', name: 'Slider Banner Hero', dim: '1920 x 1080 px / 1920 x 800 px', ratio: '16:9 / Wide Landscape', format: 'JPG / WebP', size: 300, desc: 'Format spanduk utama beranda. Pastikan fokus visual berada di tengah.' },
{ id: 'leader', name: 'Foto Pimpinan / Kepsek', dim: '600 x 800 px / 800 x 1067 px', ratio: '3:4 Portrait', format: 'JPG / WebP', size: 200, desc: 'Digunakan pada seksi Sambutan Kepala Sekolah (About Us).' },
{ id: 'flyer', name: 'Flyer Pop-up PPDB', dim: 'Minimal 800 x 800 px', ratio: '1:1 Persegi atau 4:5', format: 'JPG / WebP', size: 250, desc: 'Poster promosi pengumuman pendaftaran siswa baru yang muncul di layar modal.' },
{ id: 'gallery', name: 'Galeri Kampus & Fasilitas', dim: '1200 x 900 px', ratio: '4:3 Landscape', format: 'JPG / WebP', size: 250, desc: 'Foto dokumentasi laboratorium, ruang kelas, dan gedung untuk template galeri.' },
{ id: 'sidebar', name: 'Poster Sidebar', dim: 'Lebar 600 px (Tinggi Bebas)', ratio: 'Vertikal', format: 'JPG / WebP', size: 200, desc: 'Gambar iklan/banner promosi yang dipasang pada bilah samping artikel.' }
],
files: [
{ path: 'functions.php', cat: 'core', role: 'Theme Router & Module Loader', desc: 'File utama yang bersih. Hanya bertindak memuat berkas-berkas di folder inc/.' },
{ path: 'style.css', cat: 'core', role: 'Main Stylesheet & CSS Variables', desc: 'Menyimpan variabel warna tema, gaya kartu modern, dropdown menu, & responsive breakpoint.' },
{ path: 'front-page.php', cat: 'template', role: 'Modular Homepage Render Engine', desc: 'Membaca konfigurasi tata letak dari wp_options dan merender seksi beranda dinamis.' },
{ path: 'header.php', cat: 'template', role: 'Main Navigation & Lang Switcher', desc: 'Menampilkan header sticky, logo institusi, dan menu navigasi bertingkat.' },
{ path: 'footer.php', cat: 'template', role: '4-Column Footer & WA Float', desc: 'Menampilkan kolom kontak, tautan cepat, sosmed, dan widget aksesibilitas melayang.' },
{ path: 'index.php', cat: 'template', role: 'System Fallback & Post Archive', desc: 'Halaman cadangan sistem untuk menampilkan daftar berita jika template spesifik tidak ada.' },
{ path: 'page-galeri.php', cat: 'template', role: 'Gallery Template with Lightbox', desc: 'Template kustom halaman galeri dengan filter kategori dan modal lightbox Vanilla JS.' },
{ path: 'single-program.php', cat: 'template', role: 'Curriculum Details Template', desc: 'Halaman khusus untuk menampilkan rincian kurikulum dan program keahlian.' },
{ path: 'inc/setup.php', cat: 'inc', role: 'Theme Support & Asset Cache Busting', desc: 'Mendaftarkan fitur title-tag, post-thumbnails, menu, dan enqueue CSS/JS dengan cache-busting time().' },
{ path: 'inc/admin-menu.php', cat: 'inc', role: 'Dashboard & Settings API UI Builder', desc: 'Membuat menu EduKarsa di dasbor admin WP dan mengelola bidang pendaftaran opsi.' },
{ path: 'inc/cpt-slider.php', cat: 'inc', role: 'Custom Post Types (Slider, Program, etc)', desc: 'Mendaftarkan CPT Slider, Program, Milestone, dan Keunggulan beserta metabox URL.' },
{ path: 'inc/security.php', cat: 'inc', role: 'Hardened HTTP Headers & Protections', desc: 'Menyuntikkan HTTP Security Headers, memblokir enumerasi author ID, dan mengamankan REST API.' },
{ path: 'inc/seo.php', cat: 'inc', role: 'JSON-LD Schema & Social Metadata', desc: 'Injeksi otomatis OpenGraph meta dan EducationalOrganization JSON-LD structured data.' },
{ path: 'inc/i18n.php', cat: 'inc', role: 'Bilingual Dictionary Engine', desc: 'Menyediakan repositori terjemahan kata untuk frontend dan antarmuka admin.' },
{ path: 'inc/popup.php', cat: 'inc', role: 'Modal Flyer Logic & Session Handler', desc: 'Mengatur kemunculan pop-up flyer pendaftaran berdasarkan sesi pengunjung.' }
],
defaultLayout: [
{ id: 'slider', name: '1. Banner Hero Slider', icon: '🖼️', enabled: true },
{ id: 'stats', name: '2. Cards Statistik (3 Kolom)', icon: '🏫', enabled: true },
{ id: 'about', name: '3. Sambutan Kepala Sekolah', icon: '👤', enabled: true },
{ id: 'milestone', name: '4. Milestones & Pencapaian', icon: '🏆', enabled: true },
{ id: 'program', name: '5. Program Unggulan Kami', icon: '📚', enabled: true },
{ id: 'video', name: '6. Video Profile & Parallax', icon: '▶️', enabled: true },
{ id: 'keunggulan', name: '7. Keunggulan Sekolah (9 Grid)', icon: '⭐', enabled: true },
{ id: 'cta', name: '8. Banner Call to Action PPDB', icon: '📣', enabled: true },
{ id: 'news', name: '9. Berita & Pengumuman Terbaru', icon: '📰', enabled: true }
]
};
// -------------------------------------------------------------
// APP STATE & SIMULATOR VARIABLES
// -------------------------------------------------------------
let currentPillarIndex = 0;
let currentAssetIndex = 1; // Default Hero Slider
let currentFileFilter = 'all';
let currentLayoutState = JSON.parse(JSON.stringify(EDU_DATA.defaultLayout));
let simFontSizeVal = 100;
let isHighContrast = false;
// -------------------------------------------------------------
// INITIALIZATION ON DOM READY
// -------------------------------------------------------------
document.addEventListener('DOMContentLoaded', () => {
initCharts();
renderPillarsUI();
renderAssetSpecUI();
renderFileTreeUI();
renderLayoutSimulatorUI();
updateSetupProgress();
});
// -------------------------------------------------------------
// SECTION 1: CHART.JS INITIALIZATION
// -------------------------------------------------------------
let benchmarkChartObj, architectureChartObj, assetSizeChartObj;
function initCharts() {
// Label truncating helper (16-char rule)
const truncateLabel = (str) => (str.length > 16 ? str.substring(0, 13) + '...' : str);
// 1. Performance Benchmark Chart (Bar Chart)
const ctxBench = document.getElementById('benchmarkChart').getContext('2d');
benchmarkChartObj = new Chart(ctxBench, {
type: 'bar',
data: {
labels: ['Waktu Muat (ms)', 'Kueri Database', 'HTTP Requests', 'Payload (KB)'].map(truncateLabel),
datasets: [
{
label: 'EduKarsa (0 Plugin)',
data: [280, 14, 18, 420],
backgroundColor: '#0b4a8e',
borderRadius: 6
},
{
label: 'Tema Lain (15+ Plugins)',
data: [1850, 92, 85, 2450],
backgroundColor: '#cbd5e1',
borderRadius: 6
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { position: 'top', labels: { font: { size: 11 } } },
tooltip: {
callbacks: {
label: (context) => `${context.dataset.label}: ${context.raw}`
}
}
},
scales: {
y: { beginAtZero: true, grid: { color: '#f1f5f9' } },
x: { grid: { display: false } }
}
}
});
// 2. Architecture Codebase Distribution Donut Chart
const ctxArch = document.getElementById('architectureChart').getContext('2d');
architectureChartObj = new Chart(ctxArch, {
type: 'doughnut',
data: {
labels: ['Admin & Settings', 'Security Headers', 'CPT & Metaboxes', 'SEO & JSON-LD', 'Templates Core', 'i18n & Utility'].map(truncateLabel),
datasets: [{
data: [25, 20, 18, 15, 12, 10],
backgroundColor: ['#0b4a8e', '#1a73e8', '#f59e0b', '#10b981', '#6366f1', '#8b5cf6'],
borderWidth: 2,
borderColor: '#ffffff'
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { position: 'right', labels: { boxWidth: 12, font: { size: 10 } } }
}
}
});
// 3. Asset Size Limits Horizontal Bar Chart
const ctxAsset = document.getElementById('assetSizeChart').getContext('2d');
assetSizeChartObj = new Chart(ctxAsset, {
type: 'bar',
data: {
labels: EDU_DATA.assets.map(a => truncateLabel(a.name)),
datasets: [{
label: 'Max Rekomendasi (KB)',
data: EDU_DATA.assets.map(a => a.size),
backgroundColor: '#f59e0b',
borderRadius: 4
}]
},
options: {
indexAxis: 'y',
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false }
},
scales: {
x: { beginAtZero: true, max: 400, grid: { color: '#f1f5f9' } },
y: { grid: { display: false } }
}
}
});
}
let isChartToggled = false;
function toggleChartMetric() {
if (!benchmarkChartObj) return;
isChartToggled = !isChartToggled;
if (isChartToggled) {
benchmarkChartObj.data.datasets[0].data = [99, 100, 100, 95];
benchmarkChartObj.data.datasets[1].data = [40, 35, 30, 25];
benchmarkChartObj.data.datasets[0].label = 'Skor GTMetrix / Lighthouse';
benchmarkChartObj.data.datasets[1].label = 'Skor Tema Plugin Heavy';
} else {
benchmarkChartObj.data.datasets[0].data = [280, 14, 18, 420];
benchmarkChartObj.data.datasets[1].data = [1850, 92, 85, 2450];
benchmarkChartObj.data.datasets[0].label = 'EduKarsa (0 Plugin)';
benchmarkChartObj.data.datasets[1].label = 'Tema Lain (15+ Plugins)';
}
benchmarkChartObj.update();
}
// -------------------------------------------------------------
// SECTION 2: PILLARS & ACCESSIBILITY SIMULATOR LOGIC
// -------------------------------------------------------------
function renderPillarsUI() {
const btnContainer = document.getElementById('pillarButtonsContainer');
btnContainer.innerHTML = '';
EDU_DATA.pillars.forEach((pillar, idx) => {
const btn = document.createElement('button');
btn.className = `w-full text-left px-3 py-2.5 rounded-xl font-medium text-xs flex items-center justify-between transition-all ${
idx === currentPillarIndex
? 'bg-brand-800 text-white shadow-md font-bold'
: 'bg-slate-50 text-slate-700 hover:bg-slate-100 border border-slate-200'
}`;
btn.onclick = () => selectPillar(idx);
btn.innerHTML = `
<span class="truncate">${pillar.title}</span>
<span class="text-[9px] px-2 py-0.5 rounded ${idx === currentPillarIndex ? 'bg-amber-400 text-slate-950 font-bold' : 'bg-slate-200 text-slate-600'}">${pillar.badge}</span>
`;
btnContainer.appendChild(btn);
});
// Render Detail Pane
const p = EDU_DATA.pillars[currentPillarIndex];
const detailPane = document.getElementById('pillarDetailPane');
detailPane.innerHTML = `
<div class="flex items-center justify-between border-b border-slate-100 pb-3">
<span class="bg-brand-100 text-brand-800 text-xs font-bold px-2.5 py-1 rounded-md uppercase">${p.badge}</span>
<span class="text-xs text-slate-400">Arsitektur Native WordPress</span>
</div>
<h3 class="text-xl font-bold text-slate-900">${p.title}</h3>
<p class="text-sm text-slate-700 font-medium leading-relaxed">${p.summary}</p>
<div class="bg-slate-50 p-4 rounded-xl border border-slate-200 space-y-2 text-xs text-slate-600">
<strong class="text-slate-800 block">Detail Implementasi Kode:</strong>
<p class="leading-relaxed">${p.details}</p>
</div>
<div class="bg-emerald-50 border border-emerald-200 text-emerald-900 p-3 rounded-xl text-xs flex items-start gap-2">
<span class="text-base">🚀</span>
<div>
<strong class="block font-bold">Dampak Performa & Keamanan:</strong>
<span>${p.impact}</span>
</div>
</div>
`;
}
function selectPillar(idx) {
currentPillarIndex = idx;
renderPillarsUI();
}
// WCAG Accessibility Sim
function simulateHighContrast() {
isHighContrast = !isHighContrast;
const target = document.getElementById('a11yTestTarget');
if (isHighContrast) {
target.classList.add('a11y-high-contrast');
} else {
target.classList.remove('a11y-high-contrast');
}
}
function changeSimFontSize(delta) {
simFontSizeVal = Math.max(80, Math.min(150, simFontSizeVal + delta * 10));
document.getElementById('simFontLabel').innerText = simFontSizeVal + '%';
document.getElementById('a11yTextSample').style.fontSize = (simFontSizeVal / 100 * 14) + 'px';
}
function simulateScreenReader() {
const text = document.getElementById('a11yTextSample').innerText;
if ('speechSynthesis' in window) {
window.speechSynthesis.cancel(); // Reset
const utterance = new SpeechSynthesisUtterance(text);
utterance.lang = 'id-ID';
utterance.rate = 0.95;
window.speechSynthesis.speak(utterance);
alert('🔊 Pembaca Suara Aktif! (Membacakan sampel teks dalam Bahasa Indonesia)');
} else {
alert('Fitur Web Speech API tidak didukung oleh browser ini.');
}
}
// -------------------------------------------------------------
// SECTION 3: ASSETS SPEC & CANVAS RATIO VISUALIZER LOGIC
// -------------------------------------------------------------
function renderAssetSpecUI() {
const selectorGrid = document.getElementById('assetSelectorGrid');
selectorGrid.innerHTML = '';
EDU_DATA.assets.forEach((asset, idx) => {
const btn = document.createElement('button');
btn.className = `px-3 py-2 rounded-xl text-left text-xs font-semibold transition-all border ${
idx === currentAssetIndex
? 'bg-brand-800 text-white border-brand-800 shadow-sm'
: 'bg-white text-slate-700 border-slate-200 hover:bg-slate-50'
}`;
btn.onclick = () => selectAsset(idx);
btn.innerHTML = `<span class="block truncate">${asset.name}</span>`;
selectorGrid.appendChild(btn);
});
// Spec Box
const a = EDU_DATA.assets[currentAssetIndex];
const specBox = document.getElementById('assetSpecBox');
specBox.innerHTML = `
<div class="flex justify-between items-center border-b border-slate-200 pb-2">
<h4 class="font-bold text-slate-900 text-sm">${a.name}</h4>
<span class="bg-amber-100 text-amber-800 text-[10px] font-bold px-2 py-0.5 rounded">Rekomendasi Resmi</span>
</div>
<div class="grid grid-cols-2 gap-3 text-xs">
<div>
<span class="text-slate-400 block">Dimensi Ideal:</span>
<strong class="text-slate-800">${a.dim}</strong>
</div>
<div>
<span class="text-slate-400 block">Rasio Aspek:</span>
<strong class="text-slate-800">${a.ratio}</strong>
</div>
<div>
<span class="text-slate-400 block">Format Berkas:</span>
<strong class="text-slate-800">${a.format}</strong>
</div>
<div>
<span class="text-slate-400 block">Batas Ukuran:</span>
<strong class="text-emerald-600">&lt; ${a.size} KB</strong>
</div>
</div>
<p class="text-xs text-slate-600 italic border-t border-slate-200 pt-2">${a.desc}</p>
`;
document.getElementById('canvasRatioBadge').innerText = a.ratio;
document.getElementById('canvasFormatText').innerText = a.format;
document.getElementById('canvasSizeText').innerText = `< ${a.size} KB`;
// Draw Canvas Ratio Box
drawAssetCanvasRatio(a);
}
function selectAsset(idx) {
currentAssetIndex = idx;
renderAssetSpecUI();
}
function drawAssetCanvasRatio(asset) {
const canvas = document.getElementById('ratioPreviewCanvas');
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Background canvas grid
ctx.fillStyle = '#f8fafc';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Determine drawing dimensions based on asset ratio
let boxW = 220, boxH = 120;
if (asset.id === 'logo') { boxW = 240; boxH = 60; }
else if (asset.id === 'slider') { boxW = 260; boxH = 110; }
else if (asset.id === 'leader') { boxW = 120; boxH = 160; }
else if (asset.id === 'flyer') { boxW = 140; boxH = 140; }
else if (asset.id === 'gallery') { boxW = 200; boxH = 140; }
else if (asset.id === 'sidebar') { boxW = 110; boxH = 170; }
const startX = (canvas.width - boxW) / 2;
const startY = (canvas.height - boxH) / 2;
// Draw bounding box box
ctx.fillStyle = '#0b4a8e';
ctx.beginPath();
ctx.roundRect(startX, startY, boxW, boxH, 8);
ctx.fill();
// Draw Text Inside Box
ctx.fillStyle = '#ffffff';
ctx.font = 'bold 11px sans-serif';
ctx.textAlign = 'center';
ctx.fillText(asset.name, canvas.width / 2, canvas.height / 2 - 4);
ctx.font = '10px sans-serif';
ctx.fillStyle = '#f59e0b';
ctx.fillText(asset.ratio, canvas.width / 2, canvas.height / 2 + 12);
}
// -------------------------------------------------------------
// SECTION 4: FILE SYSTEM TREE EXPLORER LOGIC
// -------------------------------------------------------------
function renderFileTreeUI() {
const treeContainer = document.getElementById('fileTreeItems');
treeContainer.innerHTML = '';
const filtered = EDU_DATA.files.filter(f => currentFileFilter === 'all' || f.cat === currentFileFilter);
document.getElementById('fileCountBadge').innerText = `${filtered.length} Berkas Ditampilkan`;
filtered.forEach((file) => {
const item = document.createElement('div');
item.className = 'p-2 rounded-lg text-xs font-mono flex items-center justify-between cursor-pointer transition-all border border-transparent hover:bg-slate-100 hover:border-slate-200';
item.onclick = () => inspectFile(file.path);
let icon = '📄';
if (file.cat === 'inc') icon = '🧩';
if (file.cat === 'core') icon = '⚙️';
if (file.cat === 'template') icon = '🖥️';
item.innerHTML = `
<div class="flex items-center gap-2 truncate">
<span>${icon}</span>
<span class="text-slate-800 font-semibold truncate">${file.path}</span>
</div>
<span class="text-[9px] px-1.5 py-0.5 rounded bg-slate-200 text-slate-600 uppercase font-sans">${file.cat}</span>
`;
treeContainer.appendChild(item);
});
// Inspect first file by default
if (filtered.length > 0) inspectFile(filtered[0].path);
}
function filterFileList(cat) {
currentFileFilter = cat;
document.querySelectorAll('.filter-file-btn').forEach(btn => {
btn.className = 'filter-file-btn bg-slate-100 text-slate-700 hover:bg-slate-200 px-3 py-1.5 rounded-lg';
});
event.target.className = 'filter-file-btn bg-brand-800 text-white px-3 py-1.5 rounded-lg';
renderFileTreeUI();
}
function inspectFile(filePath) {
const f = EDU_DATA.files.find(item => item.path === filePath);
if (!f) return;
const inspector = document.getElementById('fileInspectorPane');
inspector.innerHTML = `
<div class="flex items-center justify-between border-b border-slate-100 pb-3">
<div class="flex items-center gap-2">
<span class="bg-brand-100 text-brand-800 font-mono text-xs font-bold px-2.5 py-1 rounded-md">${f.path}</span>
<span class="text-xs text-slate-400">Tipe Modul: ${f.cat.toUpperCase()}</span>
</div>
<span class="text-xs text-emerald-600 font-bold">✓ Native & Zero Plugin</span>
</div>
<div>
<h3 class="font-bold text-slate-900 text-base">${f.role}</h3>
<p class="text-xs text-slate-600 mt-1 leading-relaxed">${f.desc}</p>
</div>
<div class="bg-slate-900 text-slate-200 p-4 rounded-xl text-xs font-mono space-y-2">
<div class="text-slate-400">// Contoh Struktur Kode Terkait (${f.path})</div>
<div class="text-amber-400">&lt;?php</div>
<div class="text-slate-300">
/**<br>
* ${f.role}<br>
* Multi-language & Hardened Security Native<br>
*/<br>
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
</div>
<div class="text-brand-100">add_action( 'init', 'edukarsa_register_${f.cat}_module' );</div>
</div>
`;
}
// -------------------------------------------------------------
// SECTION 5: HOMEPAGE LAYOUT BUILDER SIMULATOR LOGIC
// -------------------------------------------------------------
function renderLayoutSimulatorUI() {
const container = document.getElementById('layoutBuilderControls');
container.innerHTML = '';
currentLayoutState.forEach((sec, idx) => {
const row = document.createElement('div');
row.className = `p-2.5 rounded-xl border flex items-center justify-between text-xs transition-all ${
sec.enabled ? 'bg-white border-slate-200 shadow-sm' : 'bg-slate-100 border-slate-200 opacity-60'
}`;
row.innerHTML = `
<div class="flex items-center gap-2">
<input type="checkbox" ${sec.enabled ? 'checked' : ''} onchange="toggleSectionEnable(${idx})" class="rounded text-brand-600">
<span class="font-bold text-slate-800">${sec.icon} ${sec.name}</span>
</div>
<div class="flex items-center gap-1">
<button onclick="moveSection(${idx}, -1)" ${idx === 0 ? 'disabled' : ''} class="px-2 py-1 bg-slate-100 hover:bg-slate-200 rounded text-slate-700 disabled:opacity-30">⬆️</button>
<button onclick="moveSection(${idx}, 1)" ${idx === currentLayoutState.length - 1 ? 'disabled' : ''} class="px-2 py-1 bg-slate-100 hover:bg-slate-200 rounded text-slate-700 disabled:opacity-30">⬇️</button>
</div>
`;
container.appendChild(row);
});
renderWireframePreview();
}
function toggleSectionEnable(idx) {
currentLayoutState[idx].enabled = !currentLayoutState[idx].enabled;
renderLayoutSimulatorUI();
}
function moveSection(idx, direction) {
const newIndex = idx + direction;
if (newIndex < 0 || newIndex >= currentLayoutState.length) return;
const temp = currentLayoutState[idx];
currentLayoutState[idx] = currentLayoutState[newIndex];
currentLayoutState[newIndex] = temp;
renderLayoutSimulatorUI();
}
function resetLayoutOrder() {
currentLayoutState = JSON.parse(JSON.stringify(EDU_DATA.defaultLayout));
renderLayoutSimulatorUI();
}
function renderWireframePreview() {
const wireframe = document.getElementById('wireframeContainer');
wireframe.innerHTML = '';
const activeSections = currentLayoutState.filter(s => s.enabled);
if (activeSections.length === 0) {
wireframe.innerHTML = '<div class="text-center py-8 text-xs text-slate-500">Semua seksi disembunyikan. Centang seksi untuk merender layout.</div>';
return;
}
activeSections.forEach((sec, idx) => {
const block = document.createElement('div');
block.className = 'p-3 rounded-lg border border-slate-700 bg-slate-800/90 text-white text-xs flex justify-between items-center shadow-sm';
block.innerHTML = `
<div class="flex items-center gap-2">
<span class="w-5 h-5 rounded-full bg-brand-600 text-[10px] font-bold flex items-center justify-center">${idx + 1}</span>
<span class="font-bold text-slate-200">${sec.name}</span>
</div>
<span class="text-[10px] bg-slate-700 text-amber-400 px-2 py-0.5 rounded font-mono">&lt;section class="edukarsa-${sec.id}"&gt;</span>
`;
wireframe.appendChild(block);
});
}
function copyLayoutConfig() {
const activeNames = currentLayoutState.filter(s => s.enabled).map((s, i) => `${i + 1}. ${s.name}`).join('\n');
navigator.clipboard.writeText(`URUTAN STRUCTURAL LAYOUT EDUKARSA:\n${activeNames}`);
alert('📋 Konfigurasi urutan tata letak berhasil disalin ke clipboard!');
}
// -------------------------------------------------------------
// SECTION 6: QUICK START CHECKLIST & PROGRESS TRACKER
// -------------------------------------------------------------
function updateSetupProgress() {
const chks = document.querySelectorAll('.setup-chk');
let checkedCount = 0;
chks.forEach(c => { if (c.checked) checkedCount++; });
const percent = Math.round((checkedCount / chks.length) * 100);
document.getElementById('setupProgressBar').style.width = percent + '%';
document.getElementById('setupProgressPercent').innerText = `${percent}% Selesai (${checkedCount}/${chks.length} Tugas)`;
}
// -------------------------------------------------------------
// GLOBAL SEARCH & UTILITIES
// -------------------------------------------------------------
function scrollToSection(id) {
const el = document.getElementById(id);
if (el) el.scrollIntoView({ behavior: 'smooth' });
}
function handleGlobalSearch() {
const query = document.getElementById('globalSearchInput').value.toLowerCase().trim();
const box = document.getElementById('searchResultsBox');
const list = document.getElementById('searchResultsList');
if (query.length < 2) {
box.classList.add('hidden');
return;
}
list.innerHTML = '';
let resultsCount = 0;
// Search in Pillars
EDU_DATA.pillars.forEach(p => {
if (p.title.toLowerCase().includes(query) || p.details.toLowerCase().includes(query)) {
resultsCount++;
list.innerHTML += `<div class="p-2 hover:bg-slate-50 rounded border border-slate-100 cursor-pointer" onclick="scrollToSection('architecture'); closeSearchBox();">
<strong class="text-brand-800">[Pilar] ${p.title}</strong>
<p class="text-xs text-slate-600">${p.summary}</p>
</div>`;
}
});
// Search in Assets
EDU_DATA.assets.forEach(a => {
if (a.name.toLowerCase().includes(query) || a.dim.toLowerCase().includes(query)) {
resultsCount++;
list.innerHTML += `<div class="p-2 hover:bg-slate-50 rounded border border-slate-100 cursor-pointer" onclick="scrollToSection('assets'); closeSearchBox();">
<strong class="text-brand-800">[Aset] ${a.name}</strong>
<p class="text-xs text-slate-600">Dimensi: ${a.dim} (${a.format})</p>
</div>`;
}
});
// Search in Files
EDU_DATA.files.forEach(f => {
if (f.path.toLowerCase().includes(query) || f.role.toLowerCase().includes(query)) {
resultsCount++;
list.innerHTML += `<div class="p-2 hover:bg-slate-50 rounded border border-slate-100 cursor-pointer" onclick="scrollToSection('code-tree'); closeSearchBox();">
<strong class="text-brand-800">[File] ${f.path}</strong>
<p class="text-xs text-slate-600">${f.role} - ${f.desc}</p>
</div>`;
}
});
if (resultsCount > 0) {
box.classList.remove('hidden');
} else {
list.innerHTML = '<div class="text-xs text-slate-400 p-2">Tidak ditemukan hasil yang cocok.</div>';
box.classList.remove('hidden');
}
}
function closeSearchBox() {
document.getElementById('searchResultsBox').classList.add('hidden');
}
</script>
</body>
</html>