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>Button Reveal Effect Configurator - BricksFusion</title>
    <style>
        :root {
            --background: #000;
            --card-bg: #1e1e1e;
            --card-bg-hover: #252525;
            --text-primary: #f2f2f7;
            --text-secondary: #8e8e93;
            --accent: #ef6013;
            --accent-hover: #c64c0c;
            --border: #2c2c2e;
            --shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
            --track: #2c2c2e;
            --thumb: #ef6013;
            --card-radius: 16px;
            --input-radius: 8px;
            --button-radius: 12px;
            --transition: all 0.25s ease;
            --font: 'Inter', BlinkMacSystemFont, "San Francisco", "Helvetica Neue", Helvetica, Arial, sans-serif;
            --action-bar-height: 70px;
            
        }

        * {
            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;
        }

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

        .preview-wrapper {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 1.5rem;
            z-index: 2;
        }

        .preview-content {
            text-align: center;
            color: white;
            font-weight: bold;
            font-size: var(--text-s);
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
            margin: 0;
        }

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

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

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

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

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

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

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

        .card-content {
            padding: 1.5rem;
        }

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

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

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

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

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

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

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

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

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

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

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

        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="range"]::-moz-range-thumb {
            width: 20px;
            height: 20px;
            background: var(--thumb);
            border: none;
            border-radius: 50%;
            cursor: pointer;
            transition: var(--transition);
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
        }

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

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

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

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

        .radio-group {
            display: flex;
            gap: 10px;
            margin-bottom: 1rem;
            flex-wrap: wrap;
        }

        .radio-option {
            flex: 1;
            min-width: 80px;
            text-align: center;
        }

        .radio-option input[type="radio"] {
            display: none;
        }

        .radio-option label {
            display: block;
            padding: 8px;
            background-color: var(--card-bg);
            border: 1px solid var(--border);
            border-radius: var(--input-radius);
            color: var(--text-secondary);
            font-size: var(--text-xs);
            cursor: pointer;
            transition: var(--transition);
        }

        .radio-option input[type="radio"]:checked + label {
            background-color: var(--accent);
            color: white;
            border-color: var(--accent);
        }

        .radio-option label:hover {
            border-color: var(--accent);
            background-color: rgba(239, 96, 19, 0.1);
        }

        .notification {
            position: fixed;
            bottom: calc(var(--action-bar-height) + 1rem);
            left: 50%;
            background-color: #28a745;
            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;
        }

        .demo-btn {
            background-color: var(--accent);
            color: white;
            border: none;
            border-radius: 8px;
            padding: 10px 20px;
            font-size: var(--text-xs);
            font-weight: 500;
            cursor: pointer;
            transition: var(--transition);
            position: relative;
            z-index: 3;
        }

        .demo-btn:hover {
            background-color: var(--accent-hover);
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(239, 96, 19, 0.3);
        }

        .video-container {
            position: fixed;
            width: 0;
            height: 0;
            display: none;
            z-index: 10000;
            overflow: hidden;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
            background-color: #000;
        }

        .video-preview {
            width: 100% !important;
            height: 100% !important;
            object-fit: cover;
            display: block;
        }

        .backdrop-preview {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            width: 100vw;
            height: 100vh;
            background-color: rgba(0, 0, 0, 0);
            backdrop-filter: blur(0px);
            z-index: 9999;
            opacity: 0;
            transition: opacity 0.5s ease, backdrop-filter 0.5s ease, background-color 0.5s ease;
            pointer-events: none;
        }
        
        .backdrop-preview.active {
            opacity: 1;
            pointer-events: auto;
        }

        @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);
            }
            
            .preview-container {
                height: 300px;
            }
            
            .page-title {
                font-size: 2rem;
            }
        }

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

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

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

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

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

        ::-webkit-scrollbar-thumb:hover {
            background: var(--accent);
        }
    </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/visual-effects/" class="breadcrumb-item">Visual effects</a>
            <span class="breadcrumb-separator">›</span>
            <span class="breadcrumb-item active">Button Reveal Effect</span>
        </nav>
        
        <div class="action-buttons">
            <div class="data-attribute-display" id="quick-attribute" title="Click to copy data attribute">
                data-button-reveal
            </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">Button Reveal Effect</h1>
            <p class="page-subtitle">Interactive video reveal animations for Bricks Builder</p>
        </div>

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

        <div class="content">
            <section class="preview-section">
                <div class="preview-container" id="button-reveal-preview">
                    <div class="backdrop-preview" id="backdrop-preview"></div>
                    <div class="video-container" id="video-container"></div>
                    <div class="preview-wrapper">
                        <div class="preview-content">Interactive Button Reveal Preview</div>
                        <button class="demo-btn" id="demo-button" data-button-reveal>
                            Click to Open Video
                        </button>
                    </div>
                </div>
            </section>

            <section class="controls-section">
                <div class="card">
                    <div class="card-heading">
                        Video Settings
                        <div class="card-actions">
                            <button class="card-action-btn" id="reset-video" title="Reset Video Settings">↺</button>
                        </div>
                    </div>
                    <div class="card-content">
                        <div class="control-group">
                            <div class="control-label">
                                <span class="label-text">Video URL</span>
                            </div>
                            <input type="url" id="video-url" placeholder="Enter video URL" value="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4">
                        </div>
                        
                        <div class="switch-container">
                            <span class="switch-label">
                                Show Video Controls
                                <span class="help-tooltip" title="Enable playback controls on the video">ℹ</span>
                            </span>
                            <label class="switch">
                                <input type="checkbox" id="video-controls">
                                <span class="slider"></span>
                            </label>
                        </div>
                        
                        <div class="control-group">
                            <div class="control-label">
                                <span class="label-text">Video Fit</span>
                            </div>
                            <div class="radio-group">
                                <div class="radio-option">
                                    <input type="radio" id="fit-cover" name="fit" value="cover" checked>
                                    <label for="fit-cover">Cover</label>
                                </div>
                                <div class="radio-option">
                                    <input type="radio" id="fit-contain" name="fit" value="contain">
                                    <label for="fit-contain">Contain</label>
                                </div>
                                <div class="radio-option">
                                    <input type="radio" id="fit-fill" name="fit" value="fill">
                                    <label for="fit-fill">Fill</label>
                                </div>
                            </div>
                        </div>
                        
                        <div class="control-group">
                            <div class="control-label">
                                <span class="label-text">Default Video Size</span>
                            </div>
                            <div class="radio-group">
                                <div class="radio-option">
                                    <input type="radio" id="size-small" name="size" value="small">
                                    <label for="size-small">Small</label>
                                </div>
                                <div class="radio-option">
                                    <input type="radio" id="size-medium" name="size" value="medium">
                                    <label for="size-medium">Medium</label>
                                </div>
                                <div class="radio-option">
                                    <input type="radio" id="size-large" name="size" value="large">
                                    <label for="size-large">Large</label>
                                </div>
                                <div class="radio-option">
                                    <input type="radio" id="size-full" name="size" value="full" checked>
                                    <label for="size-full">Full</label>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
          
                <div class="card">
                    <div class="card-heading">
                        Animation Settings
                        <div class="card-actions">
                            <button class="card-action-btn" id="reset-animation" title="Reset Animation Settings">↺</button>
                        </div>
                    </div>
                    <div class="card-content">
                        <div class="control-group">
                            <div class="control-label">
                                <span class="label-text">
                                    Animation Speed
                                    <span class="help-tooltip" title="Overall speed multiplier for animations">ℹ</span>
                                </span>
                                <div class="value-display">
                                    <span class="value-text"><span id="animation-speed-value">1</span>x</span>
                                    <button class="reset-btn" onclick="resetParameter('animation-speed', 1)">↺</button>
                                </div>
                            </div>
                            <input type="range" id="animation-speed" min="0.5" max="2" step="0.1" value="1">
                        </div>
                        
                        <div class="control-group">
                            <div class="control-label">
                                <span class="label-text">
                                    Base Duration
                                    <span class="help-tooltip" title="Base animation duration in seconds">ℹ</span>
                                </span>
                                <div class="value-display">
                                    <span class="value-text"><span id="animation-duration-value">1</span>s</span>
                                    <button class="reset-btn" onclick="resetParameter('animation-duration', 1)">↺</button>
                                </div>
                            </div>
                            <input type="range" id="animation-duration" min="0.5" max="2" step="0.1" value="1">
                        </div>
                        
                        <div class="control-group">
                            <div class="control-label">
                                <span class="label-text">
                                    Mobile Animation Duration
                                    <span class="help-tooltip" title="Animation duration for mobile devices">ℹ</span>
                                </span>
                                <div class="value-display">
                                    <span class="value-text"><span id="mobile-duration-value">0.8</span>s</span>
                                    <button class="reset-btn" onclick="resetParameter('mobile-duration', 0.8)">↺</button>
                                </div>
                            </div>
                            <input type="range" id="mobile-duration" min="0.3" max="1.5" step="0.1" value="0.8">
                        </div>
                        
                        <div class="control-group">
                            <div class="control-label">
                                <span class="label-text">
                                    Mobile Scale Factor
                                    <span class="help-tooltip" title="Scale factor for mobile animations">ℹ</span>
                                </span>
                                <div class="value-display">
                                    <span class="value-text"><span id="mobile-scale-value">0.9</span>x</span>
                                    <button class="reset-btn" onclick="resetParameter('mobile-scale', 0.9)">↺</button>
                                </div>
                            </div>
                            <input type="range" id="mobile-scale" min="0.7" max="1" step="0.05" value="0.9">
                        </div>
                        
                        <div class="control-group">
                            <div class="control-label">
                                <span class="label-text">Easing Animation</span>
                            </div>
                            <div class="radio-group">
                                <div class="radio-option">
                                    <input type="radio" id="easing-power2" name="easing" value="power2.inOut" checked>
                                    <label for="easing-power2">Smooth</label>
                                </div>
                                <div class="radio-option">
                                    <input type="radio" id="easing-power3" name="easing" value="power3.inOut">
                                    <label for="easing-power3">Strong</label>
                                </div>
                                <div class="radio-option">
                                    <input type="radio" id="easing-back" name="easing" value="back.out">
                                    <label for="easing-back">Bounce</label>
                                </div>
                                <div class="radio-option">
                                    <input type="radio" id="easing-elastic" name="easing" value="elastic.out">
                                    <label for="easing-elastic">Elastic</label>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                
                <div class="card">
                    <div class="card-heading">
                        Visual Settings
                        <div class="card-actions">
                            <button class="card-action-btn" id="reset-visual" title="Reset Visual Settings">↺</button>
                        </div>
                    </div>
                    <div class="card-content">
                        <div class="control-group">
                            <div class="control-label">
                                <span class="label-text">
                                    Border Radius
                                    <span class="help-tooltip" title="Corner radius of the video container">ℹ</span>
                                </span>
                                <div class="value-display">
                                    <span class="value-text"><span id="border-radius-value">20</span>px</span>
                                    <button class="reset-btn" onclick="resetParameter('border-radius', 20)">↺</button>
                                </div>
                            </div>
                            <input type="range" id="border-radius" min="0" max="40" step="1" value="20">
                        </div>
                        
                        <div class="control-group">
                            <div class="control-label">
                                <span class="label-text">
                                    Backdrop Blur Amount
                                    <span class="help-tooltip" title="Blur effect for the background overlay">ℹ</span>
                                </span>
                                <div class="value-display">
                                    <span class="value-text"><span id="backdrop-blur-value">10</span>px</span>
                                    <button class="reset-btn" onclick="resetParameter('backdrop-blur', 10)">↺</button>
                                </div>
                            </div>
                            <input type="range" id="backdrop-blur" min="0" max="20" step="1" value="10">
                        </div>
                        
                        <div class="control-group">
                            <div class="control-label">
                                <span class="label-text">
                                    Backdrop Opacity
                                    <span class="help-tooltip" title="Opacity of the background overlay">ℹ</span>
                                </span>
                                <div class="value-display">
                                    <span class="value-text"><span id="backdrop-opacity-value">0.5</span></span>
                                    <button class="reset-btn" onclick="resetParameter('backdrop-opacity', 0.5)">↺</button>
                                </div>
                            </div>
                            <input type="range" id="backdrop-opacity" min="0" max="1" step="0.05" value="0.5">
                        </div>
                    </div>
                </div>
            </section>
        </div>
    </div>

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

    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.4/gsap.min.js"></script>
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            let brConfig = {
                animation: {
                    defaultSpeed: 1,
                    duration: 1,
                    mobileDuration: 0.8,
                    mobileScale: 0.9,
                    easingIn: 'power2.inOut',
                    easingOut: 'power2.inOut',
                },
                video: {
                    url: 'https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4',
                    controls: false,
                    fit: 'cover',
                    size: 'full',
                },
                container: {
                    borderRadius: 20,
                    backdropBlur: 10,
                    backdropOpacity: 0.5,
                }
            };
            
            const defaultConfig = JSON.parse(JSON.stringify(brConfig));
            
            let previewVideo = null;
            let previewState = 'closed';
            let activeAnimation = null;
            
            function initializeUI() {
                setupRangeSliders();
                setupInputs();
                setupRadioButtons();
                setupSwitches();
                setupButtons();
                setupInstructions();
                setupDemoButton();
                setupKeyboardShortcuts();
                loadConfiguration();
                updatePreview();
                
                setTimeout(() => {
                    showNotification('Button Reveal Effect Configurator loaded!');
                }, 500);
            }
            
            function setupRangeSliders() {
                const rangeInputs = [
                    { id: 'animation-speed', key: 'animation.defaultSpeed' },
                    { id: 'animation-duration', key: 'animation.duration' },
                    { id: 'mobile-duration', key: 'animation.mobileDuration' },
                    { id: 'mobile-scale', key: 'animation.mobileScale' },
                    { id: 'border-radius', key: 'container.borderRadius' },
                    { id: 'backdrop-blur', key: 'container.backdropBlur' },
                    { id: 'backdrop-opacity', key: 'container.backdropOpacity' }
                ];
                
                rangeInputs.forEach(({ id, key }) => {
                    const slider = document.getElementById(id);
                    const valueDisplay = document.getElementById(`${id}-value`);
                    
                    if (slider && valueDisplay) {
                        valueDisplay.textContent = slider.value;
                        
                        slider.addEventListener('input', function() {
                            valueDisplay.textContent = this.value;
                            updateConfigValue(key, parseFloat(this.value));
                            updateConfig();
                        });
                    }
                });
            }
            
            function setupInputs() {
                const videoUrlInput = document.getElementById('video-url');
                
                ['input', 'change', 'paste'].forEach(eventType => {
                    videoUrlInput.addEventListener(eventType, function() {
                        setTimeout(() => {
                            brConfig.video.url = this.value.trim();
                            updateConfig();
                        }, 100);
                    });
                });
            }
            
            function setupRadioButtons() {
                document.querySelectorAll('input[name="easing"]').forEach(radio => {
                    radio.addEventListener('change', function() {
                        if (this.checked) {
                            brConfig.animation.easingIn = this.value;
                            brConfig.animation.easingOut = this.value;
                            updateConfig();
                        }
                    });
                });
                
                document.querySelectorAll('input[name="size"]').forEach(radio => {
                    radio.addEventListener('change', function() {
                        if (this.checked) {
                            brConfig.video.size = this.value;
                            updateConfig();
                        }
                    });
                });
                
                document.querySelectorAll('input[name="fit"]').forEach(radio => {
                    radio.addEventListener('change', function() {
                        if (this.checked) {
                            brConfig.video.fit = this.value;
                            updateConfig();
                        }
                    });
                });
            }
            
            function setupSwitches() {
                const videoControlsSwitch = document.getElementById('video-controls');
                videoControlsSwitch.addEventListener('change', function() {
                    brConfig.video.controls = this.checked;
                    updateConfig();
                });
            }
            
            function setupButtons() {
                document.getElementById('quick-attribute').addEventListener('click', () => {
                    copyToClipboard('data-button-reveal');
                });
                
                document.getElementById('download-config').addEventListener('click', function() {
                    const downloadBtn = this;
                    if (downloadBtn.hasAttribute('data-protection-animation')) {
                        copyJsToClipboard();
                    } else {
                        copyJsToClipboard();
                    }
                });
                
                document.getElementById('copy-full-section').addEventListener('click', function() {
                    const fullSectionBtn = this;
                    if (fullSectionBtn.hasAttribute('data-protection-animation')) {
                        copyFullSectionToClipboard();
                    } else {
                        copyFullSectionToClipboard();
                    }
                });
                
                document.getElementById('reset-video').addEventListener('click', () => {
                    brConfig.video = JSON.parse(JSON.stringify(defaultConfig.video));
                    updateUIFromConfig();
                    updateConfig();
                    showNotification('Video settings reset to default');
                });
                
                document.getElementById('reset-animation').addEventListener('click', () => {
                    brConfig.animation = JSON.parse(JSON.stringify(defaultConfig.animation));
                    updateUIFromConfig();
                    updateConfig();
                    showNotification('Animation settings reset to default');
                });
                
                document.getElementById('reset-visual').addEventListener('click', () => {
                    brConfig.container = JSON.parse(JSON.stringify(defaultConfig.container));
                    updateUIFromConfig();
                    updateConfig();
                    showNotification('Visual settings reset to default');
                });
            }
            
            function setupInstructions() {
                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');
                    }
                });
            }
            
            function setupDemoButton() {
                const demoButton = document.getElementById('demo-button');
                const videoContainer = document.getElementById('video-container');
                const backdropPreview = document.getElementById('backdrop-preview');
                
                demoButton.addEventListener('click', function() {
                    if (previewState === 'closed') {
                        openPreview();
                    } else if (previewState === 'open') {
                        closePreview();
                    }
                });
                
                backdropPreview.addEventListener('click', function() {
                    if (previewState === 'open') {
                        closePreview();
                    }
                });
                
                videoContainer.addEventListener('click', function(e) {
                    if (previewState === 'open' && (!brConfig.video.controls || e.target !== previewVideo)) {
                        e.stopPropagation();
                        closePreview();
                    }
                });
            }
            
            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.click();
                                }
                                break;
                            case 's':
                                e.preventDefault();
                                const fullSectionBtn = document.getElementById('copy-full-section');
                                if (fullSectionBtn) {
                                    fullSectionBtn.click();
                                }
                                break;
                        }
                    }
                });
            }
            
            function updateConfigValue(path, value) {
                const keys = path.split('.');
                let obj = brConfig;
                for (let i = 0; i < keys.length - 1; i++) {
                    obj = obj[keys[i]];
                }
                obj[keys[keys.length - 1]] = value;
            }
            
            function updateConfig() {
                if (previewVideo && previewState === 'open') {
                    if (previewVideo.tagName === 'VIDEO') {
                        previewVideo.controls = brConfig.video.controls;
                        previewVideo.muted = !brConfig.video.controls;
                        previewVideo.style.objectFit = brConfig.video.fit;
                    }
                    
                    const videoContainer = document.getElementById('video-container');
                    const backdropPreview = document.getElementById('backdrop-preview');
                    
                    if (videoContainer) {
                        videoContainer.style.borderRadius = `${brConfig.container.borderRadius}px`;
                    }
                    
                    if (backdropPreview) {
                        backdropPreview.style.backdropFilter = `blur(${brConfig.container.backdropBlur}px)`;
                        backdropPreview.style.backgroundColor = `rgba(0, 0, 0, ${brConfig.container.backdropOpacity})`;
                    }
                }
                saveConfiguration();
            }
            
            function updatePreview() {
                updateConfig();
            }
            
            function updateUIFromConfig() {
                document.getElementById('video-url').value = brConfig.video.url;
                document.getElementById('video-controls').checked = brConfig.video.controls;
                
                document.querySelector(`input[name="fit"][value="${brConfig.video.fit}"]`).checked = true;
                document.querySelector(`input[name="size"][value="${brConfig.video.size}"]`).checked = true;
                document.querySelector(`input[name="easing"][value="${brConfig.animation.easingIn}"]`).checked = true;
                
                const sliders = [
                    { id: 'animation-speed', value: brConfig.animation.defaultSpeed },
                    { id: 'animation-duration', value: brConfig.animation.duration },
                    { id: 'mobile-duration', value: brConfig.animation.mobileDuration },
                    { id: 'mobile-scale', value: brConfig.animation.mobileScale },
                    { id: 'border-radius', value: brConfig.container.borderRadius },
                    { id: 'backdrop-blur', value: brConfig.container.backdropBlur },
                    { id: 'backdrop-opacity', value: brConfig.container.backdropOpacity }
                ];
                
                sliders.forEach(({ id, value }) => {
                    const slider = document.getElementById(id);
                    const valueDisplay = document.getElementById(`${id}-value`);
                    if (slider && valueDisplay) {
                        slider.value = value;
                        valueDisplay.textContent = value;
                    }
                });
            }
            
            function createVideoElement() {
                const videoContainer = document.getElementById('video-container');
                videoContainer.innerHTML = '';
                
                if (previewVideo) {
                    if (previewVideo.tagName === 'VIDEO') {
                        previewVideo.pause();
                        previewVideo.removeAttribute('src');
                        previewVideo.load();
                    }
                    previewVideo = null;
                }
                
                const latestUrl = document.getElementById('video-url').value.trim();
                brConfig.video.url = latestUrl;
                
                const fallbackUrl = "https://storage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4";
                
                if (!latestUrl) {
                    brConfig.video.url = fallbackUrl;
                }
                
                const isStreamingService = (url) => {
                    return url.includes('youtube.com') || url.includes('youtu.be') || 
                           url.includes('vimeo.com') || url.includes('player.vimeo.com');
                };
                
                if (isStreamingService(brConfig.video.url)) {
                    const iframe = document.createElement('iframe');
                    let embedUrl = brConfig.video.url;
                    
                    if (brConfig.video.url.includes('youtube.com') || brConfig.video.url.includes('youtu.be')) {
                        const videoId = brConfig.video.url.includes('youtu.be/') 
                            ? brConfig.video.url.split('youtu.be/')[1].split('?')[0]
                            : brConfig.video.url.includes('v=') 
                                ? brConfig.video.url.split('v=')[1].split('&')[0] 
                                : '';
                        
                        if (videoId) {
                            embedUrl = `https://www.youtube.com/embed/${videoId}?autoplay=1&mute=${!brConfig.video.controls ? 1 : 0}&controls=${brConfig.video.controls ? 1 : 0}`;
                        }
                    } else if (brConfig.video.url.includes('vimeo.com')) {
                        const vimeoId = brConfig.video.url.split('vimeo.com/')[1]?.split('/')[0]?.split('?')[0];
                        if (vimeoId) {
                            embedUrl = `https://player.vimeo.com/video/${vimeoId}?autoplay=1&muted=${!brConfig.video.controls ? 1 : 0}`;
                        }
                    }
                    
                    iframe.src = embedUrl;
                    iframe.style.width = '100%';
                    iframe.style.height = '100%';
                    iframe.style.border = 'none';
                    iframe.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture';
                    iframe.allowFullscreen = true;
                    
                    videoContainer.appendChild(iframe);
                    return iframe;
                }
                
                previewVideo = document.createElement('video');
                previewVideo.className = 'video-preview';
                previewVideo.muted = !brConfig.video.controls;
                previewVideo.controls = brConfig.video.controls;
                previewVideo.loop = true;
                previewVideo.playsInline = true;
                previewVideo.setAttribute('playsinline', '');
                previewVideo.style.objectFit = brConfig.video.fit;
                previewVideo.style.width = "100%";
                previewVideo.style.height = "100%";
                
                previewVideo.addEventListener('error', function(e) {
                    if (previewVideo.src !== fallbackUrl) {
                        previewVideo.src = fallbackUrl;
                        previewVideo.load();
                    }
                });
                
                videoContainer.appendChild(previewVideo);
                
                try {
                    previewVideo.src = brConfig.video.url;
                    previewVideo.load();
                } catch (err) {
                    previewVideo.src = fallbackUrl;
                    previewVideo.load();
                }
                
                return previewVideo;
            }
            
            function openPreview() {
                if (activeAnimation) {
                    activeAnimation.kill();
                }
                
                previewState = 'opening';
                
                const demoButton = document.getElementById('demo-button');
                const videoContainer = document.getElementById('video-container');
                const backdropPreview = document.getElementById('backdrop-preview');
                
                const latestUrl = document.getElementById('video-url').value.trim();
                brConfig.video.url = latestUrl;
                
                backdropPreview.style.position = 'fixed';
                backdropPreview.style.top = '0';
                backdropPreview.style.left = '0';
                backdropPreview.style.width = '100%';
                backdropPreview.style.height = '100%';
                backdropPreview.style.zIndex = '9999';
                backdropPreview.style.backdropFilter = `blur(${brConfig.container.backdropBlur}px)`;
                backdropPreview.style.backgroundColor = `rgba(0, 0, 0, ${brConfig.container.backdropOpacity})`;
                backdropPreview.classList.add('active');
                
                const btnRect = demoButton.getBoundingClientRect();
                
                videoContainer.style.position = 'fixed';
                videoContainer.style.zIndex = '10000';
                videoContainer.style.display = 'block';
                videoContainer.style.borderRadius = `${brConfig.container.borderRadius}px`;
                videoContainer.style.overflow = 'hidden';
                
                const newVideo = createVideoElement();
                
                const duration = brConfig.animation.duration / brConfig.animation.defaultSpeed;
                
                activeAnimation = gsap.timeline();
                
                activeAnimation.to(demoButton, {
                    opacity: 0,
                    scale: 0.8,
                    duration: duration * 0.5,
                    ease: brConfig.animation.easingOut
                });
                
                const windowWidth = window.innerWidth;
                const windowHeight = window.innerHeight;
                const sizeInPx = getVideoSizeInPx(brConfig.video.size);
                
                const finalWidth = sizeInPx.width === '100%' ? windowWidth * 0.9 : Math.min(sizeInPx.width, windowWidth * 0.9);
                const finalHeight = sizeInPx.height === '100%' ? windowHeight * 0.9 : Math.min(sizeInPx.height, windowHeight * 0.9);
                
                gsap.set(videoContainer, {
                    left: btnRect.left,
                    top: btnRect.top,
                    width: btnRect.width,
                    height: btnRect.height,
                    opacity: 0,
                    xPercent: 0,
                    yPercent: 0,
                    scale: 1,
                    transformOrigin: "center center"
                });
                
                activeAnimation.to(videoContainer, {
                    left: (windowWidth - finalWidth) / 2,
                    top: (windowHeight - finalHeight) / 2,
                    width: finalWidth,
                    height: finalHeight,
                    opacity: 1,
                    duration: duration,
                    ease: brConfig.animation.easingIn,
                    onComplete: () => {
                        previewState = 'open';
                        if (newVideo && newVideo.tagName === 'VIDEO') {
                            newVideo.play().catch(err => {
                                const fallbackUrl = "https://storage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4";
                                if (newVideo.src !== fallbackUrl) {
                                    newVideo.src = fallbackUrl;
                                    newVideo.load();
                                    newVideo.play().catch(secondErr => {});
                                }
                            });
                        }
                    }
                }, "-=0.3");
            }
            
            function closePreview() {
                if (activeAnimation) {
                    activeAnimation.kill();
                }
                
                previewState = 'closing';
                
                const demoButton = document.getElementById('demo-button');
                const videoContainer = document.getElementById('video-container');
                const backdropPreview = document.getElementById('backdrop-preview');
                
                if (previewVideo && previewVideo.tagName === 'VIDEO') {
                    previewVideo.pause();
                }
                
                backdropPreview.classList.remove('active');
                
                const duration = brConfig.animation.duration / brConfig.animation.defaultSpeed;
                const btnRect = demoButton.getBoundingClientRect();
                
                activeAnimation = gsap.timeline();
                
                activeAnimation.to(videoContainer, {
                    left: btnRect.left,
                    top: btnRect.top,
                    width: btnRect.width,
                    height: btnRect.height,
                    opacity: 0,
                    duration: duration,
                    ease: brConfig.animation.easingOut,
                    onComplete: () => {
                        videoContainer.style.display = 'none';
                        videoContainer.innerHTML = '';
                        previewVideo = null;
                        previewState = 'closed';
                    }
                });
                
                activeAnimation.to(demoButton, {
                    opacity: 1,
                    scale: 1,
                    duration: duration * 0.5,
                    ease: brConfig.animation.easingIn
                }, "-=0.3");
            }
            
            function getVideoSizeInPx(size) {
                switch(size) {
                    case 'small': return { width: 300, height: 300 };
                    case 'medium': return { width: 600, height: 400 };
                    case 'large': return { width: 800, height: 600 };
                    default: return { width: '100%', height: '100%' };
                }
            }
            
            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;
                    }
                    
                    const pathMap = {
                        'animation-speed': 'animation.defaultSpeed',
                        'animation-duration': 'animation.duration',
                        'mobile-duration': 'animation.mobileDuration',
                        'mobile-scale': 'animation.mobileScale',
                        'border-radius': 'container.borderRadius',
                        'backdrop-blur': 'container.backdropBlur',
                        'backdrop-opacity': 'container.backdropOpacity'
                    };
                    
                    if (pathMap[parameterId]) {
                        updateConfigValue(pathMap[parameterId], defaultValue);
                        updateConfig();
                    }
                    
                    showNotification(`${parameterId.replace(/-/g, ' ')} reset to default`);
                }
            };

            function generateUniqueId() {
    return Math.random().toString(36).substr(2, 9) + Date.now().toString(36);
}
            
            function generateFullSectionJSON() {
  // Generar IDs únicos para todos los elementos
  const sectionId = generateUniqueId();
  const containerId = generateUniqueId();
  const divId = generateUniqueId();
  const buttonId = generateUniqueId();
  const codeId = generateUniqueId();
  const attributeId = generateUniqueId();

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

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

  return JSON.stringify(bricksJSON, null, 2);
}
            
            function generateJavaScriptCode() {
                return `(function() {
  class AnimationManager {
    constructor() {
      this.animationQueue = [];
      this.isAnimating = false;
    }
  
    queue(animationFunction) {
      this.animationQueue.push(animationFunction);
      if (!this.isAnimating) {
        this.processQueue();
      }
    }
  
    async processQueue() {
      if (this.animationQueue.length === 0) {
        this.isAnimating = false;
        return;
      }
  
      this.isAnimating = true;
      const nextAnimation = this.animationQueue.shift();
      await nextAnimation();
      this.processQueue();
    }
  }
  
  const CONFIG = {
    ATTRIBUTES: {
      button: 'data-button-reveal',
      videoUrl: null
    },
    SIZES: {
      small: { width: 300, height: 300 },
      medium: { width: 600, height: 400 },
      large: { width: 800, height: 600 },
      full: { width: '100%', height: '100%' }
    },
    ANIMATION: {
      defaultSpeed: ${brConfig.animation.defaultSpeed},
      duration: ${brConfig.animation.duration},
      easingIn: '${brConfig.animation.easingIn}',
      easingOut: '${brConfig.animation.easingOut}',
      mobileScale: ${brConfig.animation.mobileScale},
      mobileDuration: ${brConfig.animation.mobileDuration}
    },
    DEFAULTS: {
      objectFit: '${brConfig.video.fit}',
      videoUrl: '${brConfig.video.url}',
      fallbackUrl: 'https://storage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
      showControls: ${brConfig.video.controls}
    },
    CONTAINER: {
      borderRadius: ${brConfig.container.borderRadius},
      backdropBlur: ${brConfig.container.backdropBlur},
      backdropColor: 'rgba(0, 0, 0, ${brConfig.container.backdropOpacity})'
    }
  };
  
  class DOMUtils {
    static createOverlay() {
      const overlay = document.createElement('div');
      overlay.className = 'br-overlay';
      return overlay;
    }
  
    static createVideoContainer() {
      const container = document.createElement('div');
      container.className = 'br-container';
      return container;
    }
  
    static createVideo(url, isMuted = !CONFIG.DEFAULTS.showControls, objectFit = CONFIG.DEFAULTS.objectFit) {
      const isStreamingService = (url) => {
        return url.includes('youtube.com') || url.includes('youtu.be') || 
               url.includes('vimeo.com') || url.includes('player.vimeo.com');
      };
      
      if (isStreamingService(url)) {
        const iframe = document.createElement('iframe');
        
        if (url.includes('youtube.com') || url.includes('youtu.be')) {
          const videoId = url.includes('youtu.be/') 
            ? url.split('youtu.be/')[1].split('?')[0]
            : url.includes('v=') 
              ? url.split('v=')[1].split('&')[0] 
              : '';
          
          if (videoId) {
            iframe.src = \`https://www.youtube.com/embed/\${videoId}?autoplay=1&mute=\${isMuted ? 1 : 0}&controls=\${!isMuted ? 1 : 0}\`;
          } else {
            iframe.src = url;
          }
        } else if (url.includes('vimeo.com')) {
          const vimeoId = url.split('vimeo.com/')[1]?.split('/')[0]?.split('?')[0];
          if (vimeoId) {
            iframe.src = \`https://player.vimeo.com/video/\${vimeoId}?autoplay=1&muted=\${isMuted ? 1 : 0}\`;
          } else {
            iframe.src = url;
          }
        } else {
          iframe.src = url;
        }
        
        iframe.className = 'br-video';
        iframe.style.width = '100%';
        iframe.style.height = '100%';
        iframe.style.border = 'none';
        iframe.style.objectFit = objectFit;
        iframe.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture';
        iframe.allowFullscreen = true;
        
        return iframe;
      }
       
      const isBubblesVideo = url.includes('Bubbles02.mp4');
       
      if (isBubblesVideo) {
        url = CONFIG.DEFAULTS.fallbackUrl;
      }
      
      const video = document.createElement('video');
      video.className = 'br-video';
      video.muted = isMuted;
      video.loop = true;
      video.playsInline = true;
      video.setAttribute('playsinline', '');
      video.style.objectFit = objectFit;
      video.style.backgroundColor = '#000';
      
      video.controls = CONFIG.DEFAULTS.showControls;
      
      const videoExtensions = ['.mp4', '.webm', '.ogg', '.mov', '.avi', '.wmv', '.flv', '.mkv'];
      let urlLower = url.toLowerCase();
      let isLikelyVideo = videoExtensions.some(ext => urlLower.includes(ext));
      
      let errorAttempts = 0;
      const maxErrorAttempts = 2;
      
      video.addEventListener('error', function(e) {
        errorAttempts++;
        
        if (errorAttempts <= maxErrorAttempts && url !== CONFIG.DEFAULTS.fallbackUrl) {
          video.src = CONFIG.DEFAULTS.fallbackUrl;
          video.load();
        }
      });
      
      if (!isLikelyVideo && !isStreamingService(url) && url !== CONFIG.DEFAULTS.fallbackUrl) {
        video.src = CONFIG.DEFAULTS.fallbackUrl;
      } else {
        try {
          video.src = url;
        } catch (err) {
          video.src = CONFIG.DEFAULTS.fallbackUrl;
        }
      }
      
      return video;
    }
  
    static getVideoSize(button, config, isMobile) {
      let size = config.SIZES['${brConfig.video.size}'];
      
      if (isMobile && size.width !== '100%') {
        const scale = CONFIG.ANIMATION.mobileScale;
        return {
          width: typeof size.width === 'number' ? size.width * scale : size.width,
          height: typeof size.height === 'number' ? size.height * scale : size.height
        };
      }
  
      return size;
    }
  
    static isTouchDevice() {
      return ('ontouchstart' in window) || (navigator.maxTouchPoints > 0);
    }
  }
  
  class VideoContainerManager {
    constructor() {
      this.currentContainer = null;
      this.initStyles();
    }
  
    initStyles() {
      const styles = \`
        .br-overlay {
          position: fixed;
          top: 0;
          left: 0;
          width: 100vw;
          height: 100vh;
          background-color: rgba(0, 0, 0, 0);
          backdrop-filter: blur(0px);
          transition: backdrop-filter 0.5s ease-in-out, background-color 0.5s ease-in-out;
          z-index: 9998;
        }
        .br-container {
          position: fixed;
          z-index: 9999;
          overflow: hidden;
          transform: none !important;
          border-radius: \${CONFIG.CONTAINER.borderRadius}px;
          transform-origin: center center;
          touch-action: none;
          -webkit-tap-highlight-color: transparent;
          background-color: #000;
          display: flex;
          align-items: center;
          justify-content: center;
          box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
        }
        .br-video {
          width: 100% !important;
          height: 100% !important;
          display: block;
          margin: 0;
          padding: 0;
          background-color: #000;
          transform: none !important;
        }
        .br-video[controls] {
          pointer-events: auto;
        }
        .br-video:not([controls]) {
          pointer-events: none;
        }
        .br-overlay.active {
          background-color: \${CONFIG.CONTAINER.backdropColor};
          backdrop-filter: blur(\${CONFIG.CONTAINER.backdropBlur}px);
        }
        @media (max-width: 768px) {
          .br-container {
            border-radius: \${Math.max(15, CONFIG.CONTAINER.borderRadius - 5)}px;
          }
        }
      \`;
  
      if (!document.querySelector('#br-styles')) {
        const styleSheet = document.createElement('style');
        styleSheet.id = 'br-styles';
        styleSheet.textContent = styles;
        document.head.appendChild(styleSheet);
      }
    }
  
    setupContainer(button) {
      const container = DOMUtils.createVideoContainer();
      const videoUrl = CONFIG.DEFAULTS.videoUrl;
      const objectFit = CONFIG.DEFAULTS.objectFit;
      const isMuted = !CONFIG.DEFAULTS.showControls;
      
      const mediaElement = DOMUtils.createVideo(videoUrl, isMuted, objectFit);
      
      if (mediaElement.tagName.toLowerCase() === 'video') {
        mediaElement.controls = CONFIG.DEFAULTS.showControls;
        mediaElement.muted = !CONFIG.DEFAULTS.showControls;
      }
      
      mediaElement.style.width = "100%";
      mediaElement.style.height = "100%";
      
      const overlay = DOMUtils.createOverlay();
      
      container.appendChild(mediaElement);
      document.body.appendChild(overlay);
      document.body.appendChild(container);
      
      if (mediaElement.tagName.toLowerCase() === 'video') {
        mediaElement.load();
      }

      return { container, video: mediaElement, overlay };
    }
  
    cleanup() {
      if (this.currentContainer) {
        const overlay = document.querySelector('.br-overlay');
        if (overlay) document.body.removeChild(overlay);
        document.body.removeChild(this.currentContainer);
        this.currentContainer = null;
      }
    }
  }
  
  class ButtonReveal {
    constructor() {
      this.config = CONFIG;
      this.animationManager = new AnimationManager();
      this.containerManager = new VideoContainerManager();
      this.isMobile = DOMUtils.isTouchDevice();
    }
  
    init() {
      const buttons = document.querySelectorAll(\`[\${this.config.ATTRIBUTES.button}]\`);
      buttons.forEach(button => this.setupButton(button));
    }
  
    setupButton(button) {
      button.addEventListener('click', (e) => {
        e.preventDefault();
        e.stopPropagation();
        this.animationManager.queue(() => this.revealVideo(button));
      });
    }

    getInitialPosition(button) {
      const rect = button.getBoundingClientRect();
      return {
        left: rect.left,
        top: rect.top,
        width: rect.width,
        height: rect.height,
        borderRadius: getComputedStyle(button).borderRadius
      };
    }

    getFinalPosition(videoSize) {
      const margin = this.isMobile ? 16 : 20;
      const maxWidth = window.innerWidth - (margin * 2);
      const maxHeight = window.innerHeight - (margin * 2);
      const finalWidth = Math.min(videoSize.width === '100%' ? maxWidth : videoSize.width, maxWidth);
      const finalHeight = Math.min(videoSize.height === '100%' ? maxHeight : videoSize.height, maxHeight);

      return {
        left: (window.innerWidth - finalWidth) / 2,
        top: (window.innerHeight - finalHeight) / 2,
        width: finalWidth,
        height: finalHeight,
        borderRadius: this.isMobile ? 
          Math.max(15, CONFIG.CONTAINER.borderRadius - 5) + "px" : 
          CONFIG.CONTAINER.borderRadius + "px"
      };
    }

    async revealVideo(button) {
      this.containerManager.cleanup();

      const { container, video, overlay } = this.containerManager.setupContainer(button);
      const speed = this.config.ANIMATION.defaultSpeed;
      const videoSize = DOMUtils.getVideoSize(button, this.config, this.isMobile);
      
      const duration = this.isMobile ? 
        this.config.ANIMATION.mobileDuration / speed : 
        this.config.ANIMATION.duration / speed;

      const initialPos = this.getInitialPosition(button);
      
      gsap.set(container, {
        left: initialPos.left,
        top: initialPos.top,
        width: initialPos.width,
        height: initialPos.height,
        borderRadius: initialPos.borderRadius,
        opacity: 0,
        transformOrigin: "center center"
      });

      gsap.set(video, { opacity: 0 });

      const tl = gsap.timeline({
        onComplete: () => {
          container.style.touchAction = 'auto';
          
          if (video.tagName.toLowerCase() === 'video') {
            video.play().catch(err => {
              if (video.src !== CONFIG.DEFAULTS.fallbackUrl) {
                video.src = CONFIG.DEFAULTS.fallbackUrl;
                video.load();
                video.play().catch(secondErr => {});
              }
            });
          }
        }
      });

      tl.to(button, {
        opacity: 0,
        scale: 0.8,
        duration: duration * 0.5,
        ease: this.config.ANIMATION.easingOut
      })
      .to(container, {
        ...this.getFinalPosition(videoSize),
        opacity: 1,
        duration: duration,
        ease: this.config.ANIMATION.easingIn
      }, "-=0.2")
      .to(video, {
        opacity: 1,
        duration: duration * 0.5,
        onStart: () => {
          overlay.classList.add('active');
        },
        onComplete: () => {
          if (video.tagName.toLowerCase() === 'video') {
            video.play().catch(err => {
              if (video.src !== CONFIG.DEFAULTS.fallbackUrl) {
                video.src = CONFIG.DEFAULTS.fallbackUrl;
                video.load();
                video.play().catch(secondErr => {});
              }
            });
          }
        }
      }, "-=0.3");

      const closeHandler = (e) => {
        if (!video.controls || (e.target !== video)) {
          if (this.containerManager.currentContainer === container) {
            this.animationManager.queue(() => this.closeVideo(container, button, overlay));
          }
        }
      };

      container.addEventListener('click', closeHandler);
      overlay.addEventListener('click', closeHandler);

      this.containerManager.currentContainer = container;
    }

    async closeVideo(container, button, overlay) {
      const video = container.querySelector('video');
      if (video) video.pause();
      
      overlay.classList.remove('active');
      container.style.touchAction = 'none';

      const duration = this.isMobile ? 
        this.config.ANIMATION.mobileDuration / 2 : 
        this.config.ANIMATION.duration / 2;

      const initialPos = this.getInitialPosition(button);

      const tl = gsap.timeline({
        onComplete: () => this.containerManager.cleanup()
      });

      tl.to(video, {
        opacity: 0,
        duration: duration * 0.5,
        ease: this.config.ANIMATION.easingOut
      })
      .to(container, {
        left: initialPos.left,
        top: initialPos.top,
        width: initialPos.width,
        height: initialPos.height,
        borderRadius: initialPos.borderRadius,
        opacity: 0,
        duration: duration,
        ease: this.config.ANIMATION.easingOut
      }, "-=0.2")
      .to(button, {
        opacity: 1,
        scale: 1,
        duration: duration,
        ease: this.config.ANIMATION.easingIn
      }, "-=0.3");
    }
  }

  async function initializeButtonReveal() {
    if (!window.gsap) {
      try {
        await new Promise((resolve, reject) => {
          const script = document.createElement('script');
          script.src = "https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.4/gsap.min.js";
          script.onload = resolve;
          script.onerror = reject;
          document.head.appendChild(script);
        });
      } catch (error) {
        return;
      }
    }

    const buttonReveal = new ButtonReveal();
    buttonReveal.init();
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initializeButtonReveal);
  } else {
    initializeButtonReveal();
  }
})();`;
            }
            
            function copyJsToClipboard() {
                const jsCode = generateJavaScriptCode();
                
                navigator.clipboard.writeText(jsCode)
                    .then(() => {
                        showNotification('JavaScript code copied to clipboard!');
                    })
                    .catch(err => {
                        try {
                            const textArea = document.createElement('textarea');
                            textArea.value = jsCode;
                            textArea.style.position = 'fixed';
                            textArea.style.opacity = '0';
                            document.body.appendChild(textArea);
                            textArea.select();
                            document.execCommand('copy');
                            document.body.removeChild(textArea);
                            showNotification('JavaScript code copied to clipboard!');
                        } catch (fallbackErr) {
                            showNotification('Failed to copy to clipboard. Please try again.', 'error');
                        }
                    });
            }
            
            function copyFullSectionToClipboard() {
                const sectionJSON = generateFullSectionJSON();
                
                navigator.clipboard.writeText(sectionJSON)
                    .then(() => {
                        showNotification('Full section JSON copied to clipboard!');
                    })
                    .catch(err => {
                        try {
                            const textArea = document.createElement('textarea');
                            textArea.value = sectionJSON;
                            textArea.style.position = 'fixed';
                            textArea.style.opacity = '0';
                            document.body.appendChild(textArea);
                            textArea.select();
                            document.execCommand('copy');
                            document.body.removeChild(textArea);
                            showNotification('Full section JSON copied to clipboard!');
                        } catch (fallbackErr) {
                            showNotification('Failed to copy to clipboard. Please try again.', 'error');
                        }
                    });
            }
            
            function copyToClipboard(text) {
                navigator.clipboard.writeText(text)
                    .then(() => {
                        showNotification('Copied to clipboard!');
                    })
                    .catch(err => {
                        showNotification('Failed to copy to clipboard', 'error');
                    });
            }
            
            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 saveConfiguration() {
                try {
                    localStorage.setItem('bricksfusion-button-reveal-config', JSON.stringify(brConfig));
                } catch (e) {}
            }
            
            function loadConfiguration() {
                try {
                    const saved = localStorage.getItem('bricksfusion-button-reveal-config');
                    if (saved) {
                        const savedConfig = JSON.parse(saved);
                        Object.assign(brConfig, savedConfig);
                        updateUIFromConfig();
                    }
                } catch (e) {}
            }
            
            initializeUI();
        });
    </script>
</body>
</html>
Button Reveal - Bricksfusion
MEDIUM

Button Reveal

Transforms a button into a fullscreen video player with smooth animations. Click the button and watch it expand into a video. Perfect for video showcases, product demos, and hero sections.

Video

Video URL text / youtube / vimeo

Link to your video file. Supports direct video links, YouTube, and Vimeo. Just paste the URL and it works automatically.

Default: Demo video

Show Controls on/off

Display video controls like play, pause, and volume. Turn off for autoplay videos without controls.

Default: Off

Object Fit cover / contain

How the video fills the space. Cover fills the entire area and crops if needed. Contain shows the full video with possible black bars.

Default: Cover

Video Size small / medium / large / full

Size of the expanded video. Small is 300x300, medium is 600x400, large is 800x600, and full takes the entire screen with margins.

Default: Full

Animation

Animation Speed 0.1-3.0

Overall speed multiplier for all animations. Higher values make everything faster, lower values slow it down.

Default: 1.0

Animation Duration 0.3-3.0 seconds

How long the button takes to expand into the video. Shorter is snappy, longer is smooth and cinematic.

Default: 1.0 seconds

Mobile Duration 0.3-2.0 seconds

Duration specifically for mobile devices. Usually faster than desktop for better mobile experience.

Default: 0.8 seconds

Easing power1 / power2 / power3 / elastic

The motion curve of the animation. Power2 is smooth and natural, elastic bounces slightly. Add .in, .out, or .inOut after the name.

Default: power2.inOut

Appearance

Border Radius 0-50 pixels

Roundness of the video container corners. 0 is sharp corners, higher values create more rounded edges.

Default: 20

Backdrop Blur 0-30 pixels

Amount of blur applied to the background when the video is open. Higher values create a stronger focus effect.

Default: 10

Backdrop Opacity 0.0-1.0

Darkness of the background overlay. 0 is transparent, 1 is completely black. Use around 0.5-0.7 for best results.

Default: 0.5

Mobile

Mobile Scale 0.5-1.0

Scales down the video size on mobile devices. 0.9 means 90% of the chosen size. Helps fit videos better on small screens.

Default: 0.9

Performance

This element requires GSAP library for smooth animations. Video playback depends on user's device capabilities. Use optimized video files for best performance. The effect automatically adjusts for mobile devices.