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>Ambient Gradient 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 styling like Aura Flow */
.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, #ee7752);
  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;
}

.switch-container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.2rem;
  padding: 0.5rem 0;
}

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

.switch {
  position: relative;
  display: inline-block;
  width: 52px;
  height: 28px;
}

.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: var(--track);
  transition: var(--transition);
  border-radius: 34px;
}

.slider:before {
  position: absolute;
  content: "";
  height: 20px;
  width: 20px;
  left: 4px;
  bottom: 4px;
  background-color: #f2f2f7;
  transition: var(--transition);
  border-radius: 50%;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}

input:checked + .slider {
  background-color: var(--accent);
}

input:checked + .slider:before {
  transform: translateX(24px);
}

.quick-actions {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1.5rem;
}

.quick-action-btn {
  flex: 1;
  padding: 0.6rem;
  background-color: rgba(30, 30, 30, 0.7);
  border: 1px solid var(--border);
  border-radius: var(--input-radius);
  color: var(--text-secondary);
  cursor: pointer;
  transition: var(--transition);
  font-size: var(--text-xs);
  text-align: center;
}

.quick-action-btn:hover {
  background-color: var(--accent);
  color: white;
  border-color: var(--accent);
}

.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">Ambient Gradient</span>
    </nav>
    
    <div class="action-buttons">
      <div class="data-attribute-display" id="quick-attribute" title="Click to copy data attribute">
        data-ambient-gradient
      </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">Ambient Gradient</h1>
      <p class="page-subtitle">Interactive gradient backgrounds 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 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-ambient-gradient</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" data-ambient-gradient="true">
          <div class="preview-content">Interactive Gradient Preview</div>
          <div class="preview-controls">
            <button class="preview-btn" id="randomize-gradient" title="Randomize (R)">🎲</button>
          </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">
                  <input type="color" id="color1" value="#ee7752">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HEX</span>
                  <input type="text" class="color-input hex-input" id="color1-hex" value="#ee7752" placeholder="#FFFFFF">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HSL</span>
                  <input type="text" class="color-input hsl-input" id="color1-hsl" placeholder="hsl(0, 100%, 50%)">
                </div>
              </div>
              
              <div class="color-row">
                <div class="color-picker-container">
                  <input type="color" id="color2" value="#e73c7e">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HEX</span>
                  <input type="text" class="color-input hex-input" id="color2-hex" value="#e73c7e" placeholder="#FFFFFF">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HSL</span>
                  <input type="text" class="color-input hsl-input" id="color2-hsl" placeholder="hsl(0, 100%, 50%)">
                </div>
              </div>
              
              <div class="color-row">
                <div class="color-picker-container">
                  <input type="color" id="color3" value="#23a6d5">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HEX</span>
                  <input type="text" class="color-input hex-input" id="color3-hex" value="#23a6d5" placeholder="#FFFFFF">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HSL</span>
                  <input type="text" class="color-input hsl-input" id="color3-hsl" placeholder="hsl(0, 100%, 50%)">
                </div>
              </div>
              
              <div class="color-row">
                <div class="color-picker-container">
                  <input type="color" id="color4" value="#23d5ab">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HEX</span>
                  <input type="text" class="color-input hex-input" id="color4-hex" value="#23d5ab" placeholder="#FFFFFF">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HSL</span>
                  <input type="text" class="color-input hsl-input" id="color4-hsl" placeholder="hsl(0, 100%, 50%)">
                </div>
              </div>
            </div>
            
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">
                  Gradient Angle
                  <span class="help-tooltip" title="Controls the direction of the gradient">ℹ</span>
                </span>
                <div class="value-display">
                  <span class="value-text"><span id="angle-value">45</span>°</span>
                  <button class="reset-btn" onclick="resetParameter('gradient-angle', 45)">↺</button>
                </div>
              </div>
              <input type="range" id="gradient-angle" min="0" max="360" value="45">
            </div>
            
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">
                  Background Size
                  <span class="help-tooltip" title="Larger values create more dramatic effects">ℹ</span>
                </span>
                <div class="value-display">
                  <span class="value-text"><span id="bg-size-value">400</span>%</span>
                  <button class="reset-btn" onclick="resetParameter('bg-size', 400)">↺</button>
                </div>
              </div>
              <input type="range" id="bg-size" min="100" max="800" value="400" step="50">
            </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="switch-container">
              <span class="switch-label">
                Auto Animation
                <span class="help-tooltip" title="Enable automatic movement without mouse interaction">ℹ</span>
              </span>
              <label class="switch">
                <input type="checkbox" id="auto-animate">
                <span class="slider"></span>
              </label>
            </div>
            
            <div id="auto-animation-settings">
              <div class="control-group">
                <div class="control-label">
                  <span class="label-text">Animation Speed</span>
                  <div class="value-display">
                    <span class="value-text" id="auto-speed-value">0.005</span>
                    <button class="reset-btn" onclick="resetParameter('auto-speed', 0.005)">↺</button>
                  </div>
                </div>
                <input type="range" id="auto-speed" min="0.001" max="0.01" step="0.001" value="0.005">
              </div>
            </div>
            
            <div id="mouse-animation-settings">
              <div class="control-group">
                <div class="control-label">
                  <span class="label-text">Mouse Influence</span>
                  <div class="value-display">
                    <span class="value-text" id="mouse-influence-value">100</span>%</span>
                    <button class="reset-btn" onclick="resetParameter('mouse-influence', 100)">↺</button>
                  </div>
                </div>
                <input type="range" id="mouse-influence" min="0" max="100" value="100">
              </div>
              
              <div class="control-group">
                <div class="control-label">
                  <span class="label-text">Idle Animation Speed</span>
                  <div class="value-display">
                    <span class="value-text" id="idle-speed-value">0.05</span>
                    <button class="reset-btn" onclick="resetParameter('idle-speed', 0.05)">↺</button>
                  </div>
                </div>
                <input type="range" id="idle-speed" min="0.01" max="0.2" step="0.01" value="0.05">
              </div>
            </div>
            
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">Transition Smoothness</span>
                <div class="value-display">
                  <span class="value-text" id="smoothness-value">0.5</span>s</span>
                  <button class="reset-btn" onclick="resetParameter('transition-smoothness', 0.5)">↺</button>
                </div>
              </div>
              <input type="range" id="transition-smoothness" min="0" max="2" 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">Z-Index Position</span>
                <div class="value-display">
                  <span class="value-text" id="z-index-value">1</span>
                  <button class="reset-btn" onclick="resetParameter('z-index', 1)">↺</button>
                </div>
              </div>
              <input type="range" id="z-index" min="-10" max="10" value="1" step="1">
            </div>
            
            <div class="switch-container">
              <span class="switch-label">Keep Content Centered</span>
              <label class="switch">
                <input type="checkbox" id="center-content" checked>
                <span class="slider"></span>
              </label>
            </div>
            
            <div class="switch-container">
              <span class="switch-label">Border Radius Inherit</span>
              <label class="switch">
                <input type="checkbox" id="border-radius-inherit" checked>
                <span class="slider"></span>
              </label>
            </div>
          </div>
        </div>
      </section>
    </div>
  </div>



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



  <script>
    document.addEventListener('DOMContentLoaded', function() {
      let gradientConfig = {
        colors: ['#ee7752', '#e73c7e', '#23a6d5', '#23d5ab'],
        angle: 45,
        backgroundSize: 400,
        autoAnimate: false,
        autoSpeed: 0.005,
        mouseInfluence: 100,
        idleSpeed: 0.05,
        transitionSmoothness: 0.5,
        zIndex: 1,
        centerContent: true,
        borderRadiusInherit: true
      };

      const defaultConfig = { ...gradientConfig };


      
      let activeGradient = null;
      
      function initAmbientGradient() {
        const sections = document.querySelectorAll('[data-ambient-gradient]:not([data-ambient-initialized="true"])');
        
        sections.forEach((section) => {
          const isAutoAnimate = section.hasAttribute('data-ambient-gradient-auto') || gradientConfig.autoAnimate;
          
          let colors = [];
          for (let i = 1; i <= 4; i++) {
            const colorAttr = `data-ambient-gradient-color${i}`;
            if (section.hasAttribute(colorAttr)) {
              colors.push(section.getAttribute(colorAttr));
            }
          }
          
          if (colors.length === 0) {
            colors = gradientConfig.colors;
          }
          
          const angle = section.hasAttribute('data-ambient-gradient-angle') 
            ? parseFloat(section.getAttribute('data-ambient-gradient-angle')) 
            : gradientConfig.angle;
            
          const bgSize = section.hasAttribute('data-ambient-gradient-size') 
            ? parseFloat(section.getAttribute('data-ambient-gradient-size')) 
            : gradientConfig.backgroundSize;
            
          const autoSpeed = section.hasAttribute('data-ambient-gradient-auto-speed') 
            ? parseFloat(section.getAttribute('data-ambient-gradient-auto-speed')) 
            : gradientConfig.autoSpeed;
            
          const mouseInfluence = section.hasAttribute('data-ambient-gradient-mouse-influence') 
            ? parseFloat(section.getAttribute('data-ambient-gradient-mouse-influence')) 
            : gradientConfig.mouseInfluence / 100;
            
          const idleSpeed = section.hasAttribute('data-ambient-gradient-idle-speed') 
            ? parseFloat(section.getAttribute('data-ambient-gradient-idle-speed')) 
            : gradientConfig.idleSpeed;
            
          const transitionSmoothness = section.hasAttribute('data-ambient-gradient-transition') 
            ? parseFloat(section.getAttribute('data-ambient-gradient-transition')) 
            : gradientConfig.transitionSmoothness;
            
          const zIndex = section.hasAttribute('data-ambient-gradient-z-index') 
            ? parseInt(section.getAttribute('data-ambient-gradient-z-index')) 
            : gradientConfig.zIndex;
            
          const centerContent = section.hasAttribute('data-ambient-gradient-center') 
            ? section.getAttribute('data-ambient-gradient-center') === 'true' 
            : gradientConfig.centerContent;
            
          const borderRadiusInherit = section.hasAttribute('data-ambient-gradient-border-inherit') 
            ? section.getAttribute('data-ambient-gradient-border-inherit') === 'true' 
            : gradientConfig.borderRadiusInherit;
            
          const options = {
            colors,
            angle,
            backgroundSize: bgSize,
            autoAnimate: isAutoAnimate,
            autoSpeed,
            mouseInfluence,
            idleSpeed,
            transitionSmoothness,
            zIndex,
            centerContent,
            borderRadiusInherit
          };
          
          const state = {
            mouseX: 0.5,
            mouseY: 0.5,
            targetX: 0.5,
            targetY: 0.5,
            isMouseInside: false,
            isAutoAnimate: isAutoAnimate
          };
          
          setupGradient(section, options);
          
          if (!isAutoAnimate) {
            setupEventListeners(section, state, options);
          }
          
          startAnimation(section, state, options);
          section.dataset.ambientInitialized = 'true';
          
          if (section.id === 'gradient-preview') {
            activeGradient = { element: section, state, options };
            gradientConfig = {
              colors: options.colors,
              angle: options.angle,
              backgroundSize: options.backgroundSize,
              autoAnimate: options.autoAnimate,
              autoSpeed: options.autoSpeed,
              mouseInfluence: options.mouseInfluence * 100,
              idleSpeed: options.idleSpeed,
              transitionSmoothness: options.transitionSmoothness,
              zIndex: options.zIndex,
              centerContent: options.centerContent,
              borderRadiusInherit: options.borderRadiusInherit
            };
          }
        });
      }
      
      function setupGradient(element, options) {
        const gradientElement = document.createElement('div');
        
        gradientElement.style.position = 'absolute';
        gradientElement.style.top = '0';
        gradientElement.style.left = '0';
        gradientElement.style.width = '100%';
        gradientElement.style.height = '100%';
        gradientElement.style.background = 'linear-gradient(' + options.angle + 'deg, ' + options.colors.join(', ') + ')';
        gradientElement.style.backgroundSize = options.backgroundSize + '% ' + options.backgroundSize + '%';
        gradientElement.style.transition = 'background-position ' + options.transitionSmoothness + 's ease-out';
        gradientElement.style.zIndex = options.zIndex;
        
        if (options.borderRadiusInherit) {
          gradientElement.style.borderRadius = 'inherit';
        }
        
        const computedStyle = window.getComputedStyle(element);
        if (computedStyle.position === 'static') {
          element.style.position = 'relative';
        }
        
        if (element.firstChild) {
          element.insertBefore(gradientElement, element.firstChild);
        } else {
          element.appendChild(gradientElement);
        }
        
        element.gradientElement = gradientElement;
        
        if (options.centerContent) {
          Array.from(element.children).forEach(child => {
            if (child !== gradientElement) {
              if (getComputedStyle(child).position === 'static') {
                child.style.position = 'relative';
              }
              child.style.zIndex = '1';
            }
          });
        }
      }
      
      function setupEventListeners(element, state, options) {
        element.addEventListener('mousemove', (e) => {
          const rect = element.getBoundingClientRect();
          state.mouseX = (e.clientX - rect.left) / rect.width;
          state.mouseY = (e.clientY - rect.top) / rect.height;
          state.isMouseInside = true;
        });
        
        element.addEventListener('mouseleave', () => {
          state.isMouseInside = false;
          state.targetX = Math.random();
          state.targetY = Math.random();
        });
        
        element.addEventListener('mouseenter', () => {
          state.isMouseInside = true;
        });
        
        element.addEventListener('touchmove', (e) => {
          e.preventDefault();
          const touch = e.touches[0];
          const rect = element.getBoundingClientRect();
          state.mouseX = (touch.clientX - rect.left) / rect.width;
          state.mouseY = (touch.clientY - rect.top) / rect.height;
          state.isMouseInside = true;
        }, { passive: false });
        
        element.addEventListener('touchend', () => {
          state.isMouseInside = false;
          state.targetX = Math.random();
          state.targetY = Math.random();
        });
        
        element.addEventListener('focus', () => {
          state.isMouseInside = true;
        });
        
        element.addEventListener('blur', () => {
          state.isMouseInside = false;
          state.targetX = Math.random();
          state.targetY = Math.random();
        });
      }
      
      function startAnimation(element, state, options) {
        let animationFrameId;
        let autoAnimateTime = 0;
        
        function updateGradient() {
          if (state.isAutoAnimate) {
            autoAnimateTime += options.autoSpeed;
            state.mouseX = (Math.sin(autoAnimateTime) + 1) / 2;
            state.mouseY = (Math.cos(autoAnimateTime * 0.8) + 1) / 2;
          } else if (!state.isMouseInside) {
            state.mouseX += (state.targetX - state.mouseX) * options.idleSpeed;
            state.mouseY += (state.targetY - state.mouseY) * options.idleSpeed;
          }
          
          const effectiveX = state.mouseX * options.mouseInfluence + 0.5 * (1 - options.mouseInfluence);
          const effectiveY = state.mouseY * options.mouseInfluence + 0.5 * (1 - options.mouseInfluence);
          
          const posX = effectiveX * 100;
          const posY = effectiveY * 100;
          element.gradientElement.style.backgroundPosition = posX + '% ' + posY + '%';
        }
        
        function smoothUpdate() {
          updateGradient();
          animationFrameId = requestAnimationFrame(smoothUpdate);
        }
        
        smoothUpdate();
        
        const observer = new IntersectionObserver((entries) => {
          entries.forEach(entry => {
            if (entry.isIntersecting) {
              if (!animationFrameId) {
                smoothUpdate();
              }
            } else {
              if (animationFrameId) {
                cancelAnimationFrame(animationFrameId);
                animationFrameId = null;
              }
            }
          });
        }, { threshold: 0 });
        
        observer.observe(element);
        
        element._cleanupGradient = () => {
          if (animationFrameId) {
            cancelAnimationFrame(animationFrameId);
          }
          observer.disconnect();
          if (element.gradientElement && element.gradientElement.parentNode) {
            element.gradientElement.parentNode.removeChild(element.gradientElement);
          }
          element.dataset.ambientInitialized = 'false';
        };
      }
      
      function updateGradientPreview() {
        const previews = ['gradient-preview'];
        
        previews.forEach(previewId => {
          const preview = document.getElementById(previewId);
          if (!preview) return;
          
          if (preview._cleanupGradient) {
            preview._cleanupGradient();
          }
          
          preview.setAttribute('data-ambient-gradient', 'true');
          
          if (gradientConfig.autoAnimate) {
            preview.setAttribute('data-ambient-gradient-auto', 'true');
          } else {
            preview.removeAttribute('data-ambient-gradient-auto');
          }
          
          for (let i = 0; i < gradientConfig.colors.length; i++) {
            preview.setAttribute(`data-ambient-gradient-color${i+1}`, gradientConfig.colors[i]);
          }
          
          preview.setAttribute('data-ambient-gradient-angle', gradientConfig.angle);
          preview.setAttribute('data-ambient-gradient-size', gradientConfig.backgroundSize);
          preview.setAttribute('data-ambient-gradient-auto-speed', gradientConfig.autoSpeed);
          preview.setAttribute('data-ambient-gradient-mouse-influence', gradientConfig.mouseInfluence / 100);
          preview.setAttribute('data-ambient-gradient-idle-speed', gradientConfig.idleSpeed);
          preview.setAttribute('data-ambient-gradient-transition', gradientConfig.transitionSmoothness);
          preview.setAttribute('data-ambient-gradient-z-index', gradientConfig.zIndex);
          preview.setAttribute('data-ambient-gradient-center', gradientConfig.centerContent);
          preview.setAttribute('data-ambient-gradient-border-inherit', gradientConfig.borderRadiusInherit);
        });
        
        initAmbientGradient();
      }

      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) {
        // Extraer valores de la cadena 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; // achromatic
        } 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) {
        // Remover espacios y caracteres no válidos
        let hex = value.replace(/[^0-9A-Fa-f#]/g, '');
        
        // Agregar # si no lo tiene
        if (!hex.startsWith('#')) {
          hex = '#' + hex;
        }
        
        // Limitar a 7 caracteres (#RRGGBB)
        if (hex.length > 7) {
          hex = hex.substring(0, 7);
        }
        
        return hex.toUpperCase();
      }

      function formatHsl(value) {
        // Limpiar la cadena y extraer números
        const cleanValue = value.replace(/[^\d,\s]/g, '');
        const numbers = cleanValue.match(/\d+/g);
        
        if (!numbers || numbers.length < 3) {
          // Si no hay suficientes números, intentar extraer de formato parcial
          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}`;
        
        // Forzar un reflow para asegurar que el estado inicial se aplique
        notification.offsetHeight;
        
        // Mostrar la notificación
        notification.style.visibility = 'visible';
        notification.classList.add('show');
        
        setTimeout(() => {
          notification.classList.remove('show');
          
          // Asegurar que esté completamente oculta después de la animación
          setTimeout(() => {
            if (!notification.classList.contains('show')) {
              notification.style.visibility = 'hidden';
            }
          }, 400);
        }, 3000);
      }

      // Función para generar IDs únicos de 6 caracteres
function generateUniqueId() {
  return Math.random().toString(36).substring(2, 8);
}

function generateFullSectionJSON() {
  // Generar IDs únicos para todos los elementos
  const sectionId = generateUniqueId();
  const container1Id = generateUniqueId();
  const block1Id = generateUniqueId();
  const div1Id = generateUniqueId();
  const textBasic1Id = generateUniqueId();
  const div2Id = generateUniqueId();
  const headingId = generateUniqueId();
  const textBasic2Id = generateUniqueId();
  const container2Id = generateUniqueId();
  const block2Id = generateUniqueId();
  const div3Id = generateUniqueId();
  const textBasic3Id = generateUniqueId();
  const textBasic4Id = generateUniqueId();
  const textBasic5Id = generateUniqueId();
  const div4Id = generateUniqueId();
  const textBasic6Id = generateUniqueId();
  const textBasic7Id = generateUniqueId();
  const textBasic8Id = generateUniqueId();
  const div5Id = generateUniqueId();
  const textBasic9Id = generateUniqueId();
  const textBasic10Id = generateUniqueId();
  const textBasic11Id = generateUniqueId();
  const div6Id = generateUniqueId();
  const textBasic12Id = generateUniqueId();
  const codeId = 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": [container1Id, container2Id, codeId],
        "settings": {
          "_justifyContent": "center",
          "_background": {"color": {"hex": "#ffffff"}},
          "_padding": {"top": "100", "right": "20", "bottom": "100", "left": "20"},
          "_height:mobile_landscape": "auto",
          "_padding:mobile_landscape": {"top": "50", "bottom": "50"}
        },
        "label": "Card 023"
      },
      {
        "id": container1Id,
        "name": "container",
        "parent": sectionId,
        "children": [block1Id],
        "settings": {
          "_rowGap": "50"
        }
      },
      {
        "id": block1Id,
        "name": "block",
        "parent": container1Id,
        "children": [div1Id, div2Id],
        "settings": {
          "_rowGap": "30"
        }
      },
      {
        "id": div1Id,
        "name": "div",
        "parent": block1Id,
        "children": [textBasic1Id],
        "settings": {}
      },
      {
        "id": textBasic1Id,
        "name": "text-basic",
        "parent": div1Id,
        "children": [],
        "settings": {
          "text": "SERVICES",
          "tag": "span",
          "_typography": {
            "color": {"hex": "#575757"},
            "font-size": "14",
            "font-weight": "400"
          }
        }
      },
      {
        "id": div2Id,
        "name": "div",
        "parent": block1Id,
        "children": [headingId, textBasic2Id],
        "settings": {
          "_display": "flex",
          "_direction": "column",
          "_rowGap": "20"
        }
      },
      {
        "id": headingId,
        "name": "heading",
        "parent": div2Id,
        "children": [],
        "settings": {
          "text": "WHAT WE <span style=\"background:linear-gradient(90deg,purple,pink);-webkit-background-clip:text;color:transparent\">CRAFT</span>",
          "_typography": {
            "color": {"hex": "#000000"},
            "font-weight": "500",
            "font-size": "var(--h1)"
          }
        }
      },
      {
        "id": textBasic2Id,
        "name": "text-basic",
        "parent": div2Id,
        "children": [],
        "settings": {
          "text": "Three essential experiences that transform ideas into reality. Each service designed to push boundaries and create something extraordinary.\n\n",
          "tag": "p",
          "_typography": {
            "color": {"hex": "#000000"},
            "font-weight": "300",
            "font-size": "18"
          }
        }
      },
      {
        "id": container2Id,
        "name": "container",
        "parent": sectionId,
        "children": [block2Id],
        "settings": {}
      },
      {
        "id": block2Id,
        "name": "block",
        "parent": container2Id,
        "children": [div3Id, div5Id],
        "settings": {
          "_display": "grid",
          "_gridTemplateColumns": "1fr 1fr",
          "_gridGap": "30",
          "_gridTemplateColumns:mobile_landscape": "1fr"
        }
      },
      {
        "id": div3Id,
        "name": "div",
        "parent": block2Id,
        "children": [textBasic3Id, textBasic4Id, textBasic5Id, div4Id],
        "settings": {
          "_display": "flex",
          "_direction": "column",
          "_rowGap": "20",
          "_padding": {"top": "20", "right": "20", "bottom": "20", "left": "20"},
          "_border": {"radius": {"top": "15", "right": "15", "bottom": "15", "left": "15"}},
          "_attributes": [{"id": generateUniqueId(), "name": "data-ambient-gradient"}],
          "_justifyContent": "space-between"
        },
        "label": "Card 1"
      },
      {
        "id": textBasic3Id,
        "name": "text-basic",
        "parent": div3Id,
        "children": [],
        "settings": {
          "text": "01 — DIGITAL IDENTITY",
          "_typography": {
            "color": {"hex": "#f2a1e9"},
            "font-weight": "300",
            "font-size": "15"
          },
          "tag": "span"
        }
      },
      {
        "id": textBasic4Id,
        "name": "text-basic",
        "parent": div3Id,
        "children": [],
        "settings": {
          "text": "Brand Universe",
          "_typography": {
            "color": {"hex": "#ffffff"},
            "font-weight": "600",
            "font-size": "30"
          },
          "tag": "span"
        }
      },
      {
        "id": textBasic5Id,
        "name": "text-basic",
        "parent": div3Id,
        "children": [],
        "settings": {
          "text": "Complete visual identity systems that live and breathe across every touchpoint. From logo to motion, we create cohesive brand experiences.",
          "tag": "p",
          "_typography": {
            "color": {"hex": "#ffffff"},
            "font-weight": "300",
            "font-size": "18"
          }
        }
      },
      {
        "id": div4Id,
        "name": "div",
        "parent": div3Id,
        "children": [textBasic6Id, textBasic7Id, textBasic8Id],
        "settings": {
          "_display": "flex",
          "_columnGap": "20"
        }
      },
      {
        "id": textBasic6Id,
        "name": "text-basic",
        "parent": div4Id,
        "children": [],
        "settings": {
          "text": "Logo Design",
          "tag": "span",
          "_typography": {
            "color": {"hex": "#ffffff"},
            "font-size": "14",
            "font-weight": "400"
          },
          "_padding": {"left": "15", "right": "15", "top": "0", "bottom": "0"},
          "_border": {"radius": {"top": "15", "right": "15", "bottom": "15", "left": "15"}},
          "_background": {"color": {"hex": "#000000", "rgb": "rgba(0, 0, 0, 0.2)", "hsl": "hsla(0, 0%, 0%, 0.2)"}}
        }
      },
      {
        "id": textBasic7Id,
        "name": "text-basic",
        "parent": div4Id,
        "children": [],
        "settings": {
          "text": "Brand Guidelines",
          "tag": "span",
          "_typography": {
            "color": {"hex": "#ffffff"},
            "font-size": "14",
            "font-weight": "400"
          },
          "_padding": {"left": "15", "right": "15", "top": "0", "bottom": "0"},
          "_border": {"radius": {"top": "15", "right": "15", "bottom": "15", "left": "15"}},
          "_background": {"color": {"hex": "#000000", "rgb": "rgba(0, 0, 0, 0.2)", "hsl": "hsla(0, 0%, 0%, 0.2)"}}
        }
      },
      {
        "id": textBasic8Id,
        "name": "text-basic",
        "parent": div4Id,
        "children": [],
        "settings": {
          "text": "Motion Graphics",
          "tag": "span",
          "_typography": {
            "color": {"hex": "#ffffff"},
            "font-size": "14",
            "font-weight": "400"
          },
          "_padding": {"left": "15", "right": "15", "top": "0", "bottom": "0"},
          "_border": {"radius": {"top": "15", "right": "15", "bottom": "15", "left": "15"}},
          "_background": {"color": {"hex": "#000000", "rgb": "rgba(0, 0, 0, 0.2)", "hsl": "hsla(0, 0%, 0%, 0.2)"}}
        }
      },
      {
        "id": div5Id,
        "name": "div",
        "parent": block2Id,
        "children": [textBasic9Id, textBasic10Id, textBasic11Id, div6Id],
        "settings": {
          "_display": "flex",
          "_direction": "column",
          "_rowGap": "20",
          "_padding": {"top": "20", "right": "20", "bottom": "20", "left": "20"},
          "_border": {"radius": {"top": "15", "right": "15", "bottom": "15", "left": "15"}},
          "_attributes": [{"id": generateUniqueId(), "name": "data-ambient-gradient"}],
          "_justifyContent": "space-between"
        },
        "label": "Card 2"
      },
      {
        "id": textBasic9Id,
        "name": "text-basic",
        "parent": div5Id,
        "children": [],
        "settings": {
          "text": "02 — DIGITAL PRESENCE",
          "_typography": {
            "color": {"hex": "#f2a1e9"},
            "font-weight": "300",
            "font-size": "15"
          },
          "tag": "span"
        }
      },
      {
        "id": textBasic10Id,
        "name": "text-basic",
        "parent": div5Id,
        "children": [],
        "settings": {
          "text": "Web\nExperiences",
          "_typography": {
            "color": {"hex": "#ffffff"},
            "font-weight": "600",
            "font-size": "30"
          },
          "tag": "span"
        }
      },
      {
        "id": textBasic11Id,
        "name": "text-basic",
        "parent": div5Id,
        "children": [],
        "settings": {
          "text": "Custom websites and web applications that perform beautifully and convert visitors into customers.",
          "tag": "p",
          "_typography": {
            "color": {"hex": "#ffffff"},
            "font-weight": "300",
            "font-size": "18"
          }
        }
      },
      {
        "id": div6Id,
        "name": "div",
        "parent": div5Id,
        "children": [textBasic12Id],
        "settings": {
          "_display": "flex",
          "_columnGap": "20"
        }
      },
      {
        "id": textBasic12Id,
        "name": "text-basic",
        "parent": div6Id,
        "children": [],
        "settings": {
          "text": "$8000+",
          "tag": "span",
          "_typography": {
            "color": {"hex": "#ffffff"},
            "font-weight": "500",
            "font-size": "20"
          }
        }
      },
      {
        "id": codeId,
        "name": "code",
        "parent": sectionId,
        "children": [],
        "settings": {
          "executeCode": true,
          "javascriptCode": jsCode,
          "_display": "none"
        },
        "label": "Ambient Gradient JS"
      }
    ],
    "source": "bricksCopiedElements",
    "sourceUrl": "https://test.bricksfusion.com",
    "version": "2.0.1",
    "globalClasses": [],
    "globalElements": []
  };

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

      function generateJavaScriptCode() {
        const colors = gradientConfig.colors;
        const angle = gradientConfig.angle;
        const bgSize = gradientConfig.backgroundSize;
        const autoAnimate = gradientConfig.autoAnimate;
        const autoSpeed = gradientConfig.autoSpeed;
        const mouseInfluence = gradientConfig.mouseInfluence / 100;
        const idleSpeed = gradientConfig.idleSpeed;
        const transitionSmoothness = gradientConfig.transitionSmoothness;
        const zIndex = gradientConfig.zIndex;
        const centerContent = gradientConfig.centerContent;
        const borderRadiusInherit = gradientConfig.borderRadiusInherit;
        
        return "(function() {\n" +
        "  const defaultConfig = {\n" +
        "    colors: " + JSON.stringify(colors) + ",\n" +
        "    angle: " + angle + ",\n" +
        "    backgroundSize: " + bgSize + ",\n" +
        "    autoAnimate: " + autoAnimate + ",\n" +
        "    autoSpeed: " + autoSpeed + ",\n" +
        "    mouseInfluence: " + mouseInfluence + ",\n" +
        "    idleSpeed: " + idleSpeed + ",\n" +
        "    transitionSmoothness: " + transitionSmoothness + ",\n" +
        "    zIndex: " + zIndex + ",\n" +
        "    centerContent: " + centerContent + ",\n" +
        "    borderRadiusInherit: " + borderRadiusInherit + "\n" +
        "  };\n" +
        "  \n" +
        "  function initAmbientGradient() {\n" +
        "    const sections = document.querySelectorAll('[data-ambient-gradient]:not([data-ambient-initialized=\"true\"])');\n" +
        "    \n" +
        "    sections.forEach((section) => {\n" +
        "      const isAutoAnimate = section.hasAttribute('data-ambient-gradient-auto') || defaultConfig.autoAnimate;\n" +
        "      \n" +
        "      let colors = [];\n" +
        "      for (let i = 1; i <= 4; i++) {\n" +
        "        const colorAttr = 'data-ambient-gradient-color' + i;\n" +
        "        if (section.hasAttribute(colorAttr)) {\n" +
        "          colors.push(section.getAttribute(colorAttr));\n" +
        "        }\n" +
        "      }\n" +
        "      \n" +
        "      if (colors.length === 0) {\n" +
        "        colors = defaultConfig.colors;\n" +
        "      }\n" +
        "      \n" +
        "      const angle = section.hasAttribute('data-ambient-gradient-angle') \n" +
        "        ? parseFloat(section.getAttribute('data-ambient-gradient-angle')) \n" +
        "        : defaultConfig.angle;\n" +
        "        \n" +
        "      const bgSize = section.hasAttribute('data-ambient-gradient-size') \n" +
        "        ? parseFloat(section.getAttribute('data-ambient-gradient-size')) \n" +
        "        : defaultConfig.backgroundSize;\n" +
        "        \n" +
        "      const autoSpeed = section.hasAttribute('data-ambient-gradient-auto-speed') \n" +
        "        ? parseFloat(section.getAttribute('data-ambient-gradient-auto-speed')) \n" +
        "        : defaultConfig.autoSpeed;\n" +
        "        \n" +
        "      const mouseInfluence = section.hasAttribute('data-ambient-gradient-mouse-influence') \n" +
        "        ? parseFloat(section.getAttribute('data-ambient-gradient-mouse-influence')) \n" +
        "        : defaultConfig.mouseInfluence;\n" +
        "        \n" +
        "      const idleSpeed = section.hasAttribute('data-ambient-gradient-idle-speed') \n" +
        "        ? parseFloat(section.getAttribute('data-ambient-gradient-idle-speed')) \n" +
        "        : defaultConfig.idleSpeed;\n" +
        "        \n" +
        "      const transitionSmoothness = section.hasAttribute('data-ambient-gradient-transition') \n" +
        "        ? parseFloat(section.getAttribute('data-ambient-gradient-transition')) \n" +
        "        : defaultConfig.transitionSmoothness;\n" +
        "        \n" +
        "      const zIndex = section.hasAttribute('data-ambient-gradient-z-index') \n" +
        "        ? parseInt(section.getAttribute('data-ambient-gradient-z-index')) \n" +
        "        : defaultConfig.zIndex;\n" +
        "        \n" +
        "      const centerContent = section.hasAttribute('data-ambient-gradient-center') \n" +
        "        ? section.getAttribute('data-ambient-gradient-center') === 'true' \n" +
        "        : defaultConfig.centerContent;\n" +
        "        \n" +
        "      const borderRadiusInherit = section.hasAttribute('data-ambient-gradient-border-inherit') \n" +
        "        ? section.getAttribute('data-ambient-gradient-border-inherit') === 'true' \n" +
        "        : defaultConfig.borderRadiusInherit;\n" +
        "      \n" +
        "      const options = {\n" +
        "        colors,\n" +
        "        angle,\n" +
        "        backgroundSize: bgSize,\n" +
        "        autoAnimate: isAutoAnimate,\n" +
        "        autoSpeed,\n" +
        "        mouseInfluence,\n" +
        "        idleSpeed,\n" +
        "        transitionSmoothness,\n" +
        "        zIndex,\n" +
        "        centerContent,\n" +
        "        borderRadiusInherit\n" +
        "      };\n" +
        "      \n" +
        "      const state = {\n" +
        "        mouseX: 0.5,\n" +
        "        mouseY: 0.5,\n" +
        "        targetX: 0.5,\n" +
        "        targetY: 0.5,\n" +
        "        isMouseInside: false,\n" +
        "        isAutoAnimate: isAutoAnimate\n" +
        "      };\n" +
        "      \n" +
        "      setupGradient(section, options);\n" +
        "      \n" +
        "      if (!isAutoAnimate) {\n" +
        "        setupEventListeners(section, state, options);\n" +
        "      }\n" +
        "      \n" +
        "      startAnimation(section, state, options);\n" +
        "      \n" +
        "      section.dataset.ambientInitialized = 'true';\n" +
        "    });\n" +
        "  }\n" +
        "  \n" +
        "  function setupGradient(element, options) {\n" +
        "    const gradientElement = document.createElement('div');\n" +
        "    \n" +
        "    gradientElement.style.position = 'absolute';\n" +
        "    gradientElement.style.top = '0';\n" +
        "    gradientElement.style.left = '0';\n" +
        "    gradientElement.style.width = '100%';\n" +
        "    gradientElement.style.height = '100%';\n" +
        "    \n" +
        "    gradientElement.style.background = 'linear-gradient(' + options.angle + 'deg, ' + options.colors.join(', ') + ')';\n" +
        "    gradientElement.style.backgroundSize = options.backgroundSize + '% ' + options.backgroundSize + '%';\n" +
        "    gradientElement.style.transition = 'background-position ' + options.transitionSmoothness + 's ease-out';\n" +
        "    gradientElement.style.zIndex = options.zIndex;\n" +
        "    \n" +
        "    if (options.borderRadiusInherit) {\n" +
        "      gradientElement.style.borderRadius = 'inherit';\n" +
        "    }\n" +
        "    \n" +
        "    const computedStyle = window.getComputedStyle(element);\n" +
        "    if (computedStyle.position === 'static') {\n" +
        "      element.style.position = 'relative';\n" +
        "    }\n" +
        "    \n" +
        "    if (element.firstChild) {\n" +
        "      element.insertBefore(gradientElement, element.firstChild);\n" +
        "    } else {\n" +
        "      element.appendChild(gradientElement);\n" +
        "    }\n" +
        "    \n" +
        "    element.gradientElement = gradientElement;\n" +
        "    \n" +
        "    if (options.centerContent) {\n" +
        "      Array.from(element.children).forEach(child => {\n" +
        "        if (child !== gradientElement) {\n" +
        "          if (getComputedStyle(child).position === 'static') {\n" +
        "            child.style.position = 'relative';\n" +
        "          }\n" +
        "          child.style.zIndex = '1';\n" +
        "        }\n" +
        "      });\n" +
        "    }\n" +
        "  }\n" +
        "  \n" +
        "  function setupEventListeners(element, state, options) {\n" +
        "    element.addEventListener('mousemove', (e) => {\n" +
        "      const rect = element.getBoundingClientRect();\n" +
        "      state.mouseX = (e.clientX - rect.left) / rect.width;\n" +
        "      state.mouseY = (e.clientY - rect.top) / rect.height;\n" +
        "      state.isMouseInside = true;\n" +
        "    });\n" +
        "    \n" +
        "    element.addEventListener('mouseleave', () => {\n" +
        "      state.isMouseInside = false;\n" +
        "      state.targetX = Math.random();\n" +
        "      state.targetY = Math.random();\n" +
        "    });\n" +
        "    \n" +
        "    element.addEventListener('mouseenter', () => {\n" +
        "      state.isMouseInside = true;\n" +
        "    });\n" +
        "    \n" +
        "    element.addEventListener('touchmove', (e) => {\n" +
        "      e.preventDefault();\n" +
        "      const touch = e.touches[0];\n" +
        "      const rect = element.getBoundingClientRect();\n" +
        "      state.mouseX = (touch.clientX - rect.left) / rect.width;\n" +
        "      state.mouseY = (touch.clientY - rect.top) / rect.height;\n" +
        "      state.isMouseInside = true;\n" +
        "    }, { passive: false });\n" +
        "    \n" +
        "    element.addEventListener('touchend', () => {\n" +
        "      state.isMouseInside = false;\n" +
        "      state.targetX = Math.random();\n" +
        "      state.targetY = Math.random();\n" +
        "    });\n" +
        "    \n" +
        "    element.addEventListener('focus', () => {\n" +
        "      state.isMouseInside = true;\n" +
        "    });\n" +
        "    \n" +
        "    element.addEventListener('blur', () => {\n" +
        "      state.isMouseInside = false;\n" +
        "      state.targetX = Math.random();\n" +
        "      state.targetY = Math.random();\n" +
        "    });\n" +
        "  }\n" +
        "  \n" +
        "  function startAnimation(element, state, options) {\n" +
        "    let animationFrameId;\n" +
        "    let autoAnimateTime = 0;\n" +
        "    \n" +
        "    function updateGradient() {\n" +
        "      if (state.isAutoAnimate) {\n" +
        "        autoAnimateTime += options.autoSpeed;\n" +
        "        state.mouseX = (Math.sin(autoAnimateTime) + 1) / 2;\n" +
        "        state.mouseY = (Math.cos(autoAnimateTime * 0.8) + 1) / 2;\n" +
        "      } \n" +
        "      else if (!state.isMouseInside) {\n" +
        "        state.mouseX += (state.targetX - state.mouseX) * options.idleSpeed;\n" +
        "        state.mouseY += (state.targetY - state.mouseY) * options.idleSpeed;\n" +
        "      }\n" +
        "      \n" +
        "      const effectiveX = state.mouseX * options.mouseInfluence + 0.5 * (1 - options.mouseInfluence);\n" +
        "      const effectiveY = state.mouseY * options.mouseInfluence + 0.5 * (1 - options.mouseInfluence);\n" +
        "      \n" +
        "      const posX = effectiveX * 100;\n" +
        "      const posY = effectiveY * 100;\n" +
        "      element.gradientElement.style.backgroundPosition = posX + '% ' + posY + '%';\n" +
        "    }\n" +
        "    \n" +
        "    function smoothUpdate() {\n" +
        "      updateGradient();\n" +
        "      animationFrameId = requestAnimationFrame(smoothUpdate);\n" +
        "    }\n" +
        "    \n" +
        "    smoothUpdate();\n" +
        "    \n" +
        "    const observer = new IntersectionObserver((entries) => {\n" +
        "      entries.forEach(entry => {\n" +
        "        if (entry.isIntersecting) {\n" +
        "          if (!animationFrameId) {\n" +
        "            smoothUpdate();\n" +
        "          }\n" +
        "        } else {\n" +
        "          if (animationFrameId) {\n" +
        "            cancelAnimationFrame(animationFrameId);\n" +
        "            animationFrameId = null;\n" +
        "          }\n" +
        "        }\n" +
        "      });\n" +
        "    }, { threshold: 0 });\n" +
        "    \n" +
        "    observer.observe(element);\n" +
        "    \n" +
        "    element._cleanupGradient = () => {\n" +
        "      if (animationFrameId) {\n" +
        "        cancelAnimationFrame(animationFrameId);\n" +
        "      }\n" +
        "      observer.disconnect();\n" +
        "      if (element.gradientElement && element.gradientElement.parentNode) {\n" +
        "        element.gradientElement.parentNode.removeChild(element.gradientElement);\n" +
        "      }\n" +
        "      element.dataset.ambientInitialized = 'false';\n" +
        "    };\n" +
        "  }\n" +
        "  \n" +
        "  if (document.readyState === 'loading') {\n" +
        "    document.addEventListener('DOMContentLoaded', initAmbientGradient);\n" +
        "  } else {\n" +
        "    initAmbientGradient();\n" +
        "  }\n" +
        "  \n" +
        "  document.addEventListener('bricks-lazy-load', initAmbientGradient);\n" +
        "})();";
      }



      function copyJsToClipboard() {
        const jsCode = generateJavaScriptCode();
        
        navigator.clipboard.writeText(jsCode)
          .then(() => {
            showNotification('JavaScript code copied to clipboard!');
          })
          .catch(err => {
            // Fallback para navegadores que no soporten clipboard API
            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 => {
            // Fallback para navegadores que no soporten clipboard API
            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 downloadJsFile() {
        const jsCode = generateJavaScriptCode();
        const blob = new Blob([jsCode], { type: 'application/javascript' });
        const url = URL.createObjectURL(blob);
        
        const a = document.createElement('a');
        a.href = url;
        a.download = 'ambient-gradient.js';
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        
        URL.revokeObjectURL(url);
        showNotification('JavaScript file downloaded successfully!');
      }

      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 'gradient-angle':
              gradientConfig.angle = defaultValue;
              break;
            case 'bg-size':
              gradientConfig.backgroundSize = defaultValue;
              break;
            case 'auto-speed':
              gradientConfig.autoSpeed = defaultValue;
              break;
            case 'mouse-influence':
              gradientConfig.mouseInfluence = defaultValue;
              break;
            case 'idle-speed':
              gradientConfig.idleSpeed = defaultValue;
              break;
            case 'transition-smoothness':
              gradientConfig.transitionSmoothness = defaultValue;
              break;
            case 'z-index':
              gradientConfig.zIndex = defaultValue;
              break;
          }
          
          updateGradientPreview();
          showNotification(`${parameterId.replace(/-/g, ' ')} reset to default`);
        }
      };

      function resetAllSettings() {
        gradientConfig = { ...defaultConfig };
        
        document.getElementById('color1').value = defaultConfig.colors[0];
        document.getElementById('color2').value = defaultConfig.colors[1];
        document.getElementById('color3').value = defaultConfig.colors[2];
        document.getElementById('color4').value = defaultConfig.colors[3];
        
        document.getElementById('gradient-angle').value = defaultConfig.angle;
        document.getElementById('bg-size').value = defaultConfig.backgroundSize;
        document.getElementById('auto-animate').checked = defaultConfig.autoAnimate;
        document.getElementById('auto-speed').value = defaultConfig.autoSpeed;
        document.getElementById('mouse-influence').value = defaultConfig.mouseInfluence;
        document.getElementById('idle-speed').value = defaultConfig.idleSpeed;
        document.getElementById('transition-smoothness').value = defaultConfig.transitionSmoothness;
        document.getElementById('z-index').value = defaultConfig.zIndex;
        document.getElementById('center-content').checked = defaultConfig.centerContent;
        document.getElementById('border-radius-inherit').checked = defaultConfig.borderRadiusInherit;
        
        document.getElementById('angle-value').textContent = defaultConfig.angle;
        document.getElementById('bg-size-value').textContent = defaultConfig.backgroundSize;
        document.getElementById('auto-speed-value').textContent = defaultConfig.autoSpeed;
        document.getElementById('mouse-influence-value').textContent = defaultConfig.mouseInfluence;
        document.getElementById('idle-speed-value').textContent = defaultConfig.idleSpeed;
        document.getElementById('smoothness-value').textContent = defaultConfig.transitionSmoothness;
        document.getElementById('z-index-value').textContent = defaultConfig.zIndex;
        
        updateColorInputs();
        updateGradientPreview();
        showNotification('All settings reset to default');
      }

      function generateRandomGradient() {
        const randomColors = Array.from({ length: 4 }, () => generateRandomColor());
        
        gradientConfig.colors = randomColors;
        gradientConfig.angle = Math.floor(Math.random() * 360);
        
        randomColors.forEach((color, index) => {
          const colorInput = document.getElementById(`color${index + 1}`);
          const hexInput = document.getElementById(`color${index + 1}-hex`);
          const hslInput = document.getElementById(`color${index + 1}-hsl`);
          
          colorInput.value = color;
          hexInput.value = color;
          hslInput.value = hexToHsl(color);
          
          // Actualizar el fondo del contenedor del selector de color
          const container = colorInput.closest('.color-picker-container');
          if (container) {
            container.style.setProperty('--current-color', color);
          }
        });
        
        document.getElementById('gradient-angle').value = gradientConfig.angle;
        document.getElementById('angle-value').textContent = gradientConfig.angle;
        
        updateGradientPreview();
        showNotification('Random gradient generated!');
      }

      function updateColorInputs() {
        for (let i = 1; i <= 4; i++) {
          const color = gradientConfig.colors[i - 1];
          const colorInput = document.getElementById(`color${i}`);
          const hexInput = document.getElementById(`color${i}-hex`);
          const hslInput = document.getElementById(`color${i}-hsl`);
          
          if (colorInput && hexInput && hslInput) {
            colorInput.value = color;
            hexInput.value = color;
            hslInput.value = hexToHsl(color);
            
            // Actualizar el fondo del contenedor del selector de color
            const container = colorInput.closest('.color-picker-container');
            if (container) {
              container.style.setProperty('--current-color', color);
            }
            
            // Remover clases de error al actualizar
            hexInput.classList.remove('invalid');
            hslInput.classList.remove('invalid');
          }
        }
      }



      function initializeUI() {
        initAmbientGradient();
        
        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-ambient-gradient');
        });



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

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

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

        document.getElementById('reset-colors').addEventListener('click', () => {
          gradientConfig.colors = [...defaultConfig.colors];
          updateColorInputs();
          updateGradientPreview();
          showNotification('Colors reset to default');
        });



        document.getElementById('reset-animation').addEventListener('click', () => {
          gradientConfig.autoAnimate = defaultConfig.autoAnimate;
          gradientConfig.autoSpeed = defaultConfig.autoSpeed;
          gradientConfig.mouseInfluence = defaultConfig.mouseInfluence;
          gradientConfig.idleSpeed = defaultConfig.idleSpeed;
          gradientConfig.transitionSmoothness = defaultConfig.transitionSmoothness;
          
          document.getElementById('auto-animate').checked = defaultConfig.autoAnimate;
          document.getElementById('auto-speed').value = defaultConfig.autoSpeed;
          document.getElementById('mouse-influence').value = defaultConfig.mouseInfluence;
          document.getElementById('idle-speed').value = defaultConfig.idleSpeed;
          document.getElementById('transition-smoothness').value = defaultConfig.transitionSmoothness;
          
          document.getElementById('auto-speed-value').textContent = defaultConfig.autoSpeed;
          document.getElementById('mouse-influence-value').textContent = defaultConfig.mouseInfluence;
          document.getElementById('idle-speed-value').textContent = defaultConfig.idleSpeed;
          document.getElementById('smoothness-value').textContent = defaultConfig.transitionSmoothness;
          
          updateGradientPreview();
          showNotification('Animation settings reset');
        });

        document.getElementById('reset-advanced').addEventListener('click', () => {
          gradientConfig.zIndex = defaultConfig.zIndex;
          gradientConfig.centerContent = defaultConfig.centerContent;
          gradientConfig.borderRadiusInherit = defaultConfig.borderRadiusInherit;
          
          document.getElementById('z-index').value = defaultConfig.zIndex;
          document.getElementById('center-content').checked = defaultConfig.centerContent;
          document.getElementById('border-radius-inherit').checked = defaultConfig.borderRadiusInherit;
          document.getElementById('z-index-value').textContent = defaultConfig.zIndex;
          
          updateGradientPreview();
          showNotification('Advanced settings reset');
        });

        const colorInputs = document.querySelectorAll('input[type="color"]');
        colorInputs.forEach((input, index) => {
          const colorIndex = index + 1;
          const hexInput = document.getElementById(`color${colorIndex}-hex`);
          const hslInput = document.getElementById(`color${colorIndex}-hsl`);
          
          // Inicializar valores HSL y el fondo del contenedor
          hslInput.value = hexToHsl(input.value);
          
          // Inicializar el fondo del contenedor del selector de color
          const container = input.closest('.color-picker-container');
          if (container) {
            container.style.setProperty('--current-color', input.value);
          }
          
          // Event listener para el selector visual de color
          input.addEventListener('input', () => {
            const color = input.value;
            hexInput.value = color;
            hslInput.value = hexToHsl(color);
            hexInput.classList.remove('invalid');
            hslInput.classList.remove('invalid');
            
            // Actualizar el fondo del contenedor del selector de color
            const container = input.closest('.color-picker-container');
            if (container) {
              container.style.setProperty('--current-color', color);
            }
            
            gradientConfig.colors[index] = color;
            updateGradientPreview();
          });
          
          // Event listener para el input HEX con validación en tiempo real
          hexInput.addEventListener('input', (e) => {
            let hex = e.target.value;
            
            // Auto-formatear mientras se escribe
            hex = formatHex(hex);
            e.target.value = hex;
            
            // Validar y actualizar
            if (isValidHex(hex)) {
              input.value = hex;
              hslInput.value = hexToHsl(hex);
              
              // Actualizar el fondo del contenedor del selector de color
              const container = input.closest('.color-picker-container');
              if (container) {
                container.style.setProperty('--current-color', hex);
              }
              
              gradientConfig.colors[index] = hex;
              e.target.classList.remove('invalid');
              hslInput.classList.remove('invalid');
              updateGradientPreview();
            } 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');
            }
          });
          
          // Event listener para el input HSL con validación en tiempo real
          hslInput.addEventListener('input', (e) => {
            let hsl = e.target.value;
            
            // Validar y actualizar si es válido
            if (isValidHsl(hsl)) {
              const hex = hslToHex(hsl);
              if (hex) {
                input.value = hex;
                hexInput.value = hex;
                
                // Actualizar el fondo del contenedor del selector de color
                const container = input.closest('.color-picker-container');
                if (container) {
                  container.style.setProperty('--current-color', hex);
                }
                
                gradientConfig.colors[index] = hex;
                e.target.classList.remove('invalid');
                hexInput.classList.remove('invalid');
                updateGradientPreview();
                return;
              }
            }
            
            // Si no es válido, marcar como inválido pero permitir seguir escribiendo
            e.target.classList.add('invalid');
          });
          
          hslInput.addEventListener('blur', (e) => {
            let hsl = e.target.value;
            
            // Intentar auto-formatear en el blur
            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;
                  
                  // Actualizar el fondo del contenedor del selector de color
                  const container = input.closest('.color-picker-container');
                  if (container) {
                    container.style.setProperty('--current-color', hex);
                  }
                  
                  gradientConfig.colors[index] = hex;
                  e.target.classList.remove('invalid');
                  hexInput.classList.remove('invalid');
                  updateGradientPreview();
                  return;
                }
              }
            }
            
            // Si sigue siendo inválido, restaurar valor válido
            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;
          
          // Mapear los IDs correctos para los elementos value
          switch (input.id) {
            case 'gradient-angle':
              valueElement = document.getElementById('angle-value');
              break;
            case 'transition-smoothness':
              valueElement = document.getElementById('smoothness-value');
              break;
            default:
              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 'gradient-angle':
                gradientConfig.angle = parseFloat(input.value);
                break;
              case 'bg-size':
                gradientConfig.backgroundSize = parseFloat(input.value);
                break;
              case 'auto-speed':
                gradientConfig.autoSpeed = parseFloat(input.value);
                break;
              case 'mouse-influence':
                gradientConfig.mouseInfluence = parseFloat(input.value);
                break;
              case 'idle-speed':
                gradientConfig.idleSpeed = parseFloat(input.value);
                break;
              case 'transition-smoothness':
                gradientConfig.transitionSmoothness = parseFloat(input.value);
                break;
              case 'z-index':
                gradientConfig.zIndex = parseInt(input.value);
                break;
            }
            
            updateGradientPreview();
          });
        });

        document.getElementById('auto-animate').addEventListener('change', function() {
          gradientConfig.autoAnimate = this.checked;
          
          document.getElementById('auto-animation-settings').style.display = 
            this.checked ? 'block' : 'none';
          document.getElementById('mouse-animation-settings').style.display = 
            this.checked ? 'none' : 'block';
          
          updateGradientPreview();
        });
        
        document.getElementById('center-content').addEventListener('change', function() {
          gradientConfig.centerContent = this.checked;
          updateGradientPreview();
        });
        
        document.getElementById('border-radius-inherit').addEventListener('change', function() {
          gradientConfig.borderRadiusInherit = this.checked;
          updateGradientPreview();
        });

        document.getElementById('auto-animation-settings').style.display = 
          document.getElementById('auto-animate').checked ? 'block' : 'none';
        document.getElementById('mouse-animation-settings').style.display = 
          document.getElementById('auto-animate').checked ? 'none' : 'block';

        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();
                // Verificar protección antes de ejecutar
                const downloadBtn = document.getElementById('download-config');
                if (downloadBtn && downloadBtn.hasAttribute('data-protection-animation')) {
                  // Simular click en el botón para que el backend maneje la protección
                  downloadBtn.click();
                } else {
                  copyJsToClipboard();
                }
                break;
              case 's':
                e.preventDefault();
                // Verificar protección antes de ejecutar
                const fullSectionBtn = document.getElementById('copy-full-section');
                if (fullSectionBtn && fullSectionBtn.hasAttribute('data-protection-animation')) {
                  // Simular click en el botón para que el backend maneje la protección
                  fullSectionBtn.click();
                } else {
                  copyFullSectionToClipboard();
                }
                break;
            }
          } else {
            switch (e.key.toLowerCase()) {
              case 'r':
                generateRandomGradient();
                break;
            }
          }
        });

        updateColorInputs();
        
        setTimeout(() => {
          showNotification('BricksFusion Ambient Gradient 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);
              
              savedConfig.colors.forEach((color, index) => {
                document.getElementById(`color${index + 1}`).value = color;
                document.getElementById(`color${index + 1}-hex`).value = color;
                document.getElementById(`color${index + 1}-hsl`).value = hexToHsl(color);
              });
              
              document.getElementById('gradient-angle').value = savedConfig.angle;
              document.getElementById('bg-size').value = savedConfig.backgroundSize;
              document.getElementById('auto-animate').checked = savedConfig.autoAnimate;
              document.getElementById('auto-speed').value = savedConfig.autoSpeed;
              document.getElementById('mouse-influence').value = savedConfig.mouseInfluence;
              document.getElementById('idle-speed').value = savedConfig.idleSpeed;
              document.getElementById('transition-smoothness').value = savedConfig.transitionSmoothness;
              document.getElementById('z-index').value = savedConfig.zIndex;
              document.getElementById('center-content').checked = savedConfig.centerContent;
              document.getElementById('border-radius-inherit').checked = savedConfig.borderRadiusInherit;
              
              document.getElementById('angle-value').textContent = savedConfig.angle;
              document.getElementById('bg-size-value').textContent = savedConfig.backgroundSize;
              document.getElementById('auto-speed-value').textContent = savedConfig.autoSpeed;
              document.getElementById('mouse-influence-value').textContent = savedConfig.mouseInfluence;
              document.getElementById('idle-speed-value').textContent = savedConfig.idleSpeed;
              document.getElementById('smoothness-value').textContent = savedConfig.transitionSmoothness;
              document.getElementById('z-index-value').textContent = savedConfig.zIndex;
              
              updateGradientPreview();
            }
          } catch (e) {
          }
        }

        const originalUpdateGradientPreview = updateGradientPreview;
        updateGradientPreview = function() {
          originalUpdateGradientPreview();
          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) {
                // Low FPS detected
              }
            }
          }
        };

        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 initDragAndDrop() {
          const colorGrid = document.querySelector('.color-grid');
          
          if (colorGrid) {
            colorGrid.addEventListener('dragover', (e) => {
              e.preventDefault();
              colorGrid.style.backgroundColor = 'rgba(239, 96, 19, 0.1)';
            });
            
            colorGrid.addEventListener('dragleave', () => {
              colorGrid.style.backgroundColor = '';
            });
            
            colorGrid.addEventListener('drop', (e) => {
              e.preventDefault();
              colorGrid.style.backgroundColor = '';
              
              showNotification('Drag & drop feature coming soon!');
            });
          }
        }

        initDragAndDrop();

        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 exportConfiguration() {
          const configData = {
            version: '1.0',
            timestamp: new Date().toISOString(),
            configuration: gradientConfig
          };
          
          const blob = new Blob([JSON.stringify(configData, null, 2)], { type: 'application/json' });
          const url = URL.createObjectURL(blob);
          
          const a = document.createElement('a');
          a.href = url;
          a.download = 'bricksfusion-gradient-config.json';
          document.body.appendChild(a);
          a.click();
          document.body.removeChild(a);
          
          URL.revokeObjectURL(url);
          showNotification('Configuration exported successfully!');
        }

        function importConfiguration(event) {
          const file = event.target.files[0];
          if (!file) return;
          
          const reader = new FileReader();
          reader.onload = (e) => {
            try {
              const configData = JSON.parse(e.target.result);
              if (configData.configuration) {
                Object.assign(gradientConfig, configData.configuration);
                updateColorInputs();
                updateGradientPreview();
                showNotification('Configuration imported successfully!');
              }
            } catch (error) {
              showNotification('Invalid configuration file', 'error');
            }
          };
          reader.readAsText(file);
        }

        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 smoothScrollTo(target) {
          const element = document.querySelector(target);
          if (element) {
            element.scrollIntoView({
              behavior: 'smooth',
              block: 'start'
            });
          }
        }

        function initAccessibility() {
          document.getElementById('gradient-preview').setAttribute('aria-label', 'Ambient gradient 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-configurator-version');
          
          if (storedVersion && storedVersion !== currentVersion) {
            showNotification('Configurator updated!', 'info');
          }
          
          localStorage.setItem('bricksfusion-configurator-version', currentVersion);
        }

        checkVersion();

        function trackEvent(eventName, eventData = {}) {
          // Event tracking (silent)
        }

        document.getElementById('download-config').addEventListener('click', () => {
          trackEvent('download_js', { colors: gradientConfig.colors.length });
        });

        document.getElementById('copy-full-section').addEventListener('click', () => {
          trackEvent('copy_full_section', { colors: gradientConfig.colors.length });
        });

        document.getElementById('randomize-gradient').addEventListener('click', () => {
          trackEvent('randomize_gradient');
        });
      }
      
      initializeUI();
    });
  </script>
</body>
</html>
Ambient Gradient - Bricksfusion
LIGHTWEIGHT

Ambient Gradient

Adds an animated gradient background that follows your visitor's mouse. Great for hero sections and interactive cards.

This is the effect in action

Colors

Color 1, 2, 3, 4 color picker

Pick up to 4 colors for your gradient. They'll blend together smoothly. Use fewer colors for a simple look, or all 4 for more variety.

Default: Purple, Pink, Blue, Teal

Settings

Angle 0-360

Changes the direction the gradient flows. 0 is bottom to top, 90 is left to right, 180 is top to bottom.

Default: 45

Gradient Size 100-800

How big the gradient is. Bigger values = more dramatic color changes when it moves. Try 300-500 for nice results.

Default: 400

Transition Speed 0.1-2.0 seconds

How fast the gradient moves to new positions. Lower = snappy, higher = smooth and flowing.

Default: 0.5

Animation

Auto Animation on/off

Turn this on to make the gradient move by itself without needing mouse interaction. Perfect for backgrounds.

Default: Off

Auto Speed 0.001-0.02

How fast the automatic animation moves. Only works when Auto Animation is on. Keep it low (0.003-0.007) for subtle movement.

Default: 0.005

Mouse Control 0.0-1.0

How much the mouse affects the gradient. 1.0 = full control, 0.5 = subtle influence, 0.0 = no mouse effect.

Default: 1.0

Idle Speed 0.01-0.2

When the mouse leaves, the gradient drifts slowly at this speed. Keeps it from looking frozen.

Default: 0.05

Advanced

Z-Index -10 to 10

Controls if the gradient is behind or in front of your content. Keep it at 1 so text stays visible on top.

Default: 1

Content On Top on/off

Automatically puts all your text and images above the gradient. Keep this on unless you know what you're doing.

Default: On

Match Corners on/off

Makes the gradient match any rounded corners on your element. Keep it on for a polished look.

Default: On

Performance

This element is lightweight and won't slow down your site. It only animates when visible on screen and pauses when scrolled out of view.