anycoder-142df3d8 / index.html
Kalvis66's picture
Upload folder using huggingface_hub
1cbcf6a verified
Raw
History Blame Contribute Delete
31.9 kB
<!DOCTYPE html>
<html lang="cs">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ECU Tuning Studio Pro</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@300;400;500;600&display=swap" rel="stylesheet">
<style>
:root {
--bg-primary: #0a0a0f;
--bg-secondary: #12121a;
--bg-card: #1a1a25;
--accent-cyan: #00f0ff;
--accent-orange: #ff6b00;
--accent-red: #ff2d55;
--accent-green: #00ff88;
--text-primary: #ffffff;
--text-muted: #6b7280;
--border-color: #2a2a3a;
}
* { box-sizing: border-box; }
body {
font-family: 'JetBrains Mono', monospace;
background: var(--bg-primary);
color: var(--text-primary);
min-height: 100vh;
overflow-x: hidden;
}
.font-display { font-family: 'Orbitron', sans-serif; }
.bg-grid {
position: fixed;
inset: 0;
background-image:
linear-gradient(rgba(0, 240, 255, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(0, 240, 255, 0.03) 1px, transparent 1px);
background-size: 50px 50px;
pointer-events: none;
z-index: 0;
}
.bg-glow {
position: fixed;
width: 600px;
height: 600px;
border-radius: 50%;
filter: blur(150px);
opacity: 0.15;
pointer-events: none;
z-index: 0;
}
.glow-1 {
top: -200px;
left: -200px;
background: var(--accent-cyan);
animation: floatGlow 15s ease-in-out infinite;
}
.glow-2 {
bottom: -200px;
right: -200px;
background: var(--accent-orange);
animation: floatGlow 18s ease-in-out infinite reverse;
}
@keyframes floatGlow {
0%, 100% { transform: translate(0, 0); }
50% { transform: translate(100px, 50px); }
}
.header {
background: linear-gradient(180deg, rgba(26, 26, 37, 0.95) 0%, rgba(10, 10, 15, 0.9) 100%);
backdrop-filter: blur(20px);
border-bottom: 1px solid var(--border-color);
position: sticky;
top: 0;
z-index: 100;
}
.card {
background: linear-gradient(145deg, rgba(26, 26, 37, 0.9) 0%, rgba(18, 18, 26, 0.95) 100%);
border: 1px solid var(--border-color);
border-radius: 16px;
backdrop-filter: blur(10px);
transition: all 0.3s ease;
}
.card:hover {
border-color: rgba(0, 240, 255, 0.3);
box-shadow: 0 0 30px rgba(0, 240, 255, 0.1);
}
.upload-zone {
border: 2px dashed var(--border-color);
border-radius: 16px;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.upload-zone::before {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(45deg, transparent 40%, rgba(0, 240, 255, 0.05) 50%, transparent 60%);
background-size: 300% 300%;
animation: shimmer 3s ease-in-out infinite;
opacity: 0;
transition: opacity 0.3s ease;
}
.upload-zone:hover::before,
.upload-zone.dragover::before { opacity: 1; }
.upload-zone:hover,
.upload-zone.dragover {
border-color: var(--accent-cyan);
box-shadow: 0 0 40px rgba(0, 240, 255, 0.15);
}
@keyframes shimmer {
0% { background-position: 100% 100%; }
100% { background-position: 0% 0%; }
}
.btn-primary {
background: linear-gradient(135deg, var(--accent-cyan) 0%, #00a8b3 100%);
color: var(--bg-primary);
font-weight: 600;
padding: 12px 24px;
border-radius: 10px;
border: none;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.btn-primary::before {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(135deg, transparent 0%, rgba(255, 255, 255, 0.2) 50%, transparent 100%);
transform: translateX(-100%);
transition: transform 0.5s ease;
}
.btn-primary:hover::before { transform: translateX(100%); }
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 10px 30px rgba(0, 240, 255, 0.3);
}
.btn-secondary {
background: transparent;
color: var(--text-primary);
font-weight: 500;
padding: 12px 24px;
border-radius: 10px;
border: 1px solid var(--border-color);
cursor: pointer;
transition: all 0.3s ease;
}
.btn-secondary:hover {
border-color: var(--accent-cyan);
background: rgba(0, 240, 255, 0.1);
}
.toggle-switch {
position: relative;
width: 60px;
height: 30px;
background: var(--bg-secondary);
border-radius: 15px;
cursor: pointer;
transition: all 0.3s ease;
border: 1px solid var(--border-color);
}
.toggle-switch::after {
content: '';
position: absolute;
width: 24px;
height: 24px;
background: var(--text-muted);
border-radius: 50%;
top: 2px;
left: 2px;
transition: all 0.3s ease;
}
.toggle-switch.active {
background: linear-gradient(135deg, var(--accent-cyan) 0%, #00a8b3 100%);
border-color: var(--accent-cyan);
}
.toggle-switch.active::after {
left: 32px;
background: var(--bg-primary);
}
.hex-viewer {
font-family: 'JetBrains Mono', monospace;
font-size: 12px;
line-height: 1.6;
background: var(--bg-primary);
border-radius: 8px;
overflow: auto;
max-height: 400px;
}
.hex-line {
display: flex;
padding: 2px 8px;
transition: background 0.2s ease;
}
.hex-line:hover { background: rgba(0, 240, 255, 0.1); }
.hex-offset {
color: var(--accent-cyan);
min-width: 80px;
opacity: 0.7;
}
.hex-bytes {
color: var(--text-primary);
min-width: 380px;
}
.hex-ascii {
color: var(--accent-green);
opacity: 0.8;
}
.info-row {
display: flex;
justify-content: space-between;
padding: 10px 0;
border-bottom: 1px solid var(--border-color);
}
.info-row:last-child { border-bottom: none; }
.info-label { color: var(--text-muted); }
.info-value {
color: var(--text-primary);
font-weight: 500;
}
.info-value.highlight { color: var(--accent-cyan); }
.mod-card {
background: linear-gradient(145deg, rgba(26, 26, 37, 0.8) 0%, rgba(18, 18, 26, 0.9) 100%);
border: 1px solid var(--border-color);
border-radius: 12px;
padding: 20px;
transition: all 0.3s ease;
}
.mod-card:hover {
transform: translateY(-4px);
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.3);
}
.mod-card.active {
border-color: var(--accent-cyan);
box-shadow: 0 0 30px rgba(0, 240, 255, 0.15);
}
.progress-bar {
height: 4px;
background: var(--bg-secondary);
border-radius: 2px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, var(--accent-cyan) 0%, var(--accent-green) 100%);
border-radius: 2px;
transition: width 0.5s ease;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--accent-green);
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; box-shadow: 0 0 10px var(--accent-green); }
50% { opacity: 0.5; box-shadow: 0 0 5px var(--accent-green); }
}
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: var(--bg-secondary); }
::-webkit-scrollbar-thumb { background: var(--border-color); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--accent-cyan); }
.fade-in { animation: fadeIn 0.5s ease forwards; }
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.slide-in { animation: slideIn 0.6s ease forwards; }
@keyframes slideIn {
from { opacity: 0; transform: translateX(-30px); }
to { opacity: 1; transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
@media (max-width: 768px) {
.hex-viewer { font-size: 10px; }
.hex-bytes { min-width: 280px; }
}
.flame-icon { animation: flicker 0.5s ease-in-out infinite alternate; }
@keyframes flicker {
0% { opacity: 0.8; transform: scale(1); }
100% { opacity: 1; transform: scale(1.1); }
}
.badge-warning {
background: linear-gradient(135deg, var(--accent-orange) 0%, #cc5500 100%);
color: white;
font-size: 10px;
padding: 2px 8px;
border-radius: 4px;
text-transform: uppercase;
font-weight: 600;
}
.badge-success {
background: linear-gradient(135deg, var(--accent-green) 0%, #00cc6a 100%);
color: var(--bg-primary);
font-size: 10px;
padding: 2px 8px;
border-radius: 4px;
text-transform: uppercase;
font-weight: 600;
}
.slider {
-webkit-appearance: none;
width: 100%;
height: 6px;
background: var(--bg-secondary);
border-radius: 3px;
outline: none;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
width: 18px;
height: 18px;
background: var(--accent-cyan);
border-radius: 50%;
cursor: pointer;
transition: all 0.2s ease;
}
.slider::-webkit-slider-thumb:hover {
transform: scale(1.2);
box-shadow: 0 0 15px var(--accent-cyan);
}
.map-item {
padding: 8px 12px;
background: rgba(0, 240, 255, 0.05);
border-radius: 6px;
cursor: pointer;
transition: all 0.2s ease;
border: 1px solid transparent;
}
.map-item:hover {
background: rgba(0, 240, 255, 0.1);
border-color: rgba(0, 240, 255, 0.3);
}
.dtc-item {
padding: 10px;
background: rgba(255, 45, 85, 0.1);
border-radius: 6px;
border-left: 3px solid var(--accent-red);
}
.dtc-item.pending {
background: rgba(255, 107, 0, 0.1);
border-left-color: var(--accent-orange);
}
.file-loaded .upload-zone {
border-color: var(--accent-green);
background: rgba(0, 255, 136, 0.05);
}
.toast {
position: fixed;
bottom: 20px;
right: 20px;
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: 12px;
padding: 16px 24px;
z-index: 1000;
animation: slideInToast 0.3s ease;
}
@keyframes slideInToast {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
.toast.success { border-color: var(--accent-green); }
.toast.error { border-color: var(--accent-red); }
.toast.warning { border-color: var(--accent-orange); }
</style>
</head>
<body>
<div class="bg-grid"></div>
<div class="bg-glow glow-1"></div>
<div class="bg-glow glow-2"></div>
<header class="header relative z-10">
<div class="max-w-7xl mx-auto px-4 py-4">
<div class="flex items-center justify-between flex-wrap gap-4">
<div class="flex items-center gap-4">
<div class="flex items-center gap-3">
<svg class="w-10 h-10 text-cyan-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2L2 7l10 5 10-5-10-5z"/>
<path d="M2 17l10 5 10-5"/>
<path d="M2 12l10 5 10-5"/>
</svg>
<div>
<h1 class="font-display text-xl font-bold tracking-wider">ECU TUNING STUDIO</h1>
<p class="text-xs text-gray-500">Professional Binary Analysis</p>
</div>
</div>
</div>
<div class="flex items-center gap-4">
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="text-xs text-gray-400 hover:text-cyan-400 transition-colors">
Built with anycoder
</a>
<div class="flex items-center gap-2">
<div class="status-dot" id="statusDot"></div>
<span class="text-xs text-gray-400" id="statusText">Ready</span>
</div>
</div>
</div>
</div>
</header>
<main class="relative z-10 max-w-7xl mx-auto px-4 py-8">
<!-- Upload section -->
<section id="uploadSection" class="mb-8 fade-in">
<div class="upload-zone p-8 text-center cursor-pointer" id="dropZone">
<input type="file" id="fileInput" accept=".bin,.BIN,.hex,.HEX" class="hidden">
<div class="relative z-10">
<svg class="w-16 h-16 mx-auto mb-4 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"/>
</svg>
<h3 class="font-display text-lg font-semibold mb-2">Nahrajte ECU soubor</h3>
<p class="text-gray-500 text-sm mb-4">Pretáhněte .bin soubor nebo klikněte pro výběr</p>
<p class="text-xs text-gray-600">Podporované formáty: .bin, .BIN, .hex | Max velikost: 2MB</p>
</div>
</div>
<div id="fileInfo" class="hidden mt-4 card p-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<svg class="w-8 h-8 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
<div>
<p class="font-semibold" id="loadedFileName">-</p>
<p class="text-xs text-gray-500" id="loadedFileSize">-</p>
</div>
</div>
<button class="btn-secondary text-xs py-2 px-4" onclick="resetFile()">Odstranit</button>
</div>
</div>
</section>
<!-- File info & analysis -->
<section id="analysisSection" class="hidden mb-8">
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div class="card p-6 slide-in">
<div class="flex items-center justify-between mb-4">
<h2 class="font-display text-sm font-semibold tracking-wider text-gray-400">RIDICI JEDNOTKA</h2>
<span class="badge-success">DETEKOVANO</span>
</div>
<div id="ecuInfo">
<div class="info-row">
<span class="info-label">ECU Typ</span>
<span class="info-value highlight" id="ecuType">-</span>
</div>
<div class="info-row">
<span class="info-label">Vyrobce</span>
<span class="info-value" id="ecuManufacturer">-</span>
</div>
<div class="info-row">
<span class="info-label">Verze SW</span>
<span class="info-value" id="swVersion">-</span>
</div>
<div class="info-row">
<span class="info-label">Verze HW</span>
<span class="info-value" id="hwVersion">-</span>
</div>
<div class="info-row">
<span class="info-label">Velikost</span>
<span class="info-value" id="fileSizeDisplay">-</span>
</div>
<div class="info-row">
<span class="info-label">Checksum</span>
<span class="info-value font-mono text-xs" id="checksum">-</span>
</div>
<div class="info-row">
<span class="info-label">Vozidlo</span>
<span class="info-value" id="vehicle">-</span>
</div>
<div class="info-row">
<span class="info-label">Motor</span>
<span class="info-value" id="engine">-</span>
</div>
</div>
</div>
<div class="card p-6 slide-in" style="animation-delay: 0.1s">
<div class="flex items-center justify-between mb-4">
<h2 class="font-display text-sm font-semibold tracking-wider text-gray-400">DETEKCE MAP</h2>
<span class="text-xs text-gray-500" id="mapCount">0 nalezeno</span>
</div>
<div id="mapList" class="space-y-2 max-h-64 overflow-y-auto"></div>
</div>
<div class="card p-6 slide-in" style="animation-delay: 0.2s">
<div class="flex items-center justify-between mb-4">
<h2 class="font-display text-sm font-semibold tracking-wider text-gray-400">DTC KODY</h2>
<span class="badge-warning" id="dtcCount">0 aktivnich</span>
</div>
<div id="dtcList" class="space-y-2"></div>
</div>
</div>
</section>
<!-- Hex Viewer & Modifications -->
<section id="mainSection" class="hidden">
<div class="grid grid-cols-1 xl:grid-cols-2 gap-6 mb-8">
<div class="card p-6">
<div class="flex items-center justify-between mb-4 flex-wrap gap-2">
<h2 class="font-display text-sm font-semibold tracking-wider text-gray-400">HEX VIEWER</h2>
<div class="flex gap-2">
<button class="btn-secondary text-xs py-2 px-3" onclick="jumpToOffset()">Skocit na offset</button>
<button class="btn-secondary text-xs py-2 px-3" onclick="searchHex()">Hledat</button>
</div>
</div>
<div class="hex-viewer p-4" id="hexViewer"></div>
<div class="mt-4 flex items-center justify-between text-xs text-gray-500">
<span id="hexOffset">Offset: 0x00000000</span>
<span id="hexSelection">Vyber: zadny</span>
</div>
</div>
<div class="card p-6">
<div class="flex items-center justify-between mb-4">
<h2 class="font-display text-sm font-semibold tracking-wider text-gray-400">MODIFIKACE</h2>
<span class="text-xs text-gray-500" id="activeModCount">0 aktivnich</span>
</div>
<div class="space-y-4" id="modificationsList">
<!-- Pop & Bangs -->
<div class="mod-card" id="mod-popbang">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-3">
<svg class="w-6 h-6 text-orange-500 flame-icon" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 23c-3.9 0-7-3.1-7-7 0-2.8 1.6-5.2 4-6.4V8c0-2.2 1.8-4 4-4s4 1.8 4 4v1.6c2.4 1.2 4 3.6 4 6.4 0 3.9-3.1 7-7 7zm0-18c-1.1 0-2 .9-2 2v2.3l-.7.4C7.8 10.7 7 12.3 7 14c0 2.8 2.2 5 5 5s5-2.2 5-5c0-1.7-.8-3.3-2.3-4.3l-.7-.4V7c0-1.1-.9-2-2-2z"/>
</svg>
<div>
<h3 class="font-semibold">POP AND BANGS</h3>
<p class="text-xs text-gray-500">Agresivni vyfukove efekty</p>
</div>
</div>
<div class="toggle-switch" data-mod="popbang" onclick="toggleMod('popbang', this)"></div>
</div>
<div class="mod-settings hidden mt-4 pt-4 border-t border-gray-700" id="settings-popbang">
<div class="space-y-4">
<div>
<label class="text-xs text-gray-400 mb-2 block">Intenzita</label>
<input type="range" class="slider" min="1" max="10" value="5" id="popbang-intensity" oninput="updateSliderValue(this, 'popbang-intensity-val')">
<div class="flex justify-between text-xs text-gray-500 mt-1">
<span>Mirna</span>
<span id="popbang-intensity-val">5</span>
<span>Extremni</span>
</div>
</div>
<div>
<label class="text-xs text-gray-400 mb-2 block">RPM rozsah</label>
<div class="flex gap-2">
<input type="number" class="bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm w-24" value="2500" placeholder="Min">
<span class="text-gray-500 self-center">-</span>
<input type="number" class="bg-gray-800 border border-gray-700 rounded px-3 py-2 text-sm w-24" value="6500" placeholder="Max">
</div>
</div>
</div>
</div>
</div>
<!-- Hardcut -->
<div class="mod-card" id="mod-hardcut">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-3">
<svg class="w-6 h-6 text-red-500 flame-icon" fill="currentColor" viewBox="0 0 24 24">
<path d="M13.5.67s.74 2.65.74 4.8c0 2.06-1.35 3.73-3.41 3.73-2.07 0-3.63-1.67-3.63-3.73l.03-.36C5.21 7.51 4 10.62 4 14c0 4.42 3.58 8 8 8s8-3.58 8-8C20 8.61 17.41 3.8 13.5.67zM11.71 19c-1.78 0-3.22-1.4-3.22-3.14 0-1.62 1.05-2.76 2.81-3.12 1.77-.36 3.6-1.21 4.62-2.58.39 1.29.59 2.65.59 4.04 0 2.65-2.15 4.8-4.8 4.8z"/>
</svg>
<div>
<h3 class="font-semibold">HARDCUT WITH FLAMES</h3>
<p class="text-xs text-gray-500">Tvrde strihani s plameny</p>
</div>
</div>
<div class="toggle-switch" data-mod="hardcut" onclick="toggleMod('hardcut', this)"></div>
</div>
<div class="mod-settings hidden mt-4 pt-4 border-t border-gray-700" id="settings-hardcut">
<div class="space-y-4">
<div>
<label class="text-xs text-gray-400 mb-2 block">Hardcut RPM</label>
<input type="range" class="slider" min="6000" max="8000" value="7200" id="hardcut-rpm" oninput="updateSliderValue(this, 'hardcut-rpm-val')">
<div class="flex justify-between text-xs text-gray-500 mt-1">
<span>6000</span>
<span id="hardcut-rpm-val">7200</span>
<span>8000</span>
</div>
</div>
<div>
<label class="text-xs text-gray-400 mb-2 block">Delka plamene (ms)</label>
<input type="range" class="slider" min="50" max="300" value="150" id="flame-duration" oninput="updateSliderValue(this, 'flame-duration-val')">
<div class="flex justify-between text-xs text-gray-500 mt-1">
<span>50</span>
<span id="flame-duration-val">150</span>
<span>300</span>
</div>
</div>
</div>
</div>
</div>
<!-- Stage 1 -->
<div class="mod-card" id="mod-stage1">
<div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-3">
<svg class="w-6 h-6 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
</svg>
<div>
<h3 class="font-semibold">STAGE 1 TUNE</h3>
<p class="text-xs text-gray-500">Zakladni optimalizace vykonu</p>
</div>
</div>
<div class="toggle-switch" data-mod="stage1" onclick="toggleMod('stage1', this)"></div>
</div>
<div class="mod-settings hidden mt-4 pt-4 border-t border-gray-700" id="settings-stage1">
<div class="grid grid-cols-2 gap-4 text-sm">
<div class="bg-gray-800/50 rounded-lg p-3">
<span class="text-gray-500 text-xs">Puvodni vykon</span>
<p class="font-display text-lg" id="originalHP">150 HP</p>
</div>
<div class="bg-gray-800/50 rounded-lg p-3">
<span class="text-gray-500 text-xs">Po uprave</span>
<p class="font-display text-lg text-green-400" id="tunedHP">195 HP</p>
</div>
<div class="bg-gray-800/50 rounded-lg p-3">
<span class="text-gray-500 text-xs">Puvodni moment</span>
<p class="font-display text-lg" id="originalNM">210 Nm</p>
</div>
<div class="bg-gray-800/50 rounded-lg p-3">
<span class="text-gray-500 text-xs">Po uprave</span>
<p class="font-display text-lg text-green-400" id="tunedNM">280 Nm</p>
</div>
</div>
</div>
</div>
<!-- DPF/EGR -->
<div class="mod-card" id="mod-dpf">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<svg class="w-6 h-6 text-yellow-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636"/>
</svg>
<div>
<h3 class="font-semibold">DPF/EGR OFF</h3>
<p class="text-xs text-gray-500">Odstraneni emisnich systemu</p>
</div>
</div>
<div class="toggle-switch" data-mod="dpf" onclick="toggleMod('dpf', this)"></div>
</div>
<div class="mt-2">
<span class="badge-warning">Pouze pro zavodni pouziti</span>
</div>
</div>
</div>
</div>
</div>
<!-- Action buttons -->
<div class="flex flex-wrap gap-4 justify-center mb-8">
<button class="btn-primary flex items-center gap-2" onclick="applyMods()">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
Aplikovat zmeny
</button>
<button class="btn-secondary flex items-center gap-2" onclick="compareFiles()">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"/>
</svg>
Porovnat s originalom
</button>
<button class="btn-secondary flex items-center gap-2" onclick="exportFile()">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/>
</svg>
Exportovat .bin
</button>
</div>
<!-- Progress section -->
<div id="progressSection" class="hidden card p-6 mb-8">
<div class="flex items-center justify-between mb-4">
<h2 class="font-display text-sm font-semibold tracking-wider text-gray-400">PRUBEH APLIKACE</h2>
<span class="text-xs text-cyan-400" id="progressPercent">0%</span>
</div>
<div class="progress-bar mb-4">
<div class="progress-fill" id="progressFill" style="width: 0%"></div>
</div>
<div id="progressLog" class="text-xs text-gray-500 space-y-1 max-h-32 overflow-y-auto"></div>
</div>
</section>
</main>
<!-- Search Modal -->
<div id="searchModal" class="fixed inset-0 bg-black/80 backdrop-blur-sm z-50 hidden flex items-center justify-center p-4">
<div class="card p-6 max-w-md w-full">
<div class="flex items-center justify-between mb-4">
<h2 class="font-display text-lg font-semibold">Hledat v HEX</h2>
<button onclick="closeSearchModal()" class="text-gray-500 hover:text-white">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
<input type="text" id="searchInput" class="w-full bg-gray-800 border border-gray-700 rounded-lg px-4 py-3 mb-4" placeholder="Zadejte HEX hodnotu (napr. FF00A1)">
<button class="btn-primary w-full" onclick="performSearch()">Hledat</button>
</div>
</div>
<!-- Offset Modal -->
<div id="offsetModal" class="fixed inset-0 bg-black/80 backdrop-blur-sm z-50 hidden flex items-center justify-center p-4">
<div class="card p-6 max-w-md w-full">
<div class="flex items-center justify-between mb-4">
<h2 class="font-display text-lg font-semibold">Skocit na offset</h2>
<button onclick="closeOffsetModal()" class="text-gray-500 hover:text-white">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
<input type="text" id="offsetInput" class="w-full bg-gray-800 border border-gray-700 rounded-lg px-4 py-3 mb-4" placeholder="Zadejte offset (napr. 0x1000 nebo 4096)">
<button class="btn-primary w-full" onclick="performJump()">Skocit</button>
</div>
</div>
<script>
// State
let fileData = null;
let originalFileData = null;
let fileName = '';
let activeMods = new Set();
let currentECU = null;
// ECU Database
const ecuDatabase = {
'Bosch ME7.5': {
manufacturer: 'Bosch',
vehicle: 'VW Golf IV 1.8T',
engine: 'AGU 150HP',
originalHP: 150,
originalNM: 210,
maps: [
{ name: 'Ignition Advance', offset: '0x00012A00', size: '24x20', type: '2D' },
{ name: 'Fuel Injection', offset: '0x00015C00', size: '16x16', type: '2D' },
{ name: 'Boost Pressure', offset: '0x00018400', size: '12x12', type: '2D' },
{ name: 'Torque Limit', offset: '0x0001A200', size: '8x8', type: '2D' },
{ name: 'Rev Limiter', offset: '0x0001B800', size: '1D', type: '1D' },
{ name: 'Speed Limiter', offset: '0x0001B900', size: '1D', type: '1D' },
{ name: 'Lambda Target', offset: '0x0001C000', size: '16x16', type: '2D' },
{ name: 'Throttle Response', offset: '0x0001E400', size: '10x10', type: '2D' }
],
dtcs: [
{ code: 'P0171', desc: 'System Too Lean (Bank 1)', status: 'active' },
{ code: 'P0300', desc: 'Random Misfire Detected', status: 'pending' },
{ code: 'P0420', desc: 'Catalyst Efficiency Below Threshold', status: 'active' }
]
},
'Bosch ME9.1': {
manufacturer: 'Bosch',
vehicle: 'Audi A4 2.0TFSI',
engine: 'BWA 200HP',
originalHP: 200,
originalNM: 280,
maps: [
{ name: 'Ignition Advance', offset: '0x00014000', size: '32x24', type: '2D' },
{ name: 'Fuel Injection', offset: '0x00018000', size: '20x20', type: '2D' },
{ name: 'Boost Pressure', offset: '0x0001C000', size: '16x16', type: '2D' },
{ name: 'Torque Limit', offset: '0x0001E000', size: '10x10', type: '2D' },
{ name: 'Rev Limiter', offset: '0x0001F000', size: '1D', type: '1D' }
],
dtcs: [
{