{"id":2163,"date":"2026-06-01T03:07:32","date_gmt":"2026-06-01T03:07:32","guid":{"rendered":"https:\/\/aiper.com\/blogs\/?page_id=2163"},"modified":"2026-11-04T09:49:17","modified_gmt":"2026-11-04T09:49:17","slug":"calculadora-tasa-recambio-piscina","status":"publish","type":"page","link":"https:\/\/aiper.com\/blogs\/es\/calculadora-tasa-recambio-piscina\/","title":{"rendered":"Calculadora de tasa de recambio de piscina"},"content":{"rendered":"<p><a href=\"#aiper-upgrade-runtime\">Tiempo diario y coste el\u00e9ctrico<\/a><\/p>\n<!-- Pool Turnover Rate Calculator - WordPress HTML Block -->\n<style>\n    :root {\n        --pool-primary: #1ecad3;\n        --pool-primary-dark: #17a8b0;\n        --pool-primary-light: #e6f9fa;\n        --pool-bg: #ffffff;\n        --pool-text: #2c3e50;\n        --pool-text-light: #5a6c7d;\n        --pool-border: #e0e8ef;\n        --pool-shadow: 0 4px 24px rgba(0, 0, 0, 0.07);\n        --pool-radius: 14px;\n        --pool-radius-sm: 8px;\n        --pool-transition: 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n        --pool-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n    }\n\n    .pool-calc-wrapper {\n        font-family: var(--pool-font);\n        max-width: 580px;\n        margin: 0 auto;\n        background: var(--pool-bg);\n        border-radius: var(--pool-radius);\n        box-shadow: var(--pool-shadow);\n        padding: 32px 28px 28px;\n        box-sizing: border-box;\n        border: 1px solid var(--pool-border);\n        position: relative;\n        overflow: hidden;\n    }\n\n    \/* Decorative top accent bar *\/\n    .pool-calc-wrapper::before {\n        content: '';\n        position: absolute;\n        top: 0;\n        left: 0;\n        right: 0;\n        height: 4px;\n        background: linear-gradient(90deg, #1ecad3 0%, #5de0e8 50%, #1ecad3 100%);\n        border-radius: var(--pool-radius) var(--pool-radius) 0 0;\n    }\n\n    .pool-calc-header {\n        text-align: center;\n        margin-bottom: 26px;\n        padding-top: 6px;\n    }\n\n    .pool-calc-header .pool-icon {\n        display: inline-flex;\n        align-items: center;\n        justify-content: center;\n        width: 50px;\n        height: 50px;\n        border-radius: 50%;\n        background: var(--pool-primary-light);\n        margin-bottom: 12px;\n    }\n\n    .pool-calc-header .pool-icon svg {\n        width: 26px;\n        height: 26px;\n        fill: var(--pool-primary);\n    }\n\n    .pool-calc-header h3 {\n        margin: 0 0 4px;\n        font-size: 1.35rem;\n        font-weight: 700;\n        color: var(--pool-text);\n        letter-spacing: -0.3px;\n    }\n\n    .pool-calc-header p {\n        margin: 0;\n        font-size: 0.9rem;\n        color: var(--pool-text-light);\n        line-height: 1.4;\n    }\n\n    \/* Step indicator *\/\n    .pool-steps-indicator {\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        gap: 6px;\n        margin-bottom: 22px;\n        flex-wrap: wrap;\n    }\n\n    .pool-step-dot {\n        width: 30px;\n        height: 30px;\n        border-radius: 50%;\n        background: #eef2f7;\n        color: #8b9aab;\n        font-weight: 700;\n        font-size: 0.8rem;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        transition: var(--pool-transition);\n        flex-shrink: 0;\n    }\n\n    .pool-step-dot.active {\n        background: var(--pool-primary);\n        color: #fff;\n        box-shadow: 0 3px 10px rgba(30, 202, 211, 0.35);\n    }\n\n    .pool-step-dot.done {\n        background: #b8f0f4;\n        color: #0d8a90;\n    }\n\n    .pool-step-line {\n        width: 28px;\n        height: 2px;\n        background: #dce3eb;\n        border-radius: 1px;\n        flex-shrink: 0;\n    }\n\n    .pool-step-line.done {\n        background: var(--pool-primary);\n    }\n\n    \/* Form groups *\/\n    .pool-form-group {\n        margin-bottom: 20px;\n        position: relative;\n    }\n\n    .pool-form-group label {\n        display: block;\n        font-weight: 600;\n        font-size: 0.9rem;\n        color: var(--pool-text);\n        margin-bottom: 6px;\n        letter-spacing: -0.2px;\n    }\n\n    .pool-form-group label .label-number {\n        display: inline-flex;\n        align-items: center;\n        justify-content: center;\n        width: 22px;\n        height: 22px;\n        border-radius: 50%;\n        background: var(--pool-primary);\n        color: #fff;\n        font-size: 0.7rem;\n        font-weight: 700;\n        margin-right: 6px;\n        vertical-align: middle;\n    }\n\n    .pool-input-row {\n        display: flex;\n        gap: 10px;\n        align-items: stretch;\n    }\n\n    .pool-input-field {\n        flex: 1;\n        padding: 12px 14px;\n        border: 2px solid var(--pool-border);\n        border-radius: var(--pool-radius-sm);\n        font-size: 1rem;\n        font-family: var(--pool-font);\n        color: var(--pool-text);\n        background: #fafbfc;\n        transition: var(--pool-transition);\n        box-sizing: border-box;\n        min-width: 0;\n        outline: none;\n        -webkit-appearance: none;\n        -moz-appearance: textfield;\n    }\n\n    .pool-input-field:focus {\n        border-color: var(--pool-primary);\n        background: #fff;\n        box-shadow: 0 0 0 4px rgba(30, 202, 211, 0.08);\n    }\n\n    .pool-input-field::placeholder {\n        color: #b0bec5;\n    }\n\n    \/* Unit toggle buttons *\/\n    .pool-unit-toggle {\n        display: flex;\n        border-radius: var(--pool-radius-sm);\n        overflow: hidden;\n        border: 2px solid var(--pool-border);\n        flex-shrink: 0;\n        background: #fafbfc;\n    }\n\n    .pool-unit-toggle button {\n        padding: 10px 14px;\n        border: none;\n        background: transparent;\n        cursor: pointer;\n        font-family: var(--pool-font);\n        font-size: 0.82rem;\n        font-weight: 600;\n        color: #6b7d8e;\n        transition: var(--pool-transition);\n        white-space: nowrap;\n        letter-spacing: -0.2px;\n        position: relative;\n    }\n\n    .pool-unit-toggle button:not(:last-child) {\n        border-right: 1px solid var(--pool-border);\n    }\n\n    .pool-unit-toggle button:hover {\n        background: #eef7f8;\n        color: #3a5a6a;\n    }\n\n    .pool-unit-toggle button.active {\n        background: var(--pool-primary);\n        color: #ffffff;\n        box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.08);\n    }\n\n    \/* Helper text \/ links *\/\n    .pool-helper-text {\n        margin-top: 6px;\n        font-size: 0.82rem;\n        color: #7d8fa0;\n        line-height: 1.4;\n    }\n\n    .pool-helper-text a {\n        color: var(--pool-primary-dark);\n        text-decoration: underline;\n        text-underline-offset: 2px;\n        font-weight: 600;\n        transition: color 0.2s;\n    }\n\n    .pool-helper-text a:hover {\n        color: #0f7a80;\n        text-decoration: none;\n    }\n\n    .pool-helper-text .helper-icon {\n        display: inline-block;\n        margin-right: 3px;\n        font-size: 0.75rem;\n    }\n\n    \/* Buttons row *\/\n    .pool-buttons-row {\n        display: flex;\n        gap: 12px;\n        margin-top: 26px;\n        flex-wrap: wrap;\n    }\n\n    .pool-btn-calculate {\n        flex: 1;\n        min-width: 140px;\n        padding: 14px 24px;\n        background: var(--pool-primary);\n        color: #ffffff;\n        border: none;\n        border-radius: var(--pool-radius-sm);\n        font-size: 1rem;\n        font-weight: 700;\n        font-family: var(--pool-font);\n        cursor: pointer;\n        transition: var(--pool-transition);\n        letter-spacing: -0.2px;\n        box-shadow: 0 4px 14px rgba(30, 202, 211, 0.3);\n        position: relative;\n        overflow: hidden;\n    }\n\n    .pool-btn-calculate:hover {\n        background: var(--pool-primary-dark);\n        box-shadow: 0 6px 20px rgba(30, 202, 211, 0.4);\n        transform: translateY(-1px);\n    }\n\n    .pool-btn-calculate:active {\n        transform: translateY(0);\n        box-shadow: 0 2px 8px rgba(30, 202, 211, 0.25);\n        background: #149ca5;\n    }\n\n    .pool-btn-reset {\n        padding: 14px 20px;\n        background: #ffffff;\n        color: #5a6c7d;\n        border: 2px solid #dce3eb;\n        border-radius: var(--pool-radius-sm);\n        font-size: 0.9rem;\n        font-weight: 600;\n        font-family: var(--pool-font);\n        cursor: pointer;\n        transition: var(--pool-transition);\n        letter-spacing: -0.2px;\n        white-space: nowrap;\n    }\n\n    .pool-btn-reset:hover {\n        background: #f5f7fa;\n        border-color: #c0ccd8;\n        color: #3a4a5a;\n    }\n\n    .pool-btn-reset:active {\n        background: #eef1f5;\n    }\n\n    \/* Result display *\/\n    .pool-result {\n        margin-top: 22px;\n        padding: 18px 20px;\n        background: linear-gradient(135deg, #f0fdfd 0%, #e6f9fa 100%);\n        border-radius: var(--pool-radius-sm);\n        border: 2px solid #c5f0f3;\n        display: none;\n        align-items: center;\n        gap: 14px;\n        animation: poolFadeIn 0.4s ease-out;\n    }\n\n    .pool-result.show {\n        display: flex;\n    }\n\n    @keyframes poolFadeIn {\n        from {\n            opacity: 0;\n            transform: translateY(8px);\n        }\n        to {\n            opacity: 1;\n            transform: translateY(0);\n        }\n    }\n\n    .pool-result-icon {\n        flex-shrink: 0;\n        width: 44px;\n        height: 44px;\n        border-radius: 50%;\n        background: var(--pool-primary);\n        display: flex;\n        align-items: center;\n        justify-content: center;\n    }\n\n    .pool-result-icon svg {\n        width: 20px;\n        height: 20px;\n        fill: #fff;\n    }\n\n    .pool-result-text {\n        flex: 1;\n        min-width: 0;\n    }\n\n    .pool-result-label {\n        font-size: 0.78rem;\n        font-weight: 600;\n        color: #5a7d82;\n        text-transform: uppercase;\n        letter-spacing: 0.5px;\n        margin-bottom: 2px;\n    }\n\n    .pool-result-value {\n        font-size: 1.6rem;\n        font-weight: 800;\n        color: #0d5c62;\n        letter-spacing: -0.5px;\n        line-height: 1.2;\n        word-break: break-all;\n    }\n\n    .pool-result-sub {\n        font-size: 0.8rem;\n        color: #5a8a8f;\n        margin-top: 2px;\n    }\n\n    \/* Error state *\/\n    .pool-input-field.error {\n        border-color: #e74c3c;\n        background: #fefafa;\n        box-shadow: 0 0 0 4px rgba(231, 76, 60, 0.06);\n    }\n\n    .pool-error-msg {\n        color: #c0392b;\n        font-size: 0.78rem;\n        margin-top: 4px;\n        display: none;\n        font-weight: 500;\n    }\n\n    .pool-error-msg.show {\n        display: block;\n    }\n\n    \/* Responsive *\/\n    @media (max-width: 500px) {\n        .pool-calc-wrapper {\n            padding: 22px 16px 20px;\n            border-radius: 10px;\n        }\n        .pool-calc-wrapper::before {\n            border-radius: 10px 10px 0 0;\n        }\n        .pool-input-row {\n            flex-direction: column;\n            gap: 8px;\n        }\n        .pool-unit-toggle {\n            align-self: flex-start;\n            border-radius: var(--pool-radius-sm);\n        }\n        .pool-unit-toggle button {\n            padding: 9px 12px;\n            font-size: 0.76rem;\n        }\n        .pool-btn-calculate {\n            font-size: 0.95rem;\n            padding: 12px 18px;\n        }\n        .pool-btn-reset {\n            padding: 12px 16px;\n            font-size: 0.85rem;\n        }\n        .pool-result-value {\n            font-size: 1.3rem;\n        }\n        .pool-calc-header h3 {\n            font-size: 1.15rem;\n        }\n        .pool-step-dot {\n            width: 26px;\n            height: 26px;\n            font-size: 0.7rem;\n        }\n        .pool-step-line {\n            width: 18px;\n        }\n    }\n<\/style>\n\n<div class=\"pool-calc-wrapper\" id=\"poolTurnoverCalculator\" role=\"form\" aria-label=\"Calculadora de tasa de recambio de piscina\">\n    <!-- Header -->\n    <div class=\"pool-calc-header\">\n\n\n        <p>Descubre cu\u00e1nto tarda en circular todo el volumen de tu piscina.<\/p>\n    <\/div>\n\n    <!-- Step indicators -->\n    <div class=\"pool-steps-indicator\" aria-hidden=\"true\">\n        <span class=\"pool-step-dot active\" id=\"stepDot1\">1<\/span>\n        <span class=\"pool-step-line\" id=\"stepLine1\"><\/span>\n        <span class=\"pool-step-dot\" id=\"stepDot2\">2<\/span>\n        <span class=\"pool-step-line\" id=\"stepLine2\"><\/span>\n        <span class=\"pool-step-dot\" id=\"stepDot3\">3<\/span>\n    <\/div>\n\n    <!-- Step 1: Pool Volume -->\n    <div class=\"pool-form-group\" id=\"formGroupVolume\">\n        <label for=\"poolVolumeInput\">\n            <span class=\"label-number\">1<\/span> Volumen de la piscina\n        <\/label>\n        <div class=\"pool-input-row\">\n            <input\n            type=\"number\"\n            id=\"poolVolumeInput\"\n            class=\"pool-input-field\"\n            placeholder=\"Introduce el volumen de la piscina\"\n            min=\"1\"\n            step=\"any\"\n            aria-label=\"Volumen de la piscina\"\n            autocomplete=\"off\"\n            >\n            <div class=\"pool-unit-toggle\" id=\"unitToggle\" role=\"radiogroup\" aria-label=\"Unidad de volumen\">\n                <button type=\"button\" data-unit=\"gallons\" class=\"active\" aria-checked=\"true\" role=\"radio\">Galones<\/button>\n                <button type=\"button\" data-unit=\"liters\" aria-checked=\"false\" role=\"radio\">Litros<\/button>\n                <button type=\"button\" data-unit=\"cubic-meters\" aria-checked=\"false\" role=\"radio\">m\u00b3<\/button>\n            <\/div>\n        <\/div>\n        <p class=\"pool-helper-text\">\n            <span class=\"helper-icon\">\ud83d\udca1<\/span> \u00bfNo lo sabes? Usa nuestra\n            <a href=\"https:\/\/aiper.com\/blogs\/pool-volume-calculator\/\" target=\"_blank\" rel=\"noopener noreferrer\">calculadora de volumen de piscina<\/a>\n        <\/p>\n        <p class=\"pool-error-msg\" id=\"volumeError\">Introduce un volumen de piscina v\u00e1lido.<\/p>\n    <\/div>\n\n    <!-- Step 2: Pump Flow Rate -->\n    <div class=\"pool-form-group\" id=\"formGroupFlow\">\n        <label for=\"pumpFlowInput\">\n            <span class=\"label-number\">2<\/span> Caudal de la bomba\n        <\/label>\n        <div class=\"pool-input-row\">\n            <input\n            type=\"number\"\n            id=\"pumpFlowInput\"\n            class=\"pool-input-field\"\n            placeholder=\"Introduce el caudal de la bomba\"\n            min=\"1\"\n            step=\"any\"\n            aria-label=\"Caudal de la bomba en GPM\"\n            autocomplete=\"off\"\n            >\n            <span style=\"display:inline-flex;align-items:center;padding:12px 14px;background:#f0f4f7;border-radius:8px;font-weight:700;font-size:0.9rem;color:#3a5a6a;white-space:nowrap;flex-shrink:0;border:2px solid #e0e8ef;\">\n                GPM\n            <\/span>\n        <\/div>\n        <p class=\"pool-helper-text\">\n            <span class=\"helper-icon\">\ud83d\udd27<\/span> \u00bfNecesitas ayuda para hallar tu caudal?\n            <a href=\"https:\/\/aiper.com\/blogs\/pool-flow-rate-calculator\/\" target=\"_blank\" rel=\"noopener noreferrer\">calculadora de caudal de piscina<\/a>\n        <\/p>\n        <p class=\"pool-error-msg\" id=\"flowError\">Introduce un caudal de bomba v\u00e1lido en GPM.<\/p>\n    <\/div>\n\n    <!-- Step 3: Action Buttons -->\n    <div class=\"pool-buttons-row\">\n        <button type=\"button\" class=\"pool-btn-calculate\" id=\"btnCalculate\" aria-label=\"Calcular la tasa de recambio\">\n            \u23f1\ufe0f Calcular\n        <\/button>\n        <button type=\"button\" class=\"pool-btn-reset\" id=\"btnReset\" aria-label=\"Restablecer todos los campos\">\n            \u21bb Restablecer\n        <\/button>\n    <\/div>\n\n    <!-- Result Display -->\n    <div class=\"pool-result\" id=\"poolResult\" role=\"status\" aria-live=\"polite\">\n        <div class=\"pool-result-icon\">\n            <svg viewBox=\"0 0 24 24\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                <path d=\"M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z\"\/>\n            <\/svg>\n        <\/div>\n        <div class=\"pool-result-text\">\n            <div class=\"pool-result-label\">Tiempo de recambio estimado<\/div>\n            <div class=\"pool-result-value\" id=\"resultValue\">&#8212; h &#8212; m<\/div>\n            <div class=\"pool-result-sub\" id=\"resultSub\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n\n<script>\n    (function() {\n        \/\/ DOM references\n        const volumeInput = document.getElementById('poolVolumeInput');\n        const flowInput = document.getElementById('pumpFlowInput');\n        const unitToggle = document.getElementById('unitToggle');\n        const btnCalculate = document.getElementById('btnCalculate');\n        const btnReset = document.getElementById('btnReset');\n        const poolResult = document.getElementById('poolResult');\n        const resultValue = document.getElementById('resultValue');\n        const resultSub = document.getElementById('resultSub');\n        const volumeError = document.getElementById('volumeError');\n        const flowError = document.getElementById('flowError');\n        const stepDot1 = document.getElementById('stepDot1');\n        const stepDot2 = document.getElementById('stepDot2');\n        const stepDot3 = document.getElementById('stepDot3');\n        const stepLine1 = document.getElementById('stepLine1');\n        const stepLine2 = document.getElementById('stepLine2');\n\n        \/\/ State\n        let selectedUnit = 'gallons';\n\n        \/\/ --- Unit toggle logic ---\n        const unitButtons = unitToggle.querySelectorAll('button');\n\n        unitButtons.forEach(btn => {\n            btn.addEventListener('click', function() {\n                unitButtons.forEach(b => {\n                    b.classList.remove('active');\n                    b.setAttribute('aria-checked', 'false');\n                });\n                this.classList.add('active');\n                this.setAttribute('aria-checked', 'true');\n                selectedUnit = this.getAttribute('data-unit');\n                \/\/ Clear result on unit change\n                hideResult();\n                \/\/ Clear errors\n                clearErrors();\n                \/\/ Update placeholder based on unit\n                updatePlaceholder();\n            });\n        });\n\n        function updatePlaceholder() {\n            const placeholders = {\n                'gallons': 'p. ej. 15.000',\n                'liters': 'p. ej. 56.000',\n                'cubic-meters': 'p. ej. 56'\n            };\n            volumeInput.placeholder = placeholders[selectedUnit] || 'Introduce el volumen de la piscina';\n        }\n\n        \/\/ --- Focus event: update step indicators ---\n        volumeInput.addEventListener('focus', function() {\n            setActiveStep(1);\n        });\n        flowInput.addEventListener('focus', function() {\n            setActiveStep(2);\n        });\n\n        function setActiveStep(step) {\n            \/\/ Reset all\n            [stepDot1, stepDot2, stepDot3].forEach(d => d.classList.remove('active', 'done'));\n            [stepLine1, stepLine2].forEach(l => l.classList.remove('done'));\n\n            if (step === 1) {\n                stepDot1.classList.add('active');\n            } else if (step === 2) {\n                stepDot1.classList.add('done');\n                stepLine1.classList.add('done');\n                stepDot2.classList.add('active');\n            } else if (step === 3) {\n                stepDot1.classList.add('done');\n                stepLine1.classList.add('done');\n                stepDot2.classList.add('done');\n                stepLine2.classList.add('done');\n                stepDot3.classList.add('active');\n            }\n        }\n\n        \/\/ --- Clear errors ---\n        function clearErrors() {\n            volumeInput.classList.remove('error');\n            flowInput.classList.remove('error');\n            volumeError.classList.remove('show');\n            flowError.classList.remove('show');\n        }\n\n        \/\/ --- Hide result ---\n        function hideResult() {\n            poolResult.classList.remove('show');\n        }\n\n        \/\/ --- Show result ---\n        function showResult(hours, minutes, totalMinutes) {\n            resultValue.textContent = hours + ' h ' + minutes + ' m';\n            const totalMinRounded = Math.round(totalMinutes);\n            resultSub.textContent = 'Total: ~' + totalMinRounded + ' minutos para completar un recambio completo';\n            poolResult.classList.add('show');\n            setActiveStep(3);\n            \/\/ Scroll result into view smoothly\n            poolResult.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n        }\n\n        \/\/ --- Conversion helpers ---\n        function convertToGallons(value, unit) {\n            switch (unit) {\n                case 'gallons':\n                    return value;\n                case 'liters':\n                    \/\/ 1 gallon = 3.78541 liters\n                    return value \/ 3.78541;\n                case 'cubic-meters':\n                    \/\/ 1 cubic meter = 264.172 gallons\n                    return value * 264.172;\n                default:\n                    return value;\n            }\n        }\n\n        \/\/ --- Main calculation ---\n        function calculateTurnover() {\n            clearErrors();\n            hideResult();\n\n            const volumeRaw = volumeInput.value.trim();\n            const flowRaw = flowInput.value.trim();\n\n            let hasError = false;\n\n            \/\/ Validate volume\n            const volumeNum = parseFloat(volumeRaw);\n            if (!volumeRaw || isNaN(volumeNum) || volumeNum <= 0) {\n                volumeInput.classList.add('error');\n                volumeError.classList.add('show');\n                hasError = true;\n            }\n\n            \/\/ Validate flow rate\n            const flowNum = parseFloat(flowRaw);\n            if (!flowRaw || isNaN(flowNum) || flowNum <= 0) {\n                flowInput.classList.add('error');\n                flowError.classList.add('show');\n                hasError = true;\n            }\n\n            if (hasError) {\n                \/\/ Shake or focus first error\n                if (volumeInput.classList.contains('error')) {\n                    volumeInput.focus();\n                } else if (flowInput.classList.contains('error')) {\n                    flowInput.focus();\n                }\n                return;\n            }\n\n            \/\/ Convert pool volume to gallons\n            const volumeGallons = convertToGallons(volumeNum, selectedUnit);\n\n            \/\/ Turnover time in hours = Volume (gal) \/ (Flow Rate GPM \u00d7 60)\n            const turnoverHours = volumeGallons \/ (flowNum * 60);\n\n            \/\/ Convert to hours and minutes\n            const wholeHours = Math.floor(turnoverHours);\n            const remainingMinutes = Math.round((turnoverHours - wholeHours) * 60);\n\n            \/\/ Handle edge case where minutes round to 60\n            let displayHours = wholeHours;\n            let displayMinutes = remainingMinutes;\n            if (remainingMinutes >= 60) {\n                displayHours += 1;\n                displayMinutes = remainingMinutes - 60;\n            }\n            \/\/ If minutes round to 60 again (unlikely but safe)\n            if (displayMinutes === 60) {\n                displayHours += 1;\n                displayMinutes = 0;\n            }\n\n            const totalMinutes = turnoverHours * 60;\n\n            showResult(displayHours, displayMinutes, totalMinutes);\n        }\n\n        \/\/ --- Reset ---\n        function resetAll() {\n            volumeInput.value = '';\n            flowInput.value = '';\n            clearErrors();\n            hideResult();\n            \/\/ Reset unit to gallons\n            selectedUnit = 'gallons';\n            unitButtons.forEach(b => {\n                b.classList.remove('active');\n                b.setAttribute('aria-checked', 'false');\n            });\n            const gallonsBtn = unitToggle.querySelector('[data-unit=\"gallons\"]');\n            if (gallonsBtn) {\n                gallonsBtn.classList.add('active');\n                gallonsBtn.setAttribute('aria-checked', 'true');\n            }\n            updatePlaceholder();\n            setActiveStep(1);\n            volumeInput.focus({ preventScroll: true });\n            \/\/ Reset step dots\n            [stepDot1, stepDot2, stepDot3].forEach(d => d.classList.remove('active', 'done'));\n            [stepLine1, stepLine2].forEach(l => l.classList.remove('done'));\n            stepDot1.classList.add('active');\n        }\n\n        \/\/ --- Event listeners ---\n        btnCalculate.addEventListener('click', calculateTurnover);\n        btnReset.addEventListener('click', resetAll);\n\n        \/\/ Allow Enter key to trigger calculation\n        volumeInput.addEventListener('keydown', function(e) {\n            if (e.key === 'Enter') {\n                e.preventDefault();\n                flowInput.focus();\n            }\n        });\n        flowInput.addEventListener('keydown', function(e) {\n            if (e.key === 'Enter') {\n                e.preventDefault();\n                calculateTurnover();\n            }\n        });\n\n        \/\/ Clear errors on input\n        volumeInput.addEventListener('input', function() {\n            if (volumeInput.classList.contains('error')) {\n                volumeInput.classList.remove('error');\n                volumeError.classList.remove('show');\n            }\n            hideResult();\n        });\n        flowInput.addEventListener('input', function() {\n            if (flowInput.classList.contains('error')) {\n                flowInput.classList.remove('error');\n                flowError.classList.remove('show');\n            }\n            hideResult();\n        });\n\n        \/\/ Initialize\n        updatePlaceholder();\n        setActiveStep(1);\n\n        \/\/ Expose for potential external use\n        window.poolTurnoverCalc = {\n            reset: resetAll,\n            calculate: calculateTurnover,\n            getResult: function() {\n                return {\n                    hours: resultValue.textContent,\n                    visible: poolResult.classList.contains('show')\n                };\n            }\n        };\n    })();\n<\/script>\n\n\n\n<div class=\"aiper-chart-container\">\n    <h2 class=\"aiper-chart-title\">Tasa de recambio de piscina: gu\u00eda r\u00e1pida<\/h2>\n    <p class=\"aiper-chart-desc\">\n        La mayor\u00eda de las piscinas residenciales necesitan un recambio completo cada <b>8 horas<\/b>. Mueve el control deslizante de abajo para ver c\u00f3mo se ajusta el volumen de tu piscina a los caudales de bomba est\u00e1ndar.\n    <\/p>\n\n    <!-- Interactive slider with live highlight -->\n    <div class=\"aiper-interactive-slider-box\">\n        <label for=\"chartVolumeSlider\" class=\"aiper-slider-label\">\n            Volumen de tu piscina: <span id=\"sliderVolumeVal\">15,000<\/span> galones\n        <\/label>\n        <input type=\"range\" id=\"chartVolumeSlider\" min=\"5000\" max=\"40000\" step=\"2500\" value=\"15000\" class=\"aiper-range-slider\">\n\n        <div class=\"aiper-quick-stat-grid\">\n            <div class=\"aiper-stat-card\">\n                <span class=\"aiper-stat-meta\">Caudal recomendado<\/span>\n                <span id=\"statFlow\" class=\"aiper-stat-num\">31 GPM<\/span>\n            <\/div>\n            <div class=\"aiper-stat-card\">\n                <span class=\"aiper-stat-meta\">Tiempo de recambio est.<\/span>\n                <span id=\"statTime\" class=\"aiper-stat-num\">8 h 0 m<\/span>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <!-- Core comparison data table -->\n    <div class=\"aiper-table-responsive\">\n        <table class=\"aiper-data-table\" id=\"turnoverDataTable\">\n            <thead>\n                <tr>\n                    <th>Tama\u00f1o de piscina (gal)<\/th>\n                    <th>Caudal de bomba (GPM)<\/th>\n                    <th>Tiempo de recambio objetivo<\/th>\n                <\/tr>\n            <\/thead>\n            <tbody>\n                <tr data-vol=\"5000\">\n                    <td>5,000 galones<\/td>\n                    <td>15 GPM<\/td>\n                    <td>5 h 33 m<\/td>\n                <\/tr>\n                <tr data-vol=\"10000\">\n                    <td>10,000 galones<\/td>\n                    <td>25 GPM<\/td>\n                    <td>6 h 40 m<\/td>\n                <\/tr>\n                <tr data-vol=\"15000\" class=\"aiper-row-highlight\">\n                    <td>15,000 galones<\/td>\n                    <td>35 GPM<\/td>\n                    <td>7 h 9 m<\/td>\n                <\/tr>\n                <tr data-vol=\"20000\">\n                    <td>20,000 galones<\/td>\n                    <td>45 GPM<\/td>\n                    <td>7 h 24 m<\/td>\n                <\/tr>\n                <tr data-vol=\"25000\">\n                    <td>25,000 galones<\/td>\n                    <td>55 GPM<\/td>\n                    <td>7 h 35 m<\/td>\n                <\/tr>\n                <tr data-vol=\"30000\">\n                    <td>30,000 galones<\/td>\n                    <td>65 GPM<\/td>\n                    <td>7 h 42 m<\/td>\n                <\/tr>\n                <tr data-vol=\"40000\">\n                    <td>40,000 galones<\/td>\n                    <td>85 GPM<\/td>\n                    <td>7 h 51 m<\/td>\n                <\/tr>\n            <\/tbody>\n        <\/table>\n    <\/div>\n<\/div>\n\n<style>\n    .aiper-chart-container {\n        font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n        max-width: 600px;\n        margin: 30px auto;\n        padding: 25px;\n        border: 1px solid #e1e1e1;\n        border-radius: 8px;\n        background-color: #ffffff;\n        box-shadow: 0 4px 12px rgba(0,0,0,0.05);\n    }\n    .aiper-chart-title {\n        color: #333333;\n        margin-top: 0;\n        margin-bottom: 10px;\n        font-size: 20px;\n        font-weight: 600;\n        text-align: center;\n    }\n    .aiper-chart-desc {\n        font-size: 14px;\n        color: #666666;\n        text-align: center;\n        line-height: 1.5;\n        margin-bottom: 25px;\n    }\n    .aiper-interactive-slider-box {\n        background-color: #fafafa;\n        padding: 20px;\n        border-radius: 6px;\n        margin-bottom: 25px;\n        border: 1px dashed #dedede;\n    }\n    .aiper-slider-label {\n        display: block;\n        font-size: 15px;\n        font-weight: 600;\n        color: #444444;\n        margin-bottom: 12px;\n    }\n    .aiper-slider-label span {\n        color: #1ecad3;\n        font-size: 18px;\n    }\n    .aiper-range-slider {\n        -webkit-appearance: none;\n        width: 100%;\n        height: 6px;\n        border-radius: 3px;\n        background: #e1e1e1;\n        outline: none;\n        margin-bottom: 20px;\n    }\n    .aiper-range-slider::-webkit-slider-thumb {\n        -webkit-appearance: none;\n        appearance: none;\n        width: 18px;\n        height: 18px;\n        border-radius: 50%;\n        background: #1ecad3;\n        cursor: pointer;\n        transition: transform 0.1s ease;\n    }\n    .aiper-range-slider::-webkit-slider-thumb:hover {\n        transform: scale(1.2);\n    }\n    .aiper-quick-stat-grid {\n        display: flex;\n        gap: 15px;\n    }\n    .aiper-stat-card {\n        flex: 1;\n        background: #ffffff;\n        padding: 10px;\n        border-radius: 4px;\n        border: 1px solid #eaeaea;\n        text-align: center;\n    }\n    .aiper-stat-meta {\n        display: block;\n        font-size: 11px;\n        text-transform: uppercase;\n        color: #888888;\n        margin-bottom: 4px;\n        letter-spacing: 0.5px;\n    }\n    .aiper-stat-num {\n        font-size: 16px;\n        font-weight: 700;\n        color: #333333;\n    }\n    .aiper-table-responsive {\n        width: 100%;\n        overflow-x: auto;\n    }\n    .aiper-data-table {\n        width: 100%;\n        border-collapse: collapse;\n        font-size: 14px;\n        text-align: left;\n    }\n    .aiper-data-table th {\n        background-color: #f5f5f5;\n        color: #555555;\n        font-weight: 600;\n        padding: 12px;\n        border-bottom: 2px solid #e5e5e5;\n    }\n    .aiper-data-table td {\n        padding: 12px;\n        border-bottom: 1px solid #eeeeee;\n        color: #444444;\n        transition: background-color 0.2s ease;\n    }\n    \/* Highlight row *\/\n    .aiper-data-table tr.aiper-row-highlight td {\n        background-color: #f4fdfd !important;\n        color: #1ecad3;\n        font-weight: 600;\n    }\n    .aiper-data-table tr:hover td {\n        background-color: #fcfcfc;\n    }\n<\/style>\n\n<script>\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n    const slider = document.getElementById(\"chartVolumeSlider\");\n    const volumeLabel = document.getElementById(\"sliderVolumeVal\");\n    const statFlow = document.getElementById(\"statFlow\");\n    const statTime = document.getElementById(\"statTime\");\n    const tableRows = document.querySelectorAll(\"#turnoverDataTable tbody tr\");\n\n    \/\/ Estimate standard parameters from the slider (recommended flow for ~8h turnover)\n    function updateChartMetrics(volume) {\n        volumeLabel.textContent = Number(volume).toLocaleString();\n\n        \/\/ Derive recommended flow from an 8-hour (480-minute) turnover baseline (GPM = Volume \/ 480)\n        \/\/ Round up so the flow rate stays a whole number\n        const recommendedGPM = Math.max(15, Math.ceil(volume \/ 480));\n        statFlow.textContent = recommendedGPM + \" GPM\";\n\n        \/\/ Compute the real turnover time and format it\n        const totalMinutes = volume \/ recommendedGPM;\n        const h = Math.floor(totalMinutes \/ 60);\n        const m = Math.round(totalMinutes % 60);\n        statTime.textContent = h + \" h \" + m + \" m\";\n\n        \/\/ Highlight the closest matching table row\n        let closestRow = null;\n        let minDiff = Infinity;\n\n        tableRows.forEach(row => {\n            row.classList.remove(\"aiper-row-highlight\");\n            const rowVol = parseInt(row.getAttribute(\"data-vol\"));\n            const diff = Math.abs(volume - rowVol);\n            if (diff < minDiff) {\n                minDiff = diff;\n                closestRow = row;\n            }\n        });\n\n        if (closestRow) {\n            closestRow.classList.add(\"aiper-row-highlight\");\n        }\n    }\n\n    slider.addEventListener(\"input\", function(e) {\n        updateChartMetrics(e.target.value);\n    });\n\n    \/\/ Run once on init\n    updateChartMetrics(slider.value);\n});\n<\/script>\n\n\n\n<!-- Pool Flow Rate Chart - Independent Module -->\n<style>\n    :root {\n        --chart-primary: #1ecad3;\n        --chart-primary-dark: #17a8b0;\n        --chart-primary-light: #e6f9fa;\n        --chart-bg: #ffffff;\n        --chart-text: #2c3e50;\n        --chart-text-light: #5a6c7d;\n        --chart-border: #e0e8ef;\n        --chart-shadow: 0 4px 24px rgba(0, 0, 0, 0.07);\n        --chart-radius: 14px;\n        --chart-radius-sm: 8px;\n        --chart-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n    }\n\n    .flow-chart-wrapper {\n        font-family: var(--chart-font);\n        max-width: 680px;\n        margin: 0 auto 24px;\n        background: var(--chart-bg);\n        border-radius: var(--chart-radius);\n        box-shadow: var(--chart-shadow);\n        padding: 28px 24px 22px;\n        box-sizing: border-box;\n        border: 1px solid var(--chart-border);\n        position: relative;\n        overflow: hidden;\n    }\n\n    \/* Top accent *\/\n    .flow-chart-wrapper::before {\n        content: '';\n        position: absolute;\n        top: 0;\n        left: 0;\n        right: 0;\n        height: 4px;\n        background: linear-gradient(90deg, #1ecad3 0%, #5de0e8 50%, #1ecad3 100%);\n        border-radius: var(--chart-radius) var(--chart-radius) 0 0;\n    }\n\n    .flow-chart-header {\n        display: flex;\n        align-items: center;\n        gap: 12px;\n        margin-bottom: 6px;\n        padding-top: 4px;\n    }\n\n    .flow-chart-header .chart-icon {\n        flex-shrink: 0;\n        width: 44px;\n        height: 44px;\n        border-radius: 50%;\n        background: var(--chart-primary-light);\n        display: flex;\n        align-items: center;\n        justify-content: center;\n    }\n\n    .flow-chart-header .chart-icon svg {\n        width: 22px;\n        height: 22px;\n        fill: var(--chart-primary);\n    }\n\n    .flow-chart-header .chart-title-group {\n        flex: 1;\n        min-width: 0;\n    }\n\n    .flow-chart-header h4 {\n        margin: 0 0 2px;\n        font-size: 1.15rem;\n        font-weight: 700;\n        color: var(--chart-text);\n        letter-spacing: -0.3px;\n    }\n\n    .flow-chart-header .chart-subtitle {\n        font-size: 0.82rem;\n        color: var(--chart-text-light);\n        margin: 0;\n    }\n\n    .chart-container {\n        position: relative;\n        width: 100%;\n        height: 380px;\n        margin: 10px 0 6px;\n    }\n\n    .chart-container canvas {\n        width: 100% !important;\n        height: 100% !important;\n    }\n\n    \/* Legend custom row *\/\n    .chart-legend-custom {\n        display: flex;\n        flex-wrap: wrap;\n        gap: 18px;\n        justify-content: center;\n        margin-top: 10px;\n        font-size: 0.82rem;\n        color: var(--chart-text-light);\n    }\n\n    .chart-legend-custom .legend-item {\n        display: flex;\n        align-items: center;\n        gap: 6px;\n        font-weight: 500;\n    }\n\n    .legend-dot {\n        width: 12px;\n        height: 12px;\n        border-radius: 3px;\n        flex-shrink: 0;\n    }\n\n    .legend-dot.min {\n        background: #f9c74f;\n        border: 1px solid #e0a800;\n    }\n    .legend-dot.max {\n        background: #f9844a;\n        border: 1px solid #d9662c;\n    }\n    .legend-dot.optimal {\n        background: #1ecad3;\n        border: 1px solid #149ca5;\n    }\n\n    .chart-note {\n        text-align: center;\n        margin-top: 8px;\n        font-size: 0.75rem;\n        color: #8b9aab;\n        line-height: 1.4;\n    }\n\n    .chart-note a {\n        color: var(--chart-primary-dark);\n        text-decoration: underline;\n        text-underline-offset: 2px;\n        font-weight: 600;\n    }\n\n    .chart-note a:hover {\n        color: #0f7a80;\n        text-decoration: none;\n    }\n\n    \/* Responsive *\/\n    @media (max-width: 500px) {\n        .flow-chart-wrapper {\n            padding: 20px 12px 16px;\n            border-radius: 10px;\n        }\n        .flow-chart-wrapper::before {\n            border-radius: 10px 10px 0 0;\n        }\n        .chart-container {\n            height: 290px;\n        }\n        .flow-chart-header h4 {\n            font-size: 1rem;\n        }\n        .chart-legend-custom {\n            gap: 10px;\n            font-size: 0.75rem;\n        }\n    }\n<\/style>\n\n<div class=\"flow-chart-wrapper\" id=\"poolFlowChartModule\" role=\"region\" aria-label=\"Tabla de recomendaci\u00f3n de caudales de tuber\u00eda de piscina\">\n    <!-- Header -->\n    <div class=\"flow-chart-header\">\n        <div class=\"chart-icon\">\n            <!-- Flow \/ pipe icon -->\n            <svg viewBox=\"0 0 24 24\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                <path d=\"M22 14h-2v-2h-2v2h-2v2h2v2h2v-2h2v-2zM4 8h2v2h2V8h2V6H8V4H6v2H4v2zm12-4V2H6v2H4v2H2v2h2v2h2v2h2v2h2v-2H8v-2h2v-2H8V8h2V6h-2V4h6zm-2 12v-2h-2v2h-2v2h2v2h2v-2h2v-2h-2z\" fill-rule=\"evenodd\"\/>\n            <\/svg>\n        <\/div>\n        <div class=\"chart-title-group\">\n            <h2>Caudales recomendados seg\u00fan el tama\u00f1o de la tuber\u00eda<\/h2>\n            <p class=\"chart-subtitle\">Tuber\u00eda de piscina de PVC est\u00e1ndar (schedule 40)<\/p>\n        <\/div>\n    <\/div>\n\n    <!-- Chart canvas -->\n    <div class=\"chart-container\">\n        <canvas id=\"flowRateChartCanvas\" aria-label=\"Gr\u00e1fico de barras que muestra los caudales m\u00ednimo, m\u00e1ximo y \u00f3ptimo en GPM para tuber\u00edas de 1,5 a 3 pulgadas\"><\/canvas>\n    <\/div>\n\n    <!-- Custom legend -->\n    <div class=\"chart-legend-custom\">\n        <span class=\"legend-item\"><span class=\"legend-dot min\"><\/span> Caudal m\u00edn (GPM)<\/span>\n        <span class=\"legend-item\"><span class=\"legend-dot max\"><\/span> Caudal m\u00e1x (GPM)<\/span>\n        <span class=\"legend-item\"><span class=\"legend-dot optimal\"><\/span> \u00d3ptimo (6\u20138 ft\/s)<\/span>\n    <\/div>\n\n    <p class=\"chart-note\">\n        \ud83d\udca1 Seg\u00fan las pautas habituales del sector para tuber\u00eda de piscina de PVC.\n\n    <\/p>\n<\/div>\n\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/chart.js@4.4.8\/dist\/chart.umd.min.js\">\n<\/script>\n\n<script>\n    (function() {\n        \/\/ Wait for Chart.js to load\n        function initChart() {\n            const canvas = document.getElementById('flowRateChartCanvas');\n            if (!canvas) return;\n\n            const ctx = canvas.getContext('2d');\n\n            \/\/ Destroy previous chart instance if any (for re-initialization safety)\n            if (window.flowRateChartInstance) {\n                window.flowRateChartInstance.destroy();\n            }\n\n            \/\/ Data: Pipe sizes (inches) vs Flow rates (GPM)\n            const pipeSizes = ['1.5\"', '2\"', '2.5\"', '3\"'];\n\n            \/\/ Typical min\/max\/optimal flow rates in GPM for each pipe size\n            const minFlow = [28, 45, 70, 100];\n            const maxFlow = [50, 80, 120, 170];\n            const optimalFlow = [38, 62, 95, 135];\n\n            \/\/ Create gradient fill for optimal bars\n            const gradientOptimal = ctx.createLinearGradient(0, 0, 0, 400);\n            gradientOptimal.addColorStop(0, 'rgba(30, 202, 211, 0.9)');\n            gradientOptimal.addColorStop(1, 'rgba(30, 202, 211, 0.45)');\n\n            const gradientMin = ctx.createLinearGradient(0, 0, 0, 400);\n            gradientMin.addColorStop(0, 'rgba(249, 199, 79, 0.85)');\n            gradientMin.addColorStop(1, 'rgba(249, 199, 79, 0.35)');\n\n            const gradientMax = ctx.createLinearGradient(0, 0, 0, 400);\n            gradientMax.addColorStop(0, 'rgba(249, 132, 74, 0.85)');\n            gradientMax.addColorStop(1, 'rgba(249, 132, 74, 0.35)');\n\n            window.flowRateChartInstance = new Chart(ctx, {\n                type: 'bar',\n                data: {\n                    labels: pipeSizes,\n                    datasets: [{\n                        label: 'Caudal m\u00edn (GPM)',\n                        data: minFlow,\n                        backgroundColor: gradientMin,\n                        borderColor: '#f9c74f',\n                        borderWidth: 1.5,\n                        borderRadius: 6,\n                        borderSkipped: false,\n                        order: 3,\n                    }, {\n                        label: 'Caudal m\u00e1x (GPM)',\n                        data: maxFlow,\n                        backgroundColor: gradientMax,\n                        borderColor: '#f9844a',\n                        borderWidth: 1.5,\n                        borderRadius: 6,\n                        borderSkipped: false,\n                        order: 2,\n                    }, {\n                        label: '\u00d3ptimo (6\u20138 ft\/s)',\n                        data: optimalFlow,\n                        backgroundColor: gradientOptimal,\n                        borderColor: '#1ecad3',\n                        borderWidth: 2,\n                        borderRadius: 6,\n                        borderSkipped: false,\n                        order: 1,\n                    }]\n                },\n                options: {\n                    responsive: true,\n                    maintainAspectRatio: false,\n                    interaction: {\n                        mode: 'index',\n                        intersect: false,\n                    },\n                    plugins: {\n                        legend: {\n                            display: false, \/\/ We use custom legend\n                        },\n                        tooltip: {\n                            backgroundColor: '#1e293b',\n                            titleFont: { weight: 'bold', size: 13, family: \"'Segoe UI', Roboto, sans-serif\" },\n                            bodyFont: { size: 12, family: \"'Segoe UI', Roboto, sans-serif\" },\n                            padding: 12,\n                            cornerRadius: 8,\n                            displayColors: true,\n                            callbacks: {\n                                label: function(context) {\n                                    return context.dataset.label + ': ' + context.raw + ' GPM';\n                                }\n                            }\n                        },\n                    },\n                    scales: {\n                        x: {\n                            title: {\n                                display: true,\n                                text: 'Di\u00e1metro de la tuber\u00eda (pulgadas)',\n                                color: '#5a6c7d',\n                                font: {\n                                    weight: '600',\n                                    size: 12,\n                                    family: \"'Segoe UI', Roboto, sans-serif\"\n                                },\n                            },\n                            grid: {\n                                display: false,\n                            },\n                            ticks: {\n                                color: '#3a4a5a',\n                                font: {\n                                    weight: '500',\n                                    size: 11,\n                                },\n                            },\n                        },\n                        y: {\n                            title: {\n                                display: true,\n                                text: 'Caudal (GPM)',\n                                color: '#5a6c7d',\n                                font: {\n                                    weight: '600',\n                                    size: 12,\n                                    family: \"'Segoe UI', Roboto, sans-serif\"\n                                },\n                            },\n                            beginAtZero: true,\n                            max: 190,\n                            ticks: {\n                                stepSize: 20,\n                                callback: function(value) {\n                                    return value + ' GPM';\n                                },\n                                color: '#3a4a5a',\n                                font: {\n                                    size: 10.5,\n                                },\n                            },\n                            grid: {\n                                color: '#eef2f7',\n                                drawBorder: false,\n                            },\n                        },\n                    },\n                    animation: {\n                        duration: 1000,\n                        easing: 'easeOutQuart',\n                    },\n                },\n            });\n        }\n\n        \/\/ Initialize on load\n        if (typeof Chart !== 'undefined') {\n            initChart();\n        } else {\n            \/\/ If Chart.js loads asynchronously, wait for it\n            window.addEventListener('load', function() {\n                if (typeof Chart !== 'undefined') {\n                    initChart();\n                } else {\n                    \/\/ Fallback: retry after a short delay\n                    setTimeout(function() {\n                        if (typeof Chart !== 'undefined') {\n                            initChart();\n                        }\n                    }, 600);\n                }\n            });\n        }\n\n        \/\/ Handle dynamic re-insertion (e.g., in some page builders)\n        document.addEventListener('DOMContentLoaded', function() {\n            if (typeof Chart !== 'undefined' && !window.flowRateChartInstance) {\n                initChart();\n            }\n        });\n    })();\n<\/script>\n\n\n<!-- aiper-tool-links -->\n<style>.aiper-i18n-upgrade{box-sizing:border-box;width:100%;max-width:100%;overflow-wrap:anywhere;padding:24px;margin:24px 0;border:1px solid #1ecad3;border-radius:12px}.aiper-i18n-upgrade form{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:16px}.aiper-i18n-upgrade label{display:flex;flex-direction:column;gap:8px}.aiper-i18n-upgrade input{min-width:0;padding:12px;border:1px solid #a0b8c4;border-radius:8px}.aiper-i18n-upgrade button{padding:12px;background:#087e8b;color:white;border:0;border-radius:8px}.aiper-i18n-upgrade p{line-height:1.7}@media(max-width:600px){.aiper-i18n-upgrade form{grid-template-columns:minmax(0,1fr)}}<\/style><section class=\"aiper-i18n-upgrade\" id=\"aiper-upgrade-runtime\"><h2>Tiempo diario y coste el\u00e9ctrico<\/h2><p>Utilice mediciones reales. El tiempo de recirculaci\u00f3n no garantiza la calidad del agua; respete el caudal y tiempo m\u00ednimos de los equipos.<\/p><p>Introduzca decimales con punto (p. ej., 1.5). Galones estadounidenses salvo indicaci\u00f3n contraria. Importes en d\u00f3lares estadounidenses (USD).<\/p><form><label>Volumen de piscina (US gal)<input type=\"number\" name=\"v\" value=\"20000\" min=\"0\" step=\"any\" required><\/label><label>Caudal medido (GPM)<input type=\"number\" name=\"q\" value=\"50\" min=\"0\" step=\"any\" required><\/label><label>Equivalentes de volumen al d\u00eda<input type=\"number\" name=\"n\" value=\"1\" min=\"0\" step=\"any\" required><\/label><label>Tiempo m\u00ednimo de equipos (h)<input type=\"number\" name=\"min\" value=\"0\" min=\"0\" step=\"any\" required><\/label><label>Potencia medida (W)<input type=\"number\" name=\"w\" value=\"700\" min=\"0\" step=\"any\" required><\/label><label>Tarifa el\u00e9ctrica ($\/kWh)<input type=\"number\" name=\"r\" value=\"0.2\" min=\"0\" step=\"any\" required><\/label><button type=\"submit\">Calcular<\/button><button type=\"reset\">Restablecer<\/button><\/form><p role=\"status\" aria-live=\"polite\"><\/p><\/section><script>(()=>{const root=document.currentScript.previousElementSibling,form=root.querySelector('form'),out=root.querySelector('[role=status]'),D={\"calc\": \"Calcular\", \"reset\": \"Restablecer\", \"format\": \"Introduzca decimales con punto (p. ej., 1.5). Galones estadounidenses salvo indicaci\u00f3n contraria.\", \"error\": \"Complete todos los campos con valores no negativos. El volumen, caudal y dimensiones deben ser positivos.\", \"unreachable\": \"No se puede alcanzar el objetivo con esta agua de reposici\u00f3n.\", \"day\": \"Por d\u00eda\", \"month\": \"Para 30 d\u00edas\", \"hours\": \"horas\", \"water\": \"Superficie del agua\", \"interior\": \"Superficie interior, fondo y paredes\", \"replace\": \"Reposici\u00f3n en una sola etapa\", \"stages\": \"Etapas iguales de reposici\u00f3n\", \"total\": \"Agua total utilizada\", \"flow\": \"Caudal medido de la manguera\", \"time\": \"Tiempo estimado de llenado\", \"target\": \"Objetivo temporal de cloro libre\", \"dose\": \"Cantidad de cloro l\u00edquido\", \"budget\": \"Presupuesto del proyecto con reserva\", \"invalid\": \"El objetivo no cabe en un d\u00eda de 24 horas.\", \"review\": \"Compruebe las mediciones, ajuste un par\u00e1metro cada vez, haga circular el agua y vuelva a medir. El revestimiento, el sistema desinfectante y la etiqueta determinan los objetivos.\", \"schedule\": \"Programa diario de varias velocidades\", \"off\": \"Apagado\", \"equal\": \"Comparaci\u00f3n con igual volumen de agua\", \"units\": \"US gal; ft; GPM; W; $\/kWh\", \"title\": [\"Tiempo diario y coste el\u00e9ctrico\", \"Comprobar superficie interior y del agua\", \"Reposici\u00f3n de agua para reducir concentraciones\", \"Medir el caudal de la manguera\", \"Reposici\u00f3n SLAM seg\u00fan el CYA\", \"Orden de ajuste del agua\", \"Presupuesto desglosado del proyecto\"], \"labels\": [\"Volumen de piscina (US gal)\", \"Caudal medido (GPM)\", \"Equivalentes de volumen al d\u00eda\", \"Tiempo m\u00ednimo de equipos (h)\", \"Potencia medida (W)\", \"Tarifa el\u00e9ctrica ($\/kWh)\", \"Longitud (ft)\", \"Anchura (ft)\", \"Profundidad m\u00ednima (ft)\", \"Profundidad m\u00e1xima (ft)\", \"Lectura actual (ppm)\", \"Lectura objetivo (ppm)\", \"Lectura del agua de reposici\u00f3n (ppm)\", \"Etapas iguales (1\u201310)\", \"Capacidad del cubo (US gal)\", \"Tiempo para llenar el cubo (s)\", \"CYA (ppm)\", \"Cloro libre actual (ppm)\", \"Concentraci\u00f3n de cloro l\u00edquido (%)\", \"Alcalinidad total (ppm)\", \"pH\", \"Dureza c\u00e1lcica (ppm)\", \"Construcci\u00f3n y equipos est\u00e1ndar ($)\", \"Excavaci\u00f3n ($)\", \"Terraza de piscina ($)\", \"Permisos y proyecto ($)\", \"Equipos opcionales ($)\", \"Reserva (%)\", \"Caudal a velocidad baja (GPM)\", \"Potencia a velocidad baja (W)\", \"Caudal a velocidad media (GPM)\", \"Potencia a velocidad media (W)\", \"Tiempo a velocidad media (h)\", \"Caudal a velocidad alta (GPM)\", \"Potencia a velocidad alta (W)\", \"Tiempo a velocidad alta (h)\"], \"help\": [\"Utilice mediciones reales. El tiempo de recirculaci\u00f3n no garantiza la calidad del agua; respete el caudal y tiempo m\u00ednimos de los equipos.\", \"El rect\u00e1ngulo incluye el fondo inclinado. Otras formas son aproximaciones sin escalones, bancos ni curvas de encuentro. Confirme medidas antes de comprar materiales.\", \"Calcule una sustancia cada vez. Antes de vaciar cantidades importantes, revise nivel fre\u00e1tico, estructura y normas de vertido; mezcle y vuelva a medir entre etapas.\", \"Mide la manguera de llenado, no el caudal de recirculaci\u00f3n requerido. Repita la medici\u00f3n con la instalaci\u00f3n real.\", \"Solo para CYA medido entre 20 y 90 ppm. El objetivo y la dosis no sustituyen el procedimiento SLAM completo. Mida el cloro libre antes de cada reposici\u00f3n, siga la etiqueta y no se ba\u00f1e durante el tratamiento.\", \"Esta lista no sustituye un an\u00e1lisis completo ni genera una mezcla autom\u00e1tica de productos.\", \"Introduzca presupuestos locales. El coste de construcci\u00f3n es distinto del pr\u00e9stamo y del mantenimiento.\"], \"pure\": \"Cantidades te\u00f3ricas para CaCl\u2082 anhidro puro al 100 % o cloruro c\u00e1lcico dihidratado puro; dureza expresada como ppm CaCO\u2083. Si el producto declara una fracci\u00f3n de CaCl\u2082 anhidro, divida la cantidad anhidra por esa fracci\u00f3n (77 % = 0.77). No aplique otra vez ese factor a la cantidad dihidratada. El hipoclorito c\u00e1lcico de choque es otro producto.\"},type=\"runtime\";form.addEventListener('submit',e=>{e.preventDefault();const inputs=[...form.querySelectorAll('input')];if(inputs.some(x=>x.value.trim()===''||!Number.isFinite(Number(x.value))||Number(x.value)<0)){out.textContent=D.error;return;}const x=Object.fromEntries(inputs.map(x=>[x.name,Number(x.value)])),fmt=n=>new Intl.NumberFormat(\"es-ES\",{maximumFractionDigits:2}).format(n),line=(k,v,u='')=>D[k]+': '+fmt(v)+' '+u;let result='';if(type==='dilution'){if(x.t>=x.c){result=line('replace',0,'US gal');}else if(x.f>=x.t){result=D.unreachable;}else if(x.v<=0||x.n<1||x.n>10||!Number.isInteger(x.n)){result=D.error;}else{let f=(x.c-x.t)\/(x.c-x.f),st=1-Math.pow((x.t-x.f)\/(x.c-x.f),1\/x.n);result=line('replace',x.v*f,'US gal')+' ('+fmt(f*100)+'%); '+line('stages',x.n)+': '+fmt(st*100)+'%; '+line('total',st*x.v*x.n,'US gal');}}else if(type==='runtime'){if(x.v<=0||x.q<=0||x.n<=0){result=D.error;}else{let h=Math.max(x.v*x.n\/x.q\/60,x.min);result=h>24?D.invalid:\"Tiempo de funcionamiento diario\"+': '+fmt(h)+' '+D.hours+'; '+line('day',h*x.w\/1000,'kWh')+'; '+line('month',h*x.w\/1000*x.r*30,'$');}}else if(type==='surface'){if(Math.min(x.l,x.b,x.s,x.d)<=0||x.d<x.s){result=D.error;}else{let a=x.b*Math.hypot(x.l,x.d-x.s)+x.l*(x.s+x.d)+x.b*(x.s+x.d);result=line('water',x.l*x.b,'ft\u00b2')+'; '+line('interior',a,'ft\u00b2');}}else if(type==='fill'){if(Math.min(x.v,x.b,x.s)<=0){result=D.error;}else{let q=x.b*60\/x.s;result=line('flow',q,'GPM')+'; '+line('time',x.v\/q\/60,D.hours);const f=document.getElementById('flowRate');if(f){f.value=q.toFixed(3);f.dispatchEvent(new Event('input',{bubbles:true}));}}}else if(type==='slam'){if(x.v<=0||x.s<=0||x.s>15||x.c<20||x.c>90){result=D.error;}else{let target=.4*x.c,litres=Math.max(0,target-x.f)*x.v*3.785411784\/(x.s*10000);result=line('target',target,'ppm')+'; '+line('dose',litres,'L');}}else if(type==='chemical'){result=D.review;}else if(type==='budget'){result=line('budget',(x.shell+x.site+x.deck+x.permit+x.extras)*(1+x.reserve\/100),'$');}else if(type==='schedule'){if(Math.min(x.v,x.n,x.q1,x.q2,x.q3)<=0){result=D.error;}else{let target=x.v*x.n,h1=Math.max(0,(target-60*(x.q2*x.h2+x.q3*x.h3))\/(60*x.q1)),h=h1+x.h2+x.h3;let energy=(h1*x.w1+x.h2*x.w2+x.h3*x.w3)\/1000;result=h>24?D.invalid:D.schedule+': '+fmt(h1)+' \/ '+fmt(x.h2)+' \/ '+fmt(x.h3)+' '+D.hours+'; '+line('off',24-h,D.hours)+'; '+line('day',energy*x.r,'$')+'; '+D.equal+': '+[1,2,3].map(i=>fmt(target\/x['q'+i]\/60*x['w'+i]\/1000*x.r)+' $').join(' \/ ');}}out.textContent=result;});form.addEventListener('reset',()=>out.textContent='');})();<\/script><section class=\"aiper-i18n-upgrade\" id=\"aiper-upgrade-schedule\"><h2>Programa diario de varias velocidades<\/h2><p>Utilice mediciones reales. El tiempo de recirculaci\u00f3n no garantiza la calidad del agua; respete el caudal y tiempo m\u00ednimos de los equipos.<\/p><p>Introduzca decimales con punto (p. ej., 1.5). Galones estadounidenses salvo indicaci\u00f3n contraria. Importes en d\u00f3lares estadounidenses (USD).<\/p><form><label>Volumen de piscina (US gal)<input type=\"number\" name=\"v\" value=\"20000\" min=\"0\" step=\"any\" required><\/label><label>Equivalentes de volumen al d\u00eda<input type=\"number\" name=\"n\" value=\"1\" min=\"0\" step=\"any\" required><\/label><label>Tarifa el\u00e9ctrica ($\/kWh)<input type=\"number\" name=\"r\" value=\"0.2\" min=\"0\" step=\"any\" required><\/label><label>Caudal a velocidad baja (GPM)<input type=\"number\" name=\"q1\" value=\"25\" min=\"0\" step=\"any\" required><\/label><label>Potencia a velocidad baja (W)<input type=\"number\" name=\"w1\" value=\"180\" min=\"0\" step=\"any\" required><\/label><label>Caudal a velocidad media (GPM)<input type=\"number\" name=\"q2\" value=\"45\" min=\"0\" step=\"any\" required><\/label><label>Potencia a velocidad media (W)<input type=\"number\" name=\"w2\" value=\"600\" min=\"0\" step=\"any\" required><\/label><label>Tiempo a velocidad media (h)<input type=\"number\" name=\"h2\" value=\"1\" min=\"0\" step=\"any\" required><\/label><label>Caudal a velocidad alta (GPM)<input type=\"number\" name=\"q3\" value=\"65\" min=\"0\" step=\"any\" required><\/label><label>Potencia a velocidad alta (W)<input type=\"number\" name=\"w3\" value=\"1400\" min=\"0\" step=\"any\" required><\/label><label>Tiempo a velocidad alta (h)<input type=\"number\" name=\"h3\" value=\"1\" min=\"0\" step=\"any\" required><\/label><button type=\"submit\">Calcular<\/button><button type=\"reset\">Restablecer<\/button><\/form><p role=\"status\" aria-live=\"polite\"><\/p><\/section><script>(()=>{const root=document.currentScript.previousElementSibling,form=root.querySelector('form'),out=root.querySelector('[role=status]'),D={\"calc\": \"Calcular\", \"reset\": \"Restablecer\", \"format\": \"Introduzca decimales con punto (p. ej., 1.5). Galones estadounidenses salvo indicaci\u00f3n contraria.\", \"error\": \"Complete todos los campos con valores no negativos. El volumen, caudal y dimensiones deben ser positivos.\", \"unreachable\": \"No se puede alcanzar el objetivo con esta agua de reposici\u00f3n.\", \"day\": \"Por d\u00eda\", \"month\": \"Para 30 d\u00edas\", \"hours\": \"horas\", \"water\": \"Superficie del agua\", \"interior\": \"Superficie interior, fondo y paredes\", \"replace\": \"Reposici\u00f3n en una sola etapa\", \"stages\": \"Etapas iguales de reposici\u00f3n\", \"total\": \"Agua total utilizada\", \"flow\": \"Caudal medido de la manguera\", \"time\": \"Tiempo estimado de llenado\", \"target\": \"Objetivo temporal de cloro libre\", \"dose\": \"Cantidad de cloro l\u00edquido\", \"budget\": \"Presupuesto del proyecto con reserva\", \"invalid\": \"El objetivo no cabe en un d\u00eda de 24 horas.\", \"review\": \"Compruebe las mediciones, ajuste un par\u00e1metro cada vez, haga circular el agua y vuelva a medir. El revestimiento, el sistema desinfectante y la etiqueta determinan los objetivos.\", \"schedule\": \"Programa diario de varias velocidades\", \"off\": \"Apagado\", \"equal\": \"Comparaci\u00f3n con igual volumen de agua\", \"units\": \"US gal; ft; GPM; W; $\/kWh\", \"title\": [\"Tiempo diario y coste el\u00e9ctrico\", \"Comprobar superficie interior y del agua\", \"Reposici\u00f3n de agua para reducir concentraciones\", \"Medir el caudal de la manguera\", \"Reposici\u00f3n SLAM seg\u00fan el CYA\", \"Orden de ajuste del agua\", \"Presupuesto desglosado del proyecto\"], \"labels\": [\"Volumen de piscina (US gal)\", \"Caudal medido (GPM)\", \"Equivalentes de volumen al d\u00eda\", \"Tiempo m\u00ednimo de equipos (h)\", \"Potencia medida (W)\", \"Tarifa el\u00e9ctrica ($\/kWh)\", \"Longitud (ft)\", \"Anchura (ft)\", \"Profundidad m\u00ednima (ft)\", \"Profundidad m\u00e1xima (ft)\", \"Lectura actual (ppm)\", \"Lectura objetivo (ppm)\", \"Lectura del agua de reposici\u00f3n (ppm)\", \"Etapas iguales (1\u201310)\", \"Capacidad del cubo (US gal)\", \"Tiempo para llenar el cubo (s)\", \"CYA (ppm)\", \"Cloro libre actual (ppm)\", \"Concentraci\u00f3n de cloro l\u00edquido (%)\", \"Alcalinidad total (ppm)\", \"pH\", \"Dureza c\u00e1lcica (ppm)\", \"Construcci\u00f3n y equipos est\u00e1ndar ($)\", \"Excavaci\u00f3n ($)\", \"Terraza de piscina ($)\", \"Permisos y proyecto ($)\", \"Equipos opcionales ($)\", \"Reserva (%)\", \"Caudal a velocidad baja (GPM)\", \"Potencia a velocidad baja (W)\", \"Caudal a velocidad media (GPM)\", \"Potencia a velocidad media (W)\", \"Tiempo a velocidad media (h)\", \"Caudal a velocidad alta (GPM)\", \"Potencia a velocidad alta (W)\", \"Tiempo a velocidad alta (h)\"], \"help\": [\"Utilice mediciones reales. El tiempo de recirculaci\u00f3n no garantiza la calidad del agua; respete el caudal y tiempo m\u00ednimos de los equipos.\", \"El rect\u00e1ngulo incluye el fondo inclinado. Otras formas son aproximaciones sin escalones, bancos ni curvas de encuentro. Confirme medidas antes de comprar materiales.\", \"Calcule una sustancia cada vez. Antes de vaciar cantidades importantes, revise nivel fre\u00e1tico, estructura y normas de vertido; mezcle y vuelva a medir entre etapas.\", \"Mide la manguera de llenado, no el caudal de recirculaci\u00f3n requerido. Repita la medici\u00f3n con la instalaci\u00f3n real.\", \"Solo para CYA medido entre 20 y 90 ppm. El objetivo y la dosis no sustituyen el procedimiento SLAM completo. Mida el cloro libre antes de cada reposici\u00f3n, siga la etiqueta y no se ba\u00f1e durante el tratamiento.\", \"Esta lista no sustituye un an\u00e1lisis completo ni genera una mezcla autom\u00e1tica de productos.\", \"Introduzca presupuestos locales. El coste de construcci\u00f3n es distinto del pr\u00e9stamo y del mantenimiento.\"], \"pure\": \"Cantidades te\u00f3ricas para CaCl\u2082 anhidro puro al 100 % o cloruro c\u00e1lcico dihidratado puro; dureza expresada como ppm CaCO\u2083. Si el producto declara una fracci\u00f3n de CaCl\u2082 anhidro, divida la cantidad anhidra por esa fracci\u00f3n (77 % = 0.77). No aplique otra vez ese factor a la cantidad dihidratada. El hipoclorito c\u00e1lcico de choque es otro producto.\"},type=\"schedule\";form.addEventListener('submit',e=>{e.preventDefault();const inputs=[...form.querySelectorAll('input')];if(inputs.some(x=>x.value.trim()===''||!Number.isFinite(Number(x.value))||Number(x.value)<0)){out.textContent=D.error;return;}const x=Object.fromEntries(inputs.map(x=>[x.name,Number(x.value)])),fmt=n=>new Intl.NumberFormat(\"es-ES\",{maximumFractionDigits:2}).format(n),line=(k,v,u='')=>D[k]+': '+fmt(v)+' '+u;let result='';if(type==='dilution'){if(x.t>=x.c){result=line('replace',0,'US gal');}else if(x.f>=x.t){result=D.unreachable;}else if(x.v<=0||x.n<1||x.n>10||!Number.isInteger(x.n)){result=D.error;}else{let f=(x.c-x.t)\/(x.c-x.f),st=1-Math.pow((x.t-x.f)\/(x.c-x.f),1\/x.n);result=line('replace',x.v*f,'US gal')+' ('+fmt(f*100)+'%); '+line('stages',x.n)+': '+fmt(st*100)+'%; '+line('total',st*x.v*x.n,'US gal');}}else if(type==='runtime'){if(x.v<=0||x.q<=0||x.n<=0){result=D.error;}else{let h=Math.max(x.v*x.n\/x.q\/60,x.min);result=h>24?D.invalid:\"Tiempo de funcionamiento diario\"+': '+fmt(h)+' '+D.hours+'; '+line('day',h*x.w\/1000,'kWh')+'; '+line('month',h*x.w\/1000*x.r*30,'$');}}else if(type==='surface'){if(Math.min(x.l,x.b,x.s,x.d)<=0||x.d<x.s){result=D.error;}else{let a=x.b*Math.hypot(x.l,x.d-x.s)+x.l*(x.s+x.d)+x.b*(x.s+x.d);result=line('water',x.l*x.b,'ft\u00b2')+'; '+line('interior',a,'ft\u00b2');}}else if(type==='fill'){if(Math.min(x.v,x.b,x.s)<=0){result=D.error;}else{let q=x.b*60\/x.s;result=line('flow',q,'GPM')+'; '+line('time',x.v\/q\/60,D.hours);const f=document.getElementById('flowRate');if(f){f.value=q.toFixed(3);f.dispatchEvent(new Event('input',{bubbles:true}));}}}else if(type==='slam'){if(x.v<=0||x.s<=0||x.s>15||x.c<20||x.c>90){result=D.error;}else{let target=.4*x.c,litres=Math.max(0,target-x.f)*x.v*3.785411784\/(x.s*10000);result=line('target',target,'ppm')+'; '+line('dose',litres,'L');}}else if(type==='chemical'){result=D.review;}else if(type==='budget'){result=line('budget',(x.shell+x.site+x.deck+x.permit+x.extras)*(1+x.reserve\/100),'$');}else if(type==='schedule'){if(Math.min(x.v,x.n,x.q1,x.q2,x.q3)<=0){result=D.error;}else{let target=x.v*x.n,h1=Math.max(0,(target-60*(x.q2*x.h2+x.q3*x.h3))\/(60*x.q1)),h=h1+x.h2+x.h3;let energy=(h1*x.w1+x.h2*x.w2+x.h3*x.w3)\/1000;result=h>24?D.invalid:D.schedule+': '+fmt(h1)+' \/ '+fmt(x.h2)+' \/ '+fmt(x.h3)+' '+D.hours+'; '+line('off',24-h,D.hours)+'; '+line('day',energy*x.r,'$')+'; '+D.equal+': '+[1,2,3].map(i=>fmt(target\/x['q'+i]\/60*x['w'+i]\/1000*x.r)+' $').join(' \/ ');}}out.textContent=result;});form.addEventListener('reset',()=>out.textContent='');})();<\/script><div class=\"aiper-tool-links\">\n  <div class=\"aiper-tl-section\">\n    <div class=\"aiper-tl-heading\">M\u00e1s herramientas<\/div>\n    <div class=\"aiper-tl-tags\">\n<a href=\"https:\/\/aiper.com\/blogs\/es\/calculadora-de-costes-de-mantenimiento-de-piscina\/\" class=\"aiper-tl-tag\">Calculadora de costes de mantenimiento de piscina<\/a>\n      <a href=\"https:\/\/aiper.com\/blogs\/es\/calculadora-caudal-piscina\/\" class=\"aiper-tl-tag\">Calculadora de caudal de piscina<\/a>\n<a href=\"https:\/\/aiper.com\/blogs\/es\/calculadora-tiempo-llenado-piscina\/\" class=\"aiper-tl-tag\">Calculadora de tiempo de llenado de piscina<\/a>\n<a href=\"https:\/\/aiper.com\/blogs\/es\/calculadora-indice-saturacion-piscina\/\" class=\"aiper-tl-tag\">Calculadora del \u00edndice de saturaci\u00f3n de piscina (LSI)<\/a>\n    <\/div>\n  <\/div>\n  <div class=\"aiper-tl-section\">\n    <div class=\"aiper-tl-heading\">Art\u00edculos relacionados<\/div>\n    <div class=\"aiper-tl-tags\">\n      <a href=\"https:\/\/aiper.com\/blogs\/es\/bajar-alcalinidad-piscina\/\" class=\"aiper-tl-tag\">C\u00f3mo bajar la alcalinidad de la piscina<\/a>\n<a href=\"https:\/\/aiper.com\/blogs\/es\/robot-piscina-atascado-desague-principal\/\" class=\"aiper-tl-tag\">\u00bfPor qu\u00e9 el robot de piscina se queda atascado en el desag\u00fce principal?<\/a>\n<a href=\"https:\/\/aiper.com\/blogs\/es\/preparar-piscina-para-invierno\/\" class=\"aiper-tl-tag\">C\u00f3mo preparar una piscina enterrada para el invierno: gu\u00eda paso a paso<\/a>\n<a href=\"https:\/\/aiper.com\/blogs\/es\/dejar-robot-limpiapiscinas-en-el-agua\/\" class=\"aiper-tl-tag\">\u00bfSe puede dejar el robot limpiapiscinas en el agua?<\/a>\n    <\/div>\n  <\/div>\n<\/div>\n\n<style>\n.aiper-tool-links{margin:2.5rem 0 1.5rem;padding:1.5rem 1.75rem;background:linear-gradient(135deg,rgba(148,134,247,.04),rgba(30,202,211,.04));border-radius:12px;border:1px solid rgba(148,134,247,.10)}\n.aiper-tl-section{margin-bottom:1.25rem}\n.aiper-tl-section:last-child{margin-bottom:0}\n.aiper-tl-heading{font-size:.75rem;font-weight:600;letter-spacing:.09em;text-transform:uppercase;color:#8899aa;margin:0 0 .65rem}\n.aiper-tl-tags{display:flex;flex-wrap:wrap;gap:.5rem}\n.aiper-tl-tag{display:inline-block;padding:.4rem .95rem;font-size:.82rem;font-weight:500;line-height:1.35;color:#9486f7;background:rgba(148,134,247,.055);border:1px solid rgba(30,202,211,.25);border-radius:22px;text-decoration:none;transition:all .18s}\n.aiper-tl-tag:hover{background:#1ecad3;color:#fff;border-color:#1ecad3;box-shadow:0 2px 10px rgba(30,202,211,.22)}\n<\/style>","protected":false},"excerpt":{"rendered":"<p>Tiempo diario y coste el\u00e9ctrico Descubre cu\u00e1nto tarda en circular todo el volumen de tu piscina. 1 2 3 1 Volumen de la piscina Galones Litros m\u00b3 \ud83d\udca1 \u00bfNo lo sabes? Usa nuestra calculadora de volumen de piscina Introduce un volumen de piscina v\u00e1lido. 2 Caudal de la bomba GPM \ud83d\udd27 \u00bfNecesitas ayuda para hallar [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"aiper_reading_time":3,"aiper_last_reviewed":"","aiper_reviewer":0,"aiper_related_ids":[],"aiper_layout":"","footnotes":""},"class_list":["post-2163","page","type-page","status-publish","hentry"],"lang":"es","translations":{"es":2163,"de":2161,"en":1844,"fr":2162},"_links":{"self":[{"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/pages\/2163","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/comments?post=2163"}],"version-history":[{"count":6,"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/pages\/2163\/revisions"}],"predecessor-version":[{"id":13298,"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/pages\/2163\/revisions\/13298"}],"wp:attachment":[{"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/media?parent=2163"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}