Deploy_ConvNext / templates /index.html
Sirius16's picture
Update templates/index.html
636818e verified
Raw
History Blame Contribute Delete
34.1 kB
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ConvNeXt CIFAR10 - Research Deployment</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Plus Jakarta Sans', sans-serif;
}
html {
scroll-behavior: smooth;
}
body {
background-color: #f4f7fe;
color: #1e293b;
display: flex;
min-height: 100vh;
overflow-x: hidden;
}
.sidebar {
width: 280px;
background: #ffffff;
height: 100vh;
position: fixed;
left: 0;
top: 0;
box-shadow: 4px 0 24px rgba(0,0,0,0.04);
display: flex;
flex-direction: column;
z-index: 1000;
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.sidebar-header {
padding: 40px 30px;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
.sidebar-logo {
font-size: 24px;
font-weight: 800;
background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
letter-spacing: -0.5px;
}
.nav-menu {
list-style: none;
padding: 0 20px;
display: flex;
flex-direction: column;
gap: 10px;
}
.nav-item {
display: block;
}
.nav-link {
display: flex;
align-items: center;
gap: 16px;
padding: 16px 20px;
text-decoration: none;
color: #64748b;
font-weight: 600;
font-size: 15px;
border-radius: 16px;
transition: all 0.3s ease;
}
.nav-link:hover, .nav-link.active {
background: #f1f5f9;
color: #4f46e5;
}
.nav-link svg {
width: 20px;
height: 20px;
stroke: currentColor;
stroke-width: 2.5;
fill: none;
}
.main-wrapper {
flex: 1;
margin-left: 280px;
display: flex;
flex-direction: column;
transition: margin-left 0.3s ease;
}
.hamburger-btn {
display: none;
position: fixed;
top: 20px;
left: 20px;
z-index: 2000;
background: #ffffff;
border: none;
width: 45px;
height: 45px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
cursor: pointer;
align-items: center;
justify-content: center;
}
.hamburger-btn svg {
width: 24px;
height: 24px;
stroke: #1e293b;
stroke-width: 2.5;
}
.hero-banner {
background: linear-gradient(120deg, #4f46e5 0%, #8b5cf6 100%);
padding: 80px 60px;
color: white;
position: relative;
overflow: hidden;
border-bottom-left-radius: 40px;
border-bottom-right-radius: 40px;
margin: 20px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
}
.hero-title {
font-size: 42px;
font-weight: 800;
margin-bottom: 12px;
letter-spacing: -1px;
position: relative;
z-index: 2;
}
.hero-subtitle {
font-size: 18px;
color: #e0e7ff;
font-weight: 500;
position: relative;
z-index: 2;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 40px;
width: 100%;
}
.dashboard-grid {
display: grid;
grid-template-columns: 1fr;
gap: 40px;
}
.card-panel {
background: #ffffff;
border-radius: 30px;
padding: 45px;
box-shadow: 0 10px 40px rgba(112, 144, 176, 0.08);
border: 1px solid rgba(226, 232, 240, 0.8);
position: relative;
overflow: hidden;
}
.support-heading {
font-size: 16px;
font-weight: 700;
color: #718096;
text-transform: uppercase;
letter-spacing: 2px;
text-align: center;
margin-bottom: 40px;
}
.support-logos-container {
display: flex;
align-items: center;
justify-content: center;
gap: 50px;
}
.support-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
flex: 1;
}
.support-img {
height: 75px;
object-fit: contain;
}
.support-divider {
width: 1px;
height: 100px;
background-color: #cbd5e0;
}
.support-text {
font-size: 15px;
font-weight: 600;
color: #718096;
text-align: center;
}
.section-header {
display: flex;
align-items: center;
gap: 15px;
margin-bottom: 35px;
}
.section-icon {
width: 48px;
height: 48px;
background: #eef2ff;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
color: #4f46e5;
}
.section-icon svg {
width: 24px;
height: 24px;
stroke: currentColor;
stroke-width: 2.5;
fill: none;
}
.section-titles h2 {
font-size: 24px;
font-weight: 800;
color: #1e293b;
}
.section-titles p {
color: #64748b;
font-size: 14px;
margin-top: 4px;
font-weight: 500;
}
.pills-grid {
display: flex;
flex-wrap: wrap;
gap: 15px;
}
.pill {
background: #f8fafc;
border: 2px solid transparent;
padding: 12px 24px;
border-radius: 16px;
font-weight: 700;
font-size: 15px;
color: #475569;
cursor: pointer;
display: flex;
align-items: center;
gap: 10px;
transition: all 0.3s;
}
.pill:hover {
border-color: #4f46e5;
background: #eef2ff;
color: #4f46e5;
transform: translateY(-3px);
box-shadow: 0 10px 20px rgba(79, 70, 229, 0.1);
}
.upload-zone {
border: 3px dashed #cbd5e0;
border-radius: 24px;
background: #f8fafc;
padding: 70px 20px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.upload-zone:hover {
border-color: #4f46e5;
background: #f5f3ff;
}
#upload-prompt {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
}
.upload-icon {
width: 70px;
height: 70px;
background: #ffffff;
border-radius: 20px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20px;
box-shadow: 0 10px 25px rgba(0,0,0,0.06);
color: #4f46e5;
transition: transform 0.3s;
}
.upload-zone:hover .upload-icon {
transform: scale(1.1);
}
.upload-text {
font-size: 20px;
font-weight: 800;
color: #1e293b;
}
.upload-subtext {
font-size: 14px;
color: #64748b;
margin-top: 8px;
font-weight: 500;
}
#preview-wrapper {
display: none;
flex-direction: column;
align-items: center;
width: 100%;
}
#preview-img {
max-height: 300px;
border-radius: 16px;
box-shadow: 0 15px 30px rgba(0,0,0,0.1);
margin-bottom: 25px;
object-fit: cover;
}
.btn-outline {
background: #ffffff;
border: 2px solid #e2e8f0;
padding: 12px 30px;
border-radius: 16px;
font-weight: 700;
font-size: 15px;
color: #475569;
cursor: pointer;
transition: all 0.3s;
}
.btn-outline:hover {
border-color: #4f46e5;
color: #4f46e5;
background: #f5f3ff;
}
.results-container {
display: none;
margin-top: 40px;
}
.cards-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
}
.result-card {
background: #ffffff;
border: 1px solid #e2e8f0;
border-radius: 24px;
padding: 30px;
box-shadow: 0 4px 20px rgba(0,0,0,0.03);
position: relative;
}
.result-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 6px;
background: linear-gradient(90deg, #4f46e5, #8b5cf6);
border-top-left-radius: 24px;
border-top-right-radius: 24px;
}
.rc-label {
font-size: 13px;
font-weight: 800;
color: #64748b;
text-transform: uppercase;
letter-spacing: 1.5px;
margin-bottom: 12px;
}
.rc-value {
font-size: 32px;
font-weight: 800;
color: #1e293b;
margin-bottom: 8px;
}
.rc-conf {
font-size: 14px;
color: #059669;
font-weight: 700;
background: #d1fae5;
padding: 6px 14px;
border-radius: 10px;
display: inline-flex;
align-items: center;
gap: 6px;
}
.rc-bars {
margin-top: 30px;
display: flex;
flex-direction: column;
gap: 12px;
}
.bar-item {
display: flex;
align-items: center;
font-size: 13px;
font-weight: 700;
color: #475569;
}
.bar-label { width: 90px; }
.bar-bg { flex: 1; height: 10px; background: #f1f5f9; border-radius: 5px; margin: 0 15px; overflow: hidden; }
.bar-fill { height: 100%; background: #4f46e5; border-radius: 5px; transition: width 0.8s cubic-bezier(0.4, 0, 0.2, 1); }
.bar-val { width: 45px; text-align: right; }
.interpretation-alert {
margin-top: 30px;
padding: 25px;
border-radius: 20px;
font-size: 15px;
line-height: 1.6;
display: flex;
align-items: flex-start;
gap: 20px;
box-shadow: 0 10px 25px rgba(0,0,0,0.03);
}
.alert-icon { font-size: 28px; line-height: 1; }
.alert-content strong { display: block; margin-bottom: 6px; font-size: 16px; font-weight: 800; }
.loader {
display: none;
text-align: center;
padding: 60px;
}
.spinner {
width: 50px;
height: 50px;
border: 5px solid #eef2ff;
border-top: 5px solid #4f46e5;
border-radius: 50%;
animation: spin 1s cubic-bezier(0.4, 0, 0.2, 1) infinite;
margin: 0 auto 20px;
}
@keyframes spin { 100% { transform: rotate(360deg); } }
.modal {
display: none;
position: fixed;
top: 0; left: 0; width: 100%; height: 100%;
background: rgba(15, 23, 42, 0.4);
backdrop-filter: blur(8px);
z-index: 9999;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s;
}
.modal.show { opacity: 1; }
.modal-content {
background: white;
padding: 40px;
border-radius: 30px;
max-width: 420px;
width: 90%;
text-align: center;
position: relative;
transform: translateY(20px);
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 25px 50px rgba(0,0,0,0.1);
}
.modal.show .modal-content { transform: translateY(0); }
.modal-close {
position: absolute;
top: 20px; right: 25px;
font-size: 28px;
color: #94a3b8;
cursor: pointer;
transition: color 0.3s;
background: none;
border: none;
}
.modal-close:hover { color: #ef4444; }
.modal-emoji { font-size: 60px; margin-bottom: 20px; }
.modal-title { font-size: 24px; font-weight: 800; color: #1e293b; margin-bottom: 12px; }
.modal-desc { font-size: 15px; color: #475569; line-height: 1.7; font-weight: 500;}
@media (max-width: 1024px) {
.sidebar { transform: translateX(-100%); }
.sidebar.active { transform: translateX(0); }
.main-wrapper { margin-left: 0; }
.hamburger-btn { display: flex; }
.hero-banner { padding: 80px 30px 60px; margin: 0; border-radius: 0; border-bottom-left-radius: 30px; border-bottom-right-radius: 30px;}
.container { padding: 30px 20px; }
}
@media (max-width: 768px) {
.cards-grid { grid-template-columns: 1fr; }
.hero-title { font-size: 32px; }
.support-logos-container { flex-direction: column; gap: 30px; }
.support-divider { width: 80%; height: 1px; }
}
</style>
</head>
<body>
<button class="hamburger-btn" id="menu-toggle">
<svg viewBox="0 0 24 24">
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</button>
<aside class="sidebar" id="sidebar">
<div class="sidebar-header">
<div class="sidebar-logo">ConvNeXt</div>
</div>
<ul class="nav-menu">
<li class="nav-item">
<a href="#beranda" class="nav-link active" onclick="closeSidebar()">
<svg viewBox="0 0 24 24"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
Beranda
</a>
</li>
<li class="nav-item">
<a href="#dukungan" class="nav-link" onclick="closeSidebar()">
<svg viewBox="0 0 24 24"><path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z"></path><line x1="7" y1="7" x2="7.01" y2="7"></line></svg>
Dukungan
</a>
</li>
<li class="nav-item">
<a href="#dataset" class="nav-link" onclick="closeSidebar()">
<svg viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="3" y1="9" x2="21" y2="9"></line><line x1="9" y1="21" x2="9" y2="9"></line></svg>
Data CIFAR-10
</a>
</li>
<li class="nav-item">
<a href="#deteksi" class="nav-link" onclick="closeSidebar()">
<svg viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="17 8 12 3 7 8"></polyline><line x1="12" y1="3" x2="12" y2="15"></line></svg>
Deteksi Objek
</a>
</li>
</ul>
</aside>
<div class="main-wrapper">
<header class="hero-banner" id="beranda">
<h1 class="hero-title">Deployment ConvNeXt pada CIFAR10</h1>
<div class="hero-subtitle">Bryan (NPM)</div>
</header>
<main class="container">
<div class="dashboard-grid">
<div class="card-panel" id="dukungan">
<h3 class="support-heading">PENELITIAN INI DIDUKUNG OLEH</h3>
<div class="support-logos-container">
<div class="support-item">
<img src="/static/DSC UI.png" class="support-img" alt="DSC">
<span class="support-text">Data Science Center, FMIPA UI</span>
</div>
<div class="support-divider"></div>
<div class="support-item">
<img src="/static/BrainAI.png" class="support-img" alt="BrainAI">
<span class="support-text">BrainAI Lab, Departemen Matematika FMIPA UI</span>
</div>
</div>
</div>
<div class="card-panel" id="dataset">
<div class="section-header">
<div class="section-icon">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg>
</div>
<div class="section-titles">
<h2>Dataset CIFAR-10</h2>
<p>Jelajahi 10 kelas objek visual yang menjadi acuan pengenalan citra.</p>
</div>
</div>
<div class="pills-grid">
<div class="pill" onclick="showClass('Pesawat', '✈️', 'Mencakup pesawat komersial, jet tempur, dan pesawat baling-baling.')">✈️ Pesawat</div>
<div class="pill" onclick="showClass('Mobil', '🚗', 'Kendaraan roda empat untuk penumpang seperti sedan dan SUV.')">🚗 Mobil</div>
<div class="pill" onclick="showClass('Burung', '🐦', 'Berbagai spesies burung liar maupun peliharaan.')">🐦 Burung</div>
<div class="pill" onclick="showClass('Kucing', '🐱', 'Mamalia famili Felidae, mencakup berbagai ras domestik.')">🐱 Kucing</div>
<div class="pill" onclick="showClass('Rusa', '🦌', 'Hewan mamalia pemamah biak dari famili Cervidae.')">🦌 Rusa</div>
<div class="pill" onclick="showClass('Anjing', '🐶', 'Mamalia karnivora yang telah didomestikasi.')">🐶 Anjing</div>
<div class="pill" onclick="showClass('Katak', '🐸', 'Amfibi tak berekor yang pandai melompat.')">🐸 Katak</div>
<div class="pill" onclick="showClass('Kuda', '🐴', 'Mamalia berkuku satu untuk berkuda atau pekerja beban.')">🐴 Kuda</div>
<div class="pill" onclick="showClass('Kapal', '🚢', 'Kendaraan air ukuran besar dan kecil.')">🚢 Kapal</div>
<div class="pill" onclick="showClass('Truk', '🚚', 'Kendaraan bermotor besar pengangkut barang.')">🚚 Truk</div>
</div>
</div>
<div class="card-panel" id="deteksi">
<div class="section-header">
<div class="section-icon">
<svg viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 16 10 5 21"></polyline></svg>
</div>
<div class="section-titles">
<h2>Deteksi Objek ConvNeXt</h2>
<p>Unggah citra untuk dianalisis oleh arsitektur ConvNeXt-MLP dan ConvNeXt-KAN.</p>
</div>
</div>
<div class="upload-zone" id="drop-zone">
<div id="upload-prompt">
<div class="upload-icon">
<svg width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="17 8 12 3 7 8"></polyline><line x1="12" y1="3" x2="12" y2="15"></line></svg>
</div>
<div class="upload-text">Drag or Drop your image here</div>
<div class="upload-subtext">Format didukung: JPG, PNG (Max 5MB)</div>
</div>
<div id="preview-wrapper">
<img id="preview-img" src="#" alt="Preview">
<button class="btn-outline" id="btn-change">Ganti Gambar</button>
</div>
<input type="file" id="file-input" accept="image/jpeg, image/png" hidden>
</div>
<div class="loader" id="loader">
<div class="spinner"></div>
<div style="color: #64748b; font-size: 15px; font-weight: 700;">Please wait while your image is being analyzed</div>
</div>
<div class="results-container" id="results">
<div class="cards-grid">
<div class="result-card">
<div class="rc-label">Model 1: ConvNeXt-MLP</div>
<div class="rc-value" id="mlp-name">-</div>
<div class="rc-conf">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>
<span id="mlp-conf">-</span>
</div>
<div class="rc-bars" id="mlp-probs"></div>
</div>
<div class="result-card">
<div class="rc-label">Model 2: ConvNeXt-KAN</div>
<div class="rc-value" id="kan-name">-</div>
<div class="rc-conf">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>
<span id="kan-conf">-</span>
</div>
<div class="rc-bars" id="kan-probs"></div>
</div>
</div>
<div class="interpretation-alert" id="inter-box">
<div class="alert-icon" id="inter-emoji"></div>
<div class="alert-content">
<strong id="inter-title"></strong>
<span id="inter-text"></span>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
<div class="modal" id="infoModal">
<div class="modal-content">
<button class="modal-close" onclick="closeModal('infoModal')">&times;</button>
<div class="modal-emoji" id="m-emoji"></div>
<div class="modal-title" id="m-title"></div>
<div class="modal-desc" id="m-desc"></div>
</div>
</div>
<script>
const menuToggle = document.getElementById('menu-toggle');
const sidebar = document.getElementById('sidebar');
menuToggle.addEventListener('click', () => {
sidebar.classList.toggle('active');
});
function closeSidebar() {
if (window.innerWidth <= 1024) {
sidebar.classList.remove('active');
}
}
const navLinks = document.querySelectorAll('.nav-link');
navLinks.forEach(link => {
link.addEventListener('click', function() {
navLinks.forEach(l => l.classList.remove('active'));
this.classList.add('active');
});
});
const dropZone = document.getElementById('drop-zone');
const fileInput = document.getElementById('file-input');
const uploadPrompt = document.getElementById('upload-prompt');
const previewWrapper = document.getElementById('preview-wrapper');
const previewImg = document.getElementById('preview-img');
const btnChange = document.getElementById('btn-change');
const loader = document.getElementById('loader');
const results = document.getElementById('results');
dropZone.addEventListener('click', (e) => {
if (e.target !== btnChange) fileInput.click();
});
btnChange.addEventListener('click', (e) => {
e.stopPropagation();
fileInput.click();
});
fileInput.addEventListener('change', (e) => {
if (e.target.files[0]) handleFile(e.target.files[0]);
});
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
dropZone.style.borderColor = '#4f46e5';
dropZone.style.backgroundColor = '#f5f3ff';
});
dropZone.addEventListener('dragleave', () => {
dropZone.style.borderColor = '#cbd5e0';
dropZone.style.backgroundColor = '#f8fafc';
});
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
dropZone.style.borderColor = '#cbd5e0';
dropZone.style.backgroundColor = '#f8fafc';
if (e.dataTransfer.files.length) {
fileInput.files = e.dataTransfer.files;
handleFile(e.dataTransfer.files[0]);
}
});
function handleFile(file) {
if (file.type === 'image/jpeg' || file.type === 'image/png') {
const reader = new FileReader();
reader.onload = (e) => {
previewImg.src = e.target.result;
uploadPrompt.style.display = 'none';
previewWrapper.style.display = 'flex';
dropZone.style.borderStyle = 'solid';
dropZone.style.padding = '30px 20px';
processUpload(file);
};
reader.readAsDataURL(file);
}
}
function translateClass(enClass) {
const mapId = {
'airplane': 'Pesawat', 'automobile': 'Mobil', 'bird': 'Burung', 'cat': 'Kucing',
'deer': 'Rusa', 'dog': 'Anjing', 'frog': 'Katak', 'horse': 'Kuda',
'ship': 'Kapal', 'truck': 'Truk'
};
return mapId[enClass] || enClass;
}
function renderProbs(containerId, probs) {
const container = document.getElementById(containerId);
container.innerHTML = '';
probs.slice(0, 5).forEach(p => {
let color = '#4f46e5';
if(p.confidence > 70) color = '#10b981';
else if(p.confidence < 15) color = '#94a3b8';
container.innerHTML += `
<div class="bar-item">
<div class="bar-label">${translateClass(p.class)}</div>
<div class="bar-bg"><div class="bar-fill" style="width: ${p.confidence}%; background: ${color}"></div></div>
<div class="bar-val">${p.confidence}%</div>
</div>
`;
});
}
function processUpload(file) {
results.style.display = 'none';
loader.style.display = 'block';
const formData = new FormData();
formData.append('file', file);
fetch('/api/predict', { method: 'POST', body: formData })
.then(res => res.json())
.then(data => {
loader.style.display = 'none';
if (data.status === 'error') {
alert("Kesalahan server.");
return;
}
results.style.display = 'block';
const c1 = translateClass(data.model_1.class);
const c2 = translateClass(data.model_2.class);
document.getElementById('mlp-name').innerText = c1;
document.getElementById('mlp-conf').innerText = data.model_1.confidence + '%';
document.getElementById('kan-name').innerText = c2;
document.getElementById('kan-conf').innerText = data.model_2.confidence + '%';
renderProbs('mlp-probs', data.model_1.all_probs);
renderProbs('kan-probs', data.model_2.all_probs);
const interBox = document.getElementById('inter-box');
const emoji = document.getElementById('inter-emoji');
const title = document.getElementById('inter-title');
const text = document.getElementById('inter-text');
if (data.is_outlier) {
interBox.style.background = '#fffbeb';
interBox.style.border = '1px solid #fde68a';
interBox.style.color = '#b45309';
title.innerText = 'Unidentified Object';
text.innerText = 'Confidence score for this image is low across both models, indicating it may not belong to any known class in the CIFAR-10 dataset.';
} else if(c1 === c2) {
interBox.style.background = '#f0fdf4';
interBox.style.border = '1px solid #bbf7d0';
interBox.style.color = '#15803d';
title.innerText = 'Consistent Prediction';
text.innerText = `Both architectures confidently classify the image as ${c1}.`;
} else {
interBox.style.background = '#fef2f2';
interBox.style.border = '1px solid #fecaca';
interBox.style.color = '#b91c1c';
title.innerText = 'Inconsistent Prediction';
text.innerText = `Model ConvNeXt-MLP sees the object as ${c1}, while ConvNeXt-KAN is inclined towards ${c2}.`;
}
setTimeout(() => {
results.scrollIntoView({ behavior: 'smooth', block: 'start' });
}, 100);
})
.catch(err => {
loader.style.display = 'none';
alert("Gagal koneksi ke server.");
});
}
function showClass(title, emoji, desc) {
document.getElementById('m-title').innerText = title;
document.getElementById('m-emoji').innerText = emoji;
document.getElementById('m-desc').innerText = desc;
const modal = document.getElementById('infoModal');
modal.style.display = 'flex';
setTimeout(() => modal.classList.add('show'), 10);
}
function closeModal(id) {
const modal = document.getElementById(id);
modal.classList.remove('show');
setTimeout(() => modal.style.display = 'none', 300);
}
window.onclick = function(event) {
if (event.target.classList.contains('modal')) closeModal(event.target.id);
}
</script>
</body>
</html>