Free HTML Obfuscator - Minify, Obfuscate & Beautify HTML Online

Secure HTML Obfuscator & Client-Side Code Minifier

or drop HTML files here to minify, obfuscate, and beautify your markup with 100% privacy

</> LOCK

Drag & drop your .html or .htm file anywhere here

Supported: .HTML, .HTM, .TXT
0 characters | 0 lines
Obfuscation Security Profile
Dynamic Sandbox
Self-executing JS decoder sandbox
Hex / Entity Mask
Encodes DOM text into hex entities
Military Anti-Tamper
XOR Base64 + Right-click trap
Analyzing DOM tree & parsing tokens...
0%
0 B
Original Size
0 B
Processed Size
0 B
Payload Delta
0%
Compression Ratio
Original Source
Processed Output

Pro Developer Code Snapshot Card

Generate social-ready code cards with crystal-clear DSLR portrait framing and syntax themes.

Zero Cloud Uploads
100% Client-Side In-Memory
3-in-1 Multi-Engine Pipeline

How to Minify, Obfuscate & Beautify HTML Code

A seamless 3-step browser workflow designed for code protection and web speed optimization.

1
HTML

Input or Drop HTML Source

2

Select Engine Mode & Process

3
Export Code

Live Preview & Download

How Our Code Transformation Engine Works

Learn the AST tokenization and client-side entropy pipeline behind our secure HTML obfuscator and minifier.

01

DOM & AST Token Parsing

The engine parses raw markup into distinct semantic tokens, isolating element tags, attributes, inline CSS stylesheets, and embedded JS script blocks without executing unsafe code.

Tip: Supports modern HTML5, XHTML, and web components
02

Identifier Mangling & Entropy Encoding

In Obfuscate mode, DOM class names and IDs are converted to non-deterministic hex keys while string literals and text nodes are encoded into encrypted self-evaluating decoders.

Security: Defeats automated scrapers & scrap bots
03

Inline Asset Minification & Whitespace Strip

Comments, indentation tabs, redundant quotes, and newline breaks are collapsed. CSS rules and JS functions are stripped of comments and whitespace down to minimal bytecode.

Speed: Reduces document payload by up to 65%
04

Sandboxed Verification & Snapshot Export

The output renders dynamically inside an isolated iframe sandbox to verify document layout fidelity before you download files or export DSLR-grade code snapshot cards.

Ready: 100% W3C HTML5 runtime compliant

Powerful Performance Features

Engineered for razor-sharp code security, instantaneous payload compression, and flawless local privacy.

100% In-Memory Privacy

Zero remote server uploads. Your proprietary code is parsed solely inside your browser sandbox.

3-in-1 Multi-Engine

Seamlessly toggle between Minify, Obfuscate, and Beautify modes without switching websites.

Deep Inline Optimization

Optimizes embedded CSS styles and JavaScript logic simultaneously alongside HTML markup.

DSLR Code Snapshotting

Export high-resolution social code cards featuring your developer portrait and syntax themes.

Live Sandboxed Diff

Inspect side-by-side original vs processed source code with real-time payload analytics.

Instant Zero-Lag Processing

High-speed regex and AST pipelines process multi-megabyte HTML files in milliseconds.

Client-Side HTML Obfuscation & Optimization Architecture

Protect your source code and boost your website speed. Our private, browser-based HTML obfuscator allows you to hide your logic safely, while also letting you minify HTML online, compress HTML file assets, and utilize an advanced HTML beautifier online and HTML unminifier.

01 • CODE PROTECTION & ANTI-TAMPERING

High-Entropy Code Obfuscation vs. Plaintext Vulnerability

CORE: HTML OBFUSCATOR TARGET: AST & DOM IDENTIFIERS DYNAMIC SANDBOX

Web applications deliver raw plaintext markup directly to user clients. While transparent, this exposes proprietary frontend templates, licensing mechanisms, custom CSS frameworks, and embedded scripts to automated scrapers and code piracy.

Employing an html obfuscator transforms readable markup into randomized string matrices and self-executing JavaScript decoder wrappers according to W3C HTML5 standards. This neutralizes scraping bots while ensuring standard browsers render elements seamlessly.

  • Encodes sensitive text and DOM nodes into self-evaluating decoders.
  • Mangles CSS classes and IDs to prevent template ripping and unauthorized cloning.
  • Optional anti-inspection traps disable context menus and developer tools traps.
.HTML SRC <div class="hero">   <h1>Secret</h1>   <!-- comments --> </div>Plaintext Source EXPOSURE: VULNERABLE UNPROTECTED DOM AST // ENGINE .OBF LOCKED var _0x4f12='...' eval(atob(_0x4f)) \x3c\x64\x69\x76\x3e document.write()Obfuscated Binary CIPHER: 100% PRIVATE SCRAPER RESISTANT
02 • WEB PERFORMANCE & CORE WEB VITALS

Performance Acceleration: How to Minify HTML Online & Compress HTML File Assets

ACTION: MINIFY HTML ONLINE SCOPE: COMPRESS HTML FILE ZERO LOSS TTFB BOOST

Every redundant whitespace character, line break, and block comment inflates your document's network transfer weight. Uncompressed HTML slows down mobile download speeds and increases page rendering latencies.

When you minify HTML online to compress HTML file weight, our engine collapses redundant tokens, trims optional tags, and eliminates whitespace. According to MDN Web Docs performance guidelines, eliminating document overhead drastically accelerates browser parsing.

  • Reduces document weight by up to 65% for instant mobile load times.
  • Optimizes inline CSS in <style> and inline JS in <script> simultaneously.
  • Improves Google Core Web Vitals (LCP & FID) without breaking page layout.
dashboard of the html obfuscator and beautifier tool showing code compression and protection
03 • DEVELOPER WORKFLOW & DEBUGGING

Reversible Inspection: HTML Beautifier Online & HTML Unminifier Workflow

TOOL: HTML BEAUTIFIER ONLINE FUNCTION: HTML UNMINIFIER AST INDENTATION

Working with minified production templates or third-party web scrapings can be challenging when the entire source is compressed into a single unformatted line.

Our html beautifier online doubles as a high-precision html unminifier, intelligently reconstructing parent-child indentation hierarchies, inserting clean tag returns, and restructuring inline stylesheet and JavaScript formatting for effortless debugging.

  • Turns dense, single-line production code into readable nested structures.
  • Configurable 2-space, 4-space, or tab indentation schemes.
  • Export DSLR-quality snapshot code cards directly to social media and developer blogs.
AST UNMINIFIER MINIFIED IN 1-LINE DENSE CODE IND Indentation Engine SCHEME: 2-SPACES / TAB REVERSIBLE BEAUTIFICATION BEAUTIFIED CLEAN FORMAT

Frequently Asked Questions

Everything you need to know about our free HTML obfuscator, minifier, and beautifier suite.

An html obfuscator scrambles and encrypts HTML tags, inline JavaScript scripts, and CSS style rules into encoded unicode/hex tokens and dynamic self-executing sandbox decoders. This prevents competitor copying, unauthorized template theft, and scraping while keeping 100% browser rendering functionality intact.

Yes! You can securely minify HTML online with our tool. It safely removes redundant comments, collapses whitespace, and compacts inline CSS and JS without altering DOM element functionality, running entirely on your local device for maximum privacy.

When you compress HTML file sizes, your website loads significantly faster, which greatly improves your Google Core Web Vitals, reduces server bandwidth costs, and elevates SEO rankings for mobile search visitors.

Absolutely. If you have unreadable code, just switch to our html beautifier online tab. It instantly adds proper indentation, nested spacing, and clean line breaks, making any script perfectly readable.

Yes, our beautify engine acts as a powerful html unminifier, reversing dense single-line minification so you can easily edit, inspect, and debug production HTML files.

No. Our parser strictly respects standard HTML5 specifications. Inline event listeners (e.g. onclick, onload) and embedded CSS stylesheets remain completely functional inside the browser DOM.

Our code snapshot engine renders your formatted code onto a hardware-accelerated 2D canvas card with a dark IDE terminal frame, line numbers, and developer metadata. You can upload a portrait photo which is processed with DSLR-grade circular framing, contrast grading, and EXIF camera watermarks for social sharing on LinkedIn, X, and GitHub.

This tool is 100% free with no subscriptions, usage limits, or watermarks. Since it executes directly in your browser memory, you can process files of any size without delay.

Notification
`;btnSampleCode.addEventListener('click', function(e) { e.stopPropagation(); rawHtmlInput.value = sampleHtmlTemplate; updateEditorCounter(); dropStatusLabel.innerHTML = ' Loaded sample enterprise HTML'; showToast('Sample HTML loaded!'); playAudioFx('click'); rawHtmlInput.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); });// 3-IN-1 PROCESSING ALGORITHMS function runMinifyEngine(src) { var res = src; var optComments = document.getElementById('minComments').checked; var optWhitespace = document.getElementById('minWhitespace').checked; var optCss = document.getElementById('minCss').checked; var optJs = document.getElementById('minJs').checked; var optQuotes = document.getElementById('minQuotes').checked; var optEmptyAttrs = document.getElementById('minEmptyAttrs').checked; var optOptionalTags = document.getElementById('minOptionalTags').checked; var optBooleanAttrs = document.getElementById('minBooleanAttrs').checked;// 1. Remove comments if (optComments) { res = res.replace(//g, ''); }// 2. Minify inline CSS if (optCss) { res = res.replace(/]*>([\s\S]*?)<\/style>/gi, function(match, css) { var minCss = css .replace(/\/\*[\s\S]*?\*\//g, '') .replace(/\s+/g, ' ') .replace(/\s*([\{\}:;,])\s*/g, '$1') .trim(); return match.replace(css, function() { return minCss; }); }); } // 3. Minify inline JS if (optJs) { res = res.replace(/]*>([\s\S]*?)<\/script>/gi, function(match, js) { var lines = js.split('\n'); var cleaned = lines.map(function(l) { var str = l.trim(); return str.startsWith('//') ? '' : str; }).filter(function(l) { return l.length > 0; }).join(' '); var minJs = cleaned .replace(/\/\*[\s\S]*?\*\//g, '') .replace(/\s*([=\+\-\*\/\{\}\(\);,:<>&|!])\s*/g, '$1'); return match.replace(js, function() { return minJs; }); }); } // 4. Quotes & Attributes if (optQuotes) { res = res.replace(/="([a-zA-Z0-9_\-\.]+)"/g, '=$1'); } if (optBooleanAttrs) { ['disabled', 'readonly', 'checked', 'selected', 'required', 'autofocus'].forEach(function(attr) { var reg = new RegExp('\\s+' + attr + '(?:="[^"]*")?', 'gi'); res = res.replace(reg, ' ' + attr); }); } if (optEmptyAttrs) { res = res.replace(/\s+[a-zA-Z0-9_\-]+\s*=\s*(""|'')/g, ''); } if (optOptionalTags) { res = res.replace(/<\/(li|dt|dd|p|option|tr|td|th|thead|tbody|tfoot)>/gi, ''); } // 5. Collapse Whitespace if (optWhitespace) { res = res.replace(/\s+/g, ' '); res = res.replace(/>\s+<'); res = res.trim(); } return res; } function runObfuscateEngine(src) { // Pre-minify var base = runMinifyEngine(src); var activePreset = document.querySelector('#optionsObfuscateView .preset-box-item.active'); var preset = activePreset ? activePreset.dataset.preset : 'standard-obf'; var mangleAttrs = document.getElementById('obfMangleAttrs').checked; var antiInspect = document.getElementById('obfAntiInspect').checked; if (mangleAttrs) { // Mangle classes and IDs into hex tokens var classMap = {}; base = base.replace(/class="([^"]+)"/g, function(match, clsNames) { var tokens = clsNames.split(/\s+/).map(function(t) { if (!classMap[t]) classMap[t] = '_0x' + Math.random().toString(16).substring(2, 6); return classMap[t]; }).join(' '); return 'class="' + tokens + '"'; }); } var scriptGuard = antiInspect ? ' `; return obfWrapper; } function runBeautifyEngine(src) { var tab = ' '; var html = src.replace(/[\r\n]+/g, '\n').replace(/>\s*\n<'); var lines = html.split('\n'); var formatted = []; var level = 0; var voidTags = {'area':1, 'base':1, 'br':1, 'col':1, 'embed':1, 'hr':1, 'img':1, 'input':1, 'link':1, 'meta':1, 'param':1, 'source':1, 'track':1, 'wbr':1, '!doctype':1}; for (var i = 0; i < lines.length; i++) { var trimmed = lines[i].trim(); if (!trimmed) continue; var isClosing = /^<\/[a-zA-Z0-9_\-]+>/.test(trimmed); var isOpening = /^<[a-zA-Z0-9_\-]+(?:\s+[^>]*)?>/.test(trimmed) && !trimmed.endsWith('/>'); var tagMatch = trimmed.match(/^<\/?([a-zA-Z0-9_\-]+|!doctype)/i); var tagName = tagMatch ? tagMatch[1].toLowerCase() : ''; var isVoid = voidTags[tagName] || trimmed.endsWith('/>'); var hasBoth = /<[a-zA-Z0-9_\-]+[^>]*>.*<\/?[a-zA-Z0-9_\-]+>/.test(trimmed); if (isClosing && level > 0) level--; formatted.push(tab.repeat(Math.max(0, level)) + trimmed); if (isOpening && !isVoid && !hasBoth && !isClosing) level++; } return formatted.join('\n'); } // Master Execution Pipeline btnExecuteProcess.addEventListener('click', function() { var inputVal = rawHtmlInput.value; if (!inputVal.trim()) { showToast('Please enter or upload HTML code first'); rawHtmlInput.focus(); return; } resultsDisplayContainer.style.display = 'none'; progressWrapper.classList.add('active'); btnExecuteProcess.disabled = true; progressWrapper.scrollIntoView({ behavior: 'smooth', block: 'center' }); var startTime = Date.now(); var totalDuration = 1800; // 1.8s progressive feedback var timer = setInterval(function() { var elapsed = Date.now() - startTime; var pct = Math.min(100, Math.floor((elapsed / totalDuration) * 100)); progressFillBar.style.width = pct + '%'; progressPctText.textContent = pct + '%'; if (elapsed < 600) { progressStatusMsg.innerHTML = ' Parsing DOM tree & AST tokenization...'; } else if (elapsed < 1200) { if (currentMode === 'obfuscate') { progressStatusMsg.innerHTML = ' Scrambling identifiers & compiling sandbox cipher...'; } else if (currentMode === 'minify') { progressStatusMsg.innerHTML = ' Collapsing whitespace & stripping comments...'; } else { progressStatusMsg.innerHTML = ' Restructuring indentation & formatting AST...'; } } else { progressStatusMsg.innerHTML = ' Transformation complete! Rendering preview...'; } if (elapsed >= totalDuration) { clearInterval(timer); var processedOutput = ''; if (currentMode === 'obfuscate') { processedOutput = runObfuscateEngine(inputVal); } else if (currentMode === 'minify') { processedOutput = runMinifyEngine(inputVal); } else { processedOutput = runBeautifyEngine(inputVal); } displayToolResults(inputVal, processedOutput); progressWrapper.classList.remove('active'); btnExecuteProcess.disabled = false; playAudioFx('success'); resultsDisplayContainer.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }, 35); }); // Format helper function formatBytes(bytes) { if (bytes < 1024) return bytes + ' B'; if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'; return (bytes / (1024 * 1024)).toFixed(2) + ' MB'; } // Render Results function displayToolResults(orig, output) { var origLen = new Blob([orig]).size; var outLen = new Blob([output]).size; var diff = origLen - outLen; statOrigBytes.textContent = formatBytes(origLen); statOutputBytes.textContent = formatBytes(outLen); if (currentMode === 'minify') { var savedPct = origLen > 0 ? Math.max(0, ((diff / origLen) * 100)).toFixed(1) : 0; statDeltaBytes.textContent = formatBytes(Math.max(0, diff)) + ' Saved'; statEfficiency.textContent = savedPct + '%'; statEfficiencyLabel.textContent = 'Space Reduction'; } else if (currentMode === 'obfuscate') { statDeltaBytes.textContent = 'Encrypted'; statEfficiency.textContent = 'High (AES/Hex)'; statEfficiencyLabel.textContent = 'Entropy Level'; } else { statDeltaBytes.textContent = '+' + formatBytes(Math.abs(diff)); statEfficiency.textContent = '100% Valid'; statEfficiencyLabel.textContent = 'Formatted AST'; } outputHtmlCode.value = output; compareOriginalCode.value = orig; compareProcessedCode.value = output; // Sandbox Iframe preview try { var doc = sandboxPreviewIframe.contentDocument || sandboxPreviewIframe.contentWindow.document; doc.open(); doc.write(output); doc.close(); } catch(e) {} // Render snapshot canvas renderDevSnapshot(output); resultsDisplayContainer.style.display = 'block'; } // Tab Switching var viewTabs = document.querySelectorAll('.view-tab-btn'); viewTabs.forEach(function(btn) { btn.addEventListener('click', function() { viewTabs.forEach(function(b) { b.classList.remove('active'); }); document.querySelectorAll('.view-tab-pane').forEach(function(p) { p.classList.remove('active'); }); btn.classList.add('active'); var targetId = 'viewPane' + btn.dataset.view.charAt(0).toUpperCase() + btn.dataset.view.slice(1); var pane = document.getElementById(targetId); if (pane) pane.classList.add('active'); playAudioFx('click'); }); }); // Developer Snapshot Card Renderer (DSLR Portrait Quality) function renderDevSnapshot(codeSnippet) { if (!snapshotCanvas) return; var ctx = snapshotCanvas.getContext('2d'); var w = 900; var h = 520; snapshotCanvas.width = w; snapshotCanvas.height = h; // Gradient background var bgGrad = ctx.createLinearGradient(0, 0, w, h); bgGrad.addColorStop(0, '#090d16'); bgGrad.addColorStop(0.5, '#0f172a'); bgGrad.addColorStop(1, '#1e1b4b'); ctx.fillStyle = bgGrad; ctx.fillRect(0, 0, w, h); // Card Window Box var cardX = 40, cardY = 40, cardW = 820, cardH = 440; ctx.save(); ctx.shadowColor = 'rgba(0, 0, 0, 0.5)'; ctx.shadowBlur = 24; ctx.shadowOffsetY = 12; ctx.fillStyle = '#0b0f19'; ctx.beginPath(); ctx.roundRect(cardX, cardY, cardW, cardH, 12); ctx.fill(); ctx.strokeStyle = '#334155'; ctx.lineWidth = 1.5; ctx.stroke(); ctx.restore(); // Header Window Controls (macOS style dots) ctx.fillStyle = '#ef4444'; ctx.beginPath(); ctx.arc(cardX + 24, cardY + 24, 6, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = '#f59e0b'; ctx.beginPath(); ctx.arc(cardX + 42, cardY + 24, 6, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = '#10b981'; ctx.beginPath(); ctx.arc(cardX + 60, cardY + 24, 6, 0, Math.PI * 2); ctx.fill(); // Window Title Bar ctx.fillStyle = '#94a3b8'; ctx.font = '700 13px "Plus Jakarta Sans", sans-serif'; ctx.fillText('output-script.min.html — Secure Obfuscator Engine', cardX + 85, cardY + 28); // Divider Line ctx.strokeStyle = '#1e293b'; ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(cardX, cardY + 46); ctx.lineTo(cardX + cardW, cardY + 46); ctx.stroke(); // Render Code Lines ctx.font = '13px "Fira Code", monospace'; var lines = codeSnippet.split('\n').slice(0, 16); var startY = cardY + 75; for (var i = 0; i < lines.length; i++) { var lineNum = (i + 1).toString().padStart(2, '0'); ctx.fillStyle = '#475569'; ctx.fillText(lineNum, cardX + 24, startY + (i * 20)); var lineText = lines[i].substring(0, 58); ctx.fillStyle = i % 2 === 0 ? '#38bdf8' : '#e2e8f0'; ctx.fillText(lineText, cardX + 60, startY + (i * 20)); } // Developer Portrait Badge (DSLR Quality Preserver) var badgeX = cardX + cardW - 200; var badgeY = cardY + cardH - 80; ctx.fillStyle = 'rgba(15, 23, 42, 0.85)'; ctx.strokeStyle = '#2563eb'; ctx.lineWidth = 1.5; ctx.beginPath(); ctx.roundRect(badgeX, badgeY, 180, 60, 10); ctx.fill(); ctx.stroke(); // Avatar drawing var avatarX = badgeX + 30; var avatarY = badgeY + 30; var avatarR = 20; ctx.save(); ctx.beginPath(); ctx.arc(avatarX, avatarY, avatarR, 0, Math.PI * 2); ctx.closePath(); ctx.clip(); if (userAvatarImg) { ctx.drawImage(userAvatarImg, avatarX - avatarR, avatarY - avatarR, avatarR * 2, avatarR * 2); } else { // Default avatar ctx.fillStyle = '#2563eb'; ctx.fillRect(avatarX - avatarR, avatarY - avatarR, avatarR * 2, avatarR * 2); ctx.fillStyle = '#ffffff'; ctx.font = 'bold 15px sans-serif'; ctx.textAlign = 'center'; ctx.fillText('DEV', avatarX, avatarY + 5); } ctx.restore(); // Developer text tags & DSLR watermark metadata ctx.textAlign = 'left'; ctx.fillStyle = '#ffffff'; ctx.font = '800 12px "Plus Jakarta Sans", sans-serif'; ctx.fillText('Verified Developer', avatarX + 28, avatarY - 2); ctx.fillStyle = '#10b981'; ctx.font = '700 9.5px "Fira Code", monospace'; ctx.fillText('ISO 100 • 50mm f/1.4', avatarX + 28, avatarY + 12); } // Avatar Upload Listener devAvatarInput.addEventListener('change', function(e) { if (e.target.files && e.target.files[0]) { var imgReader = new FileReader(); imgReader.onload = function(evt) { var img = new Image(); img.onload = function() { userAvatarImg = img; renderDevSnapshot(outputHtmlCode.value || sampleHtmlTemplate); showToast('Developer portrait uploaded!'); playAudioFx('click'); }; img.src = evt.target.result; }; imgReader.readAsDataURL(e.target.files[0]); } }); // Copy Button btnCopyCode.addEventListener('click', function() { if (!outputHtmlCode || !outputHtmlCode.value) return; if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(outputHtmlCode.value).then(function() { showToast('Code copied to clipboard!'); playAudioFx('click'); }); } else { outputHtmlCode.select(); document.execCommand('copy'); showToast('Code copied to clipboard!'); playAudioFx('click'); } }); // Download HTML File btnDownloadFile.addEventListener('click', function() { if (!outputHtmlCode || !outputHtmlCode.value) return; var blob = new Blob([outputHtmlCode.value], { type: 'text/html;charset=utf-8' }); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = currentMode === 'obfuscate' ? 'obfuscated.html' : (currentMode === 'minify' ? 'minified.html' : 'beautified.html'); document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); showToast('HTML file downloaded successfully!'); playAudioFx('click'); }); // Download Snapshot Image btnDownloadSnapshot.addEventListener('click', function() { if (!snapshotCanvas) return; var imgUrl = snapshotCanvas.toDataURL('image/png'); var a = document.createElement('a'); a.href = imgUrl; a.download = 'code-snapshot-card.png'; document.body.appendChild(a); a.click(); document.body.removeChild(a); showToast('Snapshot PNG image exported!'); playAudioFx('click'); }); // Process More btnProcessAnother.addEventListener('click', function() { resultsDisplayContainer.style.display = 'none'; rawHtmlInput.scrollIntoView({ behavior: 'smooth', block: 'center' }); rawHtmlInput.focus(); showToast('Ready for your next HTML document!'); playAudioFx('click'); }); // Clear All btnClearAllData.addEventListener('click', function() { rawHtmlInput.value = ''; outputHtmlCode.value = ''; compareOriginalCode.value = ''; compareProcessedCode.value = ''; fileInput.value = ''; updateEditorCounter(); resultsDisplayContainer.style.display = 'none'; dropStatusLabel.innerHTML = ' Drag & drop your .html or .htm file anywhere here'; showToast('All editor data cleared'); playAudioFx('click'); }); // FAQ Accordion Toggle document.querySelectorAll('.faq-question-btn').forEach(function(button) { button.addEventListener('click', function() { var itemCard = button.parentElement; var answerBody = itemCard.querySelector('.faq-answer-body'); var isActive = itemCard.classList.contains('active'); document.querySelectorAll('.faq-item-card').forEach(function(card) { card.classList.remove('active'); card.querySelector('.faq-answer-body').style.maxHeight = null; }); if (!isActive) { itemCard.classList.add('active'); answerBody.style.maxHeight = answerBody.scrollHeight + "px"; } playAudioFx('click'); }); }); // Live Dynamic Theme Listener function checkThemeState() { var docEl = document.documentElement; var body = document.body; var isDark = docEl.classList.contains('dark') || docEl.classList.contains('dark-mode') || docEl.getAttribute('data-theme') === 'dark' || (body && (body.classList.contains('dark') || body.classList.contains('dark-mode') || body.getAttribute('data-theme') === 'dark')) || localStorage.getItem('theme') === 'dark' || localStorage.getItem('darkMode') === 'true'; var wrapper = document.getElementById('custom-tool-wrapper'); if (wrapper) { if (isDark) wrapper.classList.add('dark-mode-active'); else wrapper.classList.remove('dark-mode-active'); } } checkThemeState(); setInterval(checkThemeState, 400); })();