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>Avatar Circles 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: #252525;
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
}

.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);
  z-index: 2;
}

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

input[type="text"],
input[type="number"],
input[type="url"] {
  width: 100%;
  padding: 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--input-radius);
  font-family: var(--font);
  font-size: var(--text-xs);
  color: var(--text-primary);
  background-color: rgba(0, 0, 0, 0.3);
  margin-bottom: 0.75rem;
  outline: none;
  transition: var(--transition);
}

input[type="text"]:focus,
input[type="number"]:focus,
input[type="url"]:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px rgba(239, 96, 19, 0.2);
}

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

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

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

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

.color-picker-container::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--current-color, #ffffff);
  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);
}

.avatar-inputs {
  margin-bottom: 1rem;
  border: 1px solid var(--border);
  border-radius: var(--input-radius);
  padding: 1rem;
  position: relative;
  background-color: rgba(30, 30, 30, 0.3);
}

.avatar-inputs:last-child {
  margin-bottom: 0;
}

.avatar-count {
  position: absolute;
  top: -10px;
  left: 10px;
  background-color: var(--accent);
  color: white;
  font-size: 12px;
  padding: 2px 8px;
  border-radius: 10px;
  font-weight: 600;
}

.avatar-action-buttons {
  display: flex;
  gap: 0.5rem;
  margin-top: 1rem;
}

.action-btn-small {
  flex: 1;
  padding: 0.7rem 1rem;
  border: none;
  border-radius: var(--input-radius);
  font-family: var(--font);
  font-size: var(--text-xs);
  font-weight: 500;
  cursor: pointer;
  transition: var(--transition);
}

.add-btn {
  background-color: var(--accent);
  color: white;
}

.add-btn:hover {
  background-color: var(--accent-hover);
  transform: translateY(-2px);
}

.remove-btn {
  background-color: rgba(220, 53, 69, 0.8);
  color: white;
}

.remove-btn:hover {
  background-color: var(--danger);
  transform: translateY(-2px);
}

.input-with-label {
  display: flex;
  flex-direction: column;
  margin-bottom: 0.75rem;
}

.input-with-label label {
  font-size: var(--text-xs);
  margin-bottom: 0.25rem;
  color: var(--text-secondary);
  font-weight: 500;
}

.background-input-wrapper {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

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

/* Estilos para animaciones en el preview */
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes breathing {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.05); }
}

@keyframes glow {
  0%, 100% { box-shadow: 0 0 5px rgba(255, 255, 255, 0.1); }
  50% { box-shadow: 0 0 15px rgba(239, 96, 19, 0.6); }
}

.avatar-cascade { 
  opacity: 0; 
  will-change: opacity, transform;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
}

.avatar-cascade.animate { 
  animation-name: fadeInUp; 
  animation-fill-mode: forwards; 
}

.avatar-breathing img { 
  animation: breathing 3s infinite ease-in-out; 
  will-change: transform;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.avatar-glow img { 
  animation: glow 3s infinite ease-in-out; 
  will-change: box-shadow;
}

.hover-lift:hover {
  transform: translateY(-5px) !important;
  will-change: transform;
  z-index: 100 !important;
}

.hover-lift:hover img {
  box-shadow: 0 5px 10px rgba(0,0,0,0.2) !important;
}

.hover-scale:hover {
  transform: scale(1.15) !important;
  will-change: transform;
  z-index: 100 !important;
}

.hover-scale:hover img {
  box-shadow: 0 5px 10px rgba(0,0,0,0.2) !important;
}

.hover-rotate:hover {
  transform: rotate(10deg) !important;
  will-change: transform;
  z-index: 100 !important;
}

.hover-rotate:hover img {
  box-shadow: 0 5px 10px rgba(0,0,0,0.2) !important;
}

.hover-combo:hover {
  transform: translateY(-5px) scale(1.08) !important;
  will-change: transform;
  z-index: 100 !important;
}

.hover-combo:hover img {
  box-shadow: 0 5px 10px rgba(0,0,0,0.2) !important;
}

/* Preview específico hover effects para testing */
.preview-container .hover-lift:hover {
  margin-top: -5px !important;
}

.preview-container .hover-scale:hover {
  transform: scale(1.15) !important;
}

.preview-container .hover-rotate:hover {
  transform: rotate(10deg) !important;
}

.preview-container .hover-combo:hover {
  margin-top: -5px !important;
  transform: scale(1.08) !important;
}

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

.radio-group {
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
  margin-bottom: 1rem;
}

.radio-option {
  display: flex;
  align-items: center;
  cursor: pointer;
}

.radio-option input[type="radio"] {
  margin-right: 0.8rem;
  cursor: pointer;
  accent-color: var(--accent);
}

.radio-option label {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  cursor: pointer;
}

.radio-option input[type="radio"]:checked + label {
  color: var(--text-primary);
  font-weight: 500;
}

.style-description {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  margin-top: 0.5rem;
  padding-left: 1.8rem;
  margin-bottom: 0.8rem;
  line-height: 1.5;
}

  </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/showcase/" class="breadcrumb-item">Showcase</a>
      <span class="breadcrumb-separator">›</span>
      <span class="breadcrumb-item active">Avatar Circles</span>
    </nav>
    
    <div class="action-buttons">
      <div class="data-attribute-display" id="quick-attribute" title="Click to copy data attribute">
        data-avatar-circles
      </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">Avatar Circles</h1>
      <p class="page-subtitle">Interactive avatar layouts 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 avatar circles 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 the JavaScript code</li>
                <li>To add the effect to any section: go to <strong>Section → Style → Attributes</strong>, add <code>data-avatar-circles</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="avatar-circles-preview" data-avatar-circles="true">
          <div class="preview-content">Interactive Avatar Circles Preview</div>
        </div>
      </section>

      <section class="controls-section">
        <div class="card">
          <div class="card-heading">
            Quick Presets
            <div class="card-actions">
              <button class="card-action-btn" id="generate-random-palette" title="Generate Random Colors">🎲</button>
            </div>
          </div>
          <div class="card-content">
            <div class="quick-actions">
              <button class="quick-action-btn" id="preset-team">Team</button>
              <button class="quick-action-btn" id="preset-clients">Clients</button>
              <button class="quick-action-btn" id="preset-reviews">Reviews</button>
            </div>
          </div>
        </div>

        <div class="card">
          <div class="card-heading">
            Avatar Configuration
            <div class="card-actions">
              <button class="card-action-btn" id="reset-avatars" title="Reset Avatars">↺</button>
            </div>
          </div>
          <div class="card-content">
            <div id="avatars-container">
            </div>
            
            <div class="avatar-action-buttons">
              <button class="action-btn-small add-btn" id="add-avatar-btn">Add Avatar</button>
              <button class="action-btn-small remove-btn" id="remove-avatar-btn">Remove Last</button>
            </div>
          </div>
        </div>

        <div class="card">
          <div class="card-heading">
            Extra People Count
            <div class="card-actions">
              <button class="card-action-btn" id="reset-extra" title="Reset Extra Count">↺</button>
            </div>
          </div>
          <div class="card-content">
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">Number of Extra People</span>
                <div class="value-display">
                  <span class="value-text"><span id="extra-count-value">3</span></span>
                </div>
              </div>
              <input type="number" id="extra-count-direct" min="0" max="999999" step="1" value="3">
            </div>
            
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">Extra People URL</span>
              </div>
              <input type="url" id="extra-url" placeholder="Link when clicking +X button..." value="#">
            </div>

            <div class="control-group">
              <div class="control-label">
                <span class="label-text">Counter Style</span>
              </div>
              <div class="radio-group">
                <div class="radio-option">
                  <input type="radio" id="counter-style-1" name="counter-style" value="circle" checked>
                  <label for="counter-style-1">Classic Circle</label>
                </div>
                <p class="style-description">Standard circular counter that matches avatar sizing</p>
                
                <div class="radio-option">
                  <input type="radio" id="counter-style-2" name="counter-style" value="auto-expand">
                  <label for="counter-style-2">Auto-expanding Circle</label>
                </div>
                <p class="style-description">Automatically expands width based on number size</p>
                
                <div class="radio-option">
                  <input type="radio" id="counter-style-3" name="counter-style" value="pill">
                  <label for="counter-style-3">Pill Shape</label>
                </div>
                <p class="style-description">Rounded rectangle that accommodates larger numbers</p>
                
                <div class="radio-option">
                  <input type="radio" id="counter-style-4" name="counter-style" value="badge">
                  <label for="counter-style-4">Badge Style</label>
                </div>
                <p class="style-description">Separate badge with emphasized appearance</p>
              </div>
            </div>

            <div class="switch-container">
              <span class="switch-label">Abbreviate Large Numbers</span>
              <label class="switch">
                <input type="checkbox" id="abbreviate-numbers" checked>
                <span class="slider"></span>
              </label>
            </div>
          </div>
        </div>

        <div class="card">
          <div class="card-heading">
            Style Settings
            <div class="card-actions">
              <button class="card-action-btn" id="reset-style" title="Reset Style Settings">↺</button>
            </div>
          </div>
          <div class="card-content">
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">Avatar Size</span>
                <div class="value-display">
                  <span class="value-text"><span id="avatar-size-value">40</span>px</span>
                  <button class="reset-btn" onclick="resetParameter('avatar-size', 40)">↺</button>
                </div>
              </div>
              <input type="range" id="avatar-size" min="20" max="100" step="1" value="40">
            </div>
            
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">Border Width</span>
                <div class="value-display">
                  <span class="value-text"><span id="border-width-value">2</span>px</span>
                  <button class="reset-btn" onclick="resetParameter('border-width', 2)">↺</button>
                </div>
              </div>
              <input type="range" id="border-width" min="0" max="10" step="1" value="2">
            </div>
            
            <div class="color-list">
              <div class="color-row">
                <div class="color-picker-container">
                  <input type="color" id="border-color" value="#ffffff">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HEX</span>
                  <input type="text" class="color-input hex-input" id="border-color-hex" value="#ffffff" placeholder="#FFFFFF">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HSL</span>
                  <input type="text" class="color-input hsl-input" id="border-color-hsl" placeholder="hsl(0, 100%, 50%)">
                </div>
              </div>
              
              <div class="color-row">
                <div class="color-picker-container">
                  <input type="color" id="extra-bg-color" value="#4a6cf7">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HEX</span>
                  <input type="text" class="color-input hex-input" id="extra-bg-color-hex" value="#4a6cf7" placeholder="#FFFFFF">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HSL</span>
                  <input type="text" class="color-input hsl-input" id="extra-bg-color-hsl" placeholder="hsl(0, 100%, 50%)">
                </div>
              </div>
              
              <div class="color-row">
                <div class="color-picker-container">
                  <input type="color" id="extra-hover-color" value="#3451b2">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HEX</span>
                  <input type="text" class="color-input hex-input" id="extra-hover-color-hex" value="#3451b2" placeholder="#FFFFFF">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HSL</span>
                  <input type="text" class="color-input hsl-input" id="extra-hover-color-hsl" placeholder="hsl(0, 100%, 50%)">
                </div>
              </div>
              
              <div class="color-row">
                <div class="color-picker-container">
                  <input type="color" id="extra-text-color" value="#ffffff">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HEX</span>
                  <input type="text" class="color-input hex-input" id="extra-text-color-hex" value="#ffffff" placeholder="#FFFFFF">
                </div>
                <div class="color-input-group">
                  <span class="color-label">HSL</span>
                  <input type="text" class="color-input hsl-input" id="extra-text-color-hsl" placeholder="hsl(0, 100%, 50%)">
                </div>
              </div>
            </div>
            
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">Overlap Distance</span>
                <div class="value-display">
                  <span class="value-text"><span id="overlap-value">16</span>px</span>
                  <button class="reset-btn" onclick="resetParameter('overlap', 16)">↺</button>
                </div>
              </div>
              <input type="range" id="overlap" min="0" max="40" step="1" value="16">
            </div>
          </div>
        </div>
        
        <div class="card">
          <div class="card-heading">
            Animation Settings
            <div class="card-actions">
              <button class="card-action-btn" id="reset-animation" title="Reset Animation Settings">↺</button>
            </div>
          </div>
          <div class="card-content">
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">Animation Type</span>
              </div>
              <div class="radio-group">
                <div class="radio-option">
                  <input type="radio" id="animation-none" name="animation-type" value="none" checked>
                  <label for="animation-none">None</label>
                </div>
                <p class="style-description">No animations applied</p>
                
                <div class="radio-option">
                  <input type="radio" id="animation-cascade" name="animation-type" value="cascade">
                  <label for="animation-cascade">Cascade</label>
                </div>
                <p class="style-description">Avatars appear one after another when in viewport</p>
                
                <div class="radio-option">
                  <input type="radio" id="animation-breathing" name="animation-type" value="breathing">
                  <label for="animation-breathing">Breathing</label>
                </div>
                <p class="style-description">Subtle pulsing animation to maintain visual interest</p>
                
                <div class="radio-option">
                  <input type="radio" id="animation-glow" name="animation-type" value="glow">
                  <label for="animation-glow">Glow Effect</label>
                </div>
                <p class="style-description">Avatars periodically glow to highlight</p>
              </div>
            </div>
            
            <div class="control-group">
              <div class="control-label">
                <span class="label-text">Animation Speed</span>
                <div class="value-display">
                  <span class="value-text"><span id="animation-speed-value">500</span>ms</span>
                  <button class="reset-btn" onclick="resetParameter('animation-speed', 500)">↺</button>
                </div>
              </div>
              <input type="range" id="animation-speed" min="100" max="2000" step="50" value="500">
            </div>
            
            <div class="switch-container">
              <span class="switch-label">Enable Animation on Scroll</span>
              <label class="switch">
                <input type="checkbox" id="animate-on-scroll" checked>
                <span class="slider"></span>
              </label>
            </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">Hover Effect</span>
              </div>
              <div class="radio-group">
                <div class="radio-option">
                  <input type="radio" id="hover-none" name="hover-effect" value="none" checked>
                  <label for="hover-none">None</label>
                </div>
                
                <div class="radio-option">
                  <input type="radio" id="hover-lift" name="hover-effect" value="lift">
                  <label for="hover-lift">Lift</label>
                </div>
                
                <div class="radio-option">
                  <input type="radio" id="hover-scale" name="hover-effect" value="scale">
                  <label for="hover-scale">Scale</label>
                </div>
                
                <div class="radio-option">
                  <input type="radio" id="hover-rotate" name="hover-effect" value="rotate">
                  <label for="hover-rotate">Rotate</label>
                </div>
                
                <div class="radio-option">
                  <input type="radio" id="hover-combo" name="hover-effect" value="combo">
                  <label for="hover-combo">Lift + Scale</label>
                </div>
              </div>
            </div>
          </div>
        </div>
      </section>
    </div>
  </div>

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

  <script>
    document.addEventListener('DOMContentLoaded', function() {
      let avatarCirclesConfig = {
        avatars: [
          {
            imageUrl: 'https://randomuser.me/api/portraits/women/44.jpg',
            profileUrl: '#',
            backgroundColor: 'transparent'
          },
          {
            imageUrl: 'https://randomuser.me/api/portraits/men/32.jpg',
            profileUrl: '#',
            backgroundColor: 'transparent'
          }
        ],
        numExtraPeople: 3, // Cambiado de 0 a 3 para ver los counter styles
        extraPeopleUrl: '#',
        avatarSize: 40,
        borderWidth: 2,
        borderColor: '#ffffff',
        extraBgColor: '#4a6cf7',
        extraHoverColor: '#3451b2',
        extraTextColor: '#ffffff',
        overlap: 16,
        counterStyle: 'circle',
        abbreviateNumbers: true,
        animationType: 'none',
        animationSpeed: 500,
        animateOnScroll: true,
        hoverEffect: 'none'
      };

      const defaultConfig = { ...avatarCirclesConfig };
      
      const previewContainer = document.getElementById('avatar-circles-preview');
      const avatarsContainer = document.getElementById('avatars-container');
      
      if (!previewContainer || !avatarsContainer) {
        return;
      }
      
      function initUI() {
        document.getElementById('extra-count-direct').value = avatarCirclesConfig.numExtraPeople;
        document.getElementById('extra-count-value').textContent = avatarCirclesConfig.numExtraPeople;
        document.getElementById('extra-url').value = avatarCirclesConfig.extraPeopleUrl;
        document.getElementById('avatar-size').value = avatarCirclesConfig.avatarSize;
        document.getElementById('avatar-size-value').textContent = avatarCirclesConfig.avatarSize;
        document.getElementById('border-width').value = avatarCirclesConfig.borderWidth;
        document.getElementById('border-width-value').textContent = avatarCirclesConfig.borderWidth;
        document.getElementById('border-color').value = avatarCirclesConfig.borderColor;
        document.getElementById('border-color-hex').value = avatarCirclesConfig.borderColor;
        document.getElementById('border-color-hsl').value = hexToHsl(avatarCirclesConfig.borderColor);
        document.getElementById('extra-bg-color').value = avatarCirclesConfig.extraBgColor;
        document.getElementById('extra-bg-color-hex').value = avatarCirclesConfig.extraBgColor;
        document.getElementById('extra-bg-color-hsl').value = hexToHsl(avatarCirclesConfig.extraBgColor);
        document.getElementById('extra-hover-color').value = avatarCirclesConfig.extraHoverColor;
        document.getElementById('extra-hover-color-hex').value = avatarCirclesConfig.extraHoverColor;
        document.getElementById('extra-hover-color-hsl').value = hexToHsl(avatarCirclesConfig.extraHoverColor);
        document.getElementById('extra-text-color').value = avatarCirclesConfig.extraTextColor;
        document.getElementById('extra-text-color-hex').value = avatarCirclesConfig.extraTextColor;
        document.getElementById('extra-text-color-hsl').value = hexToHsl(avatarCirclesConfig.extraTextColor);
        document.getElementById('overlap').value = avatarCirclesConfig.overlap;
        document.getElementById('overlap-value').textContent = avatarCirclesConfig.overlap;
        document.getElementById('counter-style-1').checked = avatarCirclesConfig.counterStyle === 'circle';
        document.getElementById('counter-style-2').checked = avatarCirclesConfig.counterStyle === 'auto-expand';
        document.getElementById('counter-style-3').checked = avatarCirclesConfig.counterStyle === 'pill';
        document.getElementById('counter-style-4').checked = avatarCirclesConfig.counterStyle === 'badge';
        document.getElementById('abbreviate-numbers').checked = avatarCirclesConfig.abbreviateNumbers;
        
        document.getElementById('animation-none').checked = avatarCirclesConfig.animationType === 'none';
        document.getElementById('animation-cascade').checked = avatarCirclesConfig.animationType === 'cascade';
        document.getElementById('animation-breathing').checked = avatarCirclesConfig.animationType === 'breathing';
        document.getElementById('animation-glow').checked = avatarCirclesConfig.animationType === 'glow';
        
        document.getElementById('animation-speed').value = avatarCirclesConfig.animationSpeed;
        document.getElementById('animation-speed-value').textContent = avatarCirclesConfig.animationSpeed;
        
        document.getElementById('animate-on-scroll').checked = avatarCirclesConfig.animateOnScroll;
        
        document.getElementById('hover-none').checked = avatarCirclesConfig.hoverEffect === 'none';
        document.getElementById('hover-lift').checked = avatarCirclesConfig.hoverEffect === 'lift';
        document.getElementById('hover-scale').checked = avatarCirclesConfig.hoverEffect === 'scale';
        document.getElementById('hover-rotate').checked = avatarCirclesConfig.hoverEffect === 'rotate';
        document.getElementById('hover-combo').checked = avatarCirclesConfig.hoverEffect === 'combo';
        
        updateColorPickerBackgrounds();
        renderAvatarInputs();
      }
      
      function renderAvatarInputs() {
        avatarsContainer.innerHTML = '';
        
        avatarCirclesConfig.avatars.forEach((avatar, index) => {
          const avatarInputs = document.createElement('div');
          avatarInputs.className = 'avatar-inputs';
          avatarInputs.innerHTML = `
            <div class="avatar-count">Avatar ${index + 1}</div>
            <div class="input-with-label">
              <label for="avatar-image-${index + 1}">Image URL</label>
              <input 
                type="url" 
                id="avatar-image-${index + 1}" 
                value="${avatar.imageUrl}"
                placeholder="Enter avatar image URL..."
                data-index="${index}"
                class="avatar-image-input"
              >
            </div>
            <div class="input-with-label">
              <label for="avatar-profile-${index + 1}">Profile URL</label>
              <input 
                type="url" 
                id="avatar-profile-${index + 1}" 
                value="${avatar.profileUrl || '#'}"
                placeholder="Enter profile link URL..."
                data-index="${index}"
                class="avatar-profile-input"
              >
            </div>
            <div class="input-with-label">
              <label for="avatar-bg-${index + 1}">Background Color</label>
              <div class="background-input-wrapper">
                <div class="switch-container" style="margin: 0 0 10px 0;">
                  <span class="switch-label">Transparent Background</span>
                  <label class="switch">
                    <input type="checkbox" 
                      id="avatar-transparent-${index + 1}" 
                      data-index="${index}" 
                      class="avatar-transparent-toggle"
                      ${avatar.backgroundColor === 'transparent' ? 'checked' : ''}>
                    <span class="slider"></span>
                  </label>
                </div>
                <div class="color-row" ${avatar.backgroundColor === 'transparent' ? 'style="opacity: 0.5;"' : ''}>
                  <div class="color-picker-container">
                    <input 
                      type="color" 
                      id="avatar-bg-${index + 1}" 
                      value="${avatar.backgroundColor !== 'transparent' ? avatar.backgroundColor : '#ffffff'}" 
                      data-index="${index}"
                      class="avatar-bg-input"
                      ${avatar.backgroundColor === 'transparent' ? 'disabled' : ''}
                    >
                  </div>
                  <div class="color-input-group">
                    <span class="color-label">HEX</span>
                    <input type="text" class="color-input hex-input avatar-bg-hex" id="avatar-bg-hex-${index + 1}" value="${avatar.backgroundColor !== 'transparent' ? avatar.backgroundColor : '#ffffff'}" placeholder="#FFFFFF" data-index="${index}" ${avatar.backgroundColor === 'transparent' ? 'disabled' : ''}>
                  </div>
                  <div class="color-input-group">
                    <span class="color-label">HSL</span>
                    <input type="text" class="color-input hsl-input avatar-bg-hsl" id="avatar-bg-hsl-${index + 1}" placeholder="hsl(0, 100%, 50%)" data-index="${index}" ${avatar.backgroundColor === 'transparent' ? 'disabled' : ''}>
                  </div>
                </div>
              </div>
            </div>
          `;
          
          avatarsContainer.appendChild(avatarInputs);
        });
        
        addAvatarInputListeners();
        updateAvatarColorInputs();
      }
      
      function addAvatarInputListeners() {
        document.querySelectorAll('.avatar-image-input').forEach(input => {
          input.addEventListener('input', debounce(function() {
            const index = parseInt(this.dataset.index);
            avatarCirclesConfig.avatars[index].imageUrl = this.value;
            updatePreview();
          }, 100));
        });
        
        document.querySelectorAll('.avatar-profile-input').forEach(input => {
          input.addEventListener('input', debounce(function() {
            const index = parseInt(this.dataset.index);
            avatarCirclesConfig.avatars[index].profileUrl = this.value;
            updatePreview();
          }, 100));
        });
        
        document.querySelectorAll('.avatar-bg-input').forEach(input => {
          input.addEventListener('input', debounce(function() {
            const index = parseInt(this.dataset.index);
            avatarCirclesConfig.avatars[index].backgroundColor = this.value;
            
            const hexInput = document.getElementById(`avatar-bg-hex-${index + 1}`);
            const hslInput = document.getElementById(`avatar-bg-hsl-${index + 1}`);
            
            hexInput.value = this.value;
            hslInput.value = hexToHsl(this.value);
            
            const container = this.closest('.color-picker-container');
            if (container) {
              container.style.setProperty('--current-color', this.value);
            }
            
            updatePreview();
          }, 10));
        });
        
        document.querySelectorAll('.avatar-bg-hex').forEach(input => {
          input.addEventListener('input', function() {
            const index = parseInt(this.dataset.index);
            let hex = formatHex(this.value);
            this.value = hex;
            
            if (isValidHex(hex)) {
              const colorInput = document.getElementById(`avatar-bg-${index + 1}`);
              const hslInput = document.getElementById(`avatar-bg-hsl-${index + 1}`);
              
              colorInput.value = hex;
              hslInput.value = hexToHsl(hex);
              
              const container = colorInput.closest('.color-picker-container');
              if (container) {
                container.style.setProperty('--current-color', hex);
              }
              
              avatarCirclesConfig.avatars[index].backgroundColor = hex;
              this.classList.remove('invalid');
              hslInput.classList.remove('invalid');
              updatePreview();
            } else {
              this.classList.add('invalid');
            }
          });
        });
        
        document.querySelectorAll('.avatar-bg-hsl').forEach(input => {
          input.addEventListener('input', function() {
            const index = parseInt(this.dataset.index);
            
            if (isValidHsl(this.value)) {
              const hex = hslToHex(this.value);
              if (hex) {
                const colorInput = document.getElementById(`avatar-bg-${index + 1}`);
                const hexInput = document.getElementById(`avatar-bg-hex-${index + 1}`);
                
                colorInput.value = hex;
                hexInput.value = hex;
                
                const container = colorInput.closest('.color-picker-container');
                if (container) {
                  container.style.setProperty('--current-color', hex);
                }
                
                avatarCirclesConfig.avatars[index].backgroundColor = hex;
                this.classList.remove('invalid');
                hexInput.classList.remove('invalid');
                updatePreview();
                return;
              }
            }
            
            this.classList.add('invalid');
          });
        });
        
        document.querySelectorAll('.avatar-transparent-toggle').forEach(checkbox => {
          checkbox.addEventListener('change', function() {
            const index = parseInt(this.dataset.index);
            const colorRow = this.closest('.background-input-wrapper').querySelector('.color-row');
            const colorInput = document.getElementById(`avatar-bg-${index + 1}`);
            const hexInput = document.getElementById(`avatar-bg-hex-${index + 1}`);
            const hslInput = document.getElementById(`avatar-bg-hsl-${index + 1}`);
            
            if (this.checked) {
              avatarCirclesConfig.avatars[index].backgroundColor = 'transparent';
              colorRow.style.opacity = '0.5';
              colorInput.disabled = true;
              hexInput.disabled = true;
              hslInput.disabled = true;
            } else {
              const colorValue = colorInput.value;
              avatarCirclesConfig.avatars[index].backgroundColor = colorValue;
              colorRow.style.opacity = '1';
              colorInput.disabled = false;
              hexInput.disabled = false;
              hslInput.disabled = false;
            }
            
            updatePreview();
          });
        });
      }
      
      function setupEventListeners() {
        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-avatar-circles');
        });

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

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

        document.getElementById('add-avatar-btn').addEventListener('click', function() {
          if (avatarCirclesConfig.avatars.length < 10) {
            const newIndex = avatarCirclesConfig.avatars.length + 1;
            const gender = Math.random() > 0.5 ? 'men' : 'women';
            const randomId = Math.floor(Math.random() * 70) + 1;
            avatarCirclesConfig.avatars.push({
              imageUrl: `https://randomuser.me/api/portraits/${gender}/${randomId}.jpg`,
              profileUrl: '#',
              backgroundColor: 'transparent'
            });
            renderAvatarInputs();
            updatePreview();
            showNotification('Avatar added successfully!');
          } else {
            showNotification('Maximum of 10 avatars allowed', 'warning');
          }
        });
        
        document.getElementById('remove-avatar-btn').addEventListener('click', function() {
          if (avatarCirclesConfig.avatars.length > 1) {
            avatarCirclesConfig.avatars.pop();
            renderAvatarInputs();
            updatePreview();
            showNotification('Avatar removed successfully!');
          } else {
            showNotification('At least one avatar is required', 'warning');
          }
        });
        
        document.getElementById('extra-count-direct').addEventListener('input', debounce(function() {
          avatarCirclesConfig.numExtraPeople = parseInt(this.value) || 0;
          document.getElementById('extra-count-value').textContent = this.value;
          updatePreview();
        }, 10));
        
        document.getElementById('extra-url').addEventListener('input', debounce(function() {
          avatarCirclesConfig.extraPeopleUrl = this.value;
          updatePreview();
        }, 100));
        
        document.getElementById('avatar-size').addEventListener('input', debounce(function() {
          avatarCirclesConfig.avatarSize = parseInt(this.value);
          document.getElementById('avatar-size-value').textContent = this.value;
          updatePreview();
        }, 10));
        
        document.getElementById('border-width').addEventListener('input', debounce(function() {
          avatarCirclesConfig.borderWidth = parseInt(this.value);
          document.getElementById('border-width-value').textContent = this.value;
          updatePreview();
        }, 10));
        
        document.getElementById('overlap').addEventListener('input', debounce(function() {
          avatarCirclesConfig.overlap = parseInt(this.value);
          document.getElementById('overlap-value').textContent = this.value;
          updatePreview();
        }, 10));
        
        document.querySelectorAll('input[name="counter-style"]').forEach(radio => {
          radio.addEventListener('change', function() {
            if (this.checked) {
              avatarCirclesConfig.counterStyle = this.value;
              updatePreview();
            }
          });
        });
        
        document.getElementById('abbreviate-numbers').addEventListener('change', function() {
          avatarCirclesConfig.abbreviateNumbers = this.checked;
          updatePreview();
        });
        
        document.querySelectorAll('input[name="animation-type"]').forEach(radio => {
          radio.addEventListener('change', function() {
            if (this.checked) {
              avatarCirclesConfig.animationType = this.value;
              updatePreview();
            }
          });
        });
        
        document.getElementById('animation-speed').addEventListener('input', debounce(function() {
          avatarCirclesConfig.animationSpeed = parseInt(this.value);
          document.getElementById('animation-speed-value').textContent = this.value;
          updatePreview();
        }, 10));
        
        document.getElementById('animate-on-scroll').addEventListener('change', function() {
          avatarCirclesConfig.animateOnScroll = this.checked;
          updatePreview();
        });
        
        document.querySelectorAll('input[name="hover-effect"]').forEach(radio => {
          radio.addEventListener('change', function() {
            if (this.checked) {
              avatarCirclesConfig.hoverEffect = this.value;
              updatePreview();
            }
          });
        });

        setupColorListeners();
        setupResetButtons();
        setupQuickPresets();
        setupKeyboardShortcuts();
      }

      function setupColorListeners() {
        const colorConfigs = [
          { id: 'border-color', property: 'borderColor' },
          { id: 'extra-bg-color', property: 'extraBgColor' },
          { id: 'extra-hover-color', property: 'extraHoverColor' },
          { id: 'extra-text-color', property: 'extraTextColor' }
        ];

        colorConfigs.forEach(config => {
          const colorInput = document.getElementById(config.id);
          const hexInput = document.getElementById(`${config.id}-hex`);
          const hslInput = document.getElementById(`${config.id}-hsl`);

          colorInput.addEventListener('input', () => {
            const color = colorInput.value;
            hexInput.value = color;
            hslInput.value = hexToHsl(color);
            hexInput.classList.remove('invalid');
            hslInput.classList.remove('invalid');
            
            const container = colorInput.closest('.color-picker-container');
            if (container) {
              container.style.setProperty('--current-color', color);
            }
            
            avatarCirclesConfig[config.property] = color;
            updatePreview();
          });

          hexInput.addEventListener('input', (e) => {
            let hex = formatHex(e.target.value);
            e.target.value = hex;
            
            if (isValidHex(hex)) {
              colorInput.value = hex;
              hslInput.value = hexToHsl(hex);
              
              const container = colorInput.closest('.color-picker-container');
              if (container) {
                container.style.setProperty('--current-color', hex);
              }
              
              avatarCirclesConfig[config.property] = hex;
              e.target.classList.remove('invalid');
              hslInput.classList.remove('invalid');
              updatePreview();
            } else {
              e.target.classList.add('invalid');
            }
          });

          hslInput.addEventListener('input', (e) => {
            if (isValidHsl(e.target.value)) {
              const hex = hslToHex(e.target.value);
              if (hex) {
                colorInput.value = hex;
                hexInput.value = hex;
                
                const container = colorInput.closest('.color-picker-container');
                if (container) {
                  container.style.setProperty('--current-color', hex);
                }
                
                avatarCirclesConfig[config.property] = hex;
                e.target.classList.remove('invalid');
                hexInput.classList.remove('invalid');
                updatePreview();
                return;
              }
            }
            
            e.target.classList.add('invalid');
          });
        });
      }

      function setupResetButtons() {
        document.getElementById('reset-avatars').addEventListener('click', () => {
          avatarCirclesConfig.avatars = [...defaultConfig.avatars];
          renderAvatarInputs();
          updatePreview();
          showNotification('Avatars reset to default');
        });

        document.getElementById('reset-extra').addEventListener('click', () => {
          avatarCirclesConfig.numExtraPeople = defaultConfig.numExtraPeople;
          avatarCirclesConfig.extraPeopleUrl = defaultConfig.extraPeopleUrl;
          avatarCirclesConfig.counterStyle = defaultConfig.counterStyle;
          avatarCirclesConfig.abbreviateNumbers = defaultConfig.abbreviateNumbers;
          
          document.getElementById('extra-count-direct').value = defaultConfig.numExtraPeople;
          document.getElementById('extra-count-value').textContent = defaultConfig.numExtraPeople;
          document.getElementById('extra-url').value = defaultConfig.extraPeopleUrl;
          document.getElementById('counter-style-1').checked = true;
          document.getElementById('abbreviate-numbers').checked = defaultConfig.abbreviateNumbers;
          
          updatePreview();
          showNotification('Extra count settings reset');
        });

        document.getElementById('reset-style').addEventListener('click', () => {
          avatarCirclesConfig.avatarSize = defaultConfig.avatarSize;
          avatarCirclesConfig.borderWidth = defaultConfig.borderWidth;
          avatarCirclesConfig.borderColor = defaultConfig.borderColor;
          avatarCirclesConfig.extraBgColor = defaultConfig.extraBgColor;
          avatarCirclesConfig.extraHoverColor = defaultConfig.extraHoverColor;
          avatarCirclesConfig.extraTextColor = defaultConfig.extraTextColor;
          avatarCirclesConfig.overlap = defaultConfig.overlap;
          
          document.getElementById('avatar-size').value = defaultConfig.avatarSize;
          document.getElementById('avatar-size-value').textContent = defaultConfig.avatarSize;
          document.getElementById('border-width').value = defaultConfig.borderWidth;
          document.getElementById('border-width-value').textContent = defaultConfig.borderWidth;
          document.getElementById('overlap').value = defaultConfig.overlap;
          document.getElementById('overlap-value').textContent = defaultConfig.overlap;
          
          updateColorInputs();
          updatePreview();
          showNotification('Style settings reset');
        });

        document.getElementById('reset-animation').addEventListener('click', () => {
          avatarCirclesConfig.animationType = defaultConfig.animationType;
          avatarCirclesConfig.animationSpeed = defaultConfig.animationSpeed;
          avatarCirclesConfig.animateOnScroll = defaultConfig.animateOnScroll;
          
          document.getElementById('animation-none').checked = true;
          document.getElementById('animation-speed').value = defaultConfig.animationSpeed;
          document.getElementById('animation-speed-value').textContent = defaultConfig.animationSpeed;
          document.getElementById('animate-on-scroll').checked = defaultConfig.animateOnScroll;
          
          updatePreview();
          showNotification('Animation settings reset');
        });

        document.getElementById('reset-advanced').addEventListener('click', () => {
          avatarCirclesConfig.hoverEffect = defaultConfig.hoverEffect;
          
          document.getElementById('hover-none').checked = true;
          
          updatePreview();
          showNotification('Advanced settings reset');
        });
      }

      function setupQuickPresets() {
        document.getElementById('generate-random-palette').addEventListener('click', () => {
          generateRandomPalette();
        });

        document.getElementById('preset-team').addEventListener('click', () => {
          applyPreset('team');
        });

        document.getElementById('preset-clients').addEventListener('click', () => {
          applyPreset('clients');
        });

        document.getElementById('preset-reviews').addEventListener('click', () => {
          applyPreset('reviews');
        });
      }

      function setupKeyboardShortcuts() {
        document.addEventListener('keydown', (e) => {
          if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') {
            return;
          }
          
          if (e.ctrlKey || e.metaKey) {
            switch (e.key.toLowerCase()) {
              case 'd':
                e.preventDefault();
                const downloadBtn = document.getElementById('download-config');
                if (downloadBtn && downloadBtn.hasAttribute('data-protection-animation')) {
                  downloadBtn.click();
                } else {
                  copyJsToClipboard();
                }
                break;
              case 's':
                e.preventDefault();
                const fullSectionBtn = document.getElementById('copy-full-section');
                if (fullSectionBtn && fullSectionBtn.hasAttribute('data-protection-animation')) {
                  fullSectionBtn.click();
                } else {
                  copyFullSectionToClipboard();
                }
                break;
            }
          } else {
            switch (e.key.toLowerCase()) {
              case 'r':
                generateRandomPalette();
                break;
            }
          }
        });
      }
      
      function debounce(func, wait) {
        let timeout;
        return function(...args) {
          const context = this;
          clearTimeout(timeout);
          timeout = setTimeout(() => func.apply(context, args), wait);
        };
      }
      
      function formatNumber(num) {
        if (!avatarCirclesConfig.abbreviateNumbers) {
          return num;
        }
        
        if (num >= 1000000) {
          return (Math.floor(num / 100000) / 10).toFixed(1).replace(/\.0$/, '') + 'M+';
        } else if (num >= 1000) {
          return (Math.floor(num / 100) / 10).toFixed(1).replace(/\.0$/, '') + 'K+';
        }
        return num + '+';
      }
      
      // FUNCIÓN UPDATEPREVIEW CORREGIDA
      function updatePreview() {
        // Preservar estado existente antes de limpiar
        const existingElements = previewContainer.querySelectorAll('a');
        const wasInitialized = previewContainer.hasAttribute('data-initialized');
        
        // Limpiar contenido manteniendo estilos del contenedor
        previewContainer.innerHTML = '';
        
        // Restablecer estilos del contenedor
        Object.assign(previewContainer.style, {
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          position: 'relative',
          zIndex: '10'
        });
        
        if (wasInitialized) {
          previewContainer.setAttribute('data-initialized', 'true');
        }
        
        // Crear fragmento para agregar elementos
        const fragment = document.createDocumentFragment();
        
        // Renderizar avatares
        avatarCirclesConfig.avatars.forEach((avatar, index) => {
          const link = document.createElement('a');
          link.href = avatar.profileUrl || '#';
          link.target = '_blank';
          link.rel = 'noopener noreferrer';
          
          // Aplicar clases de animación
          if (avatarCirclesConfig.animationType !== 'none') {
            link.classList.add(`avatar-${avatarCirclesConfig.animationType}`);
          }
          
          // Aplicar clases de hover
          if (avatarCirclesConfig.hoverEffect !== 'none') {
            link.classList.add(`hover-${avatarCirclesConfig.hoverEffect}`);
          }
          
          // Configurar animaciones específicas
          if (avatarCirclesConfig.animationType === 'cascade') {
            const delay = index * (avatarCirclesConfig.animationSpeed / 1000 / avatarCirclesConfig.avatars.length);
            link.style.animationDelay = `${delay}s`;
            link.style.animationDuration = `${avatarCirclesConfig.animationSpeed / 1000}s`;
          }
          
          // Estilos de posicionamiento
          Object.assign(link.style, {
            marginLeft: index > 0 ? `-${avatarCirclesConfig.overlap}px` : '0',
            transition: `all ${avatarCirclesConfig.animationSpeed / 1000}s ease`,
            position: 'relative',
            zIndex: avatarCirclesConfig.avatars.length - index,
            display: 'inline-block'
          });
          
          const defaultImage = 'https://randomuser.me/api/portraits/women/44.jpg';
          
          const img = document.createElement('img');
          img.src = avatar.imageUrl && avatar.imageUrl.trim() !== '' ? avatar.imageUrl : defaultImage;
          img.width = avatarCirclesConfig.avatarSize;
          img.height = avatarCirclesConfig.avatarSize;
          img.alt = `Avatar ${index + 1}`;
          
          // Estilos de imagen
          Object.assign(img.style, {
            height: `${avatarCirclesConfig.avatarSize}px`,
            width: `${avatarCirclesConfig.avatarSize}px`,
            borderRadius: '50%',
            border: `${avatarCirclesConfig.borderWidth}px solid ${avatarCirclesConfig.borderColor}`,
            backgroundColor: avatar.backgroundColor || 'transparent',
            transition: `all ${avatarCirclesConfig.animationSpeed / 1000}s ease`,
            objectFit: 'cover',
            display: 'block'
          });
          
          // Aplicar animaciones de imagen específicas
          if (avatarCirclesConfig.animationType === 'breathing') {
            const duration = (avatarCirclesConfig.animationSpeed * 3) / 1000;
            img.style.animationDuration = `${duration}s`;
          } else if (avatarCirclesConfig.animationType === 'glow') {
            const duration = (avatarCirclesConfig.animationSpeed * 3) / 1000;
            img.style.animationDuration = `${duration}s`;
          }
          
          link.appendChild(img);
          fragment.appendChild(link);
        });
        
        // Renderizar contador de personas extra
        if (avatarCirclesConfig.numExtraPeople > 0) {
          const morePeopleLink = document.createElement('a');
          morePeopleLink.href = avatarCirclesConfig.extraPeopleUrl || '#';
          morePeopleLink.target = '_blank';
          morePeopleLink.rel = 'noopener noreferrer';
          
          const formattedCount = formatNumber(avatarCirclesConfig.numExtraPeople);
morePeopleLink.textContent = formattedCount;
          
          // Aplicar clases de animación y hover
          if (avatarCirclesConfig.animationType !== 'none') {
            morePeopleLink.classList.add(`avatar-${avatarCirclesConfig.animationType}`);
          }
          
          if (avatarCirclesConfig.hoverEffect !== 'none') {
            morePeopleLink.classList.add(`hover-${avatarCirclesConfig.hoverEffect}`);
          }
          
          // Configurar animaciones específicas
          if (avatarCirclesConfig.animationType === 'cascade') {
            const delay = avatarCirclesConfig.avatars.length * (avatarCirclesConfig.animationSpeed / 1000 / (avatarCirclesConfig.avatars.length + 1));
            morePeopleLink.style.animationDelay = `${delay}s`;
            morePeopleLink.style.animationDuration = `${avatarCirclesConfig.animationSpeed / 1000}s`;
          } else if (avatarCirclesConfig.animationType === 'breathing') {
            const duration = (avatarCirclesConfig.animationSpeed * 3) / 1000;
            morePeopleLink.style.animationDuration = `${duration}s`;
          } else if (avatarCirclesConfig.animationType === 'glow') {
            const duration = (avatarCirclesConfig.animationSpeed * 3) / 1000;
            morePeopleLink.style.animationDuration = `${duration}s`;
          }
          
          // Aplicar estilos específicos según el counter style
          const baseCounterStyles = {
            display: 'inline-flex',
            alignItems: 'center',
            justifyContent: 'center',
            backgroundColor: avatarCirclesConfig.extraBgColor,
            color: avatarCirclesConfig.extraTextColor,
            fontSize: `${Math.max(12, avatarCirclesConfig.avatarSize / 3)}px`,
            fontWeight: '600',
            textDecoration: 'none',
            transition: 'all 0.3s ease',
            position: 'relative'
          };
          
          switch(avatarCirclesConfig.counterStyle) {
            case 'circle':
              Object.assign(morePeopleLink.style, {
                ...baseCounterStyles,
                height: `${avatarCirclesConfig.avatarSize}px`,
                width: `${avatarCirclesConfig.avatarSize}px`,
                borderRadius: '50%',
                border: `${avatarCirclesConfig.borderWidth}px solid ${avatarCirclesConfig.borderColor}`,
                marginLeft: `-${avatarCirclesConfig.overlap}px`
              });
              break;
              
            case 'auto-expand':
              const digitCount = String(formattedCount).length;
              const extraWidth = avatarCirclesConfig.avatarSize * (1 + (digitCount > 2 ? (digitCount - 2) * 0.35 : 0));
              
              Object.assign(morePeopleLink.style, {
                ...baseCounterStyles,
                height: `${avatarCirclesConfig.avatarSize}px`,
                width: `${extraWidth}px`,
                borderRadius: '50%',
                border: `${avatarCirclesConfig.borderWidth}px solid ${avatarCirclesConfig.borderColor}`,
                marginLeft: `-${avatarCirclesConfig.overlap}px`
              });
              break;
              
            case 'pill':
              Object.assign(morePeopleLink.style, {
                ...baseCounterStyles,
                height: `${avatarCirclesConfig.avatarSize}px`,
                minWidth: `${avatarCirclesConfig.avatarSize}px`,
                padding: '0 10px',
                borderRadius: `${avatarCirclesConfig.avatarSize / 2}px`,
                border: `${avatarCirclesConfig.borderWidth}px solid ${avatarCirclesConfig.borderColor}`,
                marginLeft: `-${avatarCirclesConfig.overlap}px`
              });
              break;
              
            case 'badge':
              Object.assign(morePeopleLink.style, {
                ...baseCounterStyles,
                height: `${Math.max(24, avatarCirclesConfig.avatarSize * 0.7)}px`,
                minWidth: `${Math.max(24, avatarCirclesConfig.avatarSize * 0.7)}px`,
                borderRadius: '20px',
                marginLeft: '8px',
                boxShadow: '0 2px 6px rgba(0,0,0,0.2)',
                whiteSpace: 'nowrap',
                paddingLeft: `${Math.max(12, String(formattedCount).length * 3)}px`,
                paddingRight: `${Math.max(12, String(formattedCount).length * 3)}px`
              });
              break;
          }
          
          fragment.appendChild(morePeopleLink);
        }
        
        // Agregar todo el contenido de una vez
        previewContainer.appendChild(fragment);
        
        // Inicializar animaciones si es necesario
        if (avatarCirclesConfig.animationType === 'cascade') {
          if (avatarCirclesConfig.animateOnScroll) {
            const observer = new IntersectionObserver((entries) => {
              if (entries[0].isIntersecting) {
                setTimeout(() => {
                  previewContainer.querySelectorAll('.avatar-cascade:not(.animate)').forEach(el => {
                    el.classList.add('animate');
                  });
                }, 50);
                observer.disconnect();
              }
            }, { threshold: 0.2 });
            
            observer.observe(previewContainer);
          } else {
            setTimeout(() => {
              previewContainer.querySelectorAll('.avatar-cascade:not(.animate)').forEach(el => {
                el.classList.add('animate');
              });
            }, 50);
          }
        }
      }

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

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

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

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

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

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

      function generateRandomPalette() {
        avatarCirclesConfig.borderColor = generateRandomColor();
        avatarCirclesConfig.extraBgColor = generateRandomColor();
        avatarCirclesConfig.extraHoverColor = generateRandomColor();
        avatarCirclesConfig.extraTextColor = generateRandomColor();
        
        updateColorInputs();
        updatePreview();
        showNotification('Random color palette generated!');
      }

      function applyPreset(presetType) {
        switch(presetType) {
          case 'team':
            avatarCirclesConfig.avatars = [
              { imageUrl: 'https://randomuser.me/api/portraits/women/44.jpg', profileUrl: '#', backgroundColor: 'transparent' },
              { imageUrl: 'https://randomuser.me/api/portraits/men/32.jpg', profileUrl: '#', backgroundColor: 'transparent' },
              { imageUrl: 'https://randomuser.me/api/portraits/women/68.jpg', profileUrl: '#', backgroundColor: 'transparent' }
            ];
            avatarCirclesConfig.numExtraPeople = 5;
            avatarCirclesConfig.extraBgColor = '#4a6cf7';
            break;
          case 'clients':
            avatarCirclesConfig.avatars = [
              { imageUrl: 'https://randomuser.me/api/portraits/men/22.jpg', profileUrl: '#', backgroundColor: 'transparent' },
              { imageUrl: 'https://randomuser.me/api/portraits/women/55.jpg', profileUrl: '#', backgroundColor: 'transparent' },
              { imageUrl: 'https://randomuser.me/api/portraits/men/45.jpg', profileUrl: '#', backgroundColor: 'transparent' },
              { imageUrl: 'https://randomuser.me/api/portraits/women/33.jpg', profileUrl: '#', backgroundColor: 'transparent' }
            ];
            avatarCirclesConfig.numExtraPeople = 100;
            avatarCirclesConfig.extraBgColor = '#28a745';
            break;
          case 'reviews':
            avatarCirclesConfig.avatars = [
              { imageUrl: 'https://randomuser.me/api/portraits/women/12.jpg', profileUrl: '#', backgroundColor: 'transparent' },
              { imageUrl: 'https://randomuser.me/api/portraits/men/15.jpg', profileUrl: '#', backgroundColor: 'transparent' }
            ];
            avatarCirclesConfig.numExtraPeople = 1200;
            avatarCirclesConfig.extraBgColor = '#ffc107';
            avatarCirclesConfig.extraTextColor = '#000000';
            break;
        }
        
        document.getElementById('extra-count-direct').value = avatarCirclesConfig.numExtraPeople;
        document.getElementById('extra-count-value').textContent = avatarCirclesConfig.numExtraPeople;
        
        renderAvatarInputs();
        updateColorInputs();
        updatePreview();
        showNotification(`${presetType.charAt(0).toUpperCase() + presetType.slice(1)} preset applied!`);
      }

      function updateColorInputs() {
        const colorConfigs = [
          { id: 'border-color', value: avatarCirclesConfig.borderColor },
          { id: 'extra-bg-color', value: avatarCirclesConfig.extraBgColor },
          { id: 'extra-hover-color', value: avatarCirclesConfig.extraHoverColor },
          { id: 'extra-text-color', value: avatarCirclesConfig.extraTextColor }
        ];

        colorConfigs.forEach(config => {
          const colorInput = document.getElementById(config.id);
          const hexInput = document.getElementById(`${config.id}-hex`);
          const hslInput = document.getElementById(`${config.id}-hsl`);

          if (colorInput && hexInput && hslInput) {
            colorInput.value = config.value;
            hexInput.value = config.value;
            hslInput.value = hexToHsl(config.value);

            const container = colorInput.closest('.color-picker-container');
            if (container) {
              container.style.setProperty('--current-color', config.value);
            }

            hexInput.classList.remove('invalid');
            hslInput.classList.remove('invalid');
          }
        });
      }

      function updateColorPickerBackgrounds() {
        const colorInputs = document.querySelectorAll('input[type="color"]');
        colorInputs.forEach(input => {
          const container = input.closest('.color-picker-container');
          if (container) {
            container.style.setProperty('--current-color', input.value);
          }
        });
      }

      function updateAvatarColorInputs() {
        avatarCirclesConfig.avatars.forEach((avatar, index) => {
          const hslInput = document.getElementById(`avatar-bg-hsl-${index + 1}`);
          if (hslInput && avatar.backgroundColor !== 'transparent') {
            hslInput.value = hexToHsl(avatar.backgroundColor);
          }

          const colorInput = document.getElementById(`avatar-bg-${index + 1}`);
          if (colorInput && avatar.backgroundColor !== 'transparent') {
            const container = colorInput.closest('.color-picker-container');
            if (container) {
              container.style.setProperty('--current-color', avatar.backgroundColor);
            }
          }
        });
      }

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

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

      function generateFullSectionJSON() {
  // Generar IDs únicos para todos los elementos
  const sectionId = generateUniqueId();
  const containerId = generateUniqueId();
  const avatarDivId = generateUniqueId();
  const codeElementId = generateUniqueId();
  const attributeId = generateUniqueId();

  // Generar el código JavaScript escapado
  const javascriptCode = generateJavaScriptCode();

  // Construir los atributos data-* basados en la configuración actual
  const dataAttributes = [
    {
      "id": attributeId,
      "name": "data-avatar-circles"
    }
  ];

  // Agregar atributos de configuración de avatares
  avatarCirclesConfig.avatars.forEach((avatar, index) => {
    const avatarNumber = index + 1;
    dataAttributes.push(
      {
        "id": generateUniqueId(),
        "name": `data-avatar-image-${avatarNumber}`,
        "value": avatar.imageUrl || ''
      },
      {
        "id": generateUniqueId(),
        "name": `data-avatar-profile-${avatarNumber}`,
        "value": avatar.profileUrl || '#'
      },
      {
        "id": generateUniqueId(),
        "name": `data-avatar-bg-${avatarNumber}`,
        "value": avatar.backgroundColor || 'transparent'
      }
    );
  });

  // Agregar resto de atributos de configuración
  dataAttributes.push(
    {
      "id": generateUniqueId(),
      "name": "data-avatar-extra",
      "value": avatarCirclesConfig.numExtraPeople.toString()
    },
    {
      "id": generateUniqueId(),
      "name": "data-avatar-extra-url",
      "value": avatarCirclesConfig.extraPeopleUrl || '#'
    },
    {
      "id": generateUniqueId(),
      "name": "data-counter-style",
      "value": avatarCirclesConfig.counterStyle
    },
    {
      "id": generateUniqueId(),
      "name": "data-abbreviate-numbers",
      "value": avatarCirclesConfig.abbreviateNumbers.toString()
    },
    {
      "id": generateUniqueId(),
      "name": "data-extra-text-color",
      "value": avatarCirclesConfig.extraTextColor
    },
    {
      "id": generateUniqueId(),
      "name": "data-animation-type",
      "value": avatarCirclesConfig.animationType
    },
    {
      "id": generateUniqueId(),
      "name": "data-animation-speed",
      "value": avatarCirclesConfig.animationSpeed.toString()
    },
    {
      "id": generateUniqueId(),
      "name": "data-animate-on-scroll",
      "value": avatarCirclesConfig.animateOnScroll.toString()
    },
    {
      "id": generateUniqueId(),
      "name": "data-hover-effect",
      "value": avatarCirclesConfig.hoverEffect
    },
    {
      "id": generateUniqueId(),
      "name": "data-avatar-size",
      "value": avatarCirclesConfig.avatarSize.toString()
    },
    {
      "id": generateUniqueId(),
      "name": "data-border-width",
      "value": avatarCirclesConfig.borderWidth.toString()
    },
    {
      "id": generateUniqueId(),
      "name": "data-border-color",
      "value": avatarCirclesConfig.borderColor
    },
    {
      "id": generateUniqueId(),
      "name": "data-extra-bg-color",
      "value": avatarCirclesConfig.extraBgColor
    },
    {
      "id": generateUniqueId(),
      "name": "data-extra-hover-color",
      "value": avatarCirclesConfig.extraHoverColor
    },
    {
      "id": generateUniqueId(),
      "name": "data-overlap",
      "value": avatarCirclesConfig.overlap.toString()
    }
  );

  // Estructura completa del JSON de Bricks Builder
  const fullSectionJSON = {
    "content": [
      {
        "id": sectionId,
        "name": "section",
        "parent": 0,
        "children": [containerId, codeElementId],
        "settings": {
          "_height": "500",
          "_justifyContent": "center",
          "_background": {
            "color": {
              "hex": "#ffffff"
            }
          }
        }
      },
      {
        "id": containerId,
        "name": "container",
        "parent": sectionId,
        "children": [avatarDivId],
        "settings": {
          "_alignItems": "center"
        }
      },
      {
        "id": avatarDivId,
        "name": "div",
        "parent": containerId,
        "children": [],
        "settings": {
          "_attributes": dataAttributes
        },
        "label": "Avatar Div"
      },
      {
        "id": codeElementId,
        "name": "code",
        "parent": sectionId,
        "children": [],
        "settings": {
          "javascriptCode": javascriptCode,
          "executeCode": true,
          "_display": "none"
        },
        "label": "Avatar JS"
      }
    ],
    "source": "bricksCopiedElements",
    "sourceUrl": "https://test.bricksfusion.com",
    "version": "2.0.1",
    "globalClasses": [],
    "globalElements": []
  };

  return fullSectionJSON;
}

      function generateJavaScriptCode() {
        const colors = avatarCirclesConfig.avatars.map(avatar => avatar.backgroundColor);
        const imageUrls = avatarCirclesConfig.avatars.map(avatar => avatar.imageUrl);
        const profileUrls = avatarCirclesConfig.avatars.map(avatar => avatar.profileUrl);
        
        return `(function() {
  window.AvatarCircles = window.AvatarCircles || {};
  
  function initAvatarCircles() {
    const containers = document.querySelectorAll('[data-avatar-circles]');
    
    containers.forEach((container) => {
      try {
        if (container.hasAttribute('data-circles-initialized')) {
          return;
        }
        
        container.setAttribute('data-circles-initialized', 'true');
        
        ${avatarCirclesConfig.avatars.map((avatar, index) => `
        container.setAttribute('data-avatar-image-${index + 1}', '${avatar.imageUrl}');
        container.setAttribute('data-avatar-profile-${index + 1}', '${avatar.profileUrl || '#'}');
        container.setAttribute('data-avatar-bg-${index + 1}', '${avatar.backgroundColor || 'transparent'}');`).join('')}
        
        container.setAttribute('data-avatar-extra', '${avatarCirclesConfig.numExtraPeople}');
        container.setAttribute('data-avatar-extra-url', '${avatarCirclesConfig.extraPeopleUrl || '#'}');
        container.setAttribute('data-counter-style', '${avatarCirclesConfig.counterStyle}');
        container.setAttribute('data-abbreviate-numbers', '${avatarCirclesConfig.abbreviateNumbers}');
        container.setAttribute('data-extra-text-color', '${avatarCirclesConfig.extraTextColor}');
        container.setAttribute('data-animation-type', '${avatarCirclesConfig.animationType}');
        container.setAttribute('data-animation-speed', '${avatarCirclesConfig.animationSpeed}');
        container.setAttribute('data-animate-on-scroll', '${avatarCirclesConfig.animateOnScroll}');
        container.setAttribute('data-hover-effect', '${avatarCirclesConfig.hoverEffect}');
        
        let avatarCount = 1;
        const avatars = [];
        
        while (true) {
          const imageUrl = container.getAttribute(\`data-avatar-image-\${avatarCount}\`);
          if (!imageUrl) break;
          
          avatars.push({
            imageUrl,
            profileUrl: container.getAttribute(\`data-avatar-profile-\${avatarCount}\`) || '#',
            backgroundColor: container.getAttribute(\`data-avatar-bg-\${avatarCount}\`) || 'transparent'
          });
          avatarCount++;
        }
        
        if (avatars.length === 0) return;
        
        const numExtraPeople = parseInt(container.getAttribute('data-avatar-extra') || '0', 10);
        const counterStyle = container.getAttribute('data-counter-style') || 'circle';
        const abbreviateNumbers = container.getAttribute('data-abbreviate-numbers') === 'true';
        const extraTextColor = container.getAttribute('data-extra-text-color') || '#ffffff';
        const animationType = container.getAttribute('data-animation-type') || 'none';
        const animationSpeed = parseInt(container.getAttribute('data-animation-speed') || '500');
        const animateOnScroll = container.getAttribute('data-animate-on-scroll') === 'true';
        const hoverEffect = container.getAttribute('data-hover-effect') || 'none';
        
        container.innerHTML = '';
        Object.assign(container.style, {
          display: 'flex',
          alignItems: 'center',
          position: 'relative',
          zIndex: '10'
        });
        
        const avatarSize = ${avatarCirclesConfig.avatarSize};
        const borderWidth = ${avatarCirclesConfig.borderWidth};
        const borderColor = '${avatarCirclesConfig.borderColor}';
        const extraBgColor = '${avatarCirclesConfig.extraBgColor}';
        const extraHoverColor = '${avatarCirclesConfig.extraHoverColor}';
        const overlap = ${avatarCirclesConfig.overlap};
        
        if (animationType !== 'none' && !document.querySelector('#avatar-circles-animations')) {
          const styleSheet = document.createElement('style');
          styleSheet.id = 'avatar-circles-animations';
          styleSheet.textContent = \`
            @keyframes fadeInUp {
              from { opacity: 0; transform: translateY(20px); }
              to { opacity: 1; transform: translateY(0); }
            }
            
            @keyframes breathing {
              0%, 100% { transform: scale(1); }
              50% { transform: scale(1.05); }
            }
            
            @keyframes glow {
              0%, 100% { box-shadow: 0 0 5px rgba(255, 255, 255, 0.1); }
              50% { box-shadow: 0 0 15px rgba(239, 96, 19, 0.6); }
            }
            
            .avatar-cascade { 
              opacity: 0; 
              will-change: opacity, transform;
              backface-visibility: hidden;
              -webkit-backface-visibility: hidden;
              transform: translateZ(0);
              -webkit-transform: translateZ(0);
            }
            .avatar-cascade.animate { 
              animation-name: fadeInUp; 
              animation-fill-mode: forwards; 
            }
            .avatar-breathing img { 
              animation: breathing 3s infinite ease-in-out; 
              will-change: transform;
              backface-visibility: hidden;
              -webkit-backface-visibility: hidden;
            }
            .avatar-glow img { 
              animation: glow 3s infinite ease-in-out; 
              will-change: box-shadow;
            }
            
            .hover-lift:hover {
              transform: translateY(-5px) !important;
              will-change: transform;
              z-index: 100 !important;
            }
            .hover-lift:hover img {
              box-shadow: 0 5px 10px rgba(0,0,0,0.2) !important;
            }
            .hover-scale:hover {
              transform: scale(1.15) !important;
              will-change: transform;
              z-index: 100 !important;
            }
            .hover-scale:hover img {
              box-shadow: 0 5px 10px rgba(0,0,0,0.2) !important;
            }
            .hover-rotate:hover {
              transform: rotate(10deg) !important;
              will-change: transform;
              z-index: 100 !important;
            }
            .hover-rotate:hover img {
              box-shadow: 0 5px 10px rgba(0,0,0,0.2) !important;
            }
            .hover-combo:hover {
              transform: translateY(-5px) scale(1.08) !important;
              will-change: transform;
              z-index: 100 !important;
            }
            .hover-combo:hover img {
              box-shadow: 0 5px 10px rgba(0,0,0,0.2) !important;
            }
          \`;
          document.head.appendChild(styleSheet);
        }
        
        function formatNumber(num) {
          if (!abbreviateNumbers) {
            return num;
          }
          
          if (num >= 1000000) {
            return (Math.floor(num / 100000) / 10).toFixed(1).replace(/\\.0$/, '') + 'M';
          } else if (num >= 1000) {
            return (Math.floor(num / 100) / 10).toFixed(1).replace(/\\.0$/, '') + 'K';
          }
          return num;
        }
        
        avatars.forEach((avatar, index) => {
          const link = document.createElement('a');
          link.href = avatar.profileUrl;
          link.target = '_blank';
          link.rel = 'noopener noreferrer';
          
          if (animationType !== 'none') {
            link.classList.add('avatar-' + animationType);
            
            if (animationType === 'cascade') {
              const delay = index * (animationSpeed / 1000 / avatars.length);
              link.style.animationDelay = delay + 's';
              link.style.animationDuration = (animationSpeed / 1000) + 's';
            }
          }
          
          if (hoverEffect !== 'none') {
            link.classList.add('hover-' + hoverEffect);
          }
          
          Object.assign(link.style, {
            marginLeft: index > 0 ? \`-\${overlap}px\` : '0',
            transition: 'all 0.3s ease',
            position: 'relative',
            zIndex: avatars.length - index,
            display: 'inline-block'
          });
          
          const img = document.createElement('img');
          img.src = avatar.imageUrl;
          img.width = avatarSize;
          img.height = avatarSize;
          img.alt = \`Avatar \${index + 1}\`;
          
          Object.assign(img.style, {
            height: \`\${avatarSize}px\`,
            width: \`\${avatarSize}px\`,
            borderRadius: '50%',
            border: \`\${borderWidth}px solid \${borderColor}\`,
            backgroundColor: avatar.backgroundColor,
            transition: 'all 0.3s ease',
            objectFit: 'cover',
            display: 'block'
          });
          
          if (animationType === 'breathing') {
            const duration = (animationSpeed * 3) / 1000;
            img.style.animationDuration = \`\${duration}s\`;
          } else if (animationType === 'glow') {
            const duration = (animationSpeed * 3) / 1000;
            img.style.animationDuration = \`\${duration}s\`;
          }
          
          link.appendChild(img);
          container.appendChild(link);
        });
        
        if (numExtraPeople > 0) {
          const morePeopleLink = document.createElement('a');
          morePeopleLink.href = container.getAttribute('data-avatar-extra-url') || '#';
          morePeopleLink.target = '_blank';
          morePeopleLink.rel = 'noopener noreferrer';
          
          let displayText = formatNumber(numExtraPeople);
morePeopleLink.textContent = displayText;
          
          if (animationType !== 'none') {
            morePeopleLink.classList.add('avatar-' + animationType);
            
            if (animationType === 'cascade') {
              const delay = avatars.length * (animationSpeed / 1000 / (avatars.length + 1));
              morePeopleLink.style.animationDelay = delay + 's';
              morePeopleLink.style.animationDuration = (animationSpeed / 1000) + 's';
            } else if (animationType === 'breathing') {
              const duration = (animationSpeed * 3) / 1000;
              morePeopleLink.style.animationDuration = \`\${duration}s\`;
            } else if (animationType === 'glow') {
              const duration = (animationSpeed * 3) / 1000;
              morePeopleLink.style.animationDuration = \`\${duration}s\`;
            }
          }
          
          if (hoverEffect !== 'none') {
            morePeopleLink.classList.add('hover-' + hoverEffect);
          }
          
          const baseCounterStyles = {
            display: 'inline-flex',
            alignItems: 'center',
            justifyContent: 'center',
            backgroundColor: extraBgColor,
            color: extraTextColor,
            fontSize: \`\${Math.max(12, avatarSize / 3)}px\`,
            fontWeight: '600',
            textDecoration: 'none',
            transition: 'all 0.3s ease',
            position: 'relative'
          };
          
          switch(counterStyle) {
            case 'circle':
              Object.assign(morePeopleLink.style, {
                ...baseCounterStyles,
                height: \`\${avatarSize}px\`,
                width: \`\${avatarSize}px\`,
                borderRadius: '50%',
                border: \`\${borderWidth}px solid \${borderColor}\`,
                marginLeft: \`-\${overlap}px\`
              });
              break;
              
            case 'auto-expand':
              const digitCount = displayText.length;
              const extraWidth = avatarSize * (1 + (digitCount > 2 ? (digitCount - 2) * 0.35 : 0));
              Object.assign(morePeopleLink.style, {
                ...baseCounterStyles,
                height: \`\${avatarSize}px\`,
                width: \`\${extraWidth}px\`,
                borderRadius: '50%',
                border: \`\${borderWidth}px solid \${borderColor}\`,
                marginLeft: \`-\${overlap}px\`
              });
              break;
              
            case 'pill':
              Object.assign(morePeopleLink.style, {
                ...baseCounterStyles,
                height: \`\${avatarSize}px\`,
                minWidth: \`\${avatarSize}px\`,
                padding: '0 10px',
                borderRadius: \`\${avatarSize / 2}px\`,
                border: \`\${borderWidth}px solid \${borderColor}\`,
                marginLeft: \`-\${overlap}px\`
              });
              break;
              
            case 'badge':
              Object.assign(morePeopleLink.style, {
                ...baseCounterStyles,
                height: \`\${Math.max(24, avatarSize * 0.7)}px\`,
                minWidth: \`\${Math.max(24, avatarSize * 0.7)}px\`,
                borderRadius: '20px',
                marginLeft: '8px',
                boxShadow: '0 2px 6px rgba(0,0,0,0.2)',
                whiteSpace: 'nowrap',
                paddingLeft: \`\${Math.max(12, displayText.length * 3)}px\`,
                paddingRight: \`\${Math.max(12, displayText.length * 3)}px\`
              });
              break;
          }
          
          container.appendChild(morePeopleLink);
        }
        
        if (animationType === 'cascade' && animateOnScroll) {
          const observer = new IntersectionObserver(entries => {
            entries.forEach(entry => {
              if (entry.isIntersecting) {
                setTimeout(() => {
                  entry.target.querySelectorAll('.avatar-cascade').forEach(el => {
                    el.classList.add('animate');
                  });
                }, 100);
                observer.unobserve(entry.target);
              }
            });
          }, { threshold: 0.2 });
          
          observer.observe(container);
        } else if (animationType === 'cascade') {
          setTimeout(() => {
            container.querySelectorAll('.avatar-cascade').forEach(el => {
              el.classList.add('animate');
            });
          }, 100);
        }
      } catch (error) {
        console.warn('Error initializing avatar circles:', error);
      }
    });
  }
  
  let initialized = false;
  
  function init() {
    if (initialized) {
      return;
    }
    
    initialized = true;
    initAvatarCircles();
  }
  
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }
  
  window.addEventListener('load', init);
  
  window.AvatarCircles = {
    init: init,
    version: '1.0'
  };
})();`;
      }

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

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

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

      window.resetParameter = function(parameterId, defaultValue) {
        const element = document.getElementById(parameterId);
        if (element) {
          element.value = defaultValue;
          const valueElement = document.getElementById(`${parameterId}-value`);
          if (valueElement) {
            valueElement.textContent = defaultValue;
          }
          
          switch (parameterId) {
            case 'avatar-size':
              avatarCirclesConfig.avatarSize = defaultValue;
              break;
            case 'border-width':
              avatarCirclesConfig.borderWidth = defaultValue;
              break;
            case 'overlap':
              avatarCirclesConfig.overlap = defaultValue;
              break;
            case 'animation-speed':
              avatarCirclesConfig.animationSpeed = defaultValue;
              break;
          }
          
          updatePreview();
          showNotification(`${parameterId.replace(/-/g, ' ')} reset to default`);
        }
      };

      function saveConfiguration() {
        try {
          localStorage.setItem('bricksfusion-avatar-circles-config', JSON.stringify(avatarCirclesConfig));
        } catch (e) {
          // localStorage no disponible o lleno
        }
      }

      function loadConfiguration() {
        try {
          const saved = localStorage.getItem('bricksfusion-avatar-circles-config');
          if (saved) {
            const savedConfig = JSON.parse(saved);
            Object.assign(avatarCirclesConfig, savedConfig);
            initUI();
            updatePreview();
          }
        } catch (e) {
          // Error loading configuration
        }
      }

      // Inicialización
      initUI();
      setupEventListeners();
      updatePreview();
      loadConfiguration();

      // Override updatePreview para guardar configuración
      const originalUpdatePreview = updatePreview;
      updatePreview = function() {
        originalUpdatePreview();
        saveConfiguration();
      };

      // Mensaje de bienvenida
      setTimeout(() => {
        showNotification('BricksFusion Avatar Circles Configurator loaded!');
      }, 500);
    });
  </script>
</body>
</html>
Avatar Stack - Bricksfusion
LIGHTWEIGHT

Avatar Stack

Displays overlapping avatars in a horizontal stack with an optional counter. Perfect for showing team members, participants, or social proof.

Hover over avatars to see effects

Avatars

Avatar Images image upload

Upload the avatar images you want to display. You can add as many as you need. They will appear in the order you upload them.

Default: Placeholder avatars if none uploaded

Appearance

Avatar Size 20-100 pixels

Size of each avatar circle. Larger sizes make them more prominent.

Default: 40

Border Radius 0-50%

Roundness of the avatars. 50 makes perfect circles, 0 makes squares, values in between create rounded squares.

Default: 50 (circle)

Overlap 0-50 pixels

How much each avatar overlaps the previous one. Higher values create tighter stacking.

Default: 16

Border Width 0-10 pixels

Thickness of the border around each avatar. Set to 0 for no border.

Default: 2

Border Color color picker

Color of the border around each avatar. Usually white or matching your background.

Default: White

Counter

Extra Count 0-999999

Shows a counter at the end like "+127". Set to 0 to hide it. Great for showing how many more people are involved.

Default: 0 (hidden)

Abbreviate Numbers on/off

Converts large numbers into shorter format. 1000 becomes "1K", 1500000 becomes "1.5M".

Default: Off

Counter Style circle / auto-expand / pill / badge

Shape of the counter. Circle matches avatar size, auto-expand widens for long numbers, pill is rounded rectangle, badge is a separate bubble.

Default: Circle

Counter Background color picker

Background color of the counter.

Default: Blue

Counter Hover Color color picker

Background color when hovering over the counter.

Default: Dark Blue

Counter Text Color color picker

Color of the number text inside the counter.

Default: White

Animation

Animation Type none / cascade / breathing / glow

Choose an entrance or continuous animation. None means no animation, cascade makes them appear one by one, breathing creates a subtle pulse, glow adds a soft glow effect.

Default: None

Animation Speed 100-2000 milliseconds

How fast the animation happens. Lower = faster, higher = slower.

Default: 500

Animate On Scroll on/off

When on, the cascade animation waits until the element is scrolled into view. Only works with cascade animation.

Default: Off

Hover Effects

Hover Effect none / lift / scale / rotate / combo

What happens when you hover over an avatar. Lift moves it up, scale makes it bigger, rotate spins it slightly, combo does both lift and scale together.

Default: Lift

Performance

This element is lightweight and uses simple animations. Safe to use many times on the same page without any performance concerns.