{"id":2552,"date":"2026-06-15T02:55:59","date_gmt":"2026-06-15T02:55:59","guid":{"rendered":"https:\/\/aiper.com\/blogs\/?page_id=2552"},"modified":"2026-06-24T04:25:39","modified_gmt":"2026-06-24T04:25:39","slug":"calculadora-grava","status":"publish","type":"page","link":"https:\/\/aiper.com\/blogs\/es\/calculadora-grava\/","title":{"rendered":"Calculadora de Grava Gratis"},"content":{"rendered":"\n<script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\n<script>\n    tailwind.config = {\n        corePlugins: { preflight: false },\n        theme: {\n            extend: {\n                colors: {\n                    primary: '#1ecad3',\n                    'primary-light': '#5cdce4',\n                    'primary-dark': '#139ea8',\n                    accent: '#9486f7',\n                    'accent-light': '#b5abfa',\n                    'accent-dark': '#7a6fe0',\n                    surface: '#f8faf9',\n                    'surface-card': '#ffffff',\n                    'text-main': '#1a1f1d',\n                    'text-subtle': '#5f6b65',\n                    'border-soft': '#dde5e0',\n                },\n                fontFamily: {\n                    sans: ['\"Inter\"', 'system-ui', 'sans-serif'],\n                },\n                borderRadius: {\n                    'xl': '0.875rem',\n                    '2xl': '1.125rem',\n                },\n                boxShadow: {\n                    'card': '0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04)',\n                    'card-hover': '0 4px 12px rgba(0,0,0,0.08), 0 2px 4px rgba(0,0,0,0.04)',\n                    'result': '0 0 0 1px rgba(30,202,211,0.12), 0 2px 8px rgba(30,202,211,0.08)',\n                },\n            }\n        }\n    }\n<\/script>\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;500;600;700&#038;display=swap\" rel=\"stylesheet\">\n<style>\n    :root {\n        --transition-fast: 180ms cubic-bezier(0.4, 0, 0.2, 1);\n        --transition-smooth: 280ms cubic-bezier(0.4, 0, 0.2, 1);\n    }\n    * { box-sizing: border-box; }\n    html { scroll-behavior: smooth; -webkit-tap-highlight-color: transparent; }\n    body { font-family: 'Inter', system-ui, sans-serif; background: #f3f6f4; color: #1a1f1d; min-height: 100vh; }\n    input[type=\"range\"] { -webkit-appearance: none; appearance: none; width: 100%; height: 8px; border-radius: 999px; background: #dde5e0; outline: none; cursor: pointer; transition: background var(--transition-fast); }\n    input[type=\"range\"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 28px; height: 28px; border-radius: 50%; background: #1ecad3; border: 3px solid #fff; box-shadow: 0 1px 4px rgba(0,0,0,0.18); cursor: pointer; transition: transform var(--transition-fast), box-shadow var(--transition-fast); }\n    input[type=\"range\"]::-webkit-slider-thumb:hover { transform: scale(1.12); box-shadow: 0 2px 8px rgba(0,0,0,0.22); }\n    input[type=\"range\"]::-moz-range-thumb { width: 28px; height: 28px; border-radius: 50%; background: #1ecad3; border: 3px solid #fff; box-shadow: 0 1px 4px rgba(0,0,0,0.18); cursor: pointer; }\n    input[type=\"number\"]::-webkit-inner-spin-button, input[type=\"number\"]::-webkit-outer-spin-button { opacity: 0.4; }\n    .depth-focus-indicator { opacity: 0; transform: translateY(-4px); transition: opacity var(--transition-smooth), transform var(--transition-smooth); pointer-events: none; }\n    .depth-wrapper:focus-within .depth-focus-indicator { opacity: 1; transform: translateY(0); }\n    .card-transition { transition: box-shadow var(--transition-smooth), border-color var(--transition-smooth); }\n    .card-transition:hover { box-shadow: 0 4px 12px rgba(0,0,0,0.08), 0 2px 4px rgba(0,0,0,0.04); }\n    .mode-tab { transition: all var(--transition-fast); position: relative; }\n    .mode-tab.active { background: #1ecad3; color: #fff; box-shadow: 0 2px 8px rgba(30,202,211,0.3); }\n    .mode-tab:not(.active):hover { background: #e0f7fa; }\n    @keyframes subtlePulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.015); } }\n    .result-pulse { animation: subtlePulse 350ms ease-out; }\n    .area-card { transition: all var(--transition-smooth); border-left: 3px solid #1ecad3; }\n    .area-card:hover { border-left-color: #5cdce4; background: #fafcfb; }\n    .toast { position: fixed; bottom: 2rem; left: 50%; transform: translateX(-50%) translateY(120px); background: #1a1f1d; color: #fff; padding: 0.75rem 1.5rem; border-radius: 999px; font-weight: 500; font-size: 0.9rem; z-index: 100; transition: transform var(--transition-smooth); box-shadow: 0 8px 24px rgba(0,0,0,0.25); }\n    .toast.show { transform: translateX(-50%) translateY(0); }\n    select { appearance: none; -webkit-appearance: none; background-image: url(\"data:image\/svg+xml,%3Csvg xmlns='http:\/\/www.w3.org\/2000\/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%235f6b65' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C\/polyline%3E%3C\/svg%3E\"); background-repeat: no-repeat; background-position: right 0.7rem center; padding-right: 2.2rem; }\n    @media (max-width: 480px) { .mode-tab { font-size: 0.8rem; padding: 0.5rem 0.6rem; } .result-value { font-size: 1.5rem; } }\n<\/style>\n\n<div id=\"toast\" class=\"toast\" role=\"status\" aria-live=\"polite\"><\/div>\n\n<div class=\"max-w-3xl mx-auto px-3 sm:px-4 md:px-6 pt-4 sm:pt-6 md:pt-8\">\n\n    <header class=\"text-center mb-5 sm:mb-7\">\n        \n        <p class=\"text-text-subtle text-sm sm:text-base mt-1.5\">\n            Calcula con precisi\u00f3n volumen, peso y coste \u2013 con soporte multi-\u00e1rea y c\u00e1lculo inverso\n        <\/p>\n    <\/header>\n\n    <!-- Barra de configuraci\u00f3n superior -->\n    <div class=\"bg-surface-card rounded-2xl shadow-card p-4 sm:p-5 mb-4 card-transition\">\n        <div class=\"flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4\">\n            <div class=\"flex-1 min-w-0\">\n                <label for=\"materialSelect\" class=\"block text-xs font-semibold text-text-subtle uppercase tracking-wide mb-1.5\">\n                    Material\n                <\/label>\n                <select id=\"materialSelect\"\n                class=\"w-full bg-surface border border-border-soft rounded-lg px-3 py-2.5 text-sm font-medium text-text-main focus:outline-none focus:ring-2 focus:ring-primary\/30 focus:border-primary transition-all\">\n                <option value=\"pea-gravel\">Grava fina (Pea Gravel)<\/option>\n                <option value=\"nominal-gravel\">Grava triturada (1\/4&#8243; &#8211; 2&#8243;)<\/option>\n                <option value=\"coarse-crushed\">Piedra triturada gruesa (2&#8243; &#8211; 6&#8243;)<\/option>\n                <option value=\"dry-sand\">Arena seca<\/option>\n                <option value=\"wet-sand\">Arena h\u00fameda<\/option>\n                <option value=\"custom\">Material personalizado<\/option>\n            <\/select>\n        <\/div>\n        <div class=\"flex-1 min-w-0\">\n            <label for=\"densityInput\" class=\"block text-xs font-semibold text-text-subtle uppercase tracking-wide mb-1.5\">\n                Densidad (<span id=\"densityUnitLabel\">kg\/m\u00b3<\/span>)\n            <\/label>\n            <input type=\"number\" id=\"densityInput\" value=\"1485\" step=\"0.1\" min=\"1\"\n            class=\"w-full bg-surface border border-border-soft rounded-lg px-3 py-2.5 text-sm font-medium text-text-main focus:outline-none focus:ring-2 focus:ring-primary\/30 focus:border-primary transition-all read-only:bg-gray-100 read-only:text-text-subtle read-only:cursor-default\"\n            readonly>\n        <\/div>\n        <div class=\"flex-shrink-0\">\n            <label class=\"block text-xs font-semibold text-text-subtle uppercase tracking-wide mb-1.5\">\n                Sistema de unidades\n            <\/label>\n            <button id=\"unitToggleBtn\"\n            class=\"w-full sm:w-auto inline-flex items-center justify-center gap-2 px-4 py-2.5 rounded-lg font-semibold text-sm transition-all duration-200 bg-primary text-white shadow-md hover:bg-primary-light active:scale-[0.97] focus:outline-none focus:ring-2 focus:ring-primary\/40\"\n            aria-label=\"Cambiar sistema de unidades\">\n            <span id=\"unitToggleIcon\">&#127760;<\/span>\n            <span id=\"unitToggleLabel\">M\u00e9trico<\/span>\n        <\/button>\n    <\/div>\n<\/div>\n<\/div>\n\n<!-- Pesta\u00f1as de modo -->\n<div class=\"flex flex-wrap gap-1.5 sm:gap-2 mb-4\" role=\"tablist\" aria-label=\"Modo de c\u00e1lculo\">\n    <button class=\"mode-tab active flex-1 min-w-[90px] py-2.5 px-3 rounded-lg font-medium text-sm text-center transition-all\"\n    data-mode=\"A\" role=\"tab\" aria-selected=\"true\" id=\"tabA\">\n    Por dimensiones\n<\/button>\n<button class=\"mode-tab flex-1 min-w-[90px] py-2.5 px-3 rounded-lg font-medium text-sm text-center transition-all\"\ndata-mode=\"B\" role=\"tab\" aria-selected=\"false\" id=\"tabB\">\n\u00c1rea directa\n<\/button>\n<button class=\"mode-tab flex-1 min-w-[90px] py-2.5 px-3 rounded-lg font-medium text-sm text-center transition-all\"\ndata-mode=\"C\" role=\"tab\" aria-selected=\"false\" id=\"tabC\">\nCombinaci\u00f3n de \u00e1reas\n<\/button>\n<\/div>\n\n<!-- Modo A: Largo x Ancho x Profundidad -->\n<div id=\"panelModeA\" class=\"bg-surface-card rounded-2xl shadow-card p-4 sm:p-5 mb-4 card-transition\">\n    <div class=\"flex items-center gap-2 mb-4\">\n        <span class=\"text-xs font-semibold text-text-subtle uppercase tracking-wide\">Forma:<\/span>\n        <button id=\"shapeRectBtn\"\n        class=\"px-3 py-1.5 rounded-full text-sm font-medium bg-primary text-white shadow-sm transition-all duration-200 focus:outline-none\"\n        data-shape=\"rectangle\">Rect\u00e1ngulo<\/button>\n        <button id=\"shapeCircleBtn\"\n        class=\"px-3 py-1.5 rounded-full text-sm font-medium bg-gray-200 text-text-subtle hover:bg-gray-300 transition-all duration-200 focus:outline-none\"\n        data-shape=\"circle\">C\u00edrculo<\/button>\n    <\/div>\n\n    <div id=\"rectInputs\" class=\"space-y-3\">\n        <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-3\">\n            <div>\n                <label for=\"lengthInput\" class=\"block text-xs font-semibold text-text-subtle uppercase tracking-wide mb-1\">Longitud<\/label>\n                <div class=\"flex gap-1.5\">\n                    <input type=\"number\" id=\"lengthInput\" value=\"5\" min=\"0\" step=\"any\"\n                    class=\"flex-1 min-w-0 bg-surface border border-border-soft rounded-lg px-3 py-2.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 focus:border-primary transition-all\">\n                    <select id=\"lengthUnit\"\n                    class=\"w-24 sm:w-28 bg-surface border border-border-soft rounded-lg px-2 py-2.5 text-xs font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 transition-all\">\n                    <option value=\"m\">m<\/option>\n                    <option value=\"cm\">cm<\/option>\n                    <option value=\"ft\">ft<\/option>\n                    <option value=\"in\">in<\/option>\n                    <option value=\"yd\">yd<\/option>\n                <\/select>\n            <\/div>\n        <\/div>\n        <div>\n            <label for=\"widthInput\" class=\"block text-xs font-semibold text-text-subtle uppercase tracking-wide mb-1\">Anchura<\/label>\n            <div class=\"flex gap-1.5\">\n                <input type=\"number\" id=\"widthInput\" value=\"3\" min=\"0\" step=\"any\"\n                class=\"flex-1 min-w-0 bg-surface border border-border-soft rounded-lg px-3 py-2.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 focus:border-primary transition-all\">\n                <select id=\"widthUnit\"\n                class=\"w-24 sm:w-28 bg-surface border border-border-soft rounded-lg px-2 py-2.5 text-xs font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 transition-all\">\n                <option value=\"m\">m<\/option>\n                <option value=\"cm\">cm<\/option>\n                <option value=\"ft\">ft<\/option>\n                <option value=\"in\">in<\/option>\n                <option value=\"yd\">yd<\/option>\n            <\/select>\n        <\/div>\n    <\/div>\n<\/div>\n<\/div>\n\n<div id=\"circleInputs\" class=\"space-y-3 hidden\">\n    <div>\n        <label for=\"diameterInput\" class=\"block text-xs font-semibold text-text-subtle uppercase tracking-wide mb-1\">Di\u00e1metro<\/label>\n        <div class=\"flex gap-1.5\">\n            <input type=\"number\" id=\"diameterInput\" value=\"4\" min=\"0\" step=\"any\"\n            class=\"flex-1 min-w-0 bg-surface border border-border-soft rounded-lg px-3 py-2.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 focus:border-primary transition-all\">\n            <select id=\"diameterUnit\"\n            class=\"w-24 sm:w-28 bg-surface border border-border-soft rounded-lg px-2 py-2.5 text-xs font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 transition-all\">\n            <option value=\"m\">m<\/option>\n            <option value=\"cm\">cm<\/option>\n            <option value=\"ft\">ft<\/option>\n            <option value=\"in\">in<\/option>\n            <option value=\"yd\">yd<\/option>\n        <\/select>\n    <\/div>\n<\/div>\n<\/div>\n\n<div class=\"depth-wrapper mt-3\">\n    <label for=\"depthInput\" class=\"block text-xs font-semibold text-text-subtle uppercase tracking-wide mb-1\">\n        Profundidad \/ Espesor\n    <\/label>\n    <div class=\"flex gap-1.5\">\n        <input type=\"number\" id=\"depthInput\" value=\"10\" min=\"0\" step=\"any\"\n        class=\"flex-1 min-w-0 bg-surface border border-border-soft rounded-lg px-3 py-2.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-accent\/50 focus:border-accent transition-all\"\n        aria-label=\"Espesor de la capa\">\n        <select id=\"depthUnit\"\n        class=\"w-24 sm:w-28 bg-surface border border-border-soft rounded-lg px-2 py-2.5 text-xs font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 transition-all\">\n        <option value=\"cm\">cm<\/option>\n        <option value=\"m\">m<\/option>\n        <option value=\"in\">in<\/option>\n        <option value=\"ft\">ft<\/option>\n    <\/select>\n<\/div>\n<p class=\"depth-focus-indicator text-xs text-accent mt-1 font-medium flex items-center gap-1\">\n    Consejo: <span>El espesor es la profundidad de la capa, p.ej. una entrada t\u00edpica tiene 10-15 cm<\/span>\n<\/p>\n<\/div>\n<\/div>\n\n<!-- Modo B: \u00c1rea directa -->\n<div id=\"panelModeB\" class=\"bg-surface-card rounded-2xl shadow-card p-4 sm:p-5 mb-4 card-transition hidden\">\n    <div class=\"space-y-3\">\n        <div>\n            <label for=\"areaInputB\" class=\"block text-xs font-semibold text-text-subtle uppercase tracking-wide mb-1\">\u00c1rea total<\/label>\n            <div class=\"flex gap-1.5\">\n                <input type=\"number\" id=\"areaInputB\" value=\"50\" min=\"0\" step=\"any\"\n                class=\"flex-1 min-w-0 bg-surface border border-border-soft rounded-lg px-3 py-2.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 focus:border-primary transition-all\">\n                <select id=\"areaUnitB\"\n                class=\"w-28 bg-surface border border-border-soft rounded-lg px-2 py-2.5 text-xs font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 transition-all\">\n                <option value=\"m2\">m\u00b2<\/option>\n                <option value=\"ft2\">ft\u00b2<\/option>\n                <option value=\"yd2\">yd\u00b2<\/option>\n            <\/select>\n        <\/div>\n    <\/div>\n    <div class=\"depth-wrapper mt-3\">\n        <label for=\"depthInputB\" class=\"block text-xs font-semibold text-text-subtle uppercase tracking-wide mb-1\">\n            Profundidad \/ Espesor\n        <\/label>\n        <div class=\"flex gap-1.5\">\n            <input type=\"number\" id=\"depthInputB\" value=\"10\" min=\"0\" step=\"any\"\n            class=\"flex-1 min-w-0 bg-surface border border-border-soft rounded-lg px-3 py-2.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-accent\/50 focus:border-accent transition-all\"\n            aria-label=\"Espesor de la capa\">\n            <select id=\"depthUnitB\"\n            class=\"w-24 sm:w-28 bg-surface border border-border-soft rounded-lg px-2 py-2.5 text-xs font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 transition-all\">\n            <option value=\"cm\">cm<\/option>\n            <option value=\"m\">m<\/option>\n            <option value=\"in\">in<\/option>\n            <option value=\"ft\">ft<\/option>\n        <\/select>\n    <\/div>\n    <p class=\"depth-focus-indicator text-xs text-accent mt-1 font-medium flex items-center gap-1\">\n        Consejo: <span>El espesor es la profundidad de la capa<\/span>\n    <\/p>\n<\/div>\n<\/div>\n<\/div>\n\n<!-- Modo C: Combinaci\u00f3n de \u00e1reas -->\n<div id=\"panelModeC\" class=\"bg-surface-card rounded-2xl shadow-card p-4 sm:p-5 mb-4 card-transition hidden\">\n    <div id=\"multiAreaList\" class=\"space-y-3 mb-3\">\n    <\/div>\n    <div id=\"multiAreaEmpty\" class=\"text-center py-6 text-text-subtle text-sm\">\n        <p class=\"text-3xl mb-2\">+<\/p>\n        <p>No se han a\u00f1adido \u00e1reas. Haga clic en el bot\u00f3n de abajo para comenzar.<\/p>\n    <\/div>\n    <button id=\"addAreaBtn\"\n    class=\"w-full py-2.5 rounded-lg font-medium text-sm border-2 border-dashed border-primary\/40 text-primary hover:bg-primary\/5 hover:border-primary transition-all duration-200 flex items-center justify-center gap-2\">\n    <span class=\"text-lg\">+<\/span> A\u00f1adir nueva \u00e1rea\n<\/button>\n<div class=\"mt-3 p-3 bg-primary\/5 rounded-lg text-center\">\n    <span class=\"text-xs text-text-subtle\">\u00c1rea total combinada: <\/span>\n    <span id=\"totalAreaDisplay\" class=\"text-lg font-bold text-primary\">0.00 m\u00b2<\/span>\n<\/div>\n<div class=\"depth-wrapper mt-3\">\n    <label for=\"depthInputC\" class=\"block text-xs font-semibold text-text-subtle uppercase tracking-wide mb-1\">\n        Profundidad \/ Espesor uniforme\n    <\/label>\n    <div class=\"flex gap-1.5\">\n        <input type=\"number\" id=\"depthInputC\" value=\"10\" min=\"0\" step=\"any\"\n        class=\"flex-1 min-w-0 bg-surface border border-border-soft rounded-lg px-3 py-2.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-accent\/50 focus:border-accent transition-all\"\n        aria-label=\"Espesor uniforme\">\n        <select id=\"depthUnitC\"\n        class=\"w-24 sm:w-28 bg-surface border border-border-soft rounded-lg px-2 py-2.5 text-xs font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 transition-all\">\n        <option value=\"cm\">cm<\/option>\n        <option value=\"m\">m<\/option>\n        <option value=\"in\">in<\/option>\n        <option value=\"ft\">ft<\/option>\n    <\/select>\n<\/div>\n<p class=\"depth-focus-indicator text-xs text-accent mt-1 font-medium flex items-center gap-1\">\n    Consejo: <span>Todas las \u00e1reas usan la misma profundidad<\/span>\n<\/p>\n<\/div>\n<\/div>\n\n<!-- Ajustes avanzados -->\n<div class=\"bg-surface-card rounded-2xl shadow-card p-4 sm:p-5 mb-4 card-transition\">\n    <h2 class=\"text-base font-semibold text-text-main mb-4 flex items-center gap-2\">\n        Ajustes avanzados de obra\n    <\/h2>\n    <div class=\"mb-4\">\n        <div class=\"flex items-center justify-between mb-2\">\n            <label for=\"wasteRateSlider\" class=\"text-sm font-medium text-text-main\">\n                Margen de p\u00e9rdida \/ excedente: <span id=\"wasteRateValue\" class=\"font-bold text-primary\">10%<\/span>\n            <\/label>\n        <\/div>\n        <input type=\"range\" id=\"wasteRateSlider\" min=\"0\" max=\"20\" value=\"10\" step=\"0.5\"\n        class=\"w-full\">\n        <p class=\"text-xs text-text-subtle mt-1\">Para compensar derrames durante el transporte y recortes<\/p>\n    <\/div>\n    <div>\n        <div class=\"flex items-center justify-between mb-2\">\n            <label for=\"compactionRateSlider\" class=\"text-sm font-medium text-text-main\">\n                Tasa de compactaci\u00f3n: <span id=\"compactionRateValue\" class=\"font-bold text-accent\">5%<\/span>\n            <\/label>\n        <\/div>\n        <div class=\"flex flex-wrap gap-2 mb-2\">\n            <button class=\"compaction-preset px-3 py-1.5 rounded-full text-xs font-medium transition-all duration-200 bg-gray-200 text-text-subtle hover:bg-gray-300\"\n            data-rate=\"0\">Acera \/ Decoraci\u00f3n: 0%<\/button>\n            <button class=\"compaction-preset px-3 py-1.5 rounded-full text-xs font-medium transition-all duration-200 bg-accent\/15 text-accent font-semibold border border-accent\/30\"\n            data-rate=\"5\">Compactaci\u00f3n ligera: 5%<\/button>\n            <button class=\"compaction-preset px-3 py-1.5 rounded-full text-xs font-medium transition-all duration-200 bg-gray-200 text-text-subtle hover:bg-gray-300\"\n            data-rate=\"20\">Base de carretera (compactaci\u00f3n fuerte): 20%<\/button>\n        <\/div>\n        <input type=\"range\" id=\"compactionRateSlider\" min=\"0\" max=\"30\" value=\"5\" step=\"0.5\"\n        class=\"w-full\">\n        <p class=\"text-xs text-text-subtle mt-1\">El volumen de grava se reduce tras la compactaci\u00f3n; la calculadora ya ha a\u00f1adido la cantidad necesaria por usted.<\/p>\n    <\/div>\n<\/div>\n\n<!-- Panel de resultados -->\n<div class=\"bg-surface-card rounded-2xl shadow-result p-4 sm:p-5 mb-4 card-transition\" id=\"resultsPanel\">\n    <h2 class=\"text-base font-semibold text-text-main mb-4 flex items-center gap-2\">\n        Resultados en tiempo real\n    <\/h2>\n    <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n        <div class=\"bg-primary\/5 rounded-xl p-4 text-center\">\n            <label for=\"resultVolume\" class=\"block text-xs font-semibold text-text-subtle uppercase tracking-wide mb-1\">\n                Volumen (<span id=\"resultVolumeUnit\">m\u00b3<\/span>)\n            <\/label>\n            <input type=\"number\" id=\"resultVolume\" value=\"1.73\" step=\"0.001\" min=\"0\"\n            class=\"result-value w-full text-center text-2xl sm:text-3xl font-bold text-primary bg-transparent border-none outline-none focus:ring-2 focus:ring-primary\/20 rounded-lg transition-all py-1\"\n            aria-label=\"Volumen final (editable para c\u00e1lculo inverso)\">\n            <p class=\"text-xs text-text-subtle mt-1\" id=\"resultVolumeSub\">Incluye p\u00e9rdida y compactaci\u00f3n<\/p>\n        <\/div>\n        <div class=\"bg-accent\/8 rounded-xl p-4 text-center\">\n            <label for=\"resultWeight\" class=\"block text-xs font-semibold text-text-subtle uppercase tracking-wide mb-1\">\n                Peso (<span id=\"resultWeightUnit\">toneladas<\/span>)\n            <\/label>\n            <input type=\"number\" id=\"resultWeight\" value=\"2.57\" step=\"0.001\" min=\"0\"\n            class=\"result-value w-full text-center text-2xl sm:text-3xl font-bold text-accent bg-transparent border-none outline-none focus:ring-2 focus:ring-accent\/30 rounded-lg transition-all py-1\"\n            aria-label=\"Peso final (editable para c\u00e1lculo inverso)\">\n            <p class=\"text-xs text-text-subtle mt-1\" id=\"resultWeightSub\">Basado en la densidad<\/p>\n        <\/div>\n    <\/div>\n    <p class=\"text-xs text-text-subtle text-center mt-3\" id=\"reverseHint\" style=\"display:none;\">\n        Modo de c\u00e1lculo inverso: Profundidad actualizada seg\u00fan su entrada.\n    <\/p>\n<\/div>\n\n<!-- Presupuesto y venta al por menor -->\n<div class=\"bg-surface-card rounded-2xl shadow-card p-4 sm:p-5 mb-4 card-transition\">\n    <h2 class=\"text-base font-semibold text-text-main mb-4 flex items-center gap-2\">\n        Presupuesto y conversi\u00f3n minorista\n    <\/h2>\n    <div class=\"flex flex-col sm:flex-row gap-3 mb-4\">\n        <div class=\"flex-1\">\n            <label for=\"unitPriceInput\" class=\"block text-xs font-semibold text-text-subtle uppercase tracking-wide mb-1\">Precio unitario<\/label>\n            <input type=\"number\" id=\"unitPriceInput\" value=\"120\" min=\"0\" step=\"any\"\n            class=\"w-full bg-surface border border-border-soft rounded-lg px-3 py-2.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 focus:border-primary transition-all\">\n        <\/div>\n        <div class=\"flex-shrink-0\">\n            <label for=\"priceUnitSelect\" class=\"block text-xs font-semibold text-text-subtle uppercase tracking-wide mb-1\">Por<\/label>\n            <select id=\"priceUnitSelect\"\n            class=\"w-full bg-surface border border-border-soft rounded-lg px-3 py-2.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 transition-all\">\n            <option value=\"per-tonne\">tonelada<\/option>\n            <option value=\"per-m3\">m\u00b3<\/option>\n            <option value=\"per-yd3\">yd\u00b3<\/option>\n            <option value=\"per-kg\">kg<\/option>\n            <option value=\"per-lb\">lb<\/option>\n        <\/select>\n    <\/div>\n<\/div>\n<div class=\"bg-accent\/10 rounded-xl p-4 text-center mb-4\">\n    <span class=\"text-sm text-text-subtle\">Coste total estimado: <\/span>\n    <span id=\"totalCostDisplay\" class=\"text-3xl font-bold text-accent\">\u20ac308,70<\/span>\n<\/div>\n<div class=\"flex items-center gap-3 mb-3\">\n    <span class=\"text-sm font-medium text-text-main\">Soy un aficionado al bricolaje y necesito sacos de grava<\/span>\n    <button id=\"baggedToggle\"\n    class=\"relative inline-flex h-6 w-11 items-center rounded-full transition-colors duration-200 bg-gray-300 focus:outline-none focus:ring-2 focus:ring-primary\/40\"\n    role=\"switch\" aria-checked=\"false\">\n    <span class=\"inline-block h-5 w-5 transform rounded-full bg-white shadow transition-transform duration-200 translate-x-0.5\"\n    id=\"baggedToggleDot\"><\/span>\n<\/button>\n<\/div>\n<div id=\"baggedDetails\" class=\"hidden space-y-3 pl-2 border-l-2 border-primary\/20\">\n    <div class=\"flex gap-2 items-end\">\n        <div class=\"flex-1\">\n            <label for=\"bagWeightInput\" class=\"block text-xs font-semibold text-text-subtle uppercase tracking-wide mb-1\">Peso por saco<\/label>\n            <input type=\"number\" id=\"bagWeightInput\" value=\"20\" min=\"0.1\" step=\"any\"\n            class=\"w-full bg-surface border border-border-soft rounded-lg px-3 py-2.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 focus:border-primary transition-all\">\n        <\/div>\n        <div class=\"flex-shrink-0\">\n            <select id=\"bagWeightUnit\"\n            class=\"bg-surface border border-border-soft rounded-lg px-3 py-2.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 transition-all\">\n            <option value=\"kg\">kg<\/option>\n            <option value=\"lb\">lb<\/option>\n        <\/select>\n    <\/div>\n<\/div>\n<div class=\"bg-primary\/5 rounded-lg p-3 text-center\">\n    <span class=\"text-sm text-text-subtle\">Necesita comprar aproximadamente: <\/span>\n    <span id=\"bagCountDisplay\" class=\"text-2xl font-bold text-primary\">&#8212; sacos<\/span>\n<\/div>\n<\/div>\n<div class=\"mt-3 p-3 bg-surface rounded-lg text-xs text-text-subtle leading-relaxed\" id=\"transportInfo\">\n    Referencia de transporte: <span id=\"transportText\">aprox. 3 camionetas est\u00e1ndar (1 t cada una) o 1 cami\u00f3n volquete grande<\/span>\n<\/div>\n<\/div>\n\n<!-- Botones Exportar y Restablecer -->\n<div class=\"text-center mb-6\">\n    <div class=\"flex justify-center gap-3 flex-wrap\">\n        <button id=\"copyReportBtn\"\n        class=\"inline-flex items-center gap-2 px-6 py-3 rounded-xl font-semibold text-sm bg-primary text-white shadow-lg hover:bg-primary-light active:scale-[0.97] transition-all duration-200 focus:outline-none focus:ring-4 focus:ring-primary\/25\">\n        Copiar informe de resultados\n    <\/button>\n    <button id=\"resetBtn\"\n    class=\"inline-flex items-center gap-2 px-6 py-3 rounded-xl font-semibold text-sm bg-gray-200 text-text-subtle hover:bg-gray-300 active:scale-[0.97] transition-all duration-200 focus:outline-none focus:ring-4 focus:ring-primary\/25\">\n    Restablecer calculadora\n<\/button>\n<\/div>\n<p class=\"text-xs text-text-subtle mt-2\">Un clic para copiar par\u00e1metros y resultados y compartirlos con proveedores o propietarios<\/p>\n<\/div>\n\n<\/div>\n\n<script>\n    (function() {\n        const MATERIAL_DB = {\n            'pea-gravel': { name: 'Grava fina', densitySI: 1485 },\n            'nominal-gravel': { name: 'Grava triturada (1\/4\" - 2\")', densitySI: 1680 },\n            'coarse-crushed': { name: 'Piedra triturada gruesa (2\" - 6\")', densitySI: 1300 },\n            'dry-sand': { name: 'Arena seca', densitySI: 1540 },\n            'wet-sand': { name: 'Arena h\u00fameda', densitySI: 1780 },\n            'custom': { name: 'Material personalizado', densitySI: 1485 },\n        };\n        const LENGTH_TO_M = { 'm': 1, 'cm': 0.01, 'ft': 0.3048, 'in': 0.0254, 'yd': 0.9144 };\n        const AREA_TO_M2 = { 'm2': 1, 'ft2': 0.09290304, 'yd2': 0.83612736 };\n        const VOLUME_TO_M3 = { 'm3': 1, 'yd3': 0.76455485798 };\n        const WEIGHT_TO_KG = { 'kg': 1, 'tonne': 1000, 'lb': 0.45359237, 'uston': 907.18474 };\n        const KGPM3_TO_LBSPFT3 = 0.06242796;\n\n        const state = {\n            unitSystem: 'metric',\n            materialKey: 'pea-gravel',\n            customDensitySI: 1485,\n            mode: 'A',\n            shapeA: 'rectangle',\n            lengthSI: 5,\n            widthSI: 3,\n            diameterSI: 4,\n            depthSI: 0.1,\n            areaSI_B: 50,\n            multiAreas: [],\n            wasteRate: 10,\n            compactionRate: 5,\n            basicVolumeSI: 0,\n            finalVolumeSI: 0,\n            finalWeightKG: 0,\n            unitPrice: 120,\n            priceUnit: 'per-tonne',\n            baggedMode: false,\n            bagWeight: 20,\n            bagWeightUnit: 'kg',\n            lastEditedField: null,\n            isReverseCalc: false,\n            focusedResultField: null,\n        };\n        let areaIdCounter = 0;\n\n        const $ = s => document.querySelector(s);\n        const $$ = s => document.querySelectorAll(s);\n        const materialSelect = $('#materialSelect');\n        const densityInput = $('#densityInput');\n        const densityUnitLabel = $('#densityUnitLabel');\n        const unitToggleBtn = $('#unitToggleBtn');\n        const unitToggleIcon = $('#unitToggleIcon');\n        const unitToggleLabel = $('#unitToggleLabel');\n        const tabA = $('#tabA'), tabB = $('#tabB'), tabC = $('#tabC');\n        const panelA = $('#panelModeA'), panelB = $('#panelModeB'), panelC = $('#panelModeC');\n        const shapeRectBtn = $('#shapeRectBtn'), shapeCircleBtn = $('#shapeCircleBtn');\n        const rectInputs = $('#rectInputs'), circleInputs = $('#circleInputs');\n        const lengthInput = $('#lengthInput'), lengthUnit = $('#lengthUnit');\n        const widthInput = $('#widthInput'), widthUnit = $('#widthUnit');\n        const diameterInput = $('#diameterInput'), diameterUnit = $('#diameterUnit');\n        const depthInput = $('#depthInput'), depthUnit = $('#depthUnit');\n        const areaInputB = $('#areaInputB'), areaUnitB = $('#areaUnitB');\n        const depthInputB = $('#depthInputB'), depthUnitB = $('#depthUnitB');\n        const multiAreaList = $('#multiAreaList'), multiAreaEmpty = $('#multiAreaEmpty');\n        const addAreaBtn = $('#addAreaBtn'), totalAreaDisplay = $('#totalAreaDisplay');\n        const depthInputC = $('#depthInputC'), depthUnitC = $('#depthUnitC');\n        const wasteRateSlider = $('#wasteRateSlider'), wasteRateValue = $('#wasteRateValue');\n        const compactionRateSlider = $('#compactionRateSlider'), compactionRateValue = $('#compactionRateValue');\n        const compactionPresets = $$('.compaction-preset');\n        const resultVolume = $('#resultVolume'), resultWeight = $('#resultWeight');\n        const resultVolumeUnit = $('#resultVolumeUnit'), resultWeightUnit = $('#resultWeightUnit');\n        const resultVolumeSub = $('#resultVolumeSub'), resultWeightSub = $('#resultWeightSub');\n        const reverseHint = $('#reverseHint');\n        const unitPriceInput = $('#unitPriceInput'), priceUnitSelect = $('#priceUnitSelect');\n        const totalCostDisplay = $('#totalCostDisplay');\n        const baggedToggle = $('#baggedToggle'), baggedToggleDot = $('#baggedToggleDot');\n        const baggedDetails = $('#baggedDetails');\n        const bagWeightInput = $('#bagWeightInput'), bagWeightUnit = $('#bagWeightUnit');\n        const bagCountDisplay = $('#bagCountDisplay');\n        const transportText = $('#transportText');\n        const copyReportBtn = $('#copyReportBtn'), resetBtn = $('#resetBtn');\n        const toast = $('#toast');\n\n        function lengthFromSI(si, u) { return si \/ LENGTH_TO_M[u]; }\n        function lengthToSI(v, u) { return v * LENGTH_TO_M[u]; }\n        function areaFromSI(si, u) { return si \/ AREA_TO_M2[u]; }\n        function areaToSI(v, u) { return v * AREA_TO_M2[u]; }\n        function getDensitySI() { return state.materialKey === 'custom' ? state.customDensitySI : MATERIAL_DB[state.materialKey].densitySI; }\n        function getDensityDisplay() { const si = getDensitySI(); return state.unitSystem === 'imperial' ? si * KGPM3_TO_LBSPFT3 : si; }\n        function getDensityUnitStr() { return state.unitSystem === 'metric' ? 'kg\/m\u00b3' : 'lbs\/ft\u00b3'; }\n        function weightFromSI(si) { return state.unitSystem === 'metric' ? si \/ 1000 : si \/ WEIGHT_TO_KG['uston']; }\n        function weightToSI(v) { return state.unitSystem === 'metric' ? v * 1000 : v * WEIGHT_TO_KG['uston']; }\n        function getWeightUnitStr() { return state.unitSystem === 'metric' ? 'toneladas' : 'US ton'; }\n        function getVolumeUnitStr() { return state.unitSystem === 'metric' ? 'm\u00b3' : 'yd\u00b3'; }\n        function volumeFromSI(si) { return state.unitSystem === 'metric' ? si : si \/ VOLUME_TO_M3['yd3']; }\n        function volumeToSI(v) { return state.unitSystem === 'metric' ? v : v * VOLUME_TO_M3['yd3']; }\n        function showToast(msg, dur = 2200) { toast.textContent = msg; toast.classList.add('show'); clearTimeout(toast._timeout); toast._timeout = setTimeout(() => toast.classList.remove('show'), dur); }\n\n        function getTotalAreaSI() {\n            if (state.mode === 'A') return state.shapeA === 'rectangle' ? state.lengthSI * state.widthSI : Math.PI * (state.diameterSI\/2)**2;\n            if (state.mode === 'B') return state.areaSI_B;\n            return state.multiAreas.reduce((s, a) => s + (a.areaSI || 0), 0);\n        }\n        function getDepthSI() { return state.depthSI; }\n        function setDepthSI(si) { state.depthSI = Math.max(0, si); updateAllDepthInputs(); }\n\n        function forwardCalculate() {\n            const area = getTotalAreaSI(), depth = getDepthSI();\n            const basic = area * depth;\n            state.basicVolumeSI = basic;\n            state.finalVolumeSI = basic * (1 + state.wasteRate\/100) * (1 + state.compactionRate\/100);\n            state.finalWeightKG = state.finalVolumeSI * getDensitySI();\n            state.lastEditedField = null; state.isReverseCalc = false;\n            updateResultsDisplay(); updateBudgetDisplay(); updateTransportInfo();\n            reverseHint.style.display = 'none';\n        }\n        function reverseFromWeight(dispW) {\n            const kg = weightToSI(dispW); if (kg <= 0 || getDensitySI() <= 0) return;\n            state.finalWeightKG = kg; state.finalVolumeSI = kg \/ getDensitySI();\n            const area = getTotalAreaSI();\n            if (area > 0) { const basic = state.finalVolumeSI \/ ((1+state.wasteRate\/100)*(1+state.compactionRate\/100)); state.basicVolumeSI = basic; setDepthSI(basic\/area); }\n            state.lastEditedField = 'weight'; state.isReverseCalc = true;\n            updateResultsDisplay(); updateBudgetDisplay(); updateTransportInfo();\n            reverseHint.style.display = 'flex'; setTimeout(() => reverseHint.style.display = 'none', 3000);\n        }\n        function reverseFromVolume(dispV) {\n            const vol = volumeToSI(dispV); if (vol <= 0) return;\n            state.finalVolumeSI = vol; state.finalWeightKG = vol * getDensitySI();\n            const area = getTotalAreaSI();\n            if (area > 0) { const basic = state.finalVolumeSI \/ ((1+state.wasteRate\/100)*(1+state.compactionRate\/100)); state.basicVolumeSI = basic; setDepthSI(basic\/area); }\n            state.lastEditedField = 'volume'; state.isReverseCalc = true;\n            updateResultsDisplay(); updateBudgetDisplay(); updateTransportInfo();\n            reverseHint.style.display = 'flex'; setTimeout(() => reverseHint.style.display = 'none', 3000);\n        }\n        function updateAllDepthInputs() {\n            const val = lengthFromSI(state.depthSI, state.mode==='A'?depthUnit.value:(state.mode==='B'?depthUnitB.value:depthUnitC.value));\n            if (state.mode==='A') depthInput.value = val.toFixed(6);\n            else if (state.mode==='B') depthInputB.value = val.toFixed(6);\n            else depthInputC.value = val.toFixed(6);\n        }\n        function updateResultsDisplay() {\n            resultVolumeUnit.textContent = getVolumeUnitStr(); resultWeightUnit.textContent = getWeightUnitStr();\n            if (state.focusedResultField !== 'volume') resultVolume.value = volumeFromSI(state.finalVolumeSI).toFixed(4);\n            if (state.focusedResultField !== 'weight') resultWeight.value = weightFromSI(state.finalWeightKG).toFixed(4);\n            resultVolumeSub.textContent = state.isReverseCalc ? '(c\u00e1lculo inverso)' : 'Incluye p\u00e9rdida y compactaci\u00f3n';\n            resultWeightSub.textContent = state.isReverseCalc ? '(c\u00e1lculo inverso)' : 'Basado en la densidad';\n            const panel = $('#resultsPanel'); panel.classList.remove('result-pulse'); void panel.offsetWidth; panel.classList.add('result-pulse');\n        }\n        function updateBudgetDisplay() {\n            const price = state.unitPrice || 0; let cost = 0;\n            switch(state.priceUnit) {\n                case 'per-tonne': cost = weightFromSI(state.finalWeightKG) * price; break;\n                case 'per-m3': cost = volumeFromSI(state.finalVolumeSI) * price; break;\n                case 'per-yd3': cost = (state.finalVolumeSI\/VOLUME_TO_M3['yd3']) * price; break;\n                case 'per-kg': cost = state.finalWeightKG * price; break;\n                case 'per-lb': cost = (state.finalWeightKG\/WEIGHT_TO_KG['lb']) * price; break;\n            }\n            totalCostDisplay.textContent = '\u20ac' + cost.toFixed(2).replace('.', ',');\n            if (state.baggedMode && state.bagWeight > 0) {\n                let bagKG = state.bagWeight; if (state.bagWeightUnit==='lb') bagKG *= WEIGHT_TO_KG['lb'];\n                bagCountDisplay.textContent = Math.ceil(state.finalWeightKG \/ bagKG) + ' sacos';\n            } else bagCountDisplay.textContent = '-- sacos';\n        }\n        function updateTransportInfo() {\n            const t = state.finalWeightKG \/ 1000;\n            if (t <= 0) { transportText.textContent = 'No necesita transporte'; return; }\n            transportText.textContent = `aprox. ${Math.ceil(t\/1)} camionetas est\u00e1ndar (1 t c\/u) o ${Math.ceil(t\/15)} camiones volquete grandes (15 t c\/u)`;\n        }\n        function fullRecalculate() {\n            if (state.isReverseCalc &#038;&#038; state.lastEditedField) {\n                if (state.lastEditedField==='weight') reverseFromWeight(parseFloat(resultWeight.value)||0);\n                else reverseFromVolume(parseFloat(resultVolume.value)||0);\n                return;\n            }\n            forwardCalculate();\n        }\n        function syncModeAInputs() {\n            if (state.shapeA==='rectangle') { state.lengthSI = lengthToSI(parseFloat(lengthInput.value)||0, lengthUnit.value); state.widthSI = lengthToSI(parseFloat(widthInput.value)||0, widthUnit.value); }\n            else state.diameterSI = lengthToSI(parseFloat(diameterInput.value)||0, diameterUnit.value);\n            state.depthSI = lengthToSI(parseFloat(depthInput.value)||0, depthUnit.value);\n        }\n        function syncModeBInputs() { state.areaSI_B = areaToSI(parseFloat(areaInputB.value)||0, areaUnitB.value); state.depthSI = lengthToSI(parseFloat(depthInputB.value)||0, depthUnitB.value); }\n        function syncModeCInputs() { state.depthSI = lengthToSI(parseFloat(depthInputC.value)||0, depthUnitC.value); }\n        function updateDensityDisplay() { densityInput.value = getDensityDisplay().toFixed(2); densityUnitLabel.textContent = getDensityUnitStr(); densityInput.readOnly = state.materialKey !== 'custom'; }\n        function updateUnitToggleUI() {\n            if (state.unitSystem==='metric') { unitToggleIcon.innerHTML = '&#127760;'; unitToggleLabel.textContent = 'M\u00e9trico'; }\n            else { unitToggleIcon.innerHTML = '&#127758;'; unitToggleLabel.textContent = 'Imperial'; }\n        }\n        function updateAllUnitDropdowns() {\n            const lDef = state.unitSystem==='metric'?['m','cm','ft','in','yd']:['ft','in','yd','m','cm'];\n            const dDef = state.unitSystem==='metric'?['cm','m','in','ft']:['in','ft','cm','m'];\n            const aDef = state.unitSystem==='metric'?['m2','ft2','yd2']:['ft2','yd2','m2'];\n            function rebuild(sel, opts, cur) { const v = cur||sel.value; sel.innerHTML = ''; const labels={'m':'m','cm':'cm','ft':'ft','in':'in','yd':'yd','m2':'m\u00b2','ft2':'ft\u00b2','yd2':'yd\u00b2'}; opts.forEach(o=>{const opt=document.createElement('option');opt.value=o;opt.textContent=labels[o]||o;if(o===v)opt.selected=true;sel.appendChild(opt);}); }\n            rebuild(lengthUnit, lDef, lengthUnit.value); rebuild(widthUnit, lDef, widthUnit.value);\n            rebuild(diameterUnit, lDef, diameterUnit.value); rebuild(depthUnit, dDef, depthUnit.value);\n            rebuild(depthUnitB, dDef, depthUnitB.value); rebuild(depthUnitC, dDef, depthUnitC.value);\n            rebuild(areaUnitB, aDef, areaUnitB.value);\n            bagWeightUnit.value = state.unitSystem==='metric'?'kg':'lb'; state.bagWeightUnit = bagWeightUnit.value;\n        }\n        function updateAllDisplayValues() {\n            lengthInput.value = lengthFromSI(state.lengthSI, lengthUnit.value).toFixed(6);\n            widthInput.value = lengthFromSI(state.widthSI, widthUnit.value).toFixed(6);\n            diameterInput.value = lengthFromSI(state.diameterSI, diameterUnit.value).toFixed(6);\n            depthInput.value = lengthFromSI(state.depthSI, depthUnit.value).toFixed(6);\n            areaInputB.value = areaFromSI(state.areaSI_B, areaUnitB.value).toFixed(6);\n            depthInputB.value = lengthFromSI(state.depthSI, depthUnitB.value).toFixed(6);\n            depthInputC.value = lengthFromSI(state.depthSI, depthUnitC.value).toFixed(6);\n            updateMultiAreaDisplay(); updateTotalAreaDisplay();\n        }\n        function updateTotalAreaDisplay() {\n            const a = getTotalAreaSI(); const u = state.unitSystem==='metric'?'m\u00b2':'ft\u00b2';\n            totalAreaDisplay.textContent = (state.unitSystem==='metric'?a:areaFromSI(a,'ft2')).toFixed(4) + ' ' + u;\n        }\n        function createAreaCard(ad) {\n            const card = document.createElement('div'); card.className = 'area-card bg-surface rounded-lg p-3 flex flex-col sm:flex-row gap-2 items-start'; card.dataset.areaId = ad.id;\n            const shapeOpts = [{v:'rectangle',l:'Rect\u00e1ngulo'},{v:'circle',l:'C\u00edrculo'}];\n            const shapeSelHTML = shapeOpts.map(s=>`<option value=\"${s.v}\" ${ad.shape===s.v?'selected':''}>${s.l}<\/option>`).join('');\n            const units = ['m','cm','ft','in','yd'];\n            const luHTML = units.map(u=>`<option value=\"${u}\" ${ad.dim1Unit===u?'selected':''}>${u}<\/option>`).join('');\n            const wuHTML = units.map(u=>`<option value=\"${u}\" ${ad.dim2Unit===u?'selected':''}>${u}<\/option>`).join('');\n            const isRect = ad.shape==='rectangle';\n            const d1Val = lengthFromSI(ad.dim1SI, ad.dim1Unit).toFixed(6);\n            const d2Val = isRect ? lengthFromSI(ad.dim2SI, ad.dim2Unit).toFixed(6) : 0;\n            const areaDisp = (state.unitSystem==='metric'?ad.areaSI.toFixed(4)+' m\u00b2':areaFromSI(ad.areaSI,'ft2').toFixed(4)+' ft\u00b2');\n            card.innerHTML = `\n            <div class=\"flex-shrink-0\"><select class=\"area-shape-select bg-surface border border-border-soft rounded-md px-2 py-1.5 text-xs font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 transition-all\">${shapeSelHTML}<\/select><\/div>\n            <div class=\"flex-1 grid grid-cols-1 xs:grid-cols-2 gap-2 w-full\">\n              <div class=\"flex gap-1\"><input type=\"number\" class=\"area-dim1 flex-1 min-w-0 bg-surface border border-border-soft rounded-md px-2 py-1.5 text-xs font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 transition-all\" value=\"${d1Val}\" min=\"0\" step=\"any\" placeholder=\"${isRect?'Longitud':'Di\u00e1metro'}\"><select class=\"area-dim1-unit w-20 bg-surface border border-border-soft rounded-md px-1.5 py-1.5 text-xs focus:outline-none transition-all\">${luHTML}<\/select><\/div>\n              <div class=\"area-dim2-wrapper flex gap-1\" style=\"${isRect?'':'display:none;'}\"><input type=\"number\" class=\"area-dim2 flex-1 min-w-0 bg-surface border border-border-soft rounded-md px-2 py-1.5 text-xs font-medium focus:outline-none focus:ring-2 focus:ring-primary\/30 transition-all\" value=\"${d2Val}\" min=\"0\" step=\"any\" placeholder=\"Anchura\"><select class=\"area-dim2-unit w-20 bg-surface border border-border-soft rounded-md px-1.5 py-1.5 text-xs focus:outline-none transition-all\">${wuHTML}<\/select><\/div>\n            <\/div>\n            <div class=\"flex items-center gap-2 flex-shrink-0\"><span class=\"text-xs font-semibold text-primary whitespace-nowrap area-card-display\">${areaDisp}<\/span><button class=\"area-remove-btn text-red-400 hover:text-red-600 hover:bg-red-50 rounded-full w-7 h-7 flex items-center justify-center transition-all text-lg leading-none\" title=\"Eliminar\">&times;<\/button><\/div>`;\n            const sSel = card.querySelector('.area-shape-select'), d1 = card.querySelector('.area-dim1'), u1 = card.querySelector('.area-dim1-unit');\n            const d2 = card.querySelector('.area-dim2'), u2 = card.querySelector('.area-dim2-unit'), d2W = card.querySelector('.area-dim2-wrapper');\n            const remBtn = card.querySelector('.area-remove-btn'), disp = card.querySelector('.area-card-display');\n            function upd() {\n                ad.shape = sSel.value; ad.dim1Unit = u1.value; ad.dim1SI = lengthToSI(parseFloat(d1.value)||0, u1.value);\n                if (ad.shape==='rectangle') { ad.dim2Unit = u2.value; ad.dim2SI = lengthToSI(parseFloat(d2.value)||0, u2.value); ad.areaSI = ad.dim1SI * ad.dim2SI; }\n                else { const r = ad.dim1SI\/2; ad.areaSI = Math.PI * r * r; }\n                disp.textContent = state.unitSystem==='metric'?ad.areaSI.toFixed(4)+' m\u00b2':areaFromSI(ad.areaSI,'ft2').toFixed(4)+' ft\u00b2';\n                d2W.style.display = ad.shape==='rectangle'?'':'none'; d1.placeholder = ad.shape==='rectangle'?'Longitud':'Di\u00e1metro';\n                updateTotalAreaDisplay(); fullRecalculate();\n            }\n            sSel.addEventListener('change', upd); d1.addEventListener('input', upd); u1.addEventListener('change', upd);\n            d2.addEventListener('input', upd); u2.addEventListener('change', upd);\n            remBtn.addEventListener('click', ()=>{ state.multiAreas = state.multiAreas.filter(a=>a.id!==ad.id); card.remove(); if(state.multiAreas.length===0) multiAreaEmpty.style.display=''; updateTotalAreaDisplay(); fullRecalculate(); });\n            return card;\n        }\n        function updateMultiAreaDisplay() { multiAreaList.querySelectorAll('.area-card').forEach(c=>{const id=parseInt(c.dataset.areaId);const a=state.multiAreas.find(x=>x.id===id);if(a){const s=c.querySelector('.area-card-display');if(s)s.textContent=state.unitSystem==='metric'?a.areaSI.toFixed(4)+' m\u00b2':areaFromSI(a.areaSI,'ft2').toFixed(4)+' ft\u00b2';}}); updateTotalAreaDisplay(); }\n        function addNewArea() {\n            const id = ++areaIdCounter; const defU = state.unitSystem==='metric'?'m':'ft';\n            const ad = { id, shape:'rectangle', dim1SI:lengthToSI(3,defU), dim1Unit:defU, dim2SI:lengthToSI(2,defU), dim2Unit:defU, areaSI:lengthToSI(3,defU)*lengthToSI(2,defU) };\n            state.multiAreas.push(ad); multiAreaList.appendChild(createAreaCard(ad)); multiAreaEmpty.style.display='none'; updateTotalAreaDisplay(); fullRecalculate();\n        }\n        function rebuildAllAreaCards() { multiAreaList.innerHTML=''; state.multiAreas.forEach(a=>multiAreaList.appendChild(createAreaCard(a))); multiAreaEmpty.style.display = state.multiAreas.length===0?'':'none'; updateTotalAreaDisplay(); }\n        function switchMode(m) {\n            state.mode = m; state.isReverseCalc=false; state.lastEditedField=null; reverseHint.style.display='none';\n            [tabA,tabB,tabC].forEach(t=>{t.classList.remove('active'); t.setAttribute('aria-selected','false');});\n            if(m==='A'){tabA.classList.add('active');tabA.setAttribute('aria-selected','true');} else if(m==='B'){tabB.classList.add('active');tabB.setAttribute('aria-selected','true');} else {tabC.classList.add('active');tabC.setAttribute('aria-selected','true');}\n            panelA.classList.add('hidden'); panelB.classList.add('hidden'); panelC.classList.add('hidden');\n            if(m==='A')panelA.classList.remove('hidden'); else if(m==='B')panelB.classList.remove('hidden'); else panelC.classList.remove('hidden');\n            updateAllDisplayValues(); if(m==='C') rebuildAllAreaCards(); fullRecalculate();\n        }\n\n        materialSelect.addEventListener('change', ()=>{\n            state.materialKey = materialSelect.value; if(state.materialKey!=='custom') state.customDensitySI = MATERIAL_DB[state.materialKey].densitySI;\n            updateDensityDisplay(); state.isReverseCalc=false; state.lastEditedField=null; reverseHint.style.display='none'; fullRecalculate();\n        });\n        densityInput.addEventListener('input', ()=>{ if(state.materialKey==='custom'){ state.customDensitySI = state.unitSystem==='imperial'?parseFloat(densityInput.value)\/KGPM3_TO_LBSPFT3:parseFloat(densityInput.value); state.isReverseCalc=false; state.lastEditedField=null; reverseHint.style.display='none'; fullRecalculate(); } });\n        unitToggleBtn.addEventListener('click', ()=>{ state.unitSystem = state.unitSystem==='metric'?'imperial':'metric'; updateUnitToggleUI(); updateAllUnitDropdowns(); updateDensityDisplay(); updateAllDisplayValues(); if(state.mode==='C') rebuildAllAreaCards(); state.isReverseCalc=false; state.lastEditedField=null; reverseHint.style.display='none'; fullRecalculate(); });\n        tabA.addEventListener('click', ()=>switchMode('A')); tabB.addEventListener('click', ()=>switchMode('B')); tabC.addEventListener('click', ()=>switchMode('C'));\n        shapeRectBtn.addEventListener('click', ()=>{ state.shapeA='rectangle'; shapeRectBtn.classList.add('bg-primary','text-white','shadow-sm'); shapeRectBtn.classList.remove('bg-gray-200','text-text-subtle','hover:bg-gray-300'); shapeCircleBtn.classList.remove('bg-primary','text-white','shadow-sm'); shapeCircleBtn.classList.add('bg-gray-200','text-text-subtle','hover:bg-gray-300'); rectInputs.classList.remove('hidden'); circleInputs.classList.add('hidden'); syncModeAInputs(); state.isReverseCalc=false; state.lastEditedField=null; reverseHint.style.display='none'; fullRecalculate(); });\n        shapeCircleBtn.addEventListener('click', ()=>{ state.shapeA='circle'; shapeCircleBtn.classList.add('bg-primary','text-white','shadow-sm'); shapeCircleBtn.classList.remove('bg-gray-200','text-text-subtle','hover:bg-gray-300'); shapeRectBtn.classList.remove('bg-primary','text-white','shadow-sm'); shapeRectBtn.classList.add('bg-gray-200','text-text-subtle','hover:bg-gray-300'); rectInputs.classList.add('hidden'); circleInputs.classList.remove('hidden'); syncModeAInputs(); state.isReverseCalc=false; state.lastEditedField=null; reverseHint.style.display='none'; fullRecalculate(); });\n        [lengthInput,widthInput,diameterInput,depthInput].forEach(e=>e.addEventListener('input', ()=>{ if(state.mode!=='A')return; syncModeAInputs(); state.isReverseCalc=false; state.lastEditedField=null; reverseHint.style.display='none'; fullRecalculate(); }));\n        [lengthUnit,widthUnit,diameterUnit,depthUnit].forEach(e=>e.addEventListener('change', ()=>{ if(state.mode!=='A')return; syncModeAInputs(); updateAllDisplayValues(); state.isReverseCalc=false; state.lastEditedField=null; reverseHint.style.display='none'; fullRecalculate(); }));\n        [areaInputB,depthInputB].forEach(e=>e.addEventListener('input', ()=>{ if(state.mode!=='B')return; syncModeBInputs(); state.isReverseCalc=false; state.lastEditedField=null; reverseHint.style.display='none'; fullRecalculate(); }));\n        [areaUnitB,depthUnitB].forEach(e=>e.addEventListener('change', ()=>{ if(state.mode!=='B')return; syncModeBInputs(); updateAllDisplayValues(); state.isReverseCalc=false; state.lastEditedField=null; reverseHint.style.display='none'; fullRecalculate(); }));\n        [depthInputC].forEach(e=>e.addEventListener('input', ()=>{ if(state.mode!=='C')return; syncModeCInputs(); state.isReverseCalc=false; state.lastEditedField=null; reverseHint.style.display='none'; fullRecalculate(); }));\n        [depthUnitC].forEach(e=>e.addEventListener('change', ()=>{ if(state.mode!=='C')return; syncModeCInputs(); updateAllDisplayValues(); state.isReverseCalc=false; state.lastEditedField=null; reverseHint.style.display='none'; fullRecalculate(); }));\n        addAreaBtn.addEventListener('click', addNewArea);\n        wasteRateSlider.addEventListener('input', ()=>{ state.wasteRate=parseFloat(wasteRateSlider.value); wasteRateValue.textContent=state.wasteRate+'%'; state.isReverseCalc=false; state.lastEditedField=null; reverseHint.style.display='none'; fullRecalculate(); });\n        compactionRateSlider.addEventListener('input', ()=>{ state.compactionRate=parseFloat(compactionRateSlider.value); compactionRateValue.textContent=state.compactionRate+'%'; updateCompactionPresetStyles(); state.isReverseCalc=false; state.lastEditedField=null; reverseHint.style.display='none'; fullRecalculate(); });\n        compactionPresets.forEach(b=>b.addEventListener('click', ()=>{ const r=parseFloat(b.dataset.rate); state.compactionRate=r; compactionRateSlider.value=r; compactionRateValue.textContent=r+'%'; updateCompactionPresetStyles(); state.isReverseCalc=false; state.lastEditedField=null; reverseHint.style.display='none'; fullRecalculate(); }));\n        function updateCompactionPresetStyles(){ compactionPresets.forEach(b=>{ const r=parseFloat(b.dataset.rate); if(Math.abs(r-state.compactionRate)<0.01){ b.classList.add('bg-accent\/15','text-accent','font-semibold','border','border-accent\/30'); b.classList.remove('bg-gray-200','text-text-subtle','hover:bg-gray-300'); } else { b.classList.remove('bg-accent\/15','text-accent','font-semibold','border','border-accent\/30'); b.classList.add('bg-gray-200','text-text-subtle','hover:bg-gray-300'); } }); }\n        resultVolume.addEventListener('focus', ()=>{ state.focusedResultField='volume'; resultVolume.dataset.prevValue=resultVolume.value; });\n        resultVolume.addEventListener('blur', ()=>{ state.focusedResultField=null; const p=parseFloat(resultVolume.dataset.prevValue||0), n=parseFloat(resultVolume.value); if(!isNaN(n)&&Math.abs(n-p)>0.0001&&n>=0) reverseFromVolume(n); });\n        resultVolume.addEventListener('keydown', e=>{ if(e.key==='Enter') resultVolume.blur(); });\n        resultWeight.addEventListener('focus', ()=>{ state.focusedResultField='weight'; resultWeight.dataset.prevValue=resultWeight.value; });\n        resultWeight.addEventListener('blur', ()=>{ state.focusedResultField=null; const p=parseFloat(resultWeight.dataset.prevValue||0), n=parseFloat(resultWeight.value); if(!isNaN(n)&&Math.abs(n-p)>0.0001&&n>=0) reverseFromWeight(n); });\n        resultWeight.addEventListener('keydown', e=>{ if(e.key==='Enter') resultWeight.blur(); });\n        unitPriceInput.addEventListener('input', ()=>{ state.unitPrice=parseFloat(unitPriceInput.value)||0; updateBudgetDisplay(); });\n        priceUnitSelect.addEventListener('change', ()=>{ state.priceUnit=priceUnitSelect.value; updateBudgetDisplay(); });\n        baggedToggle.addEventListener('click', ()=>{ state.baggedMode=!state.baggedMode; if(state.baggedMode){ baggedToggle.classList.remove('bg-gray-300'); baggedToggle.classList.add('bg-primary'); baggedToggleDot.classList.remove('translate-x-0.5'); baggedToggleDot.classList.add('translate-x-5'); baggedToggle.setAttribute('aria-checked','true'); baggedDetails.classList.remove('hidden'); } else { baggedToggle.classList.add('bg-gray-300'); baggedToggle.classList.remove('bg-primary'); baggedToggleDot.classList.add('translate-x-0.5'); baggedToggleDot.classList.remove('translate-x-5'); baggedToggle.setAttribute('aria-checked','false'); baggedDetails.classList.add('hidden'); } updateBudgetDisplay(); });\n        bagWeightInput.addEventListener('input', ()=>{ state.bagWeight=parseFloat(bagWeightInput.value)||0; updateBudgetDisplay(); });\n        bagWeightUnit.addEventListener('change', ()=>{ state.bagWeightUnit=bagWeightUnit.value; updateBudgetDisplay(); });\n        copyReportBtn.addEventListener('click', ()=>{ const r=generateReport(); if(navigator.clipboard?.writeText) navigator.clipboard.writeText(r).then(()=>showToast('\u00a1Informe copiado al portapapeles!')).catch(()=>fallbackCopy(r)); else fallbackCopy(r); });\n        resetBtn.addEventListener('click', ()=>{ init(); showToast('Calculadora restablecida.'); });\n        function fallbackCopy(t){ const ta=document.createElement('textarea'); ta.value=t; ta.style.position='fixed'; ta.style.opacity='0'; document.body.appendChild(ta); ta.select(); try{document.execCommand('copy');showToast('\u00a1Informe copiado!');}catch(e){showToast('Error al copiar.');} document.body.removeChild(ta); }\n        function generateReport(){\n            const mat = MATERIAL_DB[state.materialKey]?.name||'Material personalizado';\n            const dens = getDensityDisplay().toFixed(2), dUnit = getDensityUnitStr();\n            const vol = volumeFromSI(state.finalVolumeSI).toFixed(4), vUnit = getVolumeUnitStr();\n            const wt = weightFromSI(state.finalWeightKG).toFixed(4), wUnit = getWeightUnitStr();\n            const area = (state.unitSystem==='metric'?getTotalAreaSI().toFixed(4)+' m\u00b2':areaFromSI(getTotalAreaSI(),'ft2').toFixed(4)+' ft\u00b2');\n            const depth = state.unitSystem==='metric'?(state.depthSI*100).toFixed(2)+' cm':(state.depthSI\/0.0254).toFixed(2)+' in';\n            const price = state.unitPrice||0; const puLabels={'per-tonne':'por tonelada','per-m3':'por m\u00b3','per-yd3':'por yd\u00b3','per-kg':'por kg','per-lb':'por lb'};\n            let cost=0; switch(state.priceUnit){ case 'per-tonne': cost=weightFromSI(state.finalWeightKG)*price; break; case 'per-m3': cost=volumeFromSI(state.finalVolumeSI)*price; break; case 'per-yd3': cost=(state.finalVolumeSI\/VOLUME_TO_M3['yd3'])*price; break; case 'per-kg': cost=state.finalWeightKG*price; break; case 'per-lb': cost=(state.finalWeightKG\/WEIGHT_TO_KG['lb'])*price; break; }\n            let r = '========================================\\n';\n            r += '   Calculadora de Grava - Informe\\n';\n            r += '========================================\\n\\n';\n            r += `Material: ${mat}\\nDensidad: ${dens} ${dUnit}\\n\u00c1rea: ${area}\\nProfundidad: ${depth}\\n`;\n            r += `Margen de p\u00e9rdida: ${state.wasteRate}%\\nCompactaci\u00f3n: ${state.compactionRate}%\\n\\n`;\n            r += `Volumen final: ${vol} ${vUnit}\\nPeso final: ${wt} ${wUnit}\\n\\n`;\n            r += `Precio unitario: \u20ac${price.toFixed(2)} ${puLabels[state.priceUnit]||state.priceUnit}\\n`;\n            r += `Coste total estimado: \u20ac${cost.toFixed(2)}\\n`;\n            if(state.baggedMode && state.bagWeight>0){ let bkg=state.bagWeight; if(state.bagWeightUnit==='lb') bkg*=WEIGHT_TO_KG['lb']; r += `Sacos: ${Math.ceil(state.finalWeightKG\/bkg)} sacos (${state.bagWeight} ${state.bagWeightUnit} c\/u)\\n`; }\n            const t = state.finalWeightKG\/1000; r += `Transporte: aprox. ${Math.ceil(t\/1)} camionetas o ${Math.ceil(t\/15)} camiones volquete grandes\\n`;\n            r += '\\n========================================\\n';\n            r += 'Generado: ' + new Date().toLocaleString('es-ES') + '\\n';\n            return r;\n        }\n        function init(){\n            state.unitSystem='metric'; state.materialKey='pea-gravel'; state.customDensitySI=MATERIAL_DB['pea-gravel'].densitySI;\n            state.mode='A'; state.shapeA='rectangle'; state.lengthSI=lengthToSI(5,'m'); state.widthSI=lengthToSI(3,'m');\n            state.diameterSI=lengthToSI(4,'m'); state.depthSI=lengthToSI(10,'cm'); state.areaSI_B=areaToSI(50,'m2');\n            state.wasteRate=10; state.compactionRate=5; state.unitPrice=120; state.priceUnit='per-tonne';\n            state.baggedMode=false; state.bagWeight=20; state.bagWeightUnit='kg'; state.multiAreas=[]; areaIdCounter=0;\n            state.lastEditedField=null; state.isReverseCalc=false; state.focusedResultField=null;\n            updateUnitToggleUI(); updateAllUnitDropdowns(); updateDensityDisplay(); updateAllDisplayValues();\n            wasteRateSlider.value=state.wasteRate; wasteRateValue.textContent=state.wasteRate+'%';\n            compactionRateSlider.value=state.compactionRate; compactionRateValue.textContent=state.compactionRate+'%'; updateCompactionPresetStyles();\n            materialSelect.value=state.materialKey; densityInput.value=getDensityDisplay().toFixed(2); densityInput.readOnly=true;\n            unitPriceInput.value=state.unitPrice; priceUnitSelect.value=state.priceUnit; bagWeightInput.value=state.bagWeight; bagWeightUnit.value=state.bagWeightUnit;\n            baggedDetails.classList.add('hidden'); baggedToggle.classList.add('bg-gray-300'); baggedToggle.classList.remove('bg-primary');\n            baggedToggleDot.classList.add('translate-x-0.5'); baggedToggleDot.classList.remove('translate-x-5'); baggedToggle.setAttribute('aria-checked','false');\n            reverseHint.style.display='none'; multiAreaEmpty.style.display=''; multiAreaList.innerHTML='';\n            panelA.classList.remove('hidden'); panelB.classList.add('hidden'); panelC.classList.add('hidden');\n            tabA.classList.add('active'); tabB.classList.remove('active'); tabC.classList.remove('active');\n            tabA.setAttribute('aria-selected','true'); tabB.setAttribute('aria-selected','false'); tabC.setAttribute('aria-selected','false');\n            rectInputs.classList.remove('hidden'); circleInputs.classList.add('hidden');\n            shapeRectBtn.classList.add('bg-primary','text-white','shadow-sm'); shapeRectBtn.classList.remove('bg-gray-200','text-text-subtle','hover:bg-gray-300');\n            shapeCircleBtn.classList.remove('bg-primary','text-white','shadow-sm'); shapeCircleBtn.classList.add('bg-gray-200','text-text-subtle','hover:bg-gray-300');\n            forwardCalculate(); updateTotalAreaDisplay();\n        }\n        init();\n    })();\n<\/script>\n\n\n<!-- aiper-tool-links -->\n<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-cercas\/\" class=\"aiper-tl-tag\">Calculadora de materiales para cercas<\/a>\n<a href=\"https:\/\/aiper.com\/blogs\/es\/calculadora-de-adoquines\/\" class=\"aiper-tl-tag\">Calculadora de Adoquines<\/a>\n<a href=\"https:\/\/aiper.com\/blogs\/es\/calculadora-de-terrazas\/\" class=\"aiper-tl-tag\">Calculadora de Terrazas<\/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\/ahuyentar-gansos-canadienses-cesped\/\" class=\"aiper-tl-tag\">C\u00f3mo ahuyentar los gansos canadienses del c\u00e9sped<\/a>\n<a href=\"https:\/\/aiper.com\/blogs\/es\/como-eliminar-setas-del-cesped\/\" class=\"aiper-tl-tag\">C\u00f3mo eliminar las setas del c\u00e9sped<\/a>\n<a href=\"https:\/\/aiper.com\/blogs\/es\/escarificar-cesped-detectar-eliminar-fieltro\/\" class=\"aiper-tl-tag\">Escarificar el c\u00e9sped: c\u00f3mo detectar y eliminar el fieltro<\/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>Calcula con precisi\u00f3n volumen, peso y coste \u2013 con soporte multi-\u00e1rea y c\u00e1lculo inverso Material Grava fina (Pea Gravel)Grava triturada (1\/4&#8243; &#8211; 2&#8243;)Piedra triturada gruesa (2&#8243; &#8211; 6&#8243;)Arena secaArena h\u00famedaMaterial personalizado Densidad (kg\/m\u00b3) Sistema de unidades &#127760; M\u00e9trico Por dimensiones \u00c1rea directa Combinaci\u00f3n de \u00e1reas Forma: Rect\u00e1ngulo C\u00edrculo Longitud mcmftinyd Anchura mcmftinyd Di\u00e1metro mcmftinyd Profundidad&#8230;<\/p>\n","protected":false},"author":3,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"class_list":["post-2552","page","type-page","status-publish","hentry"],"lang":"es","translations":{"es":2552,"en":2546,"de":2548,"fr":2550},"_links":{"self":[{"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/pages\/2552","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=2552"}],"version-history":[{"count":3,"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/pages\/2552\/revisions"}],"predecessor-version":[{"id":4382,"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/pages\/2552\/revisions\/4382"}],"wp:attachment":[{"href":"https:\/\/aiper.com\/blogs\/wp-json\/wp\/v2\/media?parent=2552"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}