<!DOCTYPE html>
<!--
    THIS IS A TEMPLATE THAT SHOULD BE USED EVERY TIME AND MODIFIED.
    WHAT TO KEEP:
    ✓ Overall structure (header, sidebar, main content)
    ✓ default branding (colors, fonts, layout)
    ✓ Seed navigation section (always include this)
    ✓ Self-contained artifact (everything inline)

    WHAT TO CREATIVELY EDIT:
    ✗ The p5.js algorithm (implement YOUR vision)
    ✗ The parameters (define what YOUR art needs)
    ✗ The UI controls (match YOUR parameters)

    Let your philosophy guide the implementation.
    The world is your oyster - be creative!
-->
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Generative Art Viewer</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.min.js"></script>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&family=Lora:wght@400;500&display=swap" rel="stylesheet">
    <style>
        /* Brand Colors */
        :root {
            --brand-dark: #141413;
            --brand-light: #faf9f5;
            --brand-mid-gray: #b0aea5;
            --brand-light-gray: #e8e6dc;
            --brand-orange: #d97757;
            --brand-blue: #6a9bcc;
            --brand-green: #788c5d;
        }

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

        body {
            font-family: 'Poppins', sans-serif;
            background: linear-gradient(135deg, var(--brand-light) 0%, #f5f3ee 100%);
            min-height: 100vh;
            color: var(--brand-dark);
        }

        .container {
            display: flex;
            min-height: 100vh;
            padding: 20px;
            gap: 20px;
        }

        /* Sidebar */
        .sidebar {
            width: 320px;
            flex-shrink: 0;
            background: rgba(255, 255, 255, 0.95);
            backdrop-filter: blur(10px);
            padding: 24px;
            border-radius: 12px;
            box-shadow: 0 10px 30px rgba(20, 20, 19, 0.1);
            overflow-y: auto;
            overflow-x: hidden;
        }

        .sidebar h1 {
            font-family: 'Lora', serif;
            font-size: 24px;
            font-weight: 500;
            color: var(--brand-dark);
            margin-bottom: 8px;
        }

        .sidebar .subtitle {
            color: var(--brand-mid-gray);
            font-size: 14px;
            margin-bottom: 32px;
            line-height: 1.4;
        }

        /* Control Sections */
        .control-section {
            margin-bottom: 32px;
        }

        .control-section h3 {
            font-size: 16px;
            font-weight: 600;
            color: var(--brand-dark);
            margin-bottom: 16px;
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .control-section h3::before {
            content: '•';
            color: var(--brand-orange);
            font-weight: bold;
        }

        /* Seed Controls */
        .seed-input {
            width: 100%;
            background: var(--brand-light);
            padding: 12px;
            border-radius: 8px;
            font-family: 'Courier New', monospace;
            font-size: 14px;
            margin-bottom: 12px;
            border: 1px solid var(--brand-light-gray);
            text-align: center;
        }

        .seed-input:focus {
            outline: none;
            border-color: var(--brand-orange);
            box-shadow: 0 0 0 2px rgba(217, 119, 87, 0.1);
            background: white;
        }

        .seed-controls {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 8px;
            margin-bottom: 8px;
        }

        .regen-button {
            margin-bottom: 0;
        }

        /* Parameter Controls */
        .control-group {
            margin-bottom: 20px;
        }

        .control-group label {
            display: block;
            font-size: 14px;
            font-weight: 500;
            color: var(--brand-dark);
            margin-bottom: 8px;
        }

        .slider-container {
            display: flex;
            align-items: center;
            gap: 12px;
        }

        .slider-container input[type="range"] {
            flex: 1;
            height: 4px;
            background: var(--brand-light-gray);
            border-radius: 2px;
            outline: none;
            -webkit-appearance: none;
        }

        .slider-container input[type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            width: 16px;
            height: 16px;
            background: var(--brand-orange);
            border-radius: 50%;
            cursor: pointer;
            transition: all 0.2s ease;
        }

        .slider-container input[type="range"]::-webkit-slider-thumb:hover {
            transform: scale(1.1);
            background: #c86641;
        }

        .slider-container input[type="range"]::-moz-range-thumb {
            width: 16px;
            height: 16px;
            background: var(--brand-orange);
            border-radius: 50%;
            border: none;
            cursor: pointer;
            transition: all 0.2s ease;
        }

        .value-display {
            font-family: 'Courier New', monospace;
            font-size: 12px;
            color: var(--brand-mid-gray);
            min-width: 60px;
            text-align: right;
        }

        /* Color Pickers */
        .color-group {
            margin-bottom: 16px;
        }

        .color-group label {
            display: block;
            font-size: 12px;
            color: var(--brand-mid-gray);
            margin-bottom: 4px;
        }

        .color-picker-container {
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .color-picker-container input[type="color"] {
            width: 32px;
            height: 32px;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            background: none;
            padding: 0;
        }

        .color-value {
            font-family: 'Courier New', monospace;
            font-size: 12px;
            color: var(--brand-mid-gray);
        }

        /* Buttons */
        .button {
            background: var(--brand-orange);
            color: white;
            border: none;
            padding: 10px 16px;
            border-radius: 6px;
            font-size: 14px;
            font-weight: 500;
            cursor: pointer;
            transition: all 0.2s ease;
            width: 100%;
        }

        .button:hover {
            background: #c86641;
            transform: translateY(-1px);
        }

        .button:active {
            transform: translateY(0);
        }

        .button.secondary {
            background: var(--brand-blue);
        }

        .button.secondary:hover {
            background: #5a8bb8;
        }

        .button.tertiary {
            background: var(--brand-green);
        }

        .button.tertiary:hover {
            background: #6b7b52;
        }

        .button-row {
            display: flex;
            gap: 8px;
        }

        .button-row .button {
            flex: 1;
        }

        /* Canvas Area */
        .canvas-area {
            flex: 1;
            display: flex;
            align-items: center;
            justify-content: center;
            min-width: 0;
        }

        #canvas-container {
            width: 100%;
            max-width: 1000px;
            border-radius: 12px;
            overflow: hidden;
            box-shadow: 0 20px 40px rgba(20, 20, 19, 0.1);
            background: white;
        }

        #canvas-container canvas {
            display: block;
            width: 100% !important;
            height: auto !important;
        }

        /* Loading State */
        .loading {
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 18px;
            color: var(--brand-mid-gray);
        }

        /* Responsive - Stack on mobile */
        @media (max-width: 600px) {
            .container {
                flex-direction: column;
            }

            .sidebar {
                width: 100%;
            }

            .canvas-area {
                padding: 20px;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <!-- Control Sidebar -->
        <div class="sidebar">
            <!-- Headers (CUSTOMIZE THIS FOR YOUR ART) -->
            <h1>TITLE - EDIT</h1>
            <div class="subtitle">SUBHEADER - EDIT</div>

            <!-- Seed Section (ALWAYS KEEP THIS) -->
            <div class="control-section">
                <h3>Seed</h3>
                <input type="number" id="seed-input" class="seed-input" value="12345" onchange="updateSeed()">
                <div class="seed-controls">
                    <button class="button secondary" onclick="previousSeed()">← Prev</button>
                    <button class="button secondary" onclick="nextSeed()">Next →</button>
                </div>
                <button class="button tertiary regen-button" onclick="randomSeedAndUpdate()">↻ Random</button>
            </div>

            <!-- Parameters Section (CUSTOMIZE THIS FOR YOUR ART) -->
            <div class="control-section">
                <h3>Parameters</h3>
                
                <!-- Particle Count -->
                <div class="control-group">
                    <label>Particle Count</label>
                    <div class="slider-container">
                        <input type="range" id="particleCount" min="1000" max="10000" step="500" value="5000" oninput="updateParam('particleCount', this.value)">
                        <span class="value-display" id="particleCount-value">5000</span>
                    </div>
                </div>

                <!-- Flow Speed -->
                <div class="control-group">
                    <label>Flow Speed</label>
                    <div class="slider-container">
                        <input type="range" id="flowSpeed" min="0.1" max="2.0" step="0.1" value="0.5" oninput="updateParam('flowSpeed', this.value)">
                        <span class="value-display" id="flowSpeed-value">0.5</span>
                    </div>
                </div>

                <!-- Noise Scale -->
                <div class="control-group">
                    <label>Noise Scale</label>
                    <div class="slider-container">
                        <input type="range" id="noiseScale" min="0.001" max="0.02" step="0.001" value="0.005" oninput="updateParam('noiseScale', this.value)">
                        <span class="value-display" id="noiseScale-value">0.005</span>
                    </div>
                </div>

                <!-- Trail Length -->
                <div class="control-group">
                    <label>Trail Length</label>
                    <div class="slider-container">
                        <input type="range" id="trailLength" min="2" max="20" step="1" value="8" oninput="updateParam('trailLength', this.value)">
                        <span class="value-display" id="trailLength-value">8</span>
                    </div>
                </div>
            </div>

            <!-- Colors Section (OPTIONAL - CUSTOMIZE OR REMOVE) -->
            <div class="control-section">
                <h3>Colors</h3>
                
                <!-- Color 1 -->
                <div class="color-group">
                    <label>Primary Color</label>
                    <div class="color-picker-container">
                        <input type="color" id="color1" value="#d97757" onchange="updateColor('color1', this.value)">
                        <span class="color-value" id="color1-value">#d97757</span>
                    </div>
                </div>

                <!-- Color 2 -->
                <div class="color-group">
                    <label>Secondary Color</label>
                    <div class="color-picker-container">
                        <input type="color" id="color2" value="#6a9bcc" onchange="updateColor('color2', this.value)">
                        <span class="color-value" id="color2-value">#6a9bcc</span>
                    </div>
                </div>

                <!-- Color 3 -->
                <div class="color-group">
                    <label>Accent Color</label>
                    <div class="color-picker-container">
                        <input type="color" id="color3" value="#788c5d" onchange="updateColor('color3', this.value)">
                        <span class="color-value" id="color3-value">#788c5d</span>
                    </div>
                </div>
            </div>

            <!-- Actions Section (ALWAYS KEEP THIS) -->
            <div class="control-section">
                <h3>Actions</h3>
                <div class="button-row">
                    <button class="button" onclick="resetParameters()">Reset</button>
                </div>
            </div>
        </div>

        <!-- Main Canvas Area -->
        <div class="canvas-area">
            <div id="canvas-container">
                <div class="loading">Initializing generative art...</div>
            </div>
        </div>
    </div>

    <script>
        // ═══════════════════════════════════════════════════════════════════════
        // GENERATIVE ART PARAMETERS - CUSTOMIZE FOR YOUR ALGORITHM
        // ═══════════════════════════════════════════════════════════════════════

        let params = {
            seed: 12345,
            particleCount: 5000,
            flowSpeed: 0.5,
            noiseScale: 0.005,
            trailLength: 8,
            colorPalette: ['#d97757', '#6a9bcc', '#788c5d']
        };

        let defaultParams = {...params}; // Store defaults for reset

        // ═══════════════════════════════════════════════════════════════════════
        // P5.JS GENERATIVE ART ALGORITHM - REPLACE WITH YOUR VISION
        // ═══════════════════════════════════════════════════════════════════════

        let particles = [];
        let flowField = [];
        let cols, rows;
        let scl = 10; // Flow field resolution

        function setup() {
            let canvas = createCanvas(1200, 1200);
            canvas.parent('canvas-container');
            
            initializeSystem();
            
            // Remove loading message
            document.querySelector('.loading').style.display = 'none';
        }

        function initializeSystem() {
            // Seed the randomness for reproducibility
            randomSeed(params.seed);
            noiseSeed(params.seed);

            // Clear particles and recreate
            particles = [];
            
            // Initialize particles
            for (let i = 0; i < params.particleCount; i++) {
                particles.push(new Particle());
            }

            // Calculate flow field dimensions
            cols = floor(width / scl);
            rows = floor(height / scl);
            
            // Generate flow field
            generateFlowField();

            // Clear background
            background(250, 249, 245); // light background
        }

        function generateFlowField() {
          // fill this in
        }

        function draw() {
            // fill this in
        }

        // ═══════════════════════════════════════════════════════════════════════
        // PARTICLE SYSTEM - CUSTOMIZE FOR YOUR ALGORITHM
        // ═══════════════════════════════════════════════════════════════════════

        class Particle {
            constructor() {
                // fill this in
            }
            // fill this in
        }

        // ═══════════════════════════════════════════════════════════════════════
        // UI CONTROL HANDLERS - CUSTOMIZE FOR YOUR PARAMETERS
        // ═══════════════════════════════════════════════════════════════════════

        function updateParam(paramName, value) {
            // fill this in
        }

        function updateColor(colorId, value) {
            // fill this in
        }

        // ═══════════════════════════════════════════════════════════════════════
        // SEED CONTROL FUNCTIONS - ALWAYS KEEP THESE
        // ═══════════════════════════════════════════════════════════════════════

        function updateSeedDisplay() {
            document.getElementById('seed-input').value = params.seed;
        }

        function updateSeed() {
            let input = document.getElementById('seed-input');
            let newSeed = parseInt(input.value);
            if (newSeed && newSeed > 0) {
                params.seed = newSeed;
                initializeSystem();
            } else {
                // Reset to current seed if invalid
                updateSeedDisplay();
            }
        }

        function previousSeed() {
            params.seed = Math.max(1, params.seed - 1);
            updateSeedDisplay();
            initializeSystem();
        }

        function nextSeed() {
            params.seed = params.seed + 1;
            updateSeedDisplay();
            initializeSystem();
        }

        function randomSeedAndUpdate() {
            params.seed = Math.floor(Math.random() * 999999) + 1;
            updateSeedDisplay();
            initializeSystem();
        }

        function resetParameters() {
            params = {...defaultParams};
            
            // Update UI elements
            document.getElementById('particleCount').value = params.particleCount;
            document.getElementById('particleCount-value').textContent = params.particleCount;
            document.getElementById('flowSpeed').value = params.flowSpeed;
            document.getElementById('flowSpeed-value').textContent = params.flowSpeed;
            document.getElementById('noiseScale').value = params.noiseScale;
            document.getElementById('noiseScale-value').textContent = params.noiseScale;
            document.getElementById('trailLength').value = params.trailLength;
            document.getElementById('trailLength-value').textContent = params.trailLength;
            
            // Reset colors
            document.getElementById('color1').value = params.colorPalette[0];
            document.getElementById('color1-value').textContent = params.colorPalette[0];
            document.getElementById('color2').value = params.colorPalette[1];
            document.getElementById('color2-value').textContent = params.colorPalette[1];
            document.getElementById('color3').value = params.colorPalette[2];
            document.getElementById('color3-value').textContent = params.colorPalette[2];
            
            updateSeedDisplay();
            initializeSystem();
        }

        // Initialize UI on load
        window.addEventListener('load', function() {
            updateSeedDisplay();
        });
    </script>
</body>
</html>