##  [Symulator PV + magazynowanie](/symulator) 

 ## INSTYTUT ENERGETYKI CIEPLNEJ

- [INSTYTUT](https://isie.put.poznan.pl/iec "Poznaj działalność naukowo-dydaktyczną Instytutu Energetyki Cieplnej, specjalizującego się w nowoczesnych technologiach energetycznych, odnawialnych źródłach energii oraz kształceniu wysoko wykwalifikowanych inżynierów.")
- [ZAKŁAD AERODYNAMIKI I MASZYN PRZEPŁYWOWYCH](https://isie.put.poznan.pl/iec/zil "Jednostka naukowo-dydaktyczna specjalizująca się w inżynierii lotniczej, energetyce cieplnej oraz badaniach nad aerodynamiką i nowoczesnymi napędami statków powietrznych.")
- [ZAKŁAD PALIW I ENERGETYKI ODNAWIALNEJ](https://isie.put.poznan.pl/iec/zpieo/o_zakladzie "Informacje o działalności dydaktycznej, naukowej i badawczej Zakładu w obszarze energetyki cieplnej, technologii niskoemisyjnych oraz wykorzystania odnawialnych źródeł energii.")
- [LABORATORIA ](https://isie.put.poznan.pl/iec/laboratoria "Zapraszamy do zapoznania się z ofertą specjalistycznych laboratoriów dydaktycznych i badawczych Instytutu Energetyki Cieplnej na Wydziale Inżynierii Środowiska i Energetyki.")
- [DLA STUDENTÓW](https://isie.put.poznan.pl/iec/dla_studentow "Znajdziesz tu niezbędne informacje dotyczące ćwiczeń laboratoryjnych, regulaminy BHP oraz dokumentację wymaganą dla studentów Instytutu Energetyki Cieplnej.")
- [DZIAŁALNOŚĆ](https://isie.put.poznan.pl/iec/dzialalnosc "Przegląd oferty dydaktycznej oraz realizowanych prac naukowo-badawczych w zakresie energetyki, maszyn przepływowych, procesów spalania i transportu ciepła.")
- [GALERIA](https://isie.put.poznan.pl/iec/galeria "Zapraszamy do zapoznania się z fotorelacjami z wydarzeń, wizyt gości oraz projektów badawczo-dydaktycznych realizowanych w Instytucie Energetyki Cieplnej.")
- [USŁUGI](https://isie.put.poznan.pl/iec/uslugi "Zapraszamy do zapoznania się z ofertą specjalistycznych usług badawczych, obliczeniowych oraz pomiarowych świadczonych przez jednostki Instytutu Energetyki Cieplnej.")
- [Symulator PV + magazynowanie](/symulator)
 
 

 INSTYTUT ENERGETYKI CIEPLNEJ

  

  Symulator PV + magazynowanie 
        #smart-grid-bess {
            --bg-color: #0f172a;
            --card-bg: #1e293b;
            --accent-pv: #eab308;
            --accent-load: #3b82f6;
            --accent-battery: #22c55e;
            --accent-grid: #a855f7;
            --text-main: #f8fafc;
            --text-sub: #94a3b8;
        }

        #smart-grid-bess * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }

        #smart-grid-bess {
            background-color: var(--bg-color);
            color: var(--text-main);
            display: flex;
            flex-direction: column;
            align-items: center;
            min-height: 100vh;
            padding: 20px;
        }

        #smart-grid-bess h1 {
            margin-bottom: 15px;
            font-size: 1.8rem;
            text-align: center;
        }

        #smart-grid-bess .container {
            display: flex;
            flex-direction: column;
            gap: 20px;
            width: 100%;
            max-width: 1400px;
            margin: 0 auto;
        }

        #smart-grid-bess .canvas-container {
            position: relative;
            background-color: var(--card-bg);
            border-radius: 16px;
            box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3);
            overflow: hidden;
            width: 100%;
            aspect-ratio: 16 / 10;
            min-height: 430px;
        }

        #smart-grid-bess canvas {
            width: 100%;
            height: 100%;
            display: block;
        }

        #smart-grid-bess .controls {
            background-color: var(--card-bg);
            border-radius: 16px;
            padding: 20px;
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
            gap: 20px;
            box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3);
        }

        #smart-grid-bess .time-panel {
            grid-column: 1 / -1;
            background-color: #0f172a;
            padding: 15px;
            border-radius: 12px;
            display: flex;
            flex-direction: column;
            gap: 10px;
            border: 1px solid #334155;
        }

        #smart-grid-bess .time-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        #smart-grid-bess .time-display {
            font-size: 1.4rem;
            font-weight: bold;
            color: #f1f5f9;
            font-family: monospace;
        }

        #smart-grid-bess .time-controls-row {
            display: flex;
            gap: 10px;
            align-items: center;
        }

        #smart-grid-bess .control-group {
            display: flex;
            flex-direction: column;
            gap: 8px;
        }

        #smart-grid-bess .control-group label {
            font-size: 0.9rem;
            color: var(--text-sub);
            display: flex;
            justify-content: space-between;
        }

        #smart-grid-bess .control-group label span {
            color: var(--text-main);
            font-weight: bold;
        }

        #smart-grid-bess input[type="range"] {
            width: 100%;
            accent-color: var(--accent-load);
            cursor: pointer;
        }

        #smart-grid-bess .preset-buttons {
            grid-column: 1 / -1;
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
            justify-content: center;
            margin-top: 5px;
        }

        #smart-grid-bess button {
            background-color: #334155;
            color: var(--text-main);
            border: none;
            padding: 8px 16px;
            border-radius: 8px;
            cursor: pointer;
            transition: background-color 0.2s, transform 0.1s;
            font-size: 0.85rem;
        }

        #smart-grid-bess button:hover {
            background-color: #475569;
        }

        #smart-grid-bess button:active {
            transform: scale(0.98);
        }

        #smart-grid-bess button.primary {
            background-color: #2563eb;
        }
        #smart-grid-bess button.primary:hover {
            background-color: #3b82f6;
        }

        #smart-grid-bess .auto-toggle {
            font-size: 0.8rem;
            color: var(--text-sub);
            display: flex;
            align-items: center;
            gap: 6px;
            cursor: pointer;
        }
    
#smart-grid-bess {--bg-color:#0f172a; --card-bg:#1e293b; --text-main:#f8fafc; --text-sub:#94a3b8; background:#0f172a; color:#f8fafc; width:100%; max-width:100%; padding:18px 12px 24px; border-radius:14px; overflow-x:auto; isolation:isolate; font-size:16px; line-height:1.5;}
#smart-grid-bess, #smart-grid-bess * {box-sizing:border-box;}
#smart-grid-bess .container {width:100%; max-width:1400px; margin:auto;}
#smart-grid-bess .canvas-container {min-width:620px; height:auto;}
#smart-grid-bess h1 {color:#f8fafc; font-size:clamp(19px,2vw,30px);}
#smart-grid-bess .controls {grid-template-columns:repeat(auto-fit,minmax(min(100%,210px),1fr));}
#smart-grid-bess .time-header {flex-wrap:wrap; gap:12px;}
#smart-grid-bess .time-controls-row {flex-wrap:wrap;}
#smart-grid-bess button {font-family:inherit; line-height:1.4; text-transform:none; box-shadow:none;}
#smart-grid-bess input {max-width:100%;}
@media(max-width:700px){#smart-grid-bess{padding:10px 6px;} #smart-grid-bess .canvas-container{min-height:390px;} #smart-grid-bess .controls{padding:12px; gap:14px;}}
# Symulator Przepływu Energii i Bilansu BESS



Czas symulacji: 12:00

Pause 1h / sek Slow (0.2h/s) Fast (3h/s)



  Automatyczny profil dobowy dla PV i Domu



Produkcja PV: 0.0 kW 

Zapotrzebowanie (Odbiorca): 0.0 kW 

Pojemność Akumulatora: 10.0 kWh 

Poziom Naładowania (SoC): 50.0% 

06:00 (Rano) 12:00 (Południe - Ładowanie) 19:00 (Szczyt - Rozładowanie) 23:00 (Noc - Pobór z Sieci)






(function(){
  'use strict';
  const root=document.getElementById('smart-grid-bess');
  if(!root) return;

        const canvas = root.querySelector('#' + 'energyCanvas');
        const ctx = canvas.getContext('2d');

        // UI Elementy
        const timeInput = root.querySelector('#' + 'timeInput');
        const timeDisplay = root.querySelector('#' + 'timeDisplay');
        const playBtn = root.querySelector('#' + 'playBtn');
        const autoProfileCheckbox = root.querySelector('#' + 'autoProfile');

        const pvInput = root.querySelector('#' + 'pvInput');
        const loadInput = root.querySelector('#' + 'loadInput');
        const capInput = root.querySelector('#' + 'capInput');
        const socInput = root.querySelector('#' + 'socInput');

        const pvValue = root.querySelector('#' + 'pvValue');
        const loadValue = root.querySelector('#' + 'loadValue');
        const capValue = root.querySelector('#' + 'capValue');
        const socValue = root.querySelector('#' + 'socValue');

        // Stan Symulacji Czasowej
        let timeMinutes = 720; // 12:00
        let isPlaying = true;
        let timeSpeedHoursPerSec = 0.5; // Domyślnie: 1 sekunda = 0.5 godziny symulowanej
        let autoProfile = true;

        // Stan Fizyczny
        let pvPower = 0;       // kW
        let loadPower = 0;     // kW
        let batteryCapacity = 10.0; // kWh
        let soc = 50.0;        // %

        let particles = [];
        let lastTimestamp = 0;

        const nodes = {
            pv: { x: 0.18, y: 0.25, label: 'Instalacja PV', color: '#eab308', icon: '☀️' },
            load: { x: 0.82, y: 0.25, label: 'Odbiorca (Dom)', color: '#3b82f6', icon: '🏠' },
            battery: { x: 0.18, y: 0.72, label: 'Magazyn Energii (BESS)', color: '#22c55e' },
            grid: { x: 0.82, y: 0.72, label: 'Sieć Elektroenergetyczna', color: '#a855f7', icon: '⚡' },
            hub: { x: 0.5, y: 0.48, label: 'Inwerter / Falownik', color: '#64748b', icon: '🔄' }
        };

        function resizeCanvas() {
            const rect = canvas.getBoundingClientRect();
            canvas.width = Math.round(rect.width * (window.devicePixelRatio || 1));
            canvas.height = Math.round(rect.height * (window.devicePixelRatio || 1));
            ctx.setTransform(window.devicePixelRatio || 1, 0, 0, window.devicePixelRatio || 1, 0, 0);
        }
        window.addEventListener('resize', resizeCanvas);
        if (window.ResizeObserver) { new ResizeObserver(resizeCanvas).observe(canvas.parentElement); }
        resizeCanvas();

        function getProfilesForTime(minutes) {
            const hours = minutes / 60;

            let pv = 0;
            if (hours >= 5 && hours <= 19) {
                pv = 8.0 * Math.sin(Math.PI * (hours - 5) / 14);
                pv = Math.max(0, pv);
            }

            let load = 0.6;
            load += 2.0 * Math.exp(-Math.pow(hours - 8, 2) / 2);
            load += 3.5 * Math.exp(-Math.pow(hours - 19.5, 2) / 4);

            return { pv: parseFloat(pv.toFixed(1)), load: parseFloat(load.toFixed(1)) };
        }

        function updateTimeDisplay() {
            const h = Math.floor(timeMinutes / 60).toString().padStart(2, '0');
            const m = Math.floor(timeMinutes % 60).toString().padStart(2, '0');
            timeDisplay.textContent = `${h}:${m}`;
            timeInput.value = timeMinutes;
        }

        function updateValuesFromUI() {
            batteryCapacity = parseFloat(capInput.value);
            capValue.textContent = batteryCapacity.toFixed(1) + ' kWh';

            if (autoProfile) {
                const profiles = getProfilesForTime(timeMinutes);
                pvPower = profiles.pv;
                loadPower = profiles.load;
                pvInput.value = pvPower;
                loadInput.value = loadPower;
            } else {
                pvPower = parseFloat(pvInput.value);
                loadPower = parseFloat(loadInput.value);
            }

            pvValue.textContent = pvPower.toFixed(1) + ' kW';
            loadValue.textContent = loadPower.toFixed(1) + ' kW';

            pvInput.disabled = autoProfile;
            loadInput.disabled = autoProfile;
        }

        timeInput.addEventListener('input', () => {
            timeMinutes = parseFloat(timeInput.value);
            updateTimeDisplay();
            updateValuesFromUI();
        });

        pvInput.addEventListener('input', updateValuesFromUI);
        loadInput.addEventListener('input', updateValuesFromUI);
        capInput.addEventListener('input', updateValuesFromUI);
        
        socInput.addEventListener('input', () => {
            soc = parseFloat(socInput.value);
            socValue.textContent = soc.toFixed(1) + '%';
        });

        function togglePlay() {
            isPlaying = !isPlaying;
            playBtn.textContent = isPlaying ? 'Pause' : 'Play';
            playBtn.classList.toggle('primary', isPlaying);
        }

        function setSpeed(spdHoursPerSec) {
            timeSpeedHoursPerSec = spdHoursPerSec;
        }

        function toggleAutoProfile() {
            autoProfile = autoProfileCheckbox.checked;
            updateValuesFromUI();
        }

        function setTimePreset(minutes) {
            timeMinutes = minutes;
            updateTimeDisplay();
            updateValuesFromUI();
        }

        class Particle {
            constructor(from, to, color, speedMultiplier) {
                this.from = from;
                this.to = to;
                this.progress = 0;
                this.color = color;
                this.speed = (0.006 + Math.random() * 0.003) * Math.min(speedMultiplier, 4);
            }

            update() {
                this.progress += this.speed;
                return this.progress >= 1;
            }

            draw(w, h) {
                const x1 = nodes[this.from].x * w;
                const y1 = nodes[this.from].y * h;
                const x2 = nodes[this.to].x * w;
                const y2 = nodes[this.to].y * h;

                const x = x1 + (x2 - x1) * this.progress;
                const y = y1 + (y2 - y1) * this.progress;

                ctx.beginPath();
                ctx.arc(x, y, 5, 0, Math.PI * 2);
                ctx.fillStyle = this.color;
                ctx.shadowColor = this.color;
                ctx.shadowBlur = 8;
                ctx.fill();
                ctx.shadowBlur = 0;
            }
        }

        function calculateFlows() {
            let pPV = pvPower;
            let pLoad = loadPower;
            let pBatt = 0; 
            let pGrid = 0; 

            let net = pPV - pLoad;

            if (net > 0) {
                // Nadwyżka PV
                if (soc < 100) {
                    pBatt = net; // Ładowanie akumulatora
                    pGrid = 0;
                } else {
                    // Akumulator pełny (100%) -> cała nadwyżka idzie do sieci
                    pBatt = 0;
                    pGrid = -net;
                }
            } else if (net < 0) {
                // Niedobór energii
                let deficit = -net;
                if (soc > 0) {
                    pBatt = -deficit; // Rozładowanie akumulatora
                    pGrid = 0;
                } else {
                    // Akumulator pusty (0%) -> pobór z sieci
                    pBatt = 0;
                    pGrid = deficit;
                }
            }

            return { pPV, pLoad, pBatt, pGrid };
        }

        function spawnParticles(flows) {
            if (flows.pPV > 0 && Math.random() < flows.pPV * 0.06) {
                particles.push(new Particle('pv', 'hub', nodes.pv.color, flows.pPV));
            }
            if (flows.pLoad > 0 && Math.random() < flows.pLoad * 0.06) {
                particles.push(new Particle('hub', 'load', nodes.load.color, flows.pLoad));
            }
            if (flows.pBatt > 0 && Math.random() < flows.pBatt * 0.06) {
                particles.push(new Particle('hub', 'battery', nodes.battery.color, flows.pBatt));
            } else if (flows.pBatt < 0 && Math.random() < Math.abs(flows.pBatt) * 0.06) {
                particles.push(new Particle('battery', 'hub', nodes.battery.color, Math.abs(flows.pBatt)));
            }
            if (flows.pGrid > 0 && Math.random() < flows.pGrid * 0.06) {
                particles.push(new Particle('grid', 'hub', nodes.grid.color, flows.pGrid));
            } else if (flows.pGrid < 0 && Math.random() < Math.abs(flows.pGrid) * 0.06) {
                particles.push(new Particle('hub', 'grid', nodes.grid.color, Math.abs(flows.pGrid)));
            }
        }

        function drawConnections(w, h) {
            ctx.lineWidth = 3;
            ctx.strokeStyle = '#334155';
            const hubX = nodes.hub.x * w;
            const hubY = nodes.hub.y * h;

            ['pv', 'load', 'battery', 'grid'].forEach(key => {
                const node = nodes[key];
                ctx.beginPath();
                ctx.moveTo(hubX, hubY);
                ctx.lineTo(node.x * w, node.y * h);
                ctx.stroke();
            });
        }

        // Rysowanie Akumulatora z dokładną podziałką i wskaźnikiem
        function drawBatteryNode(nx, ny, flows) {
            const bWidth = 64;
            const bHeight = 110;
            const x = nx - bWidth / 2;
            const y = ny - bHeight / 2;

            // Zewnętrzna obudowa akumulatora
            ctx.fillStyle = '#0f172a';
            ctx.strokeStyle = '#334155';
            ctx.lineWidth = 3;
            ctx.fillRect(x, y, bWidth, bHeight);
            ctx.strokeRect(x, y, bWidth, bHeight);

            // Dodatni styk (plus) na górze
            ctx.fillStyle = '#475569';
            ctx.fillRect(nx - 12, y - 8, 24, 8);

            // Obliczenie poziomu wypełnienia cieczy/energii
            const innerMargin = 4;
            const maxHeight = bHeight - (innerMargin * 2);
            const fillHeight = maxHeight * (soc / 100);

            let fillColor = '#22c55e'; // Zielony
            if (soc < 20) fillColor = '#ef4444'; // Czerwony
            else if (soc < 50) fillColor = '#eab308'; // Żółty

            // Wypełnienie zielone / kolor dynamiczny
            if (fillHeight > 0) {
                ctx.fillStyle = fillColor;
                ctx.fillRect(
                    x + innerMargin, 
                    y + bHeight - innerMargin - fillHeight, 
                    bWidth - (innerMargin * 2), 
                    fillHeight
                );
            }

            // Linie pomocnicze podziałki (25%, 50%, 75%)
            ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)';
            ctx.lineWidth = 1;
            [0.25, 0.5, 0.75].forEach(ratio => {
                const lineY = y + bHeight - innerMargin - (maxHeight * ratio);
                ctx.beginPath();
                ctx.moveTo(x + innerMargin, lineY);
                ctx.lineTo(x + bWidth - innerMargin, lineY);
                ctx.stroke();
            });

            // Odczyt % na środku akumulatora
            ctx.font = 'bold 15px Segoe UI';
            ctx.fillStyle = '#ffffff';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.shadowColor = '#000000';
            ctx.shadowBlur = 4;
            ctx.fillText(`${soc.toFixed(1)}%`, nx, ny);
            ctx.shadowBlur = 0;

            // Etykieta główna pod baterią
            ctx.font = '12px Segoe UI';
            ctx.fillStyle = '#94a3b8';
            ctx.fillText(nodes.battery.label, nx, ny + bHeight / 2 + 16);

            // Bilans energii w kWh i mocy kW
            const storedKWh = (batteryCapacity * (soc / 100)).toFixed(2);
            ctx.font = 'bold 13px Segoe UI';
            ctx.fillStyle = '#f8fafc';
            ctx.fillText(`${storedKWh} / ${batteryCapacity.toFixed(0)} kWh`, nx, ny + bHeight / 2 + 33);

            // Status ładowania / rozładowania i zmiana %
            const percentRatePerHour = (flows.pBatt / batteryCapacity) * 100;
            ctx.font = '11px Segoe UI';
            if (flows.pBatt > 0.01) {
                ctx.fillStyle = '#22c55e';
                ctx.fillText(`⚡ Ładowanie: +${flows.pBatt.toFixed(1)} kW (+${percentRatePerHour.toFixed(0)}%/h)`, nx, ny + bHeight / 2 + 50);
            } else if (flows.pBatt < -0.01) {
                ctx.fillStyle = '#ef4444';
                ctx.fillText(`⬇ Rozładowanie: ${flows.pBatt.toFixed(1)} kW (${percentRatePerHour.toFixed(0)}%/h)`, nx, ny + bHeight / 2 + 50);
            } else {
                ctx.fillStyle = '#94a3b8';
                ctx.fillText(`Brak przepływu (0.0 kW)`, nx, ny + bHeight / 2 + 50);
            }
        }

        function drawNodes(w, h, flows) {
            const radius = 35;

            for (const key in nodes) {
                if (key === 'battery') {
                    drawBatteryNode(nodes.battery.x * w, nodes.battery.y * h, flows);
                    continue;
                }

                const node = nodes[key];
                const nx = node.x * w;
                const ny = node.y * h;

                ctx.beginPath();
                ctx.arc(nx, ny, radius, 0, Math.PI * 2);
                ctx.fillStyle = '#1e293b';
                ctx.strokeStyle = node.color;
                ctx.lineWidth = 3;
                ctx.fill();
                ctx.stroke();

                ctx.font = '22px Arial';
                ctx.textAlign = 'center';
                ctx.textBaseline = 'middle';
                ctx.fillText(node.icon, nx, ny - 2);

                ctx.font = '12px Segoe UI';
                ctx.fillStyle = '#94a3b8';
                ctx.fillText(node.label, nx, ny + radius + 15);

                ctx.font = 'bold 13px Segoe UI';
                ctx.fillStyle = '#f8fafc';
                let valText = '';

                if (key === 'pv') valText = `${flows.pPV.toFixed(1)} kW`;
                if (key === 'load') valText = `${flows.pLoad.toFixed(1)} kW`;
                if (key === 'grid') {
                    const status = flows.pGrid > 0 ? 'Pobór' : (flows.pGrid < 0 ? 'Oddawanie' : '0.0 kW');
                    valText = flows.pGrid !== 0 ? `${status}: ${Math.abs(flows.pGrid).toFixed(1)} kW` : status;
                }

                if (valText) {
                    ctx.fillText(valText, nx, ny + radius + 32);
                }
            }
        }

        function animate(timestamp) {
            if (!lastTimestamp) lastTimestamp = timestamp;
            const dt = (timestamp - lastTimestamp) / 1000; // Czas w sekundach rzeczywistych
            lastTimestamp = timestamp;

            // Zegar symulacji
            if (isPlaying && dt < 0.2) {
                const simulatedHoursPassed = dt * timeSpeedHoursPerSec;
                timeMinutes += simulatedHoursPassed * 60;
                if (timeMinutes >= 1440) timeMinutes -= 1440;
                
                updateTimeDisplay();
                updateValuesFromUI();

                // DOKŁADNA FIZYKA AKUMULATORA
                const flows = calculateFlows();
                // E = P * t (kWh = kW * h)
                const addedKWh = flows.pBatt * simulatedHoursPassed;
                const addedSoC = (addedKWh / batteryCapacity) * 100;

                soc = Math.max(0, Math.min(100, soc + addedSoC));
                
                socInput.value = soc;
                socValue.textContent = soc.toFixed(1) + '%';
            }

            const flows = calculateFlows();
            const w = canvas.getBoundingClientRect().width;
            const h = canvas.getBoundingClientRect().height;

            ctx.clearRect(0, 0, w, h);

            drawConnections(w, h);
            spawnParticles(flows);

            particles = particles.filter(p => {
                const isFinished = p.update();
                if (!isFinished) p.draw(w, h);
                return !isFinished;
            });

            drawNodes(w, h, flows);

            requestAnimationFrame(animate);
        }

        updateTimeDisplay();
        updateValuesFromUI();
        requestAnimationFrame(animate);
    
root.querySelectorAll('[data-bess-call]').forEach((button) => button.addEventListener('click', () => {
  const call=button.getAttribute('data-bess-call');
  if(call==='togglePlay()') togglePlay();
  else if(call.startsWith('setSpeed(')) setSpeed(Number(call.match(/\(([^)]+)\)/)?.[1]));
  else if(call.startsWith('setTimePreset(')) setTimePreset(Number(call.match(/\(([^)]+)\)/)?.[1]));
}));
root.querySelectorAll('[data-bess-change]').forEach((input) => input.addEventListener('change',toggleAutoProfile));

})();