NEW RELEASE
v2.2 - 40+ new elementsWhat's new
<!DOCTYPE html>
<html lang="en">
<head>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">

  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Fire Plasma Effect Configurator - BricksFusion</title>
  <style>
    :root {
  --background: #000;
  --card-bg: #1e1e1e;
  --card-bg-hover: #252525;
  --text-primary: #f2f2f7;
  --text-secondary: #8e8e93;
  --accent: #ef6013;
  --accent-hover: #c64c0c;
  --border: #2c2c2e;
  --shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
  --track: #2c2c2e;
  --thumb: #ef6013;
  --card-radius: 16px;
  --input-radius: 8px;
  --button-radius: 12px;
  --transition: all 0.25s ease;
  --font: 'Inter', BlinkMacSystemFont, "San Francisco", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --action-bar-height: 70px;
  --success: #28a745;
  --warning: #ffc107;
  --danger: #dc3545;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: var(--font);
  background-color: var(--background);
  color: var(--text-primary);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  padding-bottom: var(--action-bar-height);
}

.action-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: var(--action-bar-height);
  background: linear-gradient(145deg, #1a1a1a, #0f0f0f);
  border-top: 1px solid var(--border);
  z-index: 1000;
  display: flex;
  align-items: center;
  padding: 0 1.5rem;
  gap: 1rem;
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(10px);
}

.breadcrumb {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: 1;
}

.breadcrumb-item {
  color: var(--text-secondary);
  font-size: var(--text-xs);
  font-weight: 500;
  text-decoration: none;
  transition: var(--transition);
  padding: 0.5rem 0.75rem;
  border-radius: 6px;
}

.breadcrumb-item:hover {
  color: var(--text-primary);
  background-color: rgba(255, 255, 255, 0.05);
}

.breadcrumb-item.active {
  color: var(--accent);
  background-color: rgba(239, 96, 19, 0.1);
}

.breadcrumb-separator {
  color: var(--text-secondary);
  font-size: var(--text-xs);
  opacity: 0.5;
}

.action-buttons {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.action-btn {
  padding: 0.6rem 1rem;
  background-color: var(--card-bg);
  color: var(--text-primary);
  font-family: var(--font);
  font-size: var(--text-xs);
  font-weight: 500;
  border: 1px solid var(--border);
  border-radius: var(--button-radius);
  cursor: pointer;
  transition: var(--transition);
  display: flex;
  align-items: center;
  gap: 0.5rem;
  text-decoration: none;
  white-space: nowrap;
}

.action-btn:hover {
  background-color: var(--card-bg-hover);
  border-color: var(--accent);
  transform: translateY(-1px);
}

.action-btn.primary {
  background: linear-gradient(90deg, var(--accent), #ff8c51);
  border-color: var(--accent);
  color: white;
}

.action-btn.primary:hover {
  background: linear-gradient(90deg, var(--accent-hover), #e67a3f);
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(239, 96, 19, 0.3);
}

.data-attribute-display {
  background-color: rgba(50, 50, 50, 0.8);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.5rem 0.75rem;
  font-family: 'Menlo', 'Monaco', 'Courier New', monospace;
  font-size: var(--text-xs);
  color: #ff8c51;
  cursor: pointer;
  transition: var(--transition);
  user-select: all;
}

.data-attribute-display:hover {
  background-color: rgba(239, 96, 19, 0.2);
  border-color: var(--accent);
}

.container {
  max-width: 100%;
  margin: 0 auto;
  padding: 2rem 1.5rem;
}

.page-header {
  text-align: center;
  margin-bottom: 2rem;
}

.page-title {
  font-size: 2.5rem;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: 0.5rem;
  background: linear-gradient(90deg, var(--accent), #ff8c51);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.page-subtitle {
  font-size: var(--text-s);
  color: var(--text-secondary);
  font-weight: 500;
}

.instructions-toggle {
  margin-bottom: 2rem;
}

.instructions-card {
  background-color: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--card-radius);
  box-shadow: var(--shadow);
  overflow: hidden;
  transition: var(--transition);
}

.instructions-header {
  padding: 1rem 1.5rem;
  cursor: pointer;
  transition: var(--transition);
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid transparent;
}

.instructions-header:hover {
  background-color: var(--card-bg-hover);
}

.instructions-card.expanded .instructions-header {
  border-bottom-color: var(--border);
}

.instructions-title {
  font-size: var(--text-s);
  font-weight: 600;
}

.toggle-icon {
  font-size: 1.2em;
  transition: transform 0.3s ease;
}

.toggle-icon.expanded {
  transform: rotate(180deg);
}

.instructions-content {
  padding: 0 1.5rem;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease, padding 0.3s ease;
}

.instructions-content.show {
  max-height: 500px;
  padding: 1.5rem;
}

.instructions-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}

.how-to-use ol {
  padding-left: 1.5rem;
}

.how-to-use li {
  margin-bottom: 0.75rem;
  font-size: var(--text-xs);
  color: var(--text-secondary);
  line-height: 1.6;
}

.how-to-use strong {
  color: var(--text-primary);
  font-weight: 600;
}

.how-to-use code {
  background-color: rgba(50, 50, 50, 0.5);
  padding: 0.2rem 0.5rem;
  border-radius: 4px;
  font-family: 'Menlo', 'Monaco', 'Courier New', monospace;
  font-size: var(--text-xs);
  color: #ff8c51;
}

.content {
  display: grid;
  grid-template-columns: 1fr 500px;
  gap: 2rem;
  align-items: start;
}

.preview-section {
  position: sticky;
  top: 2rem;
}

.controls-section {
  max-width: 500px;
}

.card {
  background-color: var(--card-bg);
  border-radius: var(--card-radius);
  box-shadow: var(--shadow);
  overflow: hidden;
  margin-bottom: 1.5rem;
  border: 1px solid var(--border);
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.card:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.4);
}

.preview-container {
  height: 400px;
  width: 100%;
  position: relative;
  overflow: hidden;
  border-radius: var(--card-radius);
  background-color: #000000;
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
}

.preview-content {
  color: white;
  text-align: center;
  font-weight: bold;
  font-size: var(--text-s);
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
}

.preview-controls {
  position: absolute;
  top: 1rem;
  right: 1rem;
  display: flex;
  gap: 0.5rem;
  z-index: 10;
}

.preview-btn {
  padding: 0.5rem;
  background-color: rgba(0, 0, 0, 0.7);
  color: white;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 6px;
  cursor: pointer;
  transition: var(--transition);
  font-size: var(--text-xs);
  backdrop-filter: blur(5px);
}

.preview-btn:hover {
  background-color: var(--accent);
  border-color: var(--accent);
}

.card-heading {
  padding: 1rem 1.5rem;
  font-size: var(--text-s);
  font-weight: 600;
  border-bottom: 1px solid var(--border);
  letter-spacing: 0.3px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.card-actions {
  display: flex;
  gap: 0.5rem;
}

.card-action-btn {
  padding: 0.4rem 0.8rem;
  background-color: transparent;
  color: var(--text-secondary);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  font-size: var(--text-xs);
  transition: var(--transition);
}

.card-action-btn:hover {
  color: var(--text-primary);
  border-color: var(--accent);
  background-color: rgba(239, 96, 19, 0.1);
}

.card-content {
  padding: 1.5rem;
}

.control-group {
  margin-bottom: 1.5rem;
  position: relative;
}

.control-group:last-child {
  margin-bottom: 0;
}

.control-label {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.75rem;
}

.label-text {
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.2px;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.help-tooltip {
  cursor: help;
  opacity: 0.7;
  transition: var(--transition);
}

.help-tooltip:hover {
  opacity: 1;
  color: var(--accent);
}

.value-display {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.value-text {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  background-color: rgba(50, 50, 50, 0.5);
  padding: 2px 8px;
  border-radius: 4px;
  min-width: 45px;
  text-align: center;
}

.reset-btn {
  padding: 0.2rem 0.4rem;
  background-color: transparent;
  color: var(--text-secondary);
  border: 1px solid var(--border);
  border-radius: 4px;
  cursor: pointer;
  font-size: 10px;
  transition: var(--transition);
}

.reset-btn:hover {
  color: var(--danger);
  border-color: var(--danger);
  background-color: rgba(220, 53, 69, 0.1);
}

input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 6px;
  background: var(--track);
  border-radius: 3px;
  outline: none;
  margin: 0.8rem 0;
  position: relative;
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  background: var(--thumb);
  border-radius: 50%;
  cursor: pointer;
  transition: var(--transition);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}

input[type="range"]::-webkit-slider-thumb:hover {
  transform: scale(1.2);
  box-shadow: 0 0 10px rgba(239, 96, 19, 0.5);
}

.color-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin-bottom: 1.5rem;
}

.color-row {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  padding: 1rem 1.25rem;
  background-color: rgba(30, 30, 30, 0.7);
  border: 1px solid var(--border);
  border-radius: var(--input-radius);
  transition: var(--transition);
}

.color-row:hover {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px rgba(239, 96, 19, 0.1);
}

.color-picker-container {
  position: relative;
  width: 40px;
  height: 40px;
  border-radius: 8px;
  overflow: hidden;
  border: 2px solid var(--border);
  cursor: pointer;
  transition: var(--transition);
  flex-shrink: 0;
  background: linear-gradient(45deg, #f0f0f0 25%, transparent 25%), 
              linear-gradient(-45deg, #f0f0f0 25%, transparent 25%), 
              linear-gradient(45deg, transparent 75%, #f0f0f0 75%), 
              linear-gradient(-45deg, transparent 75%, #f0f0f0 75%);
  background-size: 8px 8px;
  background-position: 0 0, 0 4px, 4px -4px, -4px 0px;
}

.color-picker-container::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--current-color, #cc0000);
  border-radius: 6px;
  z-index: 1;
}

.color-picker-container:hover {
  border-color: var(--accent);
  transform: scale(1.05);
}

input[type="color"] {
  position: absolute;
  top: -2px;
  left: -2px;
  width: calc(100% + 4px);
  height: calc(100% + 4px);
  border: none;
  cursor: pointer;
  background: transparent;
  z-index: 2;
  opacity: 0;
}

.color-input-group {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.color-label {
  font-size: 10px;
  font-weight: 500;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-left: 0.25rem;
}

.color-input {
  padding: 0.5rem 0.75rem;
  background-color: rgba(0, 0, 0, 0.3);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-primary);
  font-family: 'Menlo', 'Monaco', 'Courier New', monospace;
  font-size: 12px;
  transition: var(--transition);
  min-width: 0;
}

.color-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px rgba(239, 96, 19, 0.2);
  outline: none;
}

.color-input.invalid {
  border-color: var(--danger);
  box-shadow: 0 0 0 1px rgba(220, 53, 69, 0.2);
}

.hex-input,
.hsl-input {
  width: 100%;
}

.color-input-group:nth-child(2) {
  flex: 0.3;
}

.color-input-group:nth-child(3) {
  flex: 0.7;
}

select {
  width: 100%;
  padding: 0.75rem;
  background-color: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--input-radius);
  color: var(--text-primary);
  font-family: var(--font);
  font-size: var(--text-xs);
  transition: var(--transition);
  cursor: pointer;
}

select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px rgba(239, 96, 19, 0.2);
  outline: none;
}

select option {
  background-color: var(--card-bg);
  color: var(--text-primary);
}

.notification {
  position: fixed;
  bottom: calc(var(--action-bar-height) + 1rem);
  left: 50%;
  background-color: var(--success);
  color: white;
  padding: 0.75rem 1rem;
  border-radius: var(--input-radius);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
  z-index: 1001;
  transform: translate(-50%, 200px);
  opacity: 0;
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.4s ease;
  font-size: var(--text-xs);
  font-weight: 500;
  max-width: 320px;
  word-wrap: break-word;
  line-height: 1.4;
  text-align: center;
}

.notification.show {
  transform: translate(-50%, 0);
  opacity: 1;
}

@media (max-width: 1200px) {
  .content {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }
  
  .preview-section {
    position: static;
  }
  
  .controls-section {
    max-width: 100%;
  }
}

@media (max-width: 768px) {
  .action-bar {
    flex-direction: column;
    height: auto;
    min-height: var(--action-bar-height);
    padding: 0.75rem;
  }
  
  .breadcrumb {
    order: 1;
    width: 100%;
  }
  
  .action-buttons {
    order: 2;
    width: 100%;
    justify-content: center;
    flex-wrap: wrap;
  }
  
  body {
    padding-bottom: calc(var(--action-bar-height) + 20px);
  }
  
  .notification {
    bottom: calc(var(--action-bar-height) + 2rem);
    max-width: 280px;
    transform: translate(-50%, 250px);
  }
  
  .notification.show {
    transform: translate(-50%, 0);
    opacity: 1;
  }
  
  .color-row {
    flex-direction: column;
    align-items: stretch;
    gap: 1rem;
    padding: 1rem;
  }
  
  .color-picker-container {
    align-self: center;
    margin-bottom: 0.5rem;
  }
  
  .color-input-group {
    align-items: stretch;
  }
  
  .hex-input,
  .hsl-input {
    width: 100%;
  }

  .preview-container {
    height: 300px;
  }
  
  .data-attribute-display {
    font-size: 10px;
    padding: 0.4rem 0.6rem;
  }
  
  .action-btn {
    font-size: 11px;
    padding: 0.5rem 0.8rem;
  }
  
  .page-title {
    font-size: 2rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

button:focus-visible,
input:focus-visible,
.action-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

::-webkit-scrollbar {
  width: 8px;
}

::-webkit-scrollbar-track {
  background: var(--background);
}

::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--accent);
}

.loading {
  opacity: 0.6;
  pointer-events: none;
  position: relative;
}

.loading::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 20px;
  height: 20px;
  margin: -10px 0 0 -10px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}
  </style>
</head>
<body>
  <div class="action-bar">
    <nav class="breadcrumb">
      <a href="https://bricksfusion.com" class="breadcrumb-item">Home</a>
      <span class="breadcrumb-separator">›</span>
      <a href="https://bricksfusion.com/corebackground/" class="breadcrumb-item">Core Backgrounds</a>
      <span class="breadcrumb-separator">›</span>
      <span class="breadcrumb-item active">Fire Plasma</span>
    </nav>
    
    <div class="action-buttons">
      <div class="data-attribute-display" id="quick-attribute" title="Click to copy data attribute">
        data-fire-plasma
      </div>
      <button class="action-btn primary" id="download-config" title="Copy JavaScript code (Ctrl+D)" data-protection-animation="true">
        <span>📋</span>
        Copy JS
      </button>
      <button class="action-btn" id="copy-full-section" title="Copy complete section JSON for Bricks Builder (Ctrl+S)" data-protection-animation="true">
        <span>📦</span>
        Copy Full Section
      </button>
    </div>
  </div>

  <div class="container">
    <div class="page-header">
      <h1 class="page-title">Fire Plasma</h1>
      <p class="page-subtitle">Interactive plasma effects for Bricks Builder</p>
    </div>

    <div class="instructions-toggle">
      <div class="instructions-card" id="instructions-card">
        <div class="instructions-header" id="instructions-toggle">
          <div class="instructions-title">
            How to Use & Code Information
          </div>
          <span class="toggle-icon">▼</span>
        </div>
        <div class="instructions-content" id="instructions-content">
          <div class="instructions-grid">
            <div class="how-to-use">
              <ol>
                <li>Customize your fire plasma effect using the controls below</li>
                <li>Click <strong>Copy JS</strong> to copy the JavaScript code to clipboard</li>
                <li>In Bricks Builder, add a <strong>Code</strong> element</li>
                <li>Paste or upload the JavaScript code</li>
                <li>To add the effect to any section: go to <strong>Section → Style → Attributes</strong>, add <code>data-fire-plasma</code> as attribute name (leave value empty)</li>
              </ol>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="content">
      <section class="preview-section">
        <div class="preview-container" id="fire-preview" data-fire-plasma="true">
          <div class="preview-content">Interactive Fire Plasma Preview</div>
          <div class="preview-controls">
            <button class="preview-btn" id="randomize-fire" title="Randomize (R)">🎲</button>
          </div>
        </div>
      </section>

      <section class="controls-section">
        <div class="card">
          <div class="card-heading">
            Fire Plasma Colors
            <div class="card-actions">
              <button class="card-action-btn" id="reset-colors" title="Reset Colors">↺</button>
            </div>
          </div>
          <div class="card-content">
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">Color Preset</span>
              </div>
              <select id="color-preset">
                <option value="red">Red Fire</option>
                <option value="blue">Blue Flame</option>
                <option value="green">Green Fire</option>
                <option value="purple">Purple Plasma</option>
                <option value="orange">Orange Blaze</option>
                <option value="teal">Teal Flame</option>
                <option value="pink">Pink Fire</option>
                <option value="yellow">Yellow Flame</option>
                <option value="rainbow">Rainbow Fire</option>
                <option value="galaxy">Galaxy Plasma</option>
              </select>
            </div>

            <div class="color-list">
              <div class="color-row">
                <div class="color-picker-container">
                  <input type="color" id="base-color" value="#cc0000">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HEX</span>
                  <input type="text" class="color-input hex-input" id="base-color-hex" value="#cc0000" placeholder="#FFFFFF">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HSL</span>
                  <input type="text" class="color-input hsl-input" id="base-color-hsl" placeholder="hsl(0, 100%, 50%)">
                </div>
              </div>
              
              <div class="color-row">
                <div class="color-picker-container">
                  <input type="color" id="accent-color" value="#ff3333">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HEX</span>
                  <input type="text" class="color-input hex-input" id="accent-color-hex" value="#ff3333" placeholder="#FFFFFF">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HSL</span>
                  <input type="text" class="color-input hsl-input" id="accent-color-hsl" placeholder="hsl(0, 100%, 50%)">
                </div>
              </div>
              
              <div class="color-row">
                <div class="color-picker-container">
                  <input type="color" id="highlight-color" value="#ff8080">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HEX</span>
                  <input type="text" class="color-input hex-input" id="highlight-color-hex" value="#ff8080" placeholder="#FFFFFF">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HSL</span>
                  <input type="text" class="color-input hsl-input" id="highlight-color-hsl" placeholder="hsl(0, 100%, 50%)">
                </div>
              </div>
            </div>
          </div>
        </div>

        <div class="card">
          <div class="card-heading">
            Animation Settings
            <div class="card-actions">
              <button class="card-action-btn" id="reset-animation" title="Reset Animation Settings">↺</button>
            </div>
          </div>
          <div class="card-content">
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">
                  Turbulence Intensity
                  <span class="help-tooltip" title="Controls the chaos and movement of the plasma effect">ℹ</span>
                </span>
                <div class="value-display">
                  <span class="value-text"><span id="turbulence-intensity-value">0.5</span></span>
                  <button class="reset-btn" onclick="resetParameter('turbulence-intensity', 0.5)">↺</button>
                </div>
              </div>
              <input type="range" id="turbulence-intensity" min="0.1" max="1.0" step="0.1" value="0.5">
            </div>
            
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">
                  Animation Speed
                  <span class="help-tooltip" title="Controls how fast the plasma moves and flows">ℹ</span>
                </span>
                <div class="value-display">
                  <span class="value-text"><span id="animation-speed-value">1</span>x</span>
                  <button class="reset-btn" onclick="resetParameter('animation-speed', 1)">↺</button>
                </div>
              </div>
              <input type="range" id="animation-speed" min="0.5" max="2" step="0.1" value="1">
            </div>
            
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">
                  Glow Intensity
                  <span class="help-tooltip" title="Controls the brightness and glow of the effect">ℹ</span>
                </span>
                <div class="value-display">
                  <span class="value-text"><span id="glow-intensity-value">0.5</span></span>
                  <button class="reset-btn" onclick="resetParameter('glow-intensity', 0.5)">↺</button>
                </div>
              </div>
              <input type="range" id="glow-intensity" min="0.1" max="1" step="0.1" value="0.5">
            </div>
          </div>
        </div>

        <div class="card">
          <div class="card-heading">
            Advanced Options
            <div class="card-actions">
              <button class="card-action-btn" id="reset-advanced" title="Reset Advanced Settings">↺</button>
            </div>
          </div>
          <div class="card-content">
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">
                  Spark Density
                  <span class="help-tooltip" title="Controls how many bright sparks appear in the effect">ℹ</span>
                </span>
                <div class="value-display">
                  <span class="value-text"><span id="spark-density-value">0.5</span></span>
                  <button class="reset-btn" onclick="resetParameter('spark-density', 0.5)">↺</button>
                </div>
              </div>
              <input type="range" id="spark-density" min="0.1" max="1" step="0.1" value="0.5">
            </div>
            
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">
                  Frame Rate
                  <span class="help-tooltip" title="Controls the smoothness of the animation">ℹ</span>
                </span>
                <div class="value-display">
                  <span class="value-text"><span id="fps-value">60</span> FPS</span>
                  <button class="reset-btn" onclick="resetParameter('fps', 60)">↺</button>
                </div>
              </div>
              <input type="range" id="fps" min="30" max="60" step="10" value="60">
            </div>
            
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">Noise Pattern</span>
              </div>
              <select id="noise-pattern">
                <option value="turbulent">Turbulent</option>
                <option value="smooth">Smooth</option>
                <option value="chaotic">Chaotic</option>
                <option value="directional">Directional</option>
              </select>
            </div>
          </div>
        </div>
      </section>
    </div>
  </div>

  <div class="notification" id="notification"></div>

  <script>
    document.addEventListener('DOMContentLoaded', function() {
      let fireConfig = {
        baseColor: '#cc0000',
        accentColor: '#ff3333',
        highlightColor: '#ff8080',
        turbulenceIntensity: 0.5,
        animationSpeed: 1,
        glowIntensity: 0.5,
        sparkDensity: 0.5,
        fps: 60,
        noisePattern: 'turbulent',
        colorPreset: 'red'
      };

      const defaultConfig = { ...fireConfig };

      let activeFirePlasma = null;

      function initFirePlasma() {
        const sections = document.querySelectorAll('[data-fire-plasma]:not([data-fire-initialized="true"])');
        
        sections.forEach((section) => {
          // For preview element, always use current fireConfig values
          let baseColor, accentColor, highlightColor, turbulence, speed, glow, sparks, fps, pattern;
          
          if (section.id === 'fire-preview') {
            console.log('Initializing preview with current fireConfig:', fireConfig);
            baseColor = fireConfig.baseColor;
            accentColor = fireConfig.accentColor;
            highlightColor = fireConfig.highlightColor;
            turbulence = fireConfig.turbulenceIntensity;
            speed = fireConfig.animationSpeed;
            glow = fireConfig.glowIntensity;
            sparks = fireConfig.sparkDensity;
            fps = fireConfig.fps;
            pattern = fireConfig.noisePattern;
          } else {
            // For other elements, use data attributes or fallback to fireConfig
            baseColor = section.hasAttribute('data-fire-plasma-base-color') 
              ? section.getAttribute('data-fire-plasma-base-color') 
              : fireConfig.baseColor;
              
            accentColor = section.hasAttribute('data-fire-plasma-accent-color') 
              ? section.getAttribute('data-fire-plasma-accent-color') 
              : fireConfig.accentColor;
              
            highlightColor = section.hasAttribute('data-fire-plasma-highlight-color') 
              ? section.getAttribute('data-fire-plasma-highlight-color') 
              : fireConfig.highlightColor;
              
            turbulence = section.hasAttribute('data-fire-plasma-turbulence') 
              ? parseFloat(section.getAttribute('data-fire-plasma-turbulence')) 
              : fireConfig.turbulenceIntensity;
              
            speed = section.hasAttribute('data-fire-plasma-speed') 
              ? parseFloat(section.getAttribute('data-fire-plasma-speed')) 
              : fireConfig.animationSpeed;
              
            glow = section.hasAttribute('data-fire-plasma-glow') 
              ? parseFloat(section.getAttribute('data-fire-plasma-glow')) 
              : fireConfig.glowIntensity;
              
            sparks = section.hasAttribute('data-fire-plasma-sparks') 
              ? parseFloat(section.getAttribute('data-fire-plasma-sparks')) 
              : fireConfig.sparkDensity;
              
            fps = section.hasAttribute('data-fire-plasma-fps') 
              ? parseInt(section.getAttribute('data-fire-plasma-fps')) 
              : fireConfig.fps;
              
            pattern = section.hasAttribute('data-fire-plasma-pattern') 
              ? section.getAttribute('data-fire-plasma-pattern') 
              : fireConfig.noisePattern;
          }
            
          const options = {
            baseColor,
            accentColor,
            highlightColor,
            turbulenceIntensity: turbulence,
            animationSpeed: speed,
            glowIntensity: glow,
            sparkDensity: sparks,
            fps,
            noisePattern: pattern
          };
          
          setupFirePlasma(section, options);
          section.dataset.fireInitialized = 'true';
          
          if (section.id === 'fire-preview') {
            activeFirePlasma = { element: section, options };
            // Don't overwrite fireConfig if it's already been modified by user
            console.log('Preview element initialized with config:', fireConfig);
          }
        });
      }

      function setupFirePlasma(element, options) {
        const wrapper = document.createElement('div');
        wrapper.style.cssText = 'position:absolute;top:0;left:0;right:0;bottom:0;overflow:hidden;pointer-events:none;z-index:0;';
        
        const containerStyle = window.getComputedStyle(element);
        wrapper.style.borderRadius = containerStyle.borderRadius;
        
        if (element.firstChild) {
          element.insertBefore(wrapper, element.firstChild);
        } else {
          element.appendChild(wrapper);
        }

        Array.from(element.children).forEach(child => {
          if (child !== wrapper) {
            if (getComputedStyle(child).position === 'static') {
              child.style.position = 'relative';
            }
            child.style.zIndex = '1';
          }
        });

        if (window.getComputedStyle(element).position === 'static') {
          element.style.position = 'relative';
        }

        if (!window.THREE) {
          loadThreeJs().then(() => {
            createFirePlasmaEffect(wrapper, options);
          });
        } else {
          createFirePlasmaEffect(wrapper, options);
        }
      }

      function loadThreeJs() {
        return new Promise((resolve, reject) => {
          const script = document.createElement('script');
          script.src = 'https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js';
          script.onload = resolve;
          script.onerror = reject;
          document.head.appendChild(script);
        });
      }

      function createFirePlasmaEffect(wrapper, options) {
        const rect = wrapper.getBoundingClientRect();
        
        const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(rect.width, rect.height);
        renderer.domElement.style.width = '100%';
        renderer.domElement.style.height = '100%';
        renderer.domElement.style.display = 'block';
        wrapper.appendChild(renderer.domElement);

        const scene = new THREE.Scene();
        const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
        const geometry = new THREE.PlaneGeometry(2, 2);

        const baseColor = hexToRgb(options.baseColor);
        const accentColor = hexToRgb(options.accentColor);
        const highlightColor = hexToRgb(options.highlightColor);

        let noisePatternValue = 0;
        switch (options.noisePattern) {
          case 'turbulent': noisePatternValue = 0; break;
          case 'smooth': noisePatternValue = 1; break;
          case 'chaotic': noisePatternValue = 2; break;
          case 'directional': noisePatternValue = 3; break;
          default: noisePatternValue = 0;
        }

        const uniforms = {
          time: { value: 0 },
          resolution: { value: new THREE.Vector2(rect.width, rect.height) },
          colorBase: { value: new THREE.Vector3(baseColor.r, baseColor.g, baseColor.b) },
          colorAccent: { value: new THREE.Vector3(accentColor.r, accentColor.g, accentColor.b) },
          colorHighlight: { value: new THREE.Vector3(highlightColor.r, highlightColor.g, highlightColor.b) },
          turbulence: { value: options.turbulenceIntensity },
          sparkDensity: { value: options.sparkDensity },
          animationSpeed: { value: options.animationSpeed },
          glowIntensity: { value: options.glowIntensity },
          noisePattern: { value: noisePatternValue }
        };

        const material = new THREE.ShaderMaterial({
          uniforms: uniforms,
          fragmentShader: getFragmentShader(),
          transparent: true
        });

        const mesh = new THREE.Mesh(geometry, material);
        scene.add(mesh);

        wrapper.fireRenderer = renderer;
        wrapper.fireScene = scene;
        wrapper.fireCamera = camera;
        wrapper.fireUniforms = uniforms;
        wrapper.fireMesh = mesh;

        startFireAnimation(wrapper, options);

        const resizeObserver = new ResizeObserver(() => {
          const newRect = wrapper.getBoundingClientRect();
          renderer.setSize(newRect.width, newRect.height);
          uniforms.resolution.value.set(newRect.width, newRect.height);
        });
        resizeObserver.observe(wrapper);

        wrapper._fireCleanup = () => {
          resizeObserver.disconnect();
          if (wrapper.fireAnimationFrame) {
            cancelAnimationFrame(wrapper.fireAnimationFrame);
          }
          if (wrapper.fireRenderer) {
            wrapper.fireRenderer.dispose();
          }
        };
      }

      function startFireAnimation(wrapper, options) {
        let lastTime = 0;
        let fpsInterval = 1000 / options.fps;
        
        // Almacenar referencia para poder actualizar dinámicamente
        wrapper.fireAnimationSpeed = options.animationSpeed;
        wrapper.fireFps = options.fps;

        function animate(currentTime) {
          wrapper.fireAnimationFrame = requestAnimationFrame(animate);

          // Actualizar FPS dinámicamente
          fpsInterval = 1000 / wrapper.fireFps;

          if (currentTime - lastTime >= fpsInterval) {
            lastTime = currentTime - ((currentTime - lastTime) % fpsInterval);
            
            // Usar la velocidad de animación actualizada dinámicamente
            wrapper.fireUniforms.time.value = currentTime * 0.001 * wrapper.fireAnimationSpeed;
            wrapper.fireRenderer.render(wrapper.fireScene, wrapper.fireCamera);
          }
        }

        animate(0);
        
        // Función para actualizar dinámicamente los parámetros de animación
        wrapper.updateAnimationParams = function(newSpeed, newFps) {
          wrapper.fireAnimationSpeed = newSpeed;
          wrapper.fireFps = newFps;
        };
      }

      function getFragmentShader() {
        return `
        #ifdef GL_ES
        precision highp float;
        #endif

        uniform float time;
        uniform vec2 resolution;
        uniform vec3 colorBase;
        uniform vec3 colorAccent;
        uniform vec3 colorHighlight;
        uniform float turbulence;
        uniform float sparkDensity;
        uniform float animationSpeed;
        uniform float glowIntensity;
        uniform float noisePattern;

        #define NUM_OCTAVES 5

        float random(vec2 st) {
          return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);
        }

        float noise(vec2 st) {
          vec2 i = floor(st);
          vec2 f = fract(st);
          float a = random(i);
          float b = random(i + vec2(1.0, 0.0));
          float c = random(i + vec2(0.0, 1.0));
          float d = random(i + vec2(1.0, 1.0));
          vec2 u = f * f * (3.0 - 2.0 * f);
          return mix(a, b, u.x) + (c - a)* u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
        }

        float fbm(vec2 st) {
          float value = 0.0;
          float amplitude = 0.5;
          float frequency = 1.0;
          for (int i = 0; i < NUM_OCTAVES; i++) {
            value += amplitude * noise(st * frequency);
            st *= 2.0;
            amplitude *= 0.5;
            frequency *= 2.0;
          }
          return value;
        }

        float patternNoise(vec2 p, float pattern) {
          if (pattern < 0.5) {
            vec2 q = vec2(fbm(p + vec2(0.0, 0.0)),
                          fbm(p + vec2(5.2, 1.3)));
            return fbm(p + 4.0 * q);
          } else if (pattern < 1.5) {
            return fbm(p * 3.0);
          } else if (pattern < 2.5) {
            vec2 q = vec2(fbm(p),
                          fbm(p + vec2(1.0)));
            vec2 r = vec2(fbm(p + 4.0*q + vec2(1.7,9.2)),
                          fbm(p + 4.0*q + vec2(8.3,2.8)));
            return fbm(p + 4.0*r);
          } else {
            float angle = time * 0.2;
            vec2 dir = vec2(cos(angle), sin(angle));
            return fbm(p + dir * fbm(p * 2.0) * 2.0);
          }
        }

        vec2 rotate(vec2 v, float a) {
          float s = sin(a);
          float c = cos(a);
          mat2 m = mat2(c, -s, s, c);
          return m * v;
        }

        void main() {
          vec2 st = gl_FragCoord.xy / resolution.xy;
          st.x *= resolution.x / resolution.y;

          vec2 distort = vec2(
            patternNoise(st + time * 0.1, noisePattern),
            patternNoise(st + vec2(1.0) - time * 0.15, noisePattern)
          );

          distort = rotate(distort, time * 0.1);

          vec2 newSt = st + distort * turbulence * 0.3;

          float f1 = patternNoise(newSt * 3.0 + time * 0.1, noisePattern);
          float f2 = patternNoise(newSt * 2.0 - time * 0.05, noisePattern);
          float f3 = patternNoise(newSt * 4.0 + time * 0.2, noisePattern);

          float f = f1 * 0.5 + f2 * 0.3 + f3 * 0.2;

          vec3 color = mix(colorBase, colorAccent, clamp(f * 1.5, 0.0, 1.0));
          color = mix(color, colorHighlight, clamp(f * f * 3.0, 0.0, 1.0));

          float actualSparkDensity = 0.98 - sparkDensity * 0.1;
          float spark = step(actualSparkDensity, random(newSt + mod(time, 10.0)));
          color += spark * colorHighlight * 0.8;

          float glow = glowIntensity * 0.1 * (1.0 + sin(time * 2.0)) * (1.0 - distance(newSt, vec2(0.5)));
          color += glow * colorHighlight;

          gl_FragColor = vec4(color, 1.0);
        }`;
      }

      function updateFirePreview() {
        const preview = document.getElementById('fire-preview');
        if (!preview) return;
        
        // Find wrapper more robustly
        let wrapper = null;
        
        // Method 1: Look for wrapper with absolute positioning
        wrapper = preview.querySelector('div[style*="position:absolute"]');
        
        // Method 2: Look for wrapper with fireUniforms property
        if (!wrapper) {
          const children = preview.querySelectorAll('div');
          for (let child of children) {
            if (child.fireUniforms) {
              wrapper = child;
              break;
            }
          }
        }
        
        // Method 3: Look for first child div
        if (!wrapper) {
          wrapper = preview.querySelector('div:first-child');
        }
        
        console.log('Wrapper found:', !!wrapper, 'Has uniforms:', !!(wrapper && wrapper.fireUniforms));
        
        if (wrapper && wrapper.fireUniforms) {
          try {
            const baseColor = hexToRgb(fireConfig.baseColor);
            const accentColor = hexToRgb(fireConfig.accentColor);
            const highlightColor = hexToRgb(fireConfig.highlightColor);
            
            console.log('Updating colors:', { baseColor: fireConfig.baseColor, accentColor: fireConfig.accentColor, highlightColor: fireConfig.highlightColor });
            
            // Update uniforms safely
            wrapper.fireUniforms.colorBase.value.set(baseColor.r, baseColor.g, baseColor.b);
            wrapper.fireUniforms.colorAccent.value.set(accentColor.r, accentColor.g, accentColor.b);
            wrapper.fireUniforms.colorHighlight.value.set(highlightColor.r, highlightColor.g, highlightColor.b);
            wrapper.fireUniforms.turbulence.value = fireConfig.turbulenceIntensity;
            wrapper.fireUniforms.sparkDensity.value = fireConfig.sparkDensity;
            wrapper.fireUniforms.glowIntensity.value = fireConfig.glowIntensity;
            
            let noisePatternValue = 0;
            switch (fireConfig.noisePattern) {
              case 'turbulent': noisePatternValue = 0; break;
              case 'smooth': noisePatternValue = 1; break;
              case 'chaotic': noisePatternValue = 2; break;
              case 'directional': noisePatternValue = 3; break;
              default: noisePatternValue = 0;
            }
            wrapper.fireUniforms.noisePattern.value = noisePatternValue;
            
            // Update animation speed and FPS dynamically
            if (wrapper.updateAnimationParams) {
              wrapper.updateAnimationParams(fireConfig.animationSpeed, fireConfig.fps);
            }
            
            console.log('Preview updated successfully');
          } catch (error) {
            console.error('Error updating uniforms:', error);
            // If update fails, reinitialize
            reinitializePreview();
          }
        } else {
          console.log('Wrapper or uniforms not found, reinitializing...');
          reinitializePreview();
        }
      }
      
      function reinitializePreview() {
        const preview = document.getElementById('fire-preview');
        if (!preview) return;
        
        console.log('Reinitializing preview...');
        
        // Clean up completely
        if (preview._fireCleanup) {
          preview._fireCleanup();
        }
        
        // Remove existing wrapper elements
        const wrappers = preview.querySelectorAll('div[style*="position:absolute"]');
        wrappers.forEach(wrapper => {
          if (wrapper.parentNode) {
            wrapper.parentNode.removeChild(wrapper);
          }
        });
        
        // Also remove any div with fireUniforms
        const allDivs = preview.querySelectorAll('div');
        allDivs.forEach(div => {
          if (div.fireUniforms) {
            if (div.parentNode) {
              div.parentNode.removeChild(div);
            }
          }
        });
        
        // Remove initialization flag
        preview.removeAttribute('data-fire-initialized');
        
        // Set new attributes
        preview.setAttribute('data-fire-plasma', 'true');
        preview.setAttribute('data-fire-plasma-base-color', fireConfig.baseColor);
        preview.setAttribute('data-fire-plasma-accent-color', fireConfig.accentColor);
        preview.setAttribute('data-fire-plasma-highlight-color', fireConfig.highlightColor);
        preview.setAttribute('data-fire-plasma-turbulence', fireConfig.turbulenceIntensity);
        preview.setAttribute('data-fire-plasma-speed', fireConfig.animationSpeed);
        preview.setAttribute('data-fire-plasma-glow', fireConfig.glowIntensity);
        preview.setAttribute('data-fire-plasma-sparks', fireConfig.sparkDensity);
        preview.setAttribute('data-fire-plasma-fps', fireConfig.fps);
        preview.setAttribute('data-fire-plasma-pattern', fireConfig.noisePattern);
        
        // Reinitialize
        setTimeout(() => {
          initFirePlasma();
          console.log('Preview reinitialized');
        }, 100);
      }
      
      function forceUpdatePreview() {
        console.log('Force updating preview with config:', fireConfig);
        reinitializePreview();
      }

      function hexToHsl(hex) {
        const r = parseInt(hex.slice(1, 3), 16) / 255;
        const g = parseInt(hex.slice(3, 5), 16) / 255;
        const b = parseInt(hex.slice(5, 7), 16) / 255;
        
        const max = Math.max(r, g, b);
        const min = Math.min(r, g, b);
        let h, s, l = (max + min) / 2;
        
        if (max === min) {
          h = s = 0;
        } else {
          const d = max - min;
          s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
          switch (max) {
            case r: h = (g - b) / d + (g < b ? 6 : 0); break;
            case g: h = (b - r) / d + 2; break;
            case b: h = (r - g) / d + 4; break;
          }
          h /= 6;
        }
        
        return `hsl(${Math.round(h * 360)}, ${Math.round(s * 100)}%, ${Math.round(l * 100)}%)`;
      }

      function hslToHex(hsl) {
        const match = hsl.match(/hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/);
        if (!match) return null;
        
        let h = parseInt(match[1]) / 360;
        let s = parseInt(match[2]) / 100;
        let l = parseInt(match[3]) / 100;
        
        const hue2rgb = (p, q, t) => {
          if (t < 0) t += 1;
          if (t > 1) t -= 1;
          if (t < 1/6) return p + (q - p) * 6 * t;
          if (t < 1/2) return q;
          if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
          return p;
        };
        
        let r, g, b;
        if (s === 0) {
          r = g = b = l;
        } else {
          const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
          const p = 2 * l - q;
          r = hue2rgb(p, q, h + 1/3);
          g = hue2rgb(p, q, h);
          b = hue2rgb(p, q, h - 1/3);
        }
        
        const toHex = (c) => {
          const hex = Math.round(c * 255).toString(16);
          return hex.length === 1 ? '0' + hex : hex;
        };
        
        return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
      }

      function hexToRgb(hex) {
        hex = hex.replace(/^#/, '');
        const bigint = parseInt(hex, 16);
        return {
          r: ((bigint >> 16) & 255) / 255,
          g: ((bigint >> 8) & 255) / 255,
          b: (bigint & 255) / 255
        };
      }

      function isValidHex(hex) {
        return /^#[0-9A-F]{6}$/i.test(hex);
      }

      function isValidHsl(hsl) {
        return /^hsl\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*\)$/i.test(hsl);
      }

      function formatHex(value) {
        let hex = value.replace(/[^0-9A-Fa-f#]/g, '');
        
        if (!hex.startsWith('#')) {
          hex = '#' + hex;
        }
        
        if (hex.length > 7) {
          hex = hex.substring(0, 7);
        }
        
        return hex.toUpperCase();
      }

      function formatHsl(value) {
        const cleanValue = value.replace(/[^\d,\s]/g, '');
        const numbers = cleanValue.match(/\d+/g);
        
        if (!numbers || numbers.length < 3) {
          const partialMatch = value.match(/(\d+)/g);
          if (partialMatch && partialMatch.length >= 1) {
            const h = Math.min(360, Math.max(0, parseInt(partialMatch[0]) || 0));
            const s = Math.min(100, Math.max(0, parseInt(partialMatch[1]) || 50));
            const l = Math.min(100, Math.max(0, parseInt(partialMatch[2]) || 50));
            return `hsl(${h}, ${s}%, ${l}%)`;
          }
          return value;
        }
        
        let h = Math.min(360, Math.max(0, parseInt(numbers[0])));
        let s = Math.min(100, Math.max(0, parseInt(numbers[1])));
        let l = Math.min(100, Math.max(0, parseInt(numbers[2])));
        
        return `hsl(${h}, ${s}%, ${l}%)`;
      }

      function generateRandomColor() {
        return '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0');
      }

      function showNotification(message, type = 'success') {
        const notification = document.getElementById('notification');
        notification.textContent = message;
        notification.className = `notification ${type}`;
        
        notification.offsetHeight;
        
        notification.style.visibility = 'visible';
        notification.classList.add('show');
        
        setTimeout(() => {
          notification.classList.remove('show');
          
          setTimeout(() => {
            if (!notification.classList.contains('show')) {
              notification.style.visibility = 'hidden';
            }
          }, 400);
        }, 3000);
      }

      function generateUniqueId() {
        return Math.random().toString(36).substring(2, 8);
      }

      function generateFullSectionJSON() {
  // Generar IDs únicos
  const sectionId = generateUniqueId();
  const containerId = generateUniqueId();
  const codeId = generateUniqueId();
  const attributeId = generateUniqueId();
  
  // Obtener el código JavaScript actual
  const jsCode = generateJavaScriptCode();
  
  // Crear el objeto JSON completo
  const fullSectionJSON = {
    "content": [
      {
        "id": sectionId,
        "name": "section",
        "parent": 0,
        "children": [containerId, codeId],
        "settings": {
          "_height": "500",
          "_justifyContent": "center",
          "_background": {
            "color": {
              "hex": "#000000"
            }
          },
          "_attributes": [
            {
              "id": attributeId,
              "name": "data-fire-plasma"
            }
          ]
        },
        "label": "Fire Effect Section"
      },
      {
        "id": containerId,
        "name": "container",
        "parent": sectionId,
        "children": [],
        "settings": [],
        "label": "Content Container"
      },
      {
        "id": codeId,
        "name": "code",
        "parent": sectionId,
        "children": [],
        "settings": {
          "javascriptCode": jsCode,
          "executeCode": true,
          "_display": "none"
        },
        "label": "Fire effect JS"
      }
    ],
    "source": "bricksCopiedElements",
    "sourceUrl": "https://bricksfusion.com",
    "version": "2.0.1",
    "globalClasses": [],
    "globalElements": []
  };
  
  return JSON.stringify(fullSectionJSON, null, 2);
}

      function generateJavaScriptCode() {
        const baseColor = fireConfig.baseColor;
        const accentColor = fireConfig.accentColor;
        const highlightColor = fireConfig.highlightColor;
        const turbulence = fireConfig.turbulenceIntensity;
        const speed = fireConfig.animationSpeed;
        const glow = fireConfig.glowIntensity;
        const sparks = fireConfig.sparkDensity;
        const fps = fireConfig.fps;
        const pattern = fireConfig.noisePattern;
        
        return `(function() {
  class FirePlasmaEffect {
    constructor() {
      this.instances = [];
      this.three = null;
      this.isInitialized = false;
      this.config = {
        baseColor: "${baseColor}",
        accentColor: "${accentColor}",
        highlightColor: "${highlightColor}",
        turbulenceIntensity: ${turbulence},
        animationSpeed: ${speed},
        glowIntensity: ${glow},
        sparkDensity: ${sparks},
        fps: ${fps},
        noisePattern: "${pattern}"
      };
    }

    async init(options = {}) {
      if (this.isInitialized) return;

      const defaultOptions = {
        selector: '[data-fire-plasma]'
      };
      this.options = { ...defaultOptions, ...options };

      await this.loadThreeJS();
      this.initInstances();
      setTimeout(() => this.initInstances(), 100);
      window.addEventListener('load', () => this.initInstances());

      const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
          if (mutation.type === 'childList') {
            this.initInstances();
          }
        });
      });

      observer.observe(document.body, { childList: true, subtree: true });

      window.addEventListener('resize', () => this.resize());

      this.isInitialized = true;
    }

    async loadThreeJS() {
      return new Promise((resolve, reject) => {
        if (window.THREE) {
          this.three = window.THREE;
          resolve();
        } else {
          const script = document.createElement('script');
          script.src = 'https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js';
          script.onload = () => {
            this.three = window.THREE;
            resolve();
          };
          script.onerror = reject;
          document.head.appendChild(script);
        }
      });
    }

    initInstances() {
      document.querySelectorAll(this.options.selector).forEach(element => {
        if (!element.hasAttribute('data-fire-initialized')) {
          this.createInstance(element);
          element.setAttribute('data-fire-initialized', 'true');
        }
      });
    }

    createInstance(element) {
      if (window.getComputedStyle(element).position === 'static') {
        element.style.position = 'relative';
      }

      const wrapper = document.createElement('div');
      wrapper.style.cssText = 'position:absolute;top:0;left:0;right:0;bottom:0;overflow:hidden;pointer-events:none;z-index:0;';
      
      const containerStyle = window.getComputedStyle(element);
      wrapper.style.borderRadius = containerStyle.borderRadius;
      
      element.insertBefore(wrapper, element.firstChild);

      Array.from(element.children).forEach(child => {
        if (child !== wrapper) {
          child.style.position = 'relative';
          child.style.zIndex = '1';
        }
      });

      const renderer = new this.three.WebGLRenderer({ alpha: true, antialias: true });
      renderer.setPixelRatio(window.devicePixelRatio);
      const rect = element.getBoundingClientRect();
      renderer.setSize(rect.width, rect.height);
      renderer.domElement.style.width = '100%';
      renderer.domElement.style.height = '100%';
      renderer.domElement.style.display = 'block';
      renderer.domElement.style.borderRadius = containerStyle.borderRadius;
      wrapper.appendChild(renderer.domElement);

      const scene = new this.three.Scene();
      const camera = new this.three.OrthographicCamera(-1, 1, 1, -1, 0, 1);
      const geometry = new this.three.PlaneGeometry(2, 2);

      const fragmentShader = this.getFragmentShader();

      const baseColor = this.hexToRgb(
        element.getAttribute('data-fire-plasma-base-color') || this.config.baseColor
      );
      const accentColor = this.hexToRgb(
        element.getAttribute('data-fire-plasma-accent-color') || this.config.accentColor
      );
      const highlightColor = this.hexToRgb(
        element.getAttribute('data-fire-plasma-highlight-color') || this.config.highlightColor
      );

      const turbulence = parseFloat(
        element.getAttribute('data-fire-plasma-turbulence') || this.config.turbulenceIntensity
      );
      const speed = parseFloat(
        element.getAttribute('data-fire-plasma-speed') || this.config.animationSpeed
      );
      const glow = parseFloat(
        element.getAttribute('data-fire-plasma-glow') || this.config.glowIntensity
      );
      const sparks = parseFloat(
        element.getAttribute('data-fire-plasma-sparks') || this.config.sparkDensity
      );
      const fps = parseInt(
        element.getAttribute('data-fire-plasma-fps') || this.config.fps
      );
      const pattern = element.getAttribute('data-fire-plasma-pattern') || this.config.noisePattern;

      let noisePatternValue = 0;
      switch (pattern) {
        case 'turbulent': noisePatternValue = 0; break;
        case 'smooth': noisePatternValue = 1; break;
        case 'chaotic': noisePatternValue = 2; break;
        case 'directional': noisePatternValue = 3; break;
        default: noisePatternValue = 0;
      }

      const uniforms = {
        time: { value: 0 },
        resolution: { value: new this.three.Vector2() },
        colorBase: { value: new this.three.Vector3(baseColor.r, baseColor.g, baseColor.b) },
        colorAccent: { value: new this.three.Vector3(accentColor.r, accentColor.g, accentColor.b) },
        colorHighlight: { value: new this.three.Vector3(highlightColor.r, highlightColor.g, highlightColor.b) },
        turbulence: { value: turbulence },
        sparkDensity: { value: sparks },
        animationSpeed: { value: speed },
        glowIntensity: { value: glow },
        noisePattern: { value: noisePatternValue }
      };

      const material = new this.three.ShaderMaterial({
        uniforms: uniforms,
        fragmentShader: fragmentShader,
        transparent: true
      });

      const mesh = new this.three.Mesh(geometry, material);
      scene.add(mesh);

      const instance = {
        element,
        wrapper,
        renderer,
        scene,
        camera,
        uniforms,
        fps,
        animationSpeed: speed,
        lastFrameTime: 0,
        resize: () => {
          const rect = element.getBoundingClientRect();
          renderer.setSize(rect.width, rect.height);
          uniforms.resolution.value.set(rect.width, rect.height);
          
          renderer.domElement.style.width = '100%';
          renderer.domElement.style.height = '100%';
          renderer.domElement.style.display = 'block';
          
          const currentStyle = window.getComputedStyle(element);
          wrapper.style.borderRadius = currentStyle.borderRadius;
          renderer.domElement.style.borderRadius = currentStyle.borderRadius;
        }
      };

      this.instances.push(instance);
      instance.resize();
      this.startAnimation(instance);
    }

    startAnimation(instance) {
      const fpsInterval = 1000 / instance.fps;
      const self = this;

      function animate(currentTime) {
        instance.animationFrame = requestAnimationFrame(animate);

        if (currentTime - instance.lastFrameTime >= fpsInterval) {
          instance.lastFrameTime = currentTime - ((currentTime - instance.lastFrameTime) % fpsInterval);
          
          if (self.isElementInViewport(instance.element)) {
            instance.uniforms.time.value = currentTime * 0.001 * instance.animationSpeed;
            instance.renderer.render(instance.scene, instance.camera);
          }
        }
      }

      animate(0);
    }

    resize() {
      this.instances.forEach(instance => instance.resize());
    }

    isElementInViewport(el) {
      const rect = el.getBoundingClientRect();
      return (
        rect.top <= (window.innerHeight || document.documentElement.clientHeight) &&
        rect.bottom >= 0 &&
        rect.left <= (window.innerWidth || document.documentElement.clientWidth) &&
        rect.right >= 0
      );
    }

    hexToRgb(hex) {
      hex = hex.replace(/^#/, '');
      const bigint = parseInt(hex, 16);
      return {
        r: ((bigint >> 16) & 255) / 255,
        g: ((bigint >> 8) & 255) / 255,
        b: (bigint & 255) / 255
      };
    }

    getFragmentShader() {
      return \`
        #ifdef GL_ES
        precision highp float;
        #endif

        uniform float time;
        uniform vec2 resolution;
        uniform vec3 colorBase;
        uniform vec3 colorAccent;
        uniform vec3 colorHighlight;
        uniform float turbulence;
        uniform float sparkDensity;
        uniform float animationSpeed;
        uniform float glowIntensity;
        uniform float noisePattern;

        #define NUM_OCTAVES 5

        float random(vec2 st) {
          return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);
        }

        float noise(vec2 st) {
          vec2 i = floor(st);
          vec2 f = fract(st);
          float a = random(i);
          float b = random(i + vec2(1.0, 0.0));
          float c = random(i + vec2(0.0, 1.0));
          float d = random(i + vec2(1.0, 1.0));
          vec2 u = f * f * (3.0 - 2.0 * f);
          return mix(a, b, u.x) + (c - a)* u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
        }

        float fbm(vec2 st) {
          float value = 0.0;
          float amplitude = 0.5;
          float frequency = 1.0;
          for (int i = 0; i < NUM_OCTAVES; i++) {
            value += amplitude * noise(st * frequency);
            st *= 2.0;
            amplitude *= 0.5;
            frequency *= 2.0;
          }
          return value;
        }

        float patternNoise(vec2 p, float pattern) {
          if (pattern < 0.5) {
            vec2 q = vec2(fbm(p + vec2(0.0, 0.0)),
                          fbm(p + vec2(5.2, 1.3)));
            return fbm(p + 4.0 * q);
          } else if (pattern < 1.5) {
            return fbm(p * 3.0);
          } else if (pattern < 2.5) {
            vec2 q = vec2(fbm(p),
                          fbm(p + vec2(1.0)));
            vec2 r = vec2(fbm(p + 4.0*q + vec2(1.7,9.2)),
                          fbm(p + 4.0*q + vec2(8.3,2.8)));
            return fbm(p + 4.0*r);
          } else {
            float angle = time * 0.2;
            vec2 dir = vec2(cos(angle), sin(angle));
            return fbm(p + dir * fbm(p * 2.0) * 2.0);
          }
        }

        vec2 rotate(vec2 v, float a) {
          float s = sin(a);
          float c = cos(a);
          mat2 m = mat2(c, -s, s, c);
          return m * v;
        }

        void main() {
          vec2 st = gl_FragCoord.xy / resolution.xy;
          st.x *= resolution.x / resolution.y;

          vec2 distort = vec2(
            patternNoise(st + time * 0.1, noisePattern),
            patternNoise(st + vec2(1.0) - time * 0.15, noisePattern)
          );

          distort = rotate(distort, time * 0.1);

          vec2 newSt = st + distort * turbulence * 0.3;

          float f1 = patternNoise(newSt * 3.0 + time * 0.1, noisePattern);
          float f2 = patternNoise(newSt * 2.0 - time * 0.05, noisePattern);
          float f3 = patternNoise(newSt * 4.0 + time * 0.2, noisePattern);

          float f = f1 * 0.5 + f2 * 0.3 + f3 * 0.2;

          vec3 color = mix(colorBase, colorAccent, clamp(f * 1.5, 0.0, 1.0));
          color = mix(color, colorHighlight, clamp(f * f * 3.0, 0.0, 1.0));

          float actualSparkDensity = 0.98 - sparkDensity * 0.1;
          float spark = step(actualSparkDensity, random(newSt + mod(time, 10.0)));
          color += spark * colorHighlight * 0.8;

          float glow = glowIntensity * 0.1 * (1.0 + sin(time * 2.0)) * (1.0 - distance(newSt, vec2(0.5)));
          color += glow * colorHighlight;

          gl_FragColor = vec4(color, 1.0);
        }
      \`;
    }
  }

  window.firePlasmaEffect = new FirePlasmaEffect();
  window.firePlasmaEffect.init();
})();`;
      }

      function copyJsToClipboard() {
        const jsCode = generateJavaScriptCode();
        
        navigator.clipboard.writeText(jsCode)
          .then(() => {
            showNotification('JavaScript code copied to clipboard!');
          })
          .catch(err => {
            try {
              const textArea = document.createElement('textarea');
              textArea.value = jsCode;
              textArea.style.position = 'fixed';
              textArea.style.opacity = '0';
              document.body.appendChild(textArea);
              textArea.select();
              document.execCommand('copy');
              document.body.removeChild(textArea);
              showNotification('JavaScript code copied to clipboard!');
            } catch (fallbackErr) {
              showNotification('Failed to copy to clipboard. Please try again.', 'error');
            }
          });
      }

      function copyFullSectionToClipboard() {
        const sectionJSON = generateFullSectionJSON();
        
        navigator.clipboard.writeText(sectionJSON)
          .then(() => {
            showNotification('Full section JSON copied to clipboard!');
          })
          .catch(err => {
            try {
              const textArea = document.createElement('textarea');
              textArea.value = sectionJSON;
              textArea.style.position = 'fixed';
              textArea.style.opacity = '0';
              document.body.appendChild(textArea);
              textArea.select();
              document.execCommand('copy');
              document.body.removeChild(textArea);
              showNotification('Full section JSON copied to clipboard!');
            } catch (fallbackErr) {
              showNotification('Failed to copy to clipboard. Please try again.', 'error');
            }
          });
      }

      function copyToClipboard(text) {
        navigator.clipboard.writeText(text)
          .then(() => {
            showNotification('Copied to clipboard!');
          })
          .catch(err => {
            showNotification('Failed to copy to clipboard', 'error');
          });
      }

      window.resetParameter = function(parameterId, defaultValue) {
        const element = document.getElementById(parameterId);
        if (element) {
          element.value = defaultValue;
          const valueElement = document.getElementById(`${parameterId}-value`);
          if (valueElement) {
            if (parameterId === 'animation-speed') {
              valueElement.textContent = defaultValue;
            } else if (parameterId === 'fps') {
              valueElement.textContent = defaultValue;
            } else {
              valueElement.textContent = defaultValue;
            }
          }
          
          switch (parameterId) {
            case 'turbulence-intensity':
              fireConfig.turbulenceIntensity = defaultValue;
              break;
            case 'animation-speed':
              fireConfig.animationSpeed = defaultValue;
              break;
            case 'glow-intensity':
              fireConfig.glowIntensity = defaultValue;
              break;
            case 'spark-density':
              fireConfig.sparkDensity = defaultValue;
              break;
            case 'fps':
              fireConfig.fps = defaultValue;
              break;
          }
          
          forceUpdatePreview();
          showNotification(`${parameterId.replace(/-/g, ' ')} reset to default`);
        }
      };

      function generateRandomFire() {
        const randomColors = Array.from({ length: 3 }, () => generateRandomColor());
        
        fireConfig.baseColor = randomColors[0];
        fireConfig.accentColor = randomColors[1];
        fireConfig.highlightColor = randomColors[2];
        
        randomColors.forEach((color, index) => {
          const ids = ['base-color', 'accent-color', 'highlight-color'];
          const colorInput = document.getElementById(ids[index]);
          const hexInput = document.getElementById(`${ids[index]}-hex`);
          const hslInput = document.getElementById(`${ids[index]}-hsl`);
          
          colorInput.value = color;
          hexInput.value = color;
          hslInput.value = hexToHsl(color);
          
          const container = colorInput.closest('.color-picker-container');
          if (container) {
            container.style.setProperty('--current-color', color);
          }
        });
        
        forceUpdatePreview();
        showNotification('Random fire colors generated!');
      }

      function updateColorInputsForPreset(preset) {
        let baseColor, accentColor, highlightColor;
        
        switch(preset) {
          case 'red':
            baseColor = '#cc0000';
            accentColor = '#ff3333';
            highlightColor = '#ff8080';
            break;
          case 'blue':
            baseColor = '#1a33cc';
            accentColor = '#3366ff';
            highlightColor = '#80a6ff';
            break;
          case 'green':
            baseColor = '#1a8019';
            accentColor = '#4dcc33';
            highlightColor = '#99ff66';
            break;
          case 'purple':
            baseColor = '#80198c';
            accentColor = '#cc33d9';
            highlightColor = '#ff99ff';
            break;
          case 'orange':
            baseColor = '#e66600';
            accentColor = '#ff9900';
            highlightColor = '#ffcc4d';
            break;
          case 'teal':
            baseColor = '#008080';
            accentColor = '#33b3b3';
            highlightColor = '#66e6e6';
            break;
          case 'pink':
            baseColor = '#e6669a';
            accentColor = '#ff99cc';
            highlightColor = '#ffcce6';
            break;
          case 'yellow':
            baseColor = '#ccb31a';
            accentColor = '#ffe633';
            highlightColor = '#fff980';
            break;
          case 'rainbow':
            baseColor = '#ff0000';
            accentColor = '#00ff00';
            highlightColor = '#0000ff';
            break;
          case 'galaxy':
            baseColor = '#1a0033';
            accentColor = '#660099';
            highlightColor = '#cc80ff';
            break;
          default:
            baseColor = '#cc0000';
            accentColor = '#ff3333';
            highlightColor = '#ff8080';
        }
        
        fireConfig.baseColor = baseColor;
        fireConfig.accentColor = accentColor;
        fireConfig.highlightColor = highlightColor;
        fireConfig.colorPreset = preset;
        
        updateColorInputs();
        forceUpdatePreview();
      }

      function updateColorInputs() {
        const colors = [fireConfig.baseColor, fireConfig.accentColor, fireConfig.highlightColor];
        const ids = ['base-color', 'accent-color', 'highlight-color'];
        
        colors.forEach((color, index) => {
          const colorInput = document.getElementById(ids[index]);
          const hexInput = document.getElementById(`${ids[index]}-hex`);
          const hslInput = document.getElementById(`${ids[index]}-hsl`);
          
          if (colorInput && hexInput && hslInput) {
            colorInput.value = color;
            hexInput.value = color;
            hslInput.value = hexToHsl(color);
            
            const container = colorInput.closest('.color-picker-container');
            if (container) {
              container.style.setProperty('--current-color', color);
            }
            
            hexInput.classList.remove('invalid');
            hslInput.classList.remove('invalid');
          }
        });
      }

      function initializeUI() {
        initFirePlasma();
        
        const instructionsToggle = document.getElementById('instructions-toggle');
        const instructionsContent = document.getElementById('instructions-content');
        const instructionsCard = document.getElementById('instructions-card');
        const toggleIcon = instructionsToggle.querySelector('.toggle-icon');
        
        instructionsToggle.addEventListener('click', () => {
          const isVisible = instructionsContent.classList.contains('show');
          
          if (isVisible) {
            instructionsContent.classList.remove('show');
            instructionsCard.classList.remove('expanded');
            toggleIcon.classList.remove('expanded');
          } else {
            instructionsContent.classList.add('show');
            instructionsCard.classList.add('expanded');
            toggleIcon.classList.add('expanded');
          }
        });

        document.getElementById('quick-attribute').addEventListener('click', () => {
          copyToClipboard('data-fire-plasma');
        });

        document.getElementById('download-config').addEventListener('click', () => {
          copyJsToClipboard();
        });

        document.getElementById('copy-full-section').addEventListener('click', () => {
          copyFullSectionToClipboard();
        });

        document.getElementById('randomize-fire').addEventListener('click', () => {
          generateRandomFire();
        });
        
        // Add debug capabilities
        window.debugFirePreview = function() {
          console.log('=== DEBUG INFO ===');
          console.log('Current fireConfig:', fireConfig);
          const preview = document.getElementById('fire-preview');
          console.log('Preview element:', preview);
          if (preview) {
            const wrapper = preview.querySelector('div[style*="position:absolute"]');
            console.log('Wrapper found:', !!wrapper);
            if (wrapper) {
              console.log('Wrapper has uniforms:', !!wrapper.fireUniforms);
              if (wrapper.fireUniforms) {
                console.log('Current uniform values:', {
                  colorBase: wrapper.fireUniforms.colorBase.value,
                  colorAccent: wrapper.fireUniforms.colorAccent.value,
                  colorHighlight: wrapper.fireUniforms.colorHighlight.value
                });
              }
            }
          }
          console.log('=== END DEBUG ===');
        };
        
        window.forceUpdatePreview = forceUpdatePreview;

        document.getElementById('reset-colors').addEventListener('click', () => {
          fireConfig.baseColor = defaultConfig.baseColor;
          fireConfig.accentColor = defaultConfig.accentColor;
          fireConfig.highlightColor = defaultConfig.highlightColor;
          fireConfig.colorPreset = defaultConfig.colorPreset;
          
          document.getElementById('color-preset').value = defaultConfig.colorPreset;
          updateColorInputs();
          forceUpdatePreview();
          showNotification('Colors reset to default');
        });

        document.getElementById('reset-animation').addEventListener('click', () => {
          fireConfig.turbulenceIntensity = defaultConfig.turbulenceIntensity;
          fireConfig.animationSpeed = defaultConfig.animationSpeed;
          fireConfig.glowIntensity = defaultConfig.glowIntensity;
          
          document.getElementById('turbulence-intensity').value = defaultConfig.turbulenceIntensity;
          document.getElementById('animation-speed').value = defaultConfig.animationSpeed;
          document.getElementById('glow-intensity').value = defaultConfig.glowIntensity;
          
          document.getElementById('turbulence-intensity-value').textContent = defaultConfig.turbulenceIntensity;
          document.getElementById('animation-speed-value').textContent = defaultConfig.animationSpeed;
          document.getElementById('glow-intensity-value').textContent = defaultConfig.glowIntensity;
          
          forceUpdatePreview();
          showNotification('Animation settings reset');
        });

        document.getElementById('reset-advanced').addEventListener('click', () => {
          fireConfig.sparkDensity = defaultConfig.sparkDensity;
          fireConfig.fps = defaultConfig.fps;
          fireConfig.noisePattern = defaultConfig.noisePattern;
          
          document.getElementById('spark-density').value = defaultConfig.sparkDensity;
          document.getElementById('fps').value = defaultConfig.fps;
          document.getElementById('noise-pattern').value = defaultConfig.noisePattern;
          
          document.getElementById('spark-density-value').textContent = defaultConfig.sparkDensity;
          document.getElementById('fps-value').textContent = defaultConfig.fps;
          
          forceUpdatePreview();
          showNotification('Advanced settings reset');
        });

        document.getElementById('color-preset').addEventListener('change', function() {
          console.log('Changing color preset to:', this.value);
          fireConfig.colorPreset = this.value;
          updateColorInputsForPreset(this.value);
        });

        const colorInputs = document.querySelectorAll('input[type="color"]');
        colorInputs.forEach((input, index) => {
          const ids = ['base-color', 'accent-color', 'highlight-color'];
          const hexInput = document.getElementById(`${ids[index]}-hex`);
          const hslInput = document.getElementById(`${ids[index]}-hsl`);
          
          hslInput.value = hexToHsl(input.value);
          
          const container = input.closest('.color-picker-container');
          if (container) {
            container.style.setProperty('--current-color', input.value);
          }
          
          input.addEventListener('input', () => {
            const color = input.value;
            console.log('Changing color', ids[index], 'to:', color);
            
            hexInput.value = color;
            hslInput.value = hexToHsl(color);
            hexInput.classList.remove('invalid');
            hslInput.classList.remove('invalid');
            
            const container = input.closest('.color-picker-container');
            if (container) {
              container.style.setProperty('--current-color', color);
            }
            
            if (ids[index] === 'base-color') fireConfig.baseColor = color;
            else if (ids[index] === 'accent-color') fireConfig.accentColor = color;
            else if (ids[index] === 'highlight-color') fireConfig.highlightColor = color;
            
            console.log('Color config updated:', fireConfig);
            updateFirePreview();
          });
          
          hexInput.addEventListener('input', (e) => {
            let hex = e.target.value;
            
            hex = formatHex(hex);
            e.target.value = hex;
            
            if (isValidHex(hex)) {
              input.value = hex;
              hslInput.value = hexToHsl(hex);
              
              const container = input.closest('.color-picker-container');
              if (container) {
                container.style.setProperty('--current-color', hex);
              }
              
              if (ids[index] === 'base-color') fireConfig.baseColor = hex;
              else if (ids[index] === 'accent-color') fireConfig.accentColor = hex;
              else if (ids[index] === 'highlight-color') fireConfig.highlightColor = hex;
              
              e.target.classList.remove('invalid');
              hslInput.classList.remove('invalid');
              updateFirePreview();
            } else {
              e.target.classList.add('invalid');
            }
          });
          
          hexInput.addEventListener('blur', (e) => {
            if (!isValidHex(e.target.value)) {
              e.target.value = input.value;
              e.target.classList.remove('invalid');
            }
          });
          
          hslInput.addEventListener('input', (e) => {
            let hsl = e.target.value;
            
            if (isValidHsl(hsl)) {
              const hex = hslToHex(hsl);
              if (hex) {
                input.value = hex;
                hexInput.value = hex;
                
                const container = input.closest('.color-picker-container');
                if (container) {
                  container.style.setProperty('--current-color', hex);
                }
                
                if (ids[index] === 'base-color') fireConfig.baseColor = hex;
                else if (ids[index] === 'accent-color') fireConfig.accentColor = hex;
                else if (ids[index] === 'highlight-color') fireConfig.highlightColor = hex;
                
                e.target.classList.remove('invalid');
                hexInput.classList.remove('invalid');
                updateFirePreview();
                return;
              }
            }
            
            e.target.classList.add('invalid');
          });
          
          hslInput.addEventListener('blur', (e) => {
            let hsl = e.target.value;
            
            if (!isValidHsl(hsl) && hsl.trim()) {
              const formatted = formatHsl(hsl);
              if (isValidHsl(formatted)) {
                e.target.value = formatted;
                const hex = hslToHex(formatted);
                if (hex) {
                  input.value = hex;
                  hexInput.value = hex;
                  
                  const container = input.closest('.color-picker-container');
                  if (container) {
                    container.style.setProperty('--current-color', hex);
                  }
                  
                  if (ids[index] === 'base-color') fireConfig.baseColor = hex;
                  else if (ids[index] === 'accent-color') fireConfig.accentColor = hex;
                  else if (ids[index] === 'highlight-color') fireConfig.highlightColor = hex;
                  
                  e.target.classList.remove('invalid');
                  hexInput.classList.remove('invalid');
                  updateFirePreview();
                  return;
                }
              }
            }
            
            if (!isValidHsl(e.target.value)) {
              e.target.value = hexToHsl(input.value);
              e.target.classList.remove('invalid');
            }
          });
        });

        const rangeInputs = document.querySelectorAll('input[type="range"]');
        rangeInputs.forEach(input => {
          let valueElement;
          
          switch (input.id) {
            case 'turbulence-intensity':
              valueElement = document.getElementById('turbulence-intensity-value');
              break;
            case 'animation-speed':
              valueElement = document.getElementById('animation-speed-value');
              break;
            case 'glow-intensity':
              valueElement = document.getElementById('glow-intensity-value');
              break;
            case 'spark-density':
              valueElement = document.getElementById('spark-density-value');
              break;
            case 'fps':
              valueElement = document.getElementById('fps-value');
              break;
            default:
              valueElement = document.getElementById(`${input.id}-value`);
          }
          
          if (valueElement) {
            if (input.id === 'animation-speed') {
              valueElement.textContent = input.value;
            } else if (input.id === 'fps') {
              valueElement.textContent = input.value;
            } else {
              valueElement.textContent = input.value;
            }
          }
          
          input.addEventListener('input', () => {
            console.log('Changing', input.id, 'to:', input.value);
            
            if (valueElement) {
              if (input.id === 'animation-speed') {
                valueElement.textContent = input.value;
              } else if (input.id === 'fps') {
                valueElement.textContent = input.value;
              } else {
                valueElement.textContent = input.value;
              }
            }
            
            switch (input.id) {
              case 'turbulence-intensity':
                fireConfig.turbulenceIntensity = parseFloat(input.value);
                break;
              case 'animation-speed':
                fireConfig.animationSpeed = parseFloat(input.value);
                break;
              case 'glow-intensity':
                fireConfig.glowIntensity = parseFloat(input.value);
                break;
              case 'spark-density':
                fireConfig.sparkDensity = parseFloat(input.value);
                break;
              case 'fps':
                fireConfig.fps = parseInt(input.value);
                break;
            }
            
            console.log('Updating fireConfig:', fireConfig);
            updateFirePreview();
          });
        });

        document.getElementById('noise-pattern').addEventListener('change', function() {
          console.log('Changing noise pattern to:', this.value);
          fireConfig.noisePattern = this.value;
          updateFirePreview();
        });

        document.addEventListener('keydown', (e) => {
          if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'SELECT') {
            return;
          }
          
          if (e.ctrlKey || e.metaKey) {
            switch (e.key.toLowerCase()) {
              case 'd':
                e.preventDefault();
                const downloadBtn = document.getElementById('download-config');
                if (downloadBtn && downloadBtn.hasAttribute('data-protection-animation')) {
                  downloadBtn.click();
                } else {
                  copyJsToClipboard();
                }
                break;
              case 's':
                e.preventDefault();
                const fullSectionBtn = document.getElementById('copy-full-section');
                if (fullSectionBtn && fullSectionBtn.hasAttribute('data-protection-animation')) {
                  fullSectionBtn.click();
                } else {
                  copyFullSectionToClipboard();
                }
                break;
            }
          } else {
            switch (e.key.toLowerCase()) {
              case 'r':
                generateRandomFire();
                break;
            }
          }
        });

        updateColorInputs();
        
        console.log('Configurator initialized. fireConfig:', fireConfig);
        console.log('Preview initialized correctly');
        
        // Force an initial preview update to ensure it's working
        setTimeout(() => {
          console.log('Forcing initial preview update...');
          forceUpdatePreview();
        }, 1000);
        
        setTimeout(() => {
          showNotification('BricksFusion Fire Plasma Configurator loaded!');
        }, 500);

        function saveConfiguration() {
          try {
            localStorage.setItem('bricksfusion-fire-config', JSON.stringify(fireConfig));
          } catch (e) {
          }
        }

        function loadConfiguration() {
          try {
            const saved = localStorage.getItem('bricksfusion-fire-config');
            if (saved) {
              const savedConfig = JSON.parse(saved);
              Object.assign(fireConfig, savedConfig);
              
              document.getElementById('base-color').value = savedConfig.baseColor;
              document.getElementById('base-color-hex').value = savedConfig.baseColor;
              document.getElementById('base-color-hsl').value = hexToHsl(savedConfig.baseColor);
              
              document.getElementById('accent-color').value = savedConfig.accentColor;
              document.getElementById('accent-color-hex').value = savedConfig.accentColor;
              document.getElementById('accent-color-hsl').value = hexToHsl(savedConfig.accentColor);
              
              document.getElementById('highlight-color').value = savedConfig.highlightColor;
              document.getElementById('highlight-color-hex').value = savedConfig.highlightColor;
              document.getElementById('highlight-color-hsl').value = hexToHsl(savedConfig.highlightColor);
              
              document.getElementById('turbulence-intensity').value = savedConfig.turbulenceIntensity;
              document.getElementById('animation-speed').value = savedConfig.animationSpeed;
              document.getElementById('glow-intensity').value = savedConfig.glowIntensity;
              document.getElementById('spark-density').value = savedConfig.sparkDensity;
              document.getElementById('fps').value = savedConfig.fps;
              document.getElementById('noise-pattern').value = savedConfig.noisePattern;
              document.getElementById('color-preset').value = savedConfig.colorPreset || 'red';
              
              document.getElementById('turbulence-intensity-value').textContent = savedConfig.turbulenceIntensity;
              document.getElementById('animation-speed-value').textContent = savedConfig.animationSpeed;
              document.getElementById('glow-intensity-value').textContent = savedConfig.glowIntensity;
              document.getElementById('spark-density-value').textContent = savedConfig.sparkDensity;
              document.getElementById('fps-value').textContent = savedConfig.fps;
              
              updateFirePreview();
            }
          } catch (e) {
          }
        }

        const originalUpdateFirePreview = updateFirePreview;
        updateFirePreview = function() {
          originalUpdateFirePreview();
          saveConfiguration();
        };

        loadConfiguration();

        let performanceMonitor = {
          animationFrames: 0,
          lastCheck: Date.now(),
          
          checkPerformance() {
            this.animationFrames++;
            const now = Date.now();
            
            if (now - this.lastCheck >= 1000) {
              const fps = this.animationFrames;
              this.animationFrames = 0;
              this.lastCheck = now;
              
              if (fps < 30) {
              }
            }
          }
        };

        setInterval(() => {
          performanceMonitor.checkPerformance();
        }, 1000);

        const observeElements = () => {
          const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
              if (entry.isIntersecting) {
                entry.target.classList.remove('loading');
              }
            });
          });

          document.querySelectorAll('.card').forEach(card => {
            observer.observe(card);
          });
        };

        observeElements();

        function initTooltips() {
          const helpTooltips = document.querySelectorAll('.help-tooltip');
          
          helpTooltips.forEach(tooltip => {
            tooltip.addEventListener('mouseenter', (e) => {
              const title = e.target.getAttribute('title');
              if (title) {
                const tooltipEl = document.createElement('div');
                tooltipEl.className = 'custom-tooltip';
                tooltipEl.textContent = title;
                tooltipEl.style.cssText = `
                  position: fixed;
                  background: var(--card-bg);
                  color: var(--text-primary);
                  padding: 0.5rem 0.75rem;
                  border-radius: 6px;
                  font-size: 12px;
                  z-index: 1002;
                  border: 1px solid var(--border);
                  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
                  max-width: 200px;
                  word-wrap: break-word;
                `;
                
                const rect = e.target.getBoundingClientRect();
                tooltipEl.style.left = (rect.left + rect.width / 2 - 100) + 'px';
                tooltipEl.style.top = (rect.top - 40) + 'px';
                
                document.body.appendChild(tooltipEl);
                e.target._tooltip = tooltipEl;
              }
            });
            
            tooltip.addEventListener('mouseleave', (e) => {
              if (e.target._tooltip) {
                document.body.removeChild(e.target._tooltip);
                e.target._tooltip = null;
              }
            });
          });
        }

        initTooltips();

        function handleResize() {
          if (window.innerWidth <= 768) {
            document.body.style.paddingBottom = 'calc(var(--action-bar-height) + 20px)';
          } else {
            document.body.style.paddingBottom = 'var(--action-bar-height)';
          }
        }

        window.addEventListener('resize', handleResize);
        handleResize();

        function initAccessibility() {
          document.getElementById('fire-preview').setAttribute('aria-label', 'Fire plasma effect preview');
          document.getElementById('quick-attribute').setAttribute('aria-label', 'Copy data attribute to clipboard');
        }

        initAccessibility();

        function handleErrors() {
          window.addEventListener('error', (e) => {
            showNotification('An error occurred. Please refresh.', 'error');
          });

          window.addEventListener('unhandledrejection', (e) => {
            showNotification('A network error occurred.', 'error');
          });
        }

        handleErrors();

        function checkVersion() {
          const currentVersion = '1.0.0';
          const storedVersion = localStorage.getItem('bricksfusion-fire-configurator-version');
          
          if (storedVersion && storedVersion !== currentVersion) {
            showNotification('Configurator updated!', 'info');
          }
          
          localStorage.setItem('bricksfusion-fire-configurator-version', currentVersion);
        }

        checkVersion();

        function trackEvent(eventName, eventData = {}) {
        }

        document.getElementById('download-config').addEventListener('click', () => {
          trackEvent('download_js', { preset: fireConfig.colorPreset });
        });

        document.getElementById('copy-full-section').addEventListener('click', () => {
          trackEvent('copy_full_section', { preset: fireConfig.colorPreset });
        });

        document.getElementById('randomize-fire').addEventListener('click', () => {
          trackEvent('randomize_fire');
        });
      }
      
      initializeUI();
    });
  </script>
</body>
</html>
Fire Plasma - Bricksfusion
HEAVY

Fire Plasma

Creates animated fire and plasma effects using WebGL shaders. Features turbulent flames, glowing embers, and sparks with customizable colors and patterns. Perfect for hero sections, dramatic backgrounds, or adding energy to any design.

Fire Plasma

Animated fire effect powered by WebGL shaders.

Colors

Base Color color picker

Deep color at the core of the fire effect. Typically dark red, orange, or blue for different flame types.

Default: #cc0000 (deep red)

Accent Color color picker

Mid-tone color that blends with base. Creates the main body of flames. Brighter than base color.

Default: #ff3333 (bright red)

Highlight Color color picker

Brightest color for hot spots and sparks. Creates peaks and intense areas. Usually white, yellow, or cyan.

Default: #ff8080 (light red)

Animation

Animation Speed 0.1-3.0

How fast the fire moves and flows. Lower is slow and calm, higher is fast and intense.

Default: 1

Turbulence Intensity 0.0-1.0

How chaotic and wild the flames are. Higher values create more distortion and movement.

Default: 0.5

Effects

Glow Intensity 0.0-1.0

Strength of the pulsing glow effect. Creates breathing, living fire with varied brightness.

Default: 0.5

Spark Density 0.0-1.0

Amount of bright sparks and embers. Higher values add more twinkling points of light.

Default: 0.5

Pattern

Noise Pattern 4 patterns

Type of movement pattern. Turbulent creates classic fire, smooth is flowing plasma, chaotic is wild flames, directional has wind-blown motion.

Default: Turbulent

Performance

FPS 30 / 60

Target frames per second. 60 is smooth but intensive, 30 saves resources on weaker devices.

Default: 60

Performance Warning

This element uses Three.js with complex GLSL fragment shaders for GPU-accelerated rendering. Uses fractal brownian motion (FBM) with 5 octaves of Perlin noise for organic patterns. Runs constantly at target FPS with real-time distortion and color mixing calculations. Very resource intensive - not recommended for multiple instances or low-end devices.