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>Gradient Essence 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: #1a1a1a;
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  display: flex;
  align-items: center;
  justify-content: center;
}

.preview-content {
  text-align: center;
}

.preview-button {
  padding: 1rem 2rem;
  background: linear-gradient(90deg, #3498db, #2ecc71, #e74c3c, #3498db);
  background-size: 300% 100%;
  border: none;
  border-radius: 8px;
  color: white;
  font-size: var(--text-s);
  font-weight: 600;
  cursor: pointer;
  animation: gradientMove 3s linear infinite;
  transition: var(--transition);
  position: relative;
  overflow: hidden;
}

.preview-button:hover {
  animation-duration: 2s;
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

@keyframes gradientMove {
  0% { background-position: 0% 50%; }
  100% { background-position: 300% 50%; }
}

.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);
}

.preview-btn svg {
  width: 18px;
  height: 18px;
  stroke: currentColor;
}

.background-selector-wrapper {
  position: relative;
  display: inline-block;
}

.background-selector-btn {
  position: relative;
}

.background-selector-btn:hover {
  background-color: rgba(239, 96, 19, 0.2);
  border-color: var(--accent);
  box-shadow: 0 0 8px rgba(239, 96, 19, 0.3);
}

.hidden-color-input {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
  z-index: 1;
}

.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;
  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: var(--card-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  --selected-color: #3498db;
}

.color-picker-container:hover {
  border-color: var(--accent);
  transform: scale(1.05);
  box-shadow: 0 0 12px rgba(239, 96, 19, 0.3);
}

.color-picker-container::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--selected-color, #3498db);
  border-radius: 6px;
  transition: var(--transition);
}

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

.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;
  border: 1px solid var(--border);
  border-radius: var(--input-radius);
  font-family: var(--font);
  font-size: var(--text-xs);
  color: var(--text-primary);
  background-color: var(--card-bg);
  margin-bottom: 0.75rem;
  outline: none;
  transition: var(--transition);
}

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

.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/button-template/" class="breadcrumb-item">Buttons</a>
      <span class="breadcrumb-separator">›</span>
      <span class="breadcrumb-item active">Gradient Essence</span>
    </nav>
    
    <div class="action-buttons">
      <div class="data-attribute-display" id="quick-attribute" title="Click to copy data attribute">
        data-essence
      </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">Gradient Essence</h1>
      <p class="page-subtitle">Interactive gradient animations 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 gradient essence animation 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 element: go to <strong>Section → Style → Attributes</strong>, add <code>data-essence</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="gradient-preview">
          <div class="preview-content">
            <button class="preview-button" data-essence="true">Interactive Gradient Button</button>
          </div>
          <div class="preview-controls">
            <button class="preview-btn" id="randomize-gradient" title="Randomize (R)">🎲</button>
            <div class="background-selector-wrapper">
              <button class="preview-btn background-selector-btn" id="background-selector">
                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                  <polygon points="12,2 2,7 12,12 22,7"/>
                  <polyline points="2,17 12,22 22,17"/>
                  <polyline points="2,12 12,17 22,12"/>
                </svg>
              </button>
              <input type="color" id="preview-background-picker" class="hidden-color-input" value="#1a1a1a" title="Change Preview Background (B)">
            </div>
          </div>
        </div>
      </section>

      <section class="controls-section">
        <div class="card">
          <div class="card-heading">
            Gradient 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="color-list">
              <div class="color-row">
                <div class="color-picker-container" style="--selected-color: #3498db;">
                  <input type="color" id="gradient-color1" value="#3498db">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HEX</span>
                  <input type="text" class="color-input hex-input" id="gradient-color1-hex" value="#3498db" placeholder="#3498db">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HSL</span>
                  <input type="text" class="color-input hsl-input" id="gradient-color1-hsl" placeholder="hsl(0, 100%, 50%)">
                </div>
              </div>
              
              <div class="color-row">
                <div class="color-picker-container" style="--selected-color: #2ecc71;">
                  <input type="color" id="gradient-color2" value="#2ecc71">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HEX</span>
                  <input type="text" class="color-input hex-input" id="gradient-color2-hex" value="#2ecc71" placeholder="#2ecc71">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HSL</span>
                  <input type="text" class="color-input hsl-input" id="gradient-color2-hsl" placeholder="hsl(0, 100%, 50%)">
                </div>
              </div>
              
              <div class="color-row">
                <div class="color-picker-container" style="--selected-color: #e74c3c;">
                  <input type="color" id="gradient-color3" value="#e74c3c">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HEX</span>
                  <input type="text" class="color-input hex-input" id="gradient-color3-hex" value="#e74c3c" placeholder="#e74c3c">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HSL</span>
                  <input type="text" class="color-input hsl-input" id="gradient-color3-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">
                  Duration
                  <span class="help-tooltip" title="Animation duration in seconds">ℹ</span>
                </span>
                <div class="value-display">
                  <span class="value-text"><span id="duration-value">3</span>s</span>
                  <button class="reset-btn" onclick="resetParameter('duration', 3)">↺</button>
                </div>
              </div>
              <input type="range" id="duration" min="1" max="10" step="0.5" value="3">
            </div>
            
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">
                  Hover Speed
                  <span class="help-tooltip" title="Animation speed on hover">ℹ</span>
                </span>
                <div class="value-display">
                  <span class="value-text"><span id="speed-value">2</span>s</span>
                  <button class="reset-btn" onclick="resetParameter('speed', 2)">↺</button>
                </div>
              </div>
              <input type="range" id="speed" min="0.5" max="5" step="0.5" value="2">
            </div>
            
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">
                  Intensity
                  <span class="help-tooltip" title="Gradient intensity/opacity">ℹ</span>
                </span>
                <div class="value-display">
                  <span class="value-text"><span id="intensity-value">1</span></span>
                  <button class="reset-btn" onclick="resetParameter('intensity', 1)">↺</button>
                </div>
              </div>
              <input type="range" id="intensity" min="0.1" max="1" step="0.1" value="1">
            </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">Gradient Direction</span>
              </div>
              <select id="direction">
                <option value="90">Horizontal (Default)</option>
                <option value="180">Vertical</option>
                <option value="45">Diagonal</option>
                <option value="135">Diagonal Reverse</option>
                <option value="270">Horizontal Reverse</option>
                <option value="0">Vertical Reverse</option>
              </select>
            </div>
          </div>
        </div>
      </section>
    </div>
  </div>

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

  <script>
    document.addEventListener('DOMContentLoaded', function() {
      let gradientConfig = {
        gradient1: '#3498db',
        gradient2: '#2ecc71',
        gradient3: '#e74c3c',
        duration: '3',
        speed: '2',
        direction: '90',
        intensity: '1'
      };

      const defaultConfig = { ...gradientConfig };
      let activeGradientEffect = null;
      
      function initGradientEssence() {
        const elements = document.querySelectorAll('[data-essence]:not([data-essence-initialized="true"])');
        
        elements.forEach((element) => {
          const gradient1 = element.hasAttribute('data-essence-color1') 
            ? element.getAttribute('data-essence-color1') 
            : gradientConfig.gradient1;
            
          const gradient2 = element.hasAttribute('data-essence-color2') 
            ? element.getAttribute('data-essence-color2') 
            : gradientConfig.gradient2;
            
          const gradient3 = element.hasAttribute('data-essence-color3') 
            ? element.getAttribute('data-essence-color3') 
            : gradientConfig.gradient3;
            
          const duration = element.hasAttribute('data-essence-duration') 
            ? element.getAttribute('data-essence-duration') 
            : gradientConfig.duration;
            
          const speed = element.hasAttribute('data-essence-speed') 
            ? element.getAttribute('data-essence-speed') 
            : gradientConfig.speed;
            
          const direction = element.hasAttribute('data-essence-direction') 
            ? element.getAttribute('data-essence-direction') 
            : gradientConfig.direction;
            
          const intensity = element.hasAttribute('data-essence-intensity') 
            ? element.getAttribute('data-essence-intensity') 
            : gradientConfig.intensity;
            
          const options = {
            gradient1,
            gradient2,
            gradient3,
            duration,
            speed,
            direction,
            intensity
          };
          
          setupGradientEssence(element, options);
          element.dataset.essenceInitialized = 'true';
          
          if (element.classList.contains('preview-button')) {
            activeGradientEffect = { element, options };
            gradientConfig = { ...options };
          }
        });
      }
      
      function setupGradientEssence(element, options) {
        const id = `essence-${Math.random().toString(36).substr(2, 9)}`;
        
        if (element.gradientStyle) {
          element.gradientStyle.remove();
        }
        
        const originalContent = element.innerHTML;
        element.innerHTML = `
          <div class="essence-background-${id}"></div>
          <span class="essence-content-${id}">${originalContent}</span>
        `;

        const style = createGradientStyle(element, options, id);
        document.head.appendChild(style);
        element.gradientStyle = style;
        element.dataset.essenceId = id;
      }
      
      function createGradientStyle(element, options, id) {
        const style = document.createElement('style');
        
        style.textContent = `
          [data-essence-id="${id}"] {
            position: relative !important;
            overflow: hidden !important;
            border: none !important;
            background: transparent !important;
          }

          .essence-background-${id} {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: linear-gradient(
              ${options.direction}deg,
              ${options.gradient1},
              ${options.gradient2},
              ${options.gradient3},
              ${options.gradient1}
            );
            background-size: 300% 100%;
            animation: gradientMove-${id} ${options.duration}s linear infinite;
            z-index: 1;
            opacity: ${options.intensity};
          }

          .essence-content-${id} {
            position: relative;
            z-index: 2;
            display: inline-block;
          }

          @keyframes gradientMove-${id} {
            0% {
              background-position: 0% 50%;
            }
            100% {
              background-position: 300% 50%;
            }
          }

          [data-essence-id="${id}"]:hover .essence-background-${id} {
            animation-duration: ${options.speed}s;
          }

          @media (prefers-reduced-motion: reduce) {
            .essence-background-${id} {
              animation: none;
              background-position: 0% 50%;
            }
          }
        `;

        return style;
      }
      
      function updateGradientPreview() {
        const previewButton = document.querySelector('.preview-button');
        if (!previewButton) return;
        
        if (previewButton.gradientStyle) {
          previewButton.gradientStyle.remove();
        }
        
        previewButton.setAttribute('data-essence', 'true');
        previewButton.setAttribute('data-essence-color1', gradientConfig.gradient1);
        previewButton.setAttribute('data-essence-color2', gradientConfig.gradient2);
        previewButton.setAttribute('data-essence-color3', gradientConfig.gradient3);
        previewButton.setAttribute('data-essence-duration', gradientConfig.duration);
        previewButton.setAttribute('data-essence-speed', gradientConfig.speed);
        previewButton.setAttribute('data-essence-direction', gradientConfig.direction);
        previewButton.setAttribute('data-essence-intensity', gradientConfig.intensity);
        
        const id = `essence-preview`;
        previewButton.innerHTML = `
          <div class="essence-background-${id}"></div>
          <span class="essence-content-${id}">Interactive Gradient Button</span>
        `;

        const style = createGradientStyle(previewButton, gradientConfig, id);
        document.head.appendChild(style);
        previewButton.gradientStyle = style;
        previewButton.dataset.essenceId = id;
      }

      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 para todos los elementos
  const sectionId = generateUniqueId();
  const containerId = generateUniqueId();
  const divId = generateUniqueId();
  const buttonId = generateUniqueId();
  const codeId = generateUniqueId();
  const attributeId = generateUniqueId();

  // Obtener el JavaScript actual con la configuración del usuario
  const jsCode = generateJavaScriptCode();

  // Crear el objeto JSON completo de Bricks Builder
  const bricksJSON = {
    "content": [
      {
        "id": sectionId,
        "name": "section",
        "parent": 0,
        "children": [containerId, codeId],
        "settings": {}
      },
      {
        "id": containerId,
        "name": "container",
        "parent": sectionId,
        "children": [divId],
        "settings": {
          "_alignItems": "center"
        }
      },
      {
        "id": divId,
        "name": "div",
        "parent": containerId,
        "children": [buttonId],
        "settings": {}
      },
      {
        "id": buttonId,
        "name": "button",
        "parent": divId,
        "children": [],
        "settings": {
          "text": "Essence button",
          "_attributes": [
            {
              "id": attributeId,
              "name": "data-essence"
            }
          ],
          "_border": {
            "radius": {
              "top": "15",
              "right": "15",
              "bottom": "15",
              "left": "15"
            }
          },
          "_typography": {
            "color": {
              "hex": "#ffffff"
            },
            "font-weight": "400",
            "font-size": "18"
          },
          "_background": {
            "color": {
              "hex": "#000000"
            }
          }
        },
        "label": "Essence button"
      },
      {
        "id": codeId,
        "name": "code",
        "parent": sectionId,
        "children": [],
        "settings": {
          "_display": "none",
          "javascriptCode": jsCode,
          "executeCode": true
        },
        "label": "Essence button JS"
      }
    ],
    "source": "bricksCopiedElements",
    "sourceUrl": "https://test.bricksfusion.com",
    "version": "2.0.1",
    "globalClasses": [],
    "globalElements": []
  };

  return JSON.stringify(bricksJSON, null, 2);
}

      function generateJavaScriptCode() {
        return `class GradientEssenceEffect {
    constructor() {
        this.buttons = new Map();
        this.config = {
            gradient1: "${gradientConfig.gradient1}",
            gradient2: "${gradientConfig.gradient2}",
            gradient3: "${gradientConfig.gradient3}",
            duration: "${gradientConfig.duration}",
            speed: "${gradientConfig.speed}",
            direction: "${gradientConfig.direction}",
            intensity: "${gradientConfig.intensity}"
        };
        this.init();
    }

    init() {
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', () => this.initializeButtons());
        } else {
            this.initializeButtons();
        }
        this.observeDOMChanges();
    }

    initializeButtons() {
        document.querySelectorAll('[data-essence]').forEach(button => this.setupButton(button));
    }

    observeDOMChanges() {
        const observer = new MutationObserver(mutations => {
            mutations.forEach(mutation => {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === 1 && node.matches('[data-essence]')) {
                        this.setupButton(node);
                    }
                });
            });
        });

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

    getButtonConfig(button) {
        return {
            id: \`essence-\${Math.random().toString(36).substr(2, 9)}\`,
            gradient1: button.getAttribute('data-essence-color1') || this.config.gradient1,
            gradient2: button.getAttribute('data-essence-color2') || this.config.gradient2,
            gradient3: button.getAttribute('data-essence-color3') || this.config.gradient3,
            duration: button.getAttribute('data-essence-duration') || this.config.duration,
            speed: button.getAttribute('data-essence-speed') || this.config.speed,
            direction: button.getAttribute('data-essence-direction') || this.config.direction,
            intensity: button.getAttribute('data-essence-intensity') || this.config.intensity
        };
    }

    setupButton(button) {
        if (this.buttons.has(button)) return;

        const config = this.getButtonConfig(button);
        
        const originalContent = button.innerHTML;
        button.innerHTML = \`
            <div class="essence-background-\${config.id}"></div>
            <span class="essence-content-\${config.id}">\${originalContent}</span>
        \`;

        const style = this.createButtonStyle(button, config);
        document.head.appendChild(style);

        this.buttons.set(button, { style });
    }

    createButtonStyle(button, config) {
        const style = document.createElement('style');
        button.dataset.essenceId = config.id;

        style.textContent = \`
            [data-essence-id="\${config.id}"] {
                position: relative !important;
                overflow: hidden !important;
                border: none !important;
                background: transparent !important;
            }

            .essence-background-\${config.id} {
                position: absolute;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background: linear-gradient(
                    \${config.direction}deg,
                    \${config.gradient1},
                    \${config.gradient2},
                    \${config.gradient3},
                    \${config.gradient1}
                );
                background-size: 300% 100%;
                animation: gradientMove-\${config.id} \${config.duration}s linear infinite;
                z-index: 1;
                opacity: \${config.intensity};
            }

            .essence-content-\${config.id} {
                position: relative;
                z-index: 2;
                display: inline-block;
            }

            @keyframes gradientMove-\${config.id} {
                0% {
                    background-position: 0% 50%;
                }
                100% {
                    background-position: 300% 50%;
                }
            }

            [data-essence-id="\${config.id}"]:hover .essence-background-\${config.id} {
                animation-duration: \${config.speed}s;
            }

            @media (prefers-reduced-motion: reduce) {
                .essence-background-\${config.id} {
                    animation: none;
                    background-position: 0% 50%;
                }
            }
        \`;

        return style;
    }

    updateConfig(newConfig) {
        this.config = { ...this.config, ...newConfig };
        this.buttons.forEach(({style}, button) => {
            style.remove();
            this.setupButton(button);
        });
    }

    destroy() {
        this.buttons.forEach(({style}, button) => {
            style.remove();
            delete button.dataset.essenceId;
        });
        this.buttons.clear();
    }
}

const essenceEffect = new GradientEssenceEffect();`;
      }

      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) {
            valueElement.textContent = defaultValue;
          }
          
          switch (parameterId) {
            case 'duration':
              gradientConfig.duration = defaultValue;
              break;
            case 'speed':
              gradientConfig.speed = defaultValue;
              break;
            case 'intensity':
              gradientConfig.intensity = defaultValue;
              break;
          }
          
          updateGradientPreview();
          showNotification(`${parameterId.replace(/-/g, ' ')} reset to default`);
        }
      };

      function generateRandomGradient() {
        gradientConfig.gradient1 = generateRandomColor();
        gradientConfig.gradient2 = generateRandomColor();
        gradientConfig.gradient3 = generateRandomColor();
        gradientConfig.duration = (Math.random() * 9 + 1).toFixed(1);
        gradientConfig.speed = (Math.random() * 4.5 + 0.5).toFixed(1);
        gradientConfig.intensity = (Math.random() * 0.9 + 0.1).toFixed(1);
        
        document.getElementById('gradient-color1').value = gradientConfig.gradient1;
        document.getElementById('gradient-color2').value = gradientConfig.gradient2;
        document.getElementById('gradient-color3').value = gradientConfig.gradient3;
        document.getElementById('duration').value = gradientConfig.duration;
        document.getElementById('speed').value = gradientConfig.speed;
        document.getElementById('intensity').value = gradientConfig.intensity;
        
        document.getElementById('duration-value').textContent = gradientConfig.duration;
        document.getElementById('speed-value').textContent = gradientConfig.speed;
        document.getElementById('intensity-value').textContent = gradientConfig.intensity;
        
        updateColorInputs();
        updateGradientPreview();
        showNotification('Random gradient generated!');
      }

      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 {
          h: Math.round(h * 360),
          s: Math.round(s * 100),
          l: 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 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 updateColorInputs() {
        const colors = ['gradient-color1', 'gradient-color2', 'gradient-color3'];
        const configKeys = ['gradient1', 'gradient2', 'gradient3'];
        
        colors.forEach((colorId, index) => {
          const colorInput = document.getElementById(colorId);
          const hexInput = document.getElementById(`${colorId}-hex`);
          const hslInput = document.getElementById(`${colorId}-hsl`);
          const configKey = configKeys[index];
          
          if (colorInput && hexInput && hslInput) {
            colorInput.value = gradientConfig[configKey];
            hexInput.value = gradientConfig[configKey];
            hslInput.value = `hsl(${hexToHsl(gradientConfig[configKey]).h}, ${hexToHsl(gradientConfig[configKey]).s}%, ${hexToHsl(gradientConfig[configKey]).l}%)`;
            
            hexInput.classList.remove('invalid');
            hslInput.classList.remove('invalid');
            
            const colorPickerContainer = colorInput.closest('.color-row').querySelector('.color-picker-container');
            if (colorPickerContainer) {
              colorPickerContainer.style.setProperty('--selected-color', gradientConfig[configKey]);
            }
          }
        });
      }

      function initializeUI() {
        initGradientEssence();
        
        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-essence');
        });

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

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

        document.getElementById('randomize-gradient').addEventListener('click', () => {
          generateRandomGradient();
        });

        const backgroundPicker = document.getElementById('preview-background-picker');
        const previewContainer = document.getElementById('gradient-preview');

        backgroundPicker.addEventListener('input', (e) => {
          const selectedColor = e.target.value;
          previewContainer.style.backgroundColor = selectedColor;
          
          showNotification(`Preview background changed to ${selectedColor}`);
        });

        previewContainer.style.backgroundColor = '#1a1a1a';

        document.getElementById('reset-colors').addEventListener('click', () => {
          gradientConfig.gradient1 = defaultConfig.gradient1;
          gradientConfig.gradient2 = defaultConfig.gradient2;
          gradientConfig.gradient3 = defaultConfig.gradient3;
          
          document.getElementById('gradient-color1').value = defaultConfig.gradient1;
          document.getElementById('gradient-color2').value = defaultConfig.gradient2;
          document.getElementById('gradient-color3').value = defaultConfig.gradient3;
          
          updateColorInputs();
          updateGradientPreview();
          showNotification('Colors reset to default');
        });

        document.getElementById('reset-animation').addEventListener('click', () => {
          gradientConfig.duration = defaultConfig.duration;
          gradientConfig.speed = defaultConfig.speed;
          gradientConfig.intensity = defaultConfig.intensity;
          
          document.getElementById('duration').value = defaultConfig.duration;
          document.getElementById('speed').value = defaultConfig.speed;
          document.getElementById('intensity').value = defaultConfig.intensity;
          
          document.getElementById('duration-value').textContent = defaultConfig.duration;
          document.getElementById('speed-value').textContent = defaultConfig.speed;
          document.getElementById('intensity-value').textContent = defaultConfig.intensity;
          
          updateGradientPreview();
          showNotification('Animation settings reset');
        });



        const colors = ['gradient-color1', 'gradient-color2', 'gradient-color3'];
        const configKeys = ['gradient1', 'gradient2', 'gradient3'];
        
        colors.forEach((colorId, index) => {
          const colorInput = document.getElementById(colorId);
          const hexInput = document.getElementById(`${colorId}-hex`);
          const hslInput = document.getElementById(`${colorId}-hsl`);
          const configKey = configKeys[index];
          
          hslInput.value = `hsl(${hexToHsl(colorInput.value).h}, ${hexToHsl(colorInput.value).s}%, ${hexToHsl(colorInput.value).l}%)`;
          
          colorInput.addEventListener('input', () => {
            const color = colorInput.value;
            hexInput.value = color;
            hslInput.value = `hsl(${hexToHsl(color).h}, ${hexToHsl(color).s}%, ${hexToHsl(color).l}%)`;
            hexInput.classList.remove('invalid');
            hslInput.classList.remove('invalid');
            gradientConfig[configKey] = color;
            
            const colorPickerContainer = colorInput.closest('.color-row').querySelector('.color-picker-container');
            colorPickerContainer.style.setProperty('--selected-color', color);
            
            updateGradientPreview();
          });
          
          hexInput.addEventListener('input', (e) => {
            let hex = e.target.value;
            
            hex = formatHex(hex);
            e.target.value = hex;
            
            if (isValidHex(hex)) {
              colorInput.value = hex;
              hslInput.value = `hsl(${hexToHsl(hex).h}, ${hexToHsl(hex).s}%, ${hexToHsl(hex).l}%)`;
              gradientConfig[configKey] = hex;
              e.target.classList.remove('invalid');
              hslInput.classList.remove('invalid');
              
              const colorPickerContainer = colorInput.closest('.color-row').querySelector('.color-picker-container');
              colorPickerContainer.style.setProperty('--selected-color', hex);
              
              updateGradientPreview();
            } else {
              e.target.classList.add('invalid');
            }
          });
          
          hexInput.addEventListener('blur', (e) => {
            if (!isValidHex(e.target.value)) {
              e.target.value = colorInput.value;
              e.target.classList.remove('invalid');
            }
          });
          
          hslInput.addEventListener('input', (e) => {
            let hsl = e.target.value;
            
            if (isValidHsl(hsl)) {
              const hex = hslToHex(hsl);
              if (hex) {
                colorInput.value = hex;
                hexInput.value = hex;
                gradientConfig[configKey] = hex;
                e.target.classList.remove('invalid');
                hexInput.classList.remove('invalid');
                
                const colorPickerContainer = colorInput.closest('.color-row').querySelector('.color-picker-container');
                colorPickerContainer.style.setProperty('--selected-color', hex);
                
                updateGradientPreview();
                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) {
                  colorInput.value = hex;
                  hexInput.value = hex;
                  gradientConfig[configKey] = hex;
                  e.target.classList.remove('invalid');
                  hexInput.classList.remove('invalid');
                  updateGradientPreview();
                  return;
                }
              }
            }
            
            if (!isValidHsl(e.target.value)) {
              e.target.value = `hsl(${hexToHsl(colorInput.value).h}, ${hexToHsl(colorInput.value).s}%, ${hexToHsl(colorInput.value).l}%)`;
              e.target.classList.remove('invalid');
            }
          });
        });

        const rangeInputs = document.querySelectorAll('input[type="range"]');
        rangeInputs.forEach(input => {
          const valueElement = document.getElementById(`${input.id}-value`);
          
          if (valueElement) {
            valueElement.textContent = input.value;
          }
          
          input.addEventListener('input', () => {
            if (valueElement) {
              valueElement.textContent = input.value;
            }
            
            switch (input.id) {
              case 'duration':
                gradientConfig.duration = input.value;
                break;
              case 'speed':
                gradientConfig.speed = input.value;
                break;
              case 'intensity':
                gradientConfig.intensity = input.value;
                break;
            }
            
            updateGradientPreview();
          });
        });



        document.addEventListener('keydown', (e) => {
          if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') {
            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':
                generateRandomGradient();
                break;
              case 'b':
                document.getElementById('preview-background-picker').click();
                break;
            }
          }
        });

        updateColorInputs();
        updateGradientPreview();
        
        setTimeout(() => {
          showNotification('BricksFusion Gradient Essence Configurator loaded!');
        }, 500);

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

        function loadConfiguration() {
          try {
            const saved = localStorage.getItem('bricksfusion-gradient-config');
            if (saved) {
              const savedConfig = JSON.parse(saved);
              Object.assign(gradientConfig, savedConfig);
              gradientConfig.direction = '90';
              
              document.getElementById('gradient-color1').value = savedConfig.gradient1;
              document.getElementById('gradient-color2').value = savedConfig.gradient2;
              document.getElementById('gradient-color3').value = savedConfig.gradient3;
              document.getElementById('duration').value = savedConfig.duration;
              document.getElementById('speed').value = savedConfig.speed;
              document.getElementById('intensity').value = savedConfig.intensity;
              
              document.getElementById('duration-value').textContent = savedConfig.duration;
              document.getElementById('speed-value').textContent = savedConfig.speed;
              document.getElementById('intensity-value').textContent = savedConfig.intensity;
              
              updateColorInputs();
              updateGradientPreview();
            }
          } catch (e) {
          }
        }

        const originalUpdateGradientPreview = updateGradientPreview;
        updateGradientPreview = function() {
          originalUpdateGradientPreview();
          saveConfiguration();
        };

        loadConfiguration();
      }
      
      initializeUI();
    });
  </script>
</body>
</html>
Essence Button - Bricksfusion
LIGHTWEIGHT

Essence Button

Adds an animated gradient background to any button. The gradient flows continuously and speeds up on hover. Perfect for CTAs, primary actions, or making buttons stand out with motion.

Colors

Color 1 color picker

First color in the gradient. This is the starting point of the animation flow.

Default: #3498db (blue)

Color 2 color picker

Second color in the gradient. Creates the middle transition point.

Default: #2ecc71 (green)

Color 3 color picker

Third color in the gradient. Adds complexity and loops back to color 1 for smooth animation.

Default: #e74c3c (red)

Animation

Duration 1-10 seconds

How long one complete gradient cycle takes. Lower is faster, higher is slower and more subtle.

Default: 3

Hover Speed 0.5-5 seconds

Animation duration when hovering. Usually faster than normal duration for interactive feedback.

Default: 2

Direction 0-360 degrees

Angle of the gradient. 0 is horizontal right, 90 is vertical down, 180 is horizontal left, 270 is vertical up.

Default: 90

Intensity 0.0-1.0

Opacity of the gradient effect. Lower values make it more subtle, higher values make it vibrant.

Default: 1

Performance

This element uses CSS animations with ::before pseudo-elements for hardware-accelerated performance. The gradient animation runs on the GPU. Respects prefers-reduced-motion for accessibility. No JavaScript animation loops - just pure CSS.