{"title":"Bolsas y Empaques","description":"\u003cp\u003eBolsas de papel kraft natural para delivery, despensa y comida para llevar. Resistentes, reciclables y con estética ecológica, ideales para cafeterías, restaurantes, abarrotes y negocios de entrega a domicilio que buscan empaques prácticos y con imagen profesional.\u003c\/p\u003e","products":[{"product_id":"fajilla-microcorrugada-faj-1","title":"Fajilla microcorrugada FAJ-1 para vaso de papel café caliente color kraft","description":"\u003cp\u003eLa \u003cstrong\u003efajilla microcorrugada FAJ-1\u003c\/strong\u003e es el complemento ideal para \u003cstrong\u003evasos de papel para café y bebidas calientes\u003c\/strong\u003e. Proporciona \u003cstrong\u003eprotección térmica\u003c\/strong\u003e, mejorando el agarre y evitando que el calor moleste a tus clientes al sostener el vaso.\u003c\/p\u003e\n\u003cp\u003eAdemás de su función de \u003cstrong\u003eaislamiento térmico\u003c\/strong\u003e, aporta una \u003cstrong\u003epresentación premium\u003c\/strong\u003e a tus bebidas y es una excelente opción para \u003cstrong\u003epersonalizar con tu marca\u003c\/strong\u003e mediante impresión o sello. Fabricada en \u003cstrong\u003ecartón microcorrugado resistente\u003c\/strong\u003e, en color \u003cstrong\u003ekraft natural\u003c\/strong\u003e, combina estética y funcionalidad en cafeterías y negocios de bebidas calientes.\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eCLAVE: \u003cstrong\u003eFAJ-1\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003cli\u003eUso: aislamiento térmico para vasos de papel con bebidas calientes\u003c\/li\u003e\n\u003cli\u003eBeneficios: protección térmica, mejor agarre, presentación premium\u003c\/li\u003e\n\u003cli\u003ePersonalización: opción de personalizar con tu marca\u003c\/li\u003e\n\u003cli\u003eColor: kraft natural\u003c\/li\u003e\n\u003cli\u003eMaterial: cartón microcorrugado resistente\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003csection class=\"customize-order-section\"\u003e\n  \u003cdiv class=\"customize-order-inner\"\u003e\n    \u003ch2 class=\"customize-order-title\"\u003ePersonaliza tu pedido\u003c\/h2\u003e\n\n    \u003cdiv class=\"customize-order-grid\"\u003e\n      \u003c!-- Columna 1: Subir logo --\u003e\n      \u003cdiv class=\"customize-step\"\u003e\n        \u003clabel for=\"logo-upload-input\" class=\"customize-upload-box\" id=\"upload-box-label\"\u003e\n          \u003cdiv class=\"upload-plus-wrapper\" id=\"upload-plus-wrapper\"\u003e\n            \u003cspan class=\"upload-icon\"\u003e+\u003c\/span\u003e\n          \u003c\/div\u003e\n\n          \u003cdiv class=\"upload-preview-wrapper\"\u003e\n            \u003cimg id=\"upload-preview-img\" src=\"\" alt=\"Vista previa de tu logo\" class=\"upload-preview-img\" style=\"display:none;\"\u003e\n          \u003c\/div\u003e\n        \u003c\/label\u003e\n\n        \u003cinput id=\"logo-upload-input\" type=\"file\" accept=\"image\/png,image\/jpeg,image\/jpg\" class=\"upload-input\"\u003e\n\n        \u003cbutton type=\"button\" id=\"clear-logo-btn\" class=\"clear-logo-btn\" style=\"display:none;\"\u003e\n          Borrar imagen\n        \u003c\/button\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Columna 2: Mockup --\u003e\n      \u003cdiv class=\"customize-step\"\u003e\n        \u003cdiv class=\"mockup-preview\"\u003e\n          \u003cimg src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/files\/FAJILLAS.png?v=1768528015\" alt=\"Vaso personalizado\" class=\"mockup-base\" width=\"800\" height=\"800\"\u003e\n\n          \u003cdiv class=\"mockup-logo-wrap\" id=\"mockup-logo-wrap\"\u003e\n            \u003cimg id=\"mockup-logo-img\" src=\"\" alt=\"Tu logotipo\" class=\"mockup-logo\" style=\"display:none;\" width=\"600\" height=\"600\"\u003e\n          \u003c\/div\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Columna 3: Cantidad + botón WhatsApp --\u003e\n      \u003cdiv class=\"customize-step customize-step--quantity\"\u003e\n        \u003ch3 class=\"step-title step-title-top\"\u003eCantidad de cajas para cotizar\u003c\/h3\u003e\n\n        \u003cdiv class=\"qty-block qty-block-top\"\u003e\n          \u003cdiv class=\"qty-control\"\u003e\n            \u003cbutton type=\"button\" class=\"qty-btn\" id=\"qty-minus\"\u003e−\u003c\/button\u003e\n            \u003cinput type=\"text\" id=\"quote-quantity\" class=\"qty-input\" value=\"1\" inputmode=\"numeric\" pattern=\"[0-9]*\"\u003e\n            \u003cbutton type=\"button\" class=\"qty-btn\" id=\"qty-plus\"\u003e+\u003c\/button\u003e\n          \u003c\/div\u003e\n          \u003cp class=\"qty-min-text\"\u003eTe cotizamos desde una caja\u003c\/p\u003e\n        \u003c\/div\u003e\n\n        \u003c!-- Botón WhatsApp verde con icono (imagen) --\u003e\n        \u003cbutton type=\"button\" id=\"custom-whatsapp-btn\" class=\"whatsapp-quote-btn\"\u003e\n          \u003cspan class=\"wa-icon-circle\"\u003e\n            \u003cimg src=\"https:\/\/upload.wikimedia.org\/wikipedia\/commons\/6\/6b\/WhatsApp.svg\" alt=\"WhatsApp\" class=\"wa-icon-img\"\u003e\n          \u003c\/span\u003e\n          \u003cspan\u003eCotizar Producto\u003c\/span\u003e\n        \u003c\/button\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Fila inferior de pasos --\u003e\n    \u003cdiv class=\"customize-steps-row\"\u003e\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e1\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eAgrega tu logo\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Solo se admiten imágenes en formato .png con fondo transparente. Tamaño máximo: 20 KB.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e2\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eVisualiza cómo se ve\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Esta es una representación digital del producto final. El resultado puede variar ligeramente en color, tamaño o proporciones.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e3\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eHaz tu pedido\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Puedes pedir desde una caja para imprimir tu logo en tu artículo, así de fácil.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Campos ocultos --\u003e\n    \u003cinput type=\"hidden\" id=\"logo-data-input\" name=\"properties[Logo personalizado]\" value=\"\"\u003e\n    \u003cinput type=\"hidden\" id=\"quote-quantity-input\" name=\"properties[Cantidad para cotización]\" value=\"1\"\u003e\n  \u003c\/div\u003e\n\n  \u003cstyle\u003e\n    .customize-order-section {\n      padding: 2.5rem 1.25rem;\n      background-color: #ffffff;\n    }\n    .customize-order-inner {\n      max-width: 1100px;\n      margin: 0 auto;\n    }\n    .customize-order-title {\n      font-size: 1.75rem;\n      font-weight: 700;\n      margin-bottom: 1.75rem;\n      text-align: left;\n      color: #2044A3;\n    }\n\n    .customize-order-grid {\n      display: grid;\n      grid-template-columns: repeat(3, minmax(0, 1fr));\n      gap: 3rem;\n      align-items: flex-start;\n      margin-bottom: 3rem;\n      justify-content: center;\n    }\n    .customize-step {\n      width: 100%;\n      max-width: 300px;\n      margin: 0 auto;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n    }\n\n    .customize-upload-box {\n      border: 2px dashed #D4D4D8;\n      border-radius: 1.5rem;\n      padding: 1.5rem;\n      min-height: 220px;\n      width: 100%;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n      justify-content: center;\n      position: relative;\n      cursor: pointer;\n      box-sizing: border-box;\n    }\n\n    .upload-plus-wrapper {\n      position: absolute;\n      top: 50%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      pointer-events: none;\n    }\n\n    .upload-icon {\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      width: 60px;\n      height: 60px;\n      border-radius: 9999px;\n      border: 2px solid #2044A3;\n      font-size: 1.85rem;\n      font-weight: 600;\n      color: #2044A3;\n      background: #ffffff;\n    }\n\n    .upload-input {\n      display: none;\n    }\n\n    .upload-preview-wrapper {\n      width: 100%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      min-height: 150px;\n    }\n    .upload-preview-img {\n      max-width: 100%;\n      max-height: 160px;\n      object-fit: contain;\n      display: block;\n    }\n\n    .clear-logo-btn {\n      margin-top: 0.75rem;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      align-self: center;\n      padding: 0.6rem 1.6rem;\n      border-radius: 9999px;\n      border: none;\n      background-color: #FFC800;\n      color: #111111;\n      font-size: 0.9rem;\n      cursor: pointer;\n      white-space: nowrap;\n    }\n    .clear-logo-btn:hover {\n      background-color: #e0ae00;\n    }\n\n    .mockup-preview {\n      position: relative;\n      border-radius: 1.5rem;\n      background-color: #F5F5F7;\n      padding: 1.5rem;\n      min-height: 220px;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      overflow: hidden;\n    }\n    .mockup-base {\n      max-width: 120%;\n      height: auto;\n      display: block;\n    }\n    .mockup-logo-wrap {\n      position: absolute;\n      top: 55%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      width: 30%;\n      pointer-events: auto;\n      cursor: move;\n      border: 2px solid transparent;\n      border-radius: 4px;\n      box-sizing: border-box;\n    }\n    .mockup-logo-wrap.is-dragging {\n      border-color: #2044A3;\n    }\n    .mockup-logo {\n      width: 100%;\n      height: auto;\n      object-fit: contain;\n      display: block;\n      filter: drop-shadow(0 1px 2px rgba(0,0,0,0.18));\n    }\n\n    .customize-step--quantity {\n      text-align: center;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n    }\n\n    .step-title-top {\n      font-size: 1rem;\n      font-weight: 700;\n      margin-bottom: 1.5rem;\n    }\n\n    .qty-min-text {\n      font-size: 0.85rem;\n      color: #6B7280;\n      margin-top: 0.25rem;\n    }\n\n    \/* === FORZAR ALINEACIÓN PERFECTA DE LA PÍLDORA DE CANTIDAD === *\/\n    .customize-order-section .qty-control {\n      display: inline-flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      border-radius: 9999px !important;\n      border: 1px solid #D4D4D8 !important;\n      overflow: hidden !important;\n      background-color: #ffffff !important;\n      padding: 0 !important;\n      line-height: 0 !important;\n    }\n\n    .customize-order-section .qty-btn {\n      display: inline-flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      width: 60px !important;\n      height: 46px !important;\n      background-color: #FFC800 !important;\n      border: none !important;\n      cursor: pointer !important;\n      color: #111111 !important;\n      font-size: 1.6rem !important;\n      line-height: 1 !important;\n      padding: 0 !important;\n      margin: 0 !important;\n      box-shadow: none !important;\n    }\n\n    .customize-order-section .qty-input {\n      width: 80px !important;\n      height: 46px !important;\n      border: none !important;\n      outline: none !important;\n      text-align: center !important;\n      font-size: 1rem !important;\n      color: #111111 !important;\n      background-color: #ffffff !important;\n      display: flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      padding: 0 !important;\n      margin: 0 !important;\n      box-sizing: border-box !important;\n      line-height: 1 !important;\n    }\n\n    .customize-order-section .qty-btn span,\n    .customize-order-section .qty-btn,\n    .customize-order-section .qty-control * {\n      line-height: 1 !important;\n    }\n\n    \/* BOTÓN WHATSAPP VERDE *\/\n    .customize-order-section .whatsapp-quote-btn {\n      margin-top: 1.25rem;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      align-self: center;\n      padding: 0.9rem 2.5rem;\n      border-radius: 9999px;\n      border: none;\n      background-color: #25D366 !important; \/* Verde WhatsApp *\/\n      color: #ffffff !important;\n      font-size: 1rem;\n      font-weight: 600;\n      cursor: pointer;\n      white-space: nowrap;\n      box-shadow: 0 8px 20px rgba(0,0,0,0.12);\n      gap: 0.5rem; \/* separa icono y texto *\/\n    }\n    .customize-order-section .whatsapp-quote-btn:hover {\n      background-color: #1eb259 !important;\n    }\n\n    \/* Círculo blanco para el ícono *\/\n    .customize-order-section .wa-icon-circle {\n      width: 22px;\n      height: 22px;\n      border-radius: 9999px;\n      background-color: #ffffff;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      overflow: hidden;\n      flex-shrink: 0;\n    }\n\n    \/* Imagen del ícono de WhatsApp *\/\n    .customize-order-section .wa-icon-img {\n      width: 16px;\n      height: 16px;\n      display: block;\n    }\n\n    .customize-order-section .wa-icon-phone,\n    .customize-order-section .wa-icon-phone::after {\n      display: none !important;\n    }\n\n    .customize-steps-row {\n      display: grid;\n      grid-template-columns: repeat(3, minmax(0, 1fr));\n      gap: 2rem;\n      margin-top: 1rem;\n      max-width: 1100px;\n      margin-left: auto;\n      margin-right: auto;\n    }\n    .customize-step-text {\n      text-align:center;\n      display:flex;\n      flex-direction:column;\n      align-items:center;\n    }\n    .step-circle {\n      width: 40px;\n      height: 40px;\n      border-radius: 9999px;\n      border: 2px solid #D4D4D8;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      margin: 0 auto 0.75rem auto;\n      font-weight: 600;\n      color: #111827;\n    }\n    .step-title {\n      font-size: 1rem;\n      font-weight: 700;\n      margin-bottom: 0.5rem;\n    }\n    .step-desc {\n      font-size: 0.875rem;\n      color: #6B7280;\n      line-height: 1.4;\n    }\n\n    @media (max-width: 900px) {\n      .customize-order-grid {\n        grid-template-columns: 1fr;\n      }\n      .customize-steps-row {\n        grid-template-columns: 1fr;\n      }\n      .customize-order-title {\n        text-align: center;\n      }\n      .customize-step--quantity {\n        text-align: center;\n        align-items: center;\n      }\n      .customize-order-section .whatsapp-quote-btn {\n        align-self: center;\n      }\n    }\n  \u003c\/style\u003e\n\n  \u003cscript\u003e\n    document.addEventListener('DOMContentLoaded', function() {\n      var fileInput       = document.getElementById('logo-upload-input');\n      var logoImg         = document.getElementById('mockup-logo-img');\n      var uploadPreview   = document.getElementById('upload-preview-img');\n      var clearBtn        = document.getElementById('clear-logo-btn');\n      var logoDataInput   = document.getElementById('logo-data-input');\n      var plusWrapper     = document.getElementById('upload-plus-wrapper');\n\n      var qtyInput  = document.getElementById('quote-quantity');\n      var qtyHidden = document.getElementById('quote-quantity-input');\n      var btnMinus  = document.getElementById('qty-minus');\n      var btnPlus   = document.getElementById('qty-plus');\n\n      var mockupPreview   = document.querySelector('.mockup-preview');\n      var mockupLogoWrap  = document.getElementById('mockup-logo-wrap');\n\n      if (fileInput \u0026\u0026 logoImg \u0026\u0026 logoDataInput) {\n        fileInput.addEventListener('change', function(event) {\n          var file = event.target.files[0];\n          if (!file) return;\n\n          var maxSizeMB = 2;\n          if (file.size \u003e maxSizeMB * 1024 * 1024) {\n            alert('La imagen es demasiado grande. Tamaño máximo: ' + maxSizeMB + ' MB');\n            fileInput.value = '';\n            return;\n          }\n\n          var reader = new FileReader();\n          reader.onload = function(e) {\n            var dataUrl = e.target.result;\n\n            logoImg.src = dataUrl;\n            logoImg.style.display = 'block';\n\n            if (uploadPreview) {\n              uploadPreview.src = dataUrl;\n              uploadPreview.style.display = 'block';\n            }\n\n            if (plusWrapper) plusWrapper.style.display = 'none';\n\n            logoDataInput.value = dataUrl;\n            clearBtn.style.display = 'inline-flex';\n\n            resetLogoPosition();\n          };\n          reader.readAsDataURL(file);\n        });\n\n        clearBtn.addEventListener('click', function() {\n          fileInput.value = '';\n\n          logoImg.src = '';\n          logoImg.style.display = 'none';\n\n          if (uploadPreview) {\n            uploadPreview.src = '';\n            uploadPreview.style.display = 'none';\n          }\n\n          if (plusWrapper) plusWrapper.style.display = 'flex';\n\n          logoDataInput.value = '';\n          clearBtn.style.display = 'none';\n\n          resetLogoPosition();\n        });\n      }\n\n      function resetLogoPosition() {\n        if (!mockupLogoWrap) return;\n        mockupLogoWrap.style.top = '55%';\n        mockupLogoWrap.style.left = '50%';\n        mockupLogoWrap.style.transform = 'translate(-50%, -50%)';\n        mockupLogoWrap.classList.remove('is-dragging');\n      }\n\n      if (mockupPreview \u0026\u0026 mockupLogoWrap) {\n        var isDragging = false;\n        var startX = 0;\n        var startY = 0;\n        var startLeft = 0;\n        var startTop = 0;\n\n        function getBounds() {\n          return mockupPreview.getBoundingClientRect();\n        }\n\n        function onPointerDown(e) {\n          if (!logoImg || logoImg.style.display === 'none') return;\n\n          isDragging = true;\n          mockupLogoWrap.classList.add('is-dragging');\n\n          var rect = getBounds();\n          var clientX = e.touches ? e.touches[0].clientX : e.clientX;\n          var clientY = e.touches ? e.touches[0].clientY : e.clientY;\n\n          startX = clientX;\n          startY = clientY;\n\n          var wrapRect = mockupLogoWrap.getBoundingClientRect();\n          startLeft = wrapRect.left - rect.left;\n          startTop  = wrapRect.top  - rect.top;\n\n          mockupLogoWrap.style.transform = 'none';\n\n          document.addEventListener('mousemove', onPointerMove);\n          document.addEventListener('mouseup', onPointerUp);\n          document.addEventListener('touchmove', onPointerMove, { passive: false });\n          document.addEventListener('touchend', onPointerUp);\n        }\n\n        function onPointerMove(e) {\n          if (!isDragging) return;\n          e.preventDefault();\n\n          var rect = getBounds();\n          var clientX = e.touches ? e.touches[0].clientX : e.clientX;\n          var clientY = e.touches ? e.touches[0].clientY : e.clientY;\n\n          var deltaX = clientX - startX;\n          var deltaY = clientY - startY;\n\n          var newLeft = startLeft + deltaX;\n          var newTop  = startTop + deltaY;\n\n          var wrapRect  = mockupLogoWrap.getBoundingClientRect();\n          var wrapWidth = wrapRect.width;\n          var wrapHeight = wrapRect.height;\n\n          var minLeft = 0;\n          var minTop  = 0;\n          var maxLeft = rect.width  - wrapWidth;\n          var maxTop  = rect.height - wrapHeight;\n\n          if (newLeft \u003c minLeft) newLeft = minLeft;\n          if (newTop  \u003c minTop)  newTop  = minTop;\n          if (newLeft \u003e maxLeft) newLeft = maxLeft;\n          if (newTop  \u003e maxTop)  newTop  = maxTop;\n\n          mockupLogoWrap.style.left = newLeft + 'px';\n          mockupLogoWrap.style.top  = newTop  + 'px';\n        }\n\n        function onPointerUp() {\n          if (!isDragging) return;\n          isDragging = false;\n          mockupLogoWrap.classList.remove('is-dragging');\n\n          document.removeEventListener('mousemove', onPointerMove);\n          document.removeEventListener('mouseup', onPointerUp);\n          document.removeEventListener('touchmove', onPointerMove);\n          document.removeEventListener('touchend', onPointerUp);\n        }\n\n        mockupLogoWrap.addEventListener('mousedown', onPointerDown);\n        mockupLogoWrap.addEventListener('touchstart', onPointerDown, { passive: true });\n      }\n\n      function sanitizeQty() {\n        if (!qtyInput || !qtyHidden) return;\n\n        var value = qtyInput.value.replace(\/[^0-9]\/g, '');\n        if (!value || Number(value) \u003c 1) {\n          value = '1';\n        }\n        qtyInput.value = value;\n        qtyHidden.value = value;\n      }\n\n      if (qtyInput \u0026\u0026 qtyHidden) {\n        qtyInput.addEventListener('change', sanitizeQty);\n        qtyInput.addEventListener('blur', sanitizeQty);\n      }\n\n      if (btnMinus \u0026\u0026 qtyInput) {\n        btnMinus.addEventListener('click', function() {\n          var current = Number(qtyInput.value || 1);\n          if (current \u003e 1) {\n            qtyInput.value = String(current - 1);\n            sanitizeQty();\n          }\n        });\n      }\n\n      if (btnPlus \u0026\u0026 qtyInput) {\n        btnPlus.addEventListener('click', function() {\n          var current = Number(qtyInput.value || 1);\n          qtyInput.value = String(current + 1);\n          sanitizeQty();\n        });\n      }\n\n      sanitizeQty();\n\n      \/* --- BOTÓN WHATSAPP --- *\/\n      var whatsappBtn    = document.getElementById('custom-whatsapp-btn');\n      var whatsappNumber = '525536684089'; \/\/ tu número sin + ni espacios\n\n      \/\/ EDITA ESTAS DOS LÍNEAS EN CADA PRODUCTO:\n      var productTitle   = \"Fajilla microcorrugada FAJ-1\";\n      var productUrl     = \"https:\/\/acesainter.com\/products\/fajilla-microcorrugada-faj-1?utm_source=copyToPasteBoard\u0026utm_medium=product-links\u0026utm_content=web\";\n\n      if (whatsappBtn \u0026\u0026 qtyHidden) {\n        whatsappBtn.addEventListener('click', function() {\n          var qty = parseInt(qtyHidden.value || '1', 10);\n          if (isNaN(qty) || qty \u003c 1) qty = 1;\n\n          var message =\n            \"Hola, quiero cotizar este producto personalizado con mi marca.%0A%0A\" +\n            \"Producto: \" + encodeURIComponent(productTitle) + \"%0A\" +\n            \"Cantidad: \" + encodeURIComponent(qty + \" cajas\") + \"%0A\" +\n            \"URL del producto: \" + encodeURIComponent(productUrl) + \"%0A%0A\" +\n            \"Por favor, confírmenme tiempos de producción, precios y opciones de personalización.\";\n\n          var waUrl = \"https:\/\/wa.me\/\" + whatsappNumber + \"?text=\" + message;\n          window.open(waUrl, \"_blank\");\n        });\n      }\n    });\n  \u003c\/script\u003e\n\u003c\/section\u003e\n","brand":"ACESA INTERABASTO S. A. de C.V.","offers":[{"title":"Default Title","offer_id":48147605225722,"sku":null,"price":10.0,"currency_code":"MXN","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/files\/34.jpg?v=1768505242"},{"product_id":"bolsa-kraft-dk-40c","title":"Bolsa kraft DK-40C para delivery y despensa 30 x 34 x 12 cm","description":"\u003cp\u003eLa \u003cstrong\u003ebolsa de papel kraft DK-40C\u003c\/strong\u003e es perfecta para \u003cstrong\u003eempaques de despensa, pedidos para llevar, alimentos, repostería o combos\u003c\/strong\u003e. Su material de \u003cstrong\u003epapel kraft natural\u003c\/strong\u003e ofrece una apariencia \u003cstrong\u003elimpia, ecológica y con estilo natural\u003c\/strong\u003e, ideal para marcas que buscan una imagen responsable.\u003c\/p\u003e\n\u003cp\u003eEs una bolsa \u003cstrong\u003eresistente y reciclable\u003c\/strong\u003e, adecuada para \u003cstrong\u003ecafeterías, restaurantes, abarrotes, tiendas de repostería y negocios de delivery\u003c\/strong\u003e. Sus medidas proporcionan buen espacio para varios productos:\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eMedidas:\u003c\/strong\u003e\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eAltura: \u003cstrong\u003e34 cm\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003cli\u003eAncho: \u003cstrong\u003e30 cm\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003cli\u003eFuelle (costado): \u003cstrong\u003e12 cm\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eCLAVE: \u003cstrong\u003eDK-40C\u003c\/strong\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eUso recomendado: delivery, despensa, alimentos, repostería, combos\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eMedidas: 30 cm (ancho) x 34 cm (alto) x 12 cm (fuelle)\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eMaterial: papel kraft natural\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eCaracterísticas: ecológica y reciclable\u003c\/p\u003e\n\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003csection class=\"customize-order-section\"\u003e\n  \u003cdiv class=\"customize-order-inner\"\u003e\n    \u003ch2 class=\"customize-order-title\"\u003ePersonaliza tu pedido\u003c\/h2\u003e\n\n    \u003cdiv class=\"customize-order-grid\"\u003e\n      \u003c!-- Columna 1: Subir logo --\u003e\n      \u003cdiv class=\"customize-step\"\u003e\n        \u003clabel for=\"logo-upload-input\" class=\"customize-upload-box\" id=\"upload-box-label\"\u003e\n          \u003cdiv class=\"upload-plus-wrapper\" id=\"upload-plus-wrapper\"\u003e\n            \u003cspan class=\"upload-icon\"\u003e+\u003c\/span\u003e\n          \u003c\/div\u003e\n\n          \u003cdiv class=\"upload-preview-wrapper\"\u003e\n            \u003cimg id=\"upload-preview-img\" src=\"\" alt=\"Vista previa de tu logo\" class=\"upload-preview-img\" style=\"display:none;\"\u003e\n          \u003c\/div\u003e\n        \u003c\/label\u003e\n\n        \u003cinput id=\"logo-upload-input\" type=\"file\" accept=\"image\/png,image\/jpeg,image\/jpg\" class=\"upload-input\"\u003e\n\n        \u003cbutton type=\"button\" id=\"clear-logo-btn\" class=\"clear-logo-btn\" style=\"display:none;\"\u003e\n          Borrar imagen\n        \u003c\/button\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Columna 2: Mockup --\u003e\n      \u003cdiv class=\"customize-step\"\u003e\n        \u003cdiv class=\"mockup-preview\"\u003e\n          \u003cimg src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/files\/BOLSA_KRAFT_DK-40C.png?v=1768528015\" alt=\"Vaso personalizado\" class=\"mockup-base\" width=\"800\" height=\"800\"\u003e\n\n          \u003cdiv class=\"mockup-logo-wrap\" id=\"mockup-logo-wrap\"\u003e\n            \u003cimg id=\"mockup-logo-img\" src=\"\" alt=\"Tu logotipo\" class=\"mockup-logo\" style=\"display:none;\" width=\"600\" height=\"600\"\u003e\n          \u003c\/div\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Columna 3: Cantidad + botón WhatsApp --\u003e\n      \u003cdiv class=\"customize-step customize-step--quantity\"\u003e\n        \u003ch3 class=\"step-title step-title-top\"\u003eCantidad de cajas para cotizar\u003c\/h3\u003e\n\n        \u003cdiv class=\"qty-block qty-block-top\"\u003e\n          \u003cdiv class=\"qty-control\"\u003e\n            \u003cbutton type=\"button\" class=\"qty-btn\" id=\"qty-minus\"\u003e−\u003c\/button\u003e\n            \u003cinput type=\"text\" id=\"quote-quantity\" class=\"qty-input\" value=\"1\" inputmode=\"numeric\" pattern=\"[0-9]*\"\u003e\n            \u003cbutton type=\"button\" class=\"qty-btn\" id=\"qty-plus\"\u003e+\u003c\/button\u003e\n          \u003c\/div\u003e\n          \u003cp class=\"qty-min-text\"\u003eTe cotizamos desde una caja\u003c\/p\u003e\n        \u003c\/div\u003e\n\n        \u003c!-- Botón WhatsApp verde con icono (imagen) --\u003e\n        \u003cbutton type=\"button\" id=\"custom-whatsapp-btn\" class=\"whatsapp-quote-btn\"\u003e\n          \u003cspan class=\"wa-icon-circle\"\u003e\n            \u003cimg src=\"https:\/\/upload.wikimedia.org\/wikipedia\/commons\/6\/6b\/WhatsApp.svg\" alt=\"WhatsApp\" class=\"wa-icon-img\"\u003e\n          \u003c\/span\u003e\n          \u003cspan\u003eCotizar Producto\u003c\/span\u003e\n        \u003c\/button\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Fila inferior de pasos --\u003e\n    \u003cdiv class=\"customize-steps-row\"\u003e\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e1\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eAgrega tu logo\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Solo se admiten imágenes en formato .png con fondo transparente. Tamaño máximo: 20 KB.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e2\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eVisualiza cómo se ve\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Esta es una representación digital del producto final. El resultado puede variar ligeramente en color, tamaño o proporciones.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e3\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eHaz tu pedido\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Puedes pedir desde una caja para imprimir tu logo en tu artículo, así de fácil.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Campos ocultos --\u003e\n    \u003cinput type=\"hidden\" id=\"logo-data-input\" name=\"properties[Logo personalizado]\" value=\"\"\u003e\n    \u003cinput type=\"hidden\" id=\"quote-quantity-input\" name=\"properties[Cantidad para cotización]\" value=\"1\"\u003e\n  \u003c\/div\u003e\n\n  \u003cstyle\u003e\n    .customize-order-section {\n      padding: 2.5rem 1.25rem;\n      background-color: #ffffff;\n    }\n    .customize-order-inner {\n      max-width: 1100px;\n      margin: 0 auto;\n    }\n    .customize-order-title {\n      font-size: 1.75rem;\n      font-weight: 700;\n      margin-bottom: 1.75rem;\n      text-align: left;\n      color: #2044A3;\n    }\n\n    .customize-order-grid {\n      display: grid;\n      grid-template-columns: repeat(3, minmax(0, 1fr));\n      gap: 3rem;\n      align-items: flex-start;\n      margin-bottom: 3rem;\n      justify-content: center;\n    }\n    .customize-step {\n      width: 100%;\n      max-width: 300px;\n      margin: 0 auto;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n    }\n\n    .customize-upload-box {\n      border: 2px dashed #D4D4D8;\n      border-radius: 1.5rem;\n      padding: 1.5rem;\n      min-height: 220px;\n      width: 100%;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n      justify-content: center;\n      position: relative;\n      cursor: pointer;\n      box-sizing: border-box;\n    }\n\n    .upload-plus-wrapper {\n      position: absolute;\n      top: 50%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      pointer-events: none;\n    }\n\n    .upload-icon {\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      width: 60px;\n      height: 60px;\n      border-radius: 9999px;\n      border: 2px solid #2044A3;\n      font-size: 1.85rem;\n      font-weight: 600;\n      color: #2044A3;\n      background: #ffffff;\n    }\n\n    .upload-input {\n      display: none;\n    }\n\n    .upload-preview-wrapper {\n      width: 100%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      min-height: 150px;\n    }\n    .upload-preview-img {\n      max-width: 100%;\n      max-height: 160px;\n      object-fit: contain;\n      display: block;\n    }\n\n    .clear-logo-btn {\n      margin-top: 0.75rem;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      align-self: center;\n      padding: 0.6rem 1.6rem;\n      border-radius: 9999px;\n      border: none;\n      background-color: #FFC800;\n      color: #111111;\n      font-size: 0.9rem;\n      cursor: pointer;\n      white-space: nowrap;\n    }\n    .clear-logo-btn:hover {\n      background-color: #e0ae00;\n    }\n\n    .mockup-preview {\n      position: relative;\n      border-radius: 1.5rem;\n      background-color: #F5F5F7;\n      padding: 1.5rem;\n      min-height: 220px;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      overflow: hidden;\n    }\n    .mockup-base {\n      max-width: 120%;\n      height: auto;\n      display: block;\n    }\n    .mockup-logo-wrap {\n      position: absolute;\n      top: 55%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      width: 45%;\n      pointer-events: auto;\n      cursor: move;\n      border: 2px solid transparent;\n      border-radius: 4px;\n      box-sizing: border-box;\n    }\n    .mockup-logo-wrap.is-dragging {\n      border-color: #2044A3;\n    }\n    .mockup-logo {\n      width: 100%;\n      height: auto;\n      object-fit: contain;\n      display: block;\n      filter: drop-shadow(0 1px 2px rgba(0,0,0,0.18));\n    }\n\n    .customize-step--quantity {\n      text-align: center;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n    }\n\n    .step-title-top {\n      font-size: 1rem;\n      font-weight: 700;\n      margin-bottom: 1.5rem;\n    }\n\n    .qty-min-text {\n      font-size: 0.85rem;\n      color: #6B7280;\n      margin-top: 0.25rem;\n    }\n\n    \/* === FORZAR ALINEACIÓN PERFECTA DE LA PÍLDORA DE CANTIDAD === *\/\n    .customize-order-section .qty-control {\n      display: inline-flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      border-radius: 9999px !important;\n      border: 1px solid #D4D4D8 !important;\n      overflow: hidden !important;\n      background-color: #ffffff !important;\n      padding: 0 !important;\n      line-height: 0 !important;\n    }\n\n    .customize-order-section .qty-btn {\n      display: inline-flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      width: 60px !important;\n      height: 46px !important;\n      background-color: #FFC800 !important;\n      border: none !important;\n      cursor: pointer !important;\n      color: #111111 !important;\n      font-size: 1.6rem !important;\n      line-height: 1 !important;\n      padding: 0 !important;\n      margin: 0 !important;\n      box-shadow: none !important;\n    }\n\n    .customize-order-section .qty-input {\n      width: 80px !important;\n      height: 46px !important;\n      border: none !important;\n      outline: none !important;\n      text-align: center !important;\n      font-size: 1rem !important;\n      color: #111111 !important;\n      background-color: #ffffff !important;\n      display: flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      padding: 0 !important;\n      margin: 0 !important;\n      box-sizing: border-box !important;\n      line-height: 1 !important;\n    }\n\n    .customize-order-section .qty-btn span,\n    .customize-order-section .qty-btn,\n    .customize-order-section .qty-control * {\n      line-height: 1 !important;\n    }\n\n    \/* BOTÓN WHATSAPP VERDE *\/\n    .customize-order-section .whatsapp-quote-btn {\n      margin-top: 1.25rem;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      align-self: center;\n      padding: 0.9rem 2.5rem;\n      border-radius: 9999px;\n      border: none;\n      background-color: #25D366 !important; \/* Verde WhatsApp *\/\n      color: #ffffff !important;\n      font-size: 1rem;\n      font-weight: 600;\n      cursor: pointer;\n      white-space: nowrap;\n      box-shadow: 0 8px 20px rgba(0,0,0,0.12);\n      gap: 0.5rem; \/* separa icono y texto *\/\n    }\n    .customize-order-section .whatsapp-quote-btn:hover {\n      background-color: #1eb259 !important;\n    }\n\n    \/* Círculo blanco para el ícono *\/\n    .customize-order-section .wa-icon-circle {\n      width: 22px;\n      height: 22px;\n      border-radius: 9999px;\n      background-color: #ffffff;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      overflow: hidden;\n      flex-shrink: 0;\n    }\n\n    \/* Imagen del ícono de WhatsApp *\/\n    .customize-order-section .wa-icon-img {\n      width: 16px;\n      height: 16px;\n      display: block;\n    }\n\n    .customize-order-section .wa-icon-phone,\n    .customize-order-section .wa-icon-phone::after {\n      display: none !important;\n    }\n\n    .customize-steps-row {\n      display: grid;\n      grid-template-columns: repeat(3, minmax(0, 1fr));\n      gap: 2rem;\n      margin-top: 1rem;\n      max-width: 1100px;\n      margin-left: auto;\n      margin-right: auto;\n    }\n    .customize-step-text {\n      text-align:center;\n      display:flex;\n      flex-direction:column;\n      align-items:center;\n    }\n    .step-circle {\n      width: 40px;\n      height: 40px;\n      border-radius: 9999px;\n      border: 2px solid #D4D4D8;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      margin: 0 auto 0.75rem auto;\n      font-weight: 600;\n      color: #111827;\n    }\n    .step-title {\n      font-size: 1rem;\n      font-weight: 700;\n      margin-bottom: 0.5rem;\n    }\n    .step-desc {\n      font-size: 0.875rem;\n      color: #6B7280;\n      line-height: 1.4;\n    }\n\n    @media (max-width: 900px) {\n      .customize-order-grid {\n        grid-template-columns: 1fr;\n      }\n      .customize-steps-row {\n        grid-template-columns: 1fr;\n      }\n      .customize-order-title {\n        text-align: center;\n      }\n      .customize-step--quantity {\n        text-align: center;\n        align-items: center;\n      }\n      .customize-order-section .whatsapp-quote-btn {\n        align-self: center;\n      }\n    }\n  \u003c\/style\u003e\n\n  \u003cscript\u003e\n    document.addEventListener('DOMContentLoaded', function() {\n      var fileInput       = document.getElementById('logo-upload-input');\n      var logoImg         = document.getElementById('mockup-logo-img');\n      var uploadPreview   = document.getElementById('upload-preview-img');\n      var clearBtn        = document.getElementById('clear-logo-btn');\n      var logoDataInput   = document.getElementById('logo-data-input');\n      var plusWrapper     = document.getElementById('upload-plus-wrapper');\n\n      var qtyInput  = document.getElementById('quote-quantity');\n      var qtyHidden = document.getElementById('quote-quantity-input');\n      var btnMinus  = document.getElementById('qty-minus');\n      var btnPlus   = document.getElementById('qty-plus');\n\n      var mockupPreview   = document.querySelector('.mockup-preview');\n      var mockupLogoWrap  = document.getElementById('mockup-logo-wrap');\n\n      if (fileInput \u0026\u0026 logoImg \u0026\u0026 logoDataInput) {\n        fileInput.addEventListener('change', function(event) {\n          var file = event.target.files[0];\n          if (!file) return;\n\n          var maxSizeMB = 2;\n          if (file.size \u003e maxSizeMB * 1024 * 1024) {\n            alert('La imagen es demasiado grande. Tamaño máximo: ' + maxSizeMB + ' MB');\n            fileInput.value = '';\n            return;\n          }\n\n          var reader = new FileReader();\n          reader.onload = function(e) {\n            var dataUrl = e.target.result;\n\n            logoImg.src = dataUrl;\n            logoImg.style.display = 'block';\n\n            if (uploadPreview) {\n              uploadPreview.src = dataUrl;\n              uploadPreview.style.display = 'block';\n            }\n\n            if (plusWrapper) plusWrapper.style.display = 'none';\n\n            logoDataInput.value = dataUrl;\n            clearBtn.style.display = 'inline-flex';\n\n            resetLogoPosition();\n          };\n          reader.readAsDataURL(file);\n        });\n\n        clearBtn.addEventListener('click', function() {\n          fileInput.value = '';\n\n          logoImg.src = '';\n          logoImg.style.display = 'none';\n\n          if (uploadPreview) {\n            uploadPreview.src = '';\n            uploadPreview.style.display = 'none';\n          }\n\n          if (plusWrapper) plusWrapper.style.display = 'flex';\n\n          logoDataInput.value = '';\n          clearBtn.style.display = 'none';\n\n          resetLogoPosition();\n        });\n      }\n\n      function resetLogoPosition() {\n        if (!mockupLogoWrap) return;\n        mockupLogoWrap.style.top = '55%';\n        mockupLogoWrap.style.left = '50%';\n        mockupLogoWrap.style.transform = 'translate(-50%, -50%)';\n        mockupLogoWrap.classList.remove('is-dragging');\n      }\n\n      if (mockupPreview \u0026\u0026 mockupLogoWrap) {\n        var isDragging = false;\n        var startX = 0;\n        var startY = 0;\n        var startLeft = 0;\n        var startTop = 0;\n\n        function getBounds() {\n          return mockupPreview.getBoundingClientRect();\n        }\n\n        function onPointerDown(e) {\n          if (!logoImg || logoImg.style.display === 'none') return;\n\n          isDragging = true;\n          mockupLogoWrap.classList.add('is-dragging');\n\n          var rect = getBounds();\n          var clientX = e.touches ? e.touches[0].clientX : e.clientX;\n          var clientY = e.touches ? e.touches[0].clientY : e.clientY;\n\n          startX = clientX;\n          startY = clientY;\n\n          var wrapRect = mockupLogoWrap.getBoundingClientRect();\n          startLeft = wrapRect.left - rect.left;\n          startTop  = wrapRect.top  - rect.top;\n\n          mockupLogoWrap.style.transform = 'none';\n\n          document.addEventListener('mousemove', onPointerMove);\n          document.addEventListener('mouseup', onPointerUp);\n          document.addEventListener('touchmove', onPointerMove, { passive: false });\n          document.addEventListener('touchend', onPointerUp);\n        }\n\n        function onPointerMove(e) {\n          if (!isDragging) return;\n          e.preventDefault();\n\n          var rect = getBounds();\n          var clientX = e.touches ? e.touches[0].clientX : e.clientX;\n          var clientY = e.touches ? e.touches[0].clientY : e.clientY;\n\n          var deltaX = clientX - startX;\n          var deltaY = clientY - startY;\n\n          var newLeft = startLeft + deltaX;\n          var newTop  = startTop + deltaY;\n\n          var wrapRect  = mockupLogoWrap.getBoundingClientRect();\n          var wrapWidth = wrapRect.width;\n          var wrapHeight = wrapRect.height;\n\n          var minLeft = 0;\n          var minTop  = 0;\n          var maxLeft = rect.width  - wrapWidth;\n          var maxTop  = rect.height - wrapHeight;\n\n          if (newLeft \u003c minLeft) newLeft = minLeft;\n          if (newTop  \u003c minTop)  newTop  = minTop;\n          if (newLeft \u003e maxLeft) newLeft = maxLeft;\n          if (newTop  \u003e maxTop)  newTop  = maxTop;\n\n          mockupLogoWrap.style.left = newLeft + 'px';\n          mockupLogoWrap.style.top  = newTop  + 'px';\n        }\n\n        function onPointerUp() {\n          if (!isDragging) return;\n          isDragging = false;\n          mockupLogoWrap.classList.remove('is-dragging');\n\n          document.removeEventListener('mousemove', onPointerMove);\n          document.removeEventListener('mouseup', onPointerUp);\n          document.removeEventListener('touchmove', onPointerMove);\n          document.removeEventListener('touchend', onPointerUp);\n        }\n\n        mockupLogoWrap.addEventListener('mousedown', onPointerDown);\n        mockupLogoWrap.addEventListener('touchstart', onPointerDown, { passive: true });\n      }\n\n      function sanitizeQty() {\n        if (!qtyInput || !qtyHidden) return;\n\n        var value = qtyInput.value.replace(\/[^0-9]\/g, '');\n        if (!value || Number(value) \u003c 1) {\n          value = '1';\n        }\n        qtyInput.value = value;\n        qtyHidden.value = value;\n      }\n\n      if (qtyInput \u0026\u0026 qtyHidden) {\n        qtyInput.addEventListener('change', sanitizeQty);\n        qtyInput.addEventListener('blur', sanitizeQty);\n      }\n\n      if (btnMinus \u0026\u0026 qtyInput) {\n        btnMinus.addEventListener('click', function() {\n          var current = Number(qtyInput.value || 1);\n          if (current \u003e 1) {\n            qtyInput.value = String(current - 1);\n            sanitizeQty();\n          }\n        });\n      }\n\n      if (btnPlus \u0026\u0026 qtyInput) {\n        btnPlus.addEventListener('click', function() {\n          var current = Number(qtyInput.value || 1);\n          qtyInput.value = String(current + 1);\n          sanitizeQty();\n        });\n      }\n\n      sanitizeQty();\n\n      \/* --- BOTÓN WHATSAPP --- *\/\n      var whatsappBtn    = document.getElementById('custom-whatsapp-btn');\n      var whatsappNumber = '525536684089'; \/\/ tu número sin + ni espacios\n\n      \/\/ EDITA ESTAS DOS LÍNEAS EN CADA PRODUCTO:\n      var productTitle   = \"Bolsa kraft DK-40C\";\n      var productUrl     = \"https:\/\/acesainter.com\/products\/bolsa-kraft-dk-40c?utm_source=copyToPasteBoard\u0026utm_medium=product-links\u0026utm_content=web\";\n\n      if (whatsappBtn \u0026\u0026 qtyHidden) {\n        whatsappBtn.addEventListener('click', function() {\n          var qty = parseInt(qtyHidden.value || '1', 10);\n          if (isNaN(qty) || qty \u003c 1) qty = 1;\n\n          var message =\n            \"Hola, quiero cotizar este producto personalizado con mi marca.%0A%0A\" +\n            \"Producto: \" + encodeURIComponent(productTitle) + \"%0A\" +\n            \"Cantidad: \" + encodeURIComponent(qty + \" cajas\") + \"%0A\" +\n            \"URL del producto: \" + encodeURIComponent(productUrl) + \"%0A%0A\" +\n            \"Por favor, confírmenme tiempos de producción, precios y opciones de personalización.\";\n\n          var waUrl = \"https:\/\/wa.me\/\" + whatsappNumber + \"?text=\" + message;\n          window.open(waUrl, \"_blank\");\n        });\n      }\n    });\n  \u003c\/script\u003e\n\u003c\/section\u003e\n","brand":"ACESA INTERABASTO S. A. de C.V.","offers":[{"title":"Default Title","offer_id":48147606012154,"sku":null,"price":10.0,"currency_code":"MXN","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/files\/35.jpg?v=1768505261"},{"product_id":"bolsa-kraft-dk20","title":"Bolsa kraft DK20 para delivery y alimentos 21 x 40 x 12 cm","description":"\u003cp\u003eLa \u003cstrong\u003ebolsa de papel kraft DK20\u003c\/strong\u003e es ideal para \u003cstrong\u003eempaques de despensa, pedidos para llevar, alimentos, repostería o combos individuales\u003c\/strong\u003e. Su diseño en \u003cstrong\u003epapel kraft natural\u003c\/strong\u003e brinda una imagen \u003cstrong\u003eecológica y sobria\u003c\/strong\u003e, apropiada para negocios que cuidan su presentación.\u003c\/p\u003e\n\u003cp\u003eEs \u003cstrong\u003eresistente, reciclable y con estilo natural\u003c\/strong\u003e, perfecta para \u003cstrong\u003ecafeterías, restaurantes, abarrotes, panaderías y negocios de delivery\u003c\/strong\u003e. Sus proporciones son altas y angostas, útiles para envases, cajas pequeñas o postres:\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eMedidas:\u003c\/strong\u003e\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eAltura: \u003cstrong\u003e40 cm\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003cli\u003eAncho: \u003cstrong\u003e21 cm\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003cli\u003eFuelle: \u003cstrong\u003e12 cm\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eCLAVE: \u003cstrong\u003eDK20\u003c\/strong\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eUso recomendado: pedidos para llevar, alimentos, repostería, despensa ligera\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eMedidas: 21 cm (ancho) x 40 cm (alto) x 12 cm (fuelle)\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eMaterial: papel kraft natural\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eCaracterísticas: ecológica y reciclable\u003c\/p\u003e\n\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003csection class=\"customize-order-section\"\u003e\n  \u003cdiv class=\"customize-order-inner\"\u003e\n    \u003ch2 class=\"customize-order-title\"\u003ePersonaliza tu pedido\u003c\/h2\u003e\n\n    \u003cdiv class=\"customize-order-grid\"\u003e\n      \u003c!-- Columna 1: Subir logo --\u003e\n      \u003cdiv class=\"customize-step\"\u003e\n        \u003clabel for=\"logo-upload-input\" class=\"customize-upload-box\" id=\"upload-box-label\"\u003e\n          \u003cdiv class=\"upload-plus-wrapper\" id=\"upload-plus-wrapper\"\u003e\n            \u003cspan class=\"upload-icon\"\u003e+\u003c\/span\u003e\n          \u003c\/div\u003e\n\n          \u003cdiv class=\"upload-preview-wrapper\"\u003e\n            \u003cimg id=\"upload-preview-img\" src=\"\" alt=\"Vista previa de tu logo\" class=\"upload-preview-img\" style=\"display:none;\"\u003e\n          \u003c\/div\u003e\n        \u003c\/label\u003e\n\n        \u003cinput id=\"logo-upload-input\" type=\"file\" accept=\"image\/png,image\/jpeg,image\/jpg\" class=\"upload-input\"\u003e\n\n        \u003cbutton type=\"button\" id=\"clear-logo-btn\" class=\"clear-logo-btn\" style=\"display:none;\"\u003e\n          Borrar imagen\n        \u003c\/button\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Columna 2: Mockup --\u003e\n      \u003cdiv class=\"customize-step\"\u003e\n        \u003cdiv class=\"mockup-preview\"\u003e\n          \u003cimg src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/files\/BOLSA_KRAFT_DK-20.png?v=1768528015\" alt=\"Vaso personalizado\" class=\"mockup-base\" width=\"800\" height=\"800\"\u003e\n\n          \u003cdiv class=\"mockup-logo-wrap\" id=\"mockup-logo-wrap\"\u003e\n            \u003cimg id=\"mockup-logo-img\" src=\"\" alt=\"Tu logotipo\" class=\"mockup-logo\" style=\"display:none;\" width=\"600\" height=\"600\"\u003e\n          \u003c\/div\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Columna 3: Cantidad + botón WhatsApp --\u003e\n      \u003cdiv class=\"customize-step customize-step--quantity\"\u003e\n        \u003ch3 class=\"step-title step-title-top\"\u003eCantidad de cajas para cotizar\u003c\/h3\u003e\n\n        \u003cdiv class=\"qty-block qty-block-top\"\u003e\n          \u003cdiv class=\"qty-control\"\u003e\n            \u003cbutton type=\"button\" class=\"qty-btn\" id=\"qty-minus\"\u003e−\u003c\/button\u003e\n            \u003cinput type=\"text\" id=\"quote-quantity\" class=\"qty-input\" value=\"1\" inputmode=\"numeric\" pattern=\"[0-9]*\"\u003e\n            \u003cbutton type=\"button\" class=\"qty-btn\" id=\"qty-plus\"\u003e+\u003c\/button\u003e\n          \u003c\/div\u003e\n          \u003cp class=\"qty-min-text\"\u003eTe cotizamos desde una caja\u003c\/p\u003e\n        \u003c\/div\u003e\n\n        \u003c!-- Botón WhatsApp verde con icono (imagen) --\u003e\n        \u003cbutton type=\"button\" id=\"custom-whatsapp-btn\" class=\"whatsapp-quote-btn\"\u003e\n          \u003cspan class=\"wa-icon-circle\"\u003e\n            \u003cimg src=\"https:\/\/upload.wikimedia.org\/wikipedia\/commons\/6\/6b\/WhatsApp.svg\" alt=\"WhatsApp\" class=\"wa-icon-img\"\u003e\n          \u003c\/span\u003e\n          \u003cspan\u003eCotizar Producto\u003c\/span\u003e\n        \u003c\/button\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Fila inferior de pasos --\u003e\n    \u003cdiv class=\"customize-steps-row\"\u003e\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e1\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eAgrega tu logo\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Solo se admiten imágenes en formato .png con fondo transparente. Tamaño máximo: 20 KB.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e2\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eVisualiza cómo se ve\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Esta es una representación digital del producto final. El resultado puede variar ligeramente en color, tamaño o proporciones.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e3\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eHaz tu pedido\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Puedes pedir desde una caja para imprimir tu logo en tu artículo, así de fácil.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Campos ocultos --\u003e\n    \u003cinput type=\"hidden\" id=\"logo-data-input\" name=\"properties[Logo personalizado]\" value=\"\"\u003e\n    \u003cinput type=\"hidden\" id=\"quote-quantity-input\" name=\"properties[Cantidad para cotización]\" value=\"1\"\u003e\n  \u003c\/div\u003e\n\n  \u003cstyle\u003e\n    .customize-order-section {\n      padding: 2.5rem 1.25rem;\n      background-color: #ffffff;\n    }\n    .customize-order-inner {\n      max-width: 1100px;\n      margin: 0 auto;\n    }\n    .customize-order-title {\n      font-size: 1.75rem;\n      font-weight: 700;\n      margin-bottom: 1.75rem;\n      text-align: left;\n      color: #2044A3;\n    }\n\n    .customize-order-grid {\n      display: grid;\n      grid-template-columns: repeat(3, minmax(0, 1fr));\n      gap: 3rem;\n      align-items: flex-start;\n      margin-bottom: 3rem;\n      justify-content: center;\n    }\n    .customize-step {\n      width: 100%;\n      max-width: 300px;\n      margin: 0 auto;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n    }\n\n    .customize-upload-box {\n      border: 2px dashed #D4D4D8;\n      border-radius: 1.5rem;\n      padding: 1.5rem;\n      min-height: 220px;\n      width: 100%;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n      justify-content: center;\n      position: relative;\n      cursor: pointer;\n      box-sizing: border-box;\n    }\n\n    .upload-plus-wrapper {\n      position: absolute;\n      top: 50%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      pointer-events: none;\n    }\n\n    .upload-icon {\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      width: 60px;\n      height: 60px;\n      border-radius: 9999px;\n      border: 2px solid #2044A3;\n      font-size: 1.85rem;\n      font-weight: 600;\n      color: #2044A3;\n      background: #ffffff;\n    }\n\n    .upload-input {\n      display: none;\n    }\n\n    .upload-preview-wrapper {\n      width: 100%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      min-height: 150px;\n    }\n    .upload-preview-img {\n      max-width: 100%;\n      max-height: 160px;\n      object-fit: contain;\n      display: block;\n    }\n\n    .clear-logo-btn {\n      margin-top: 0.75rem;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      align-self: center;\n      padding: 0.6rem 1.6rem;\n      border-radius: 9999px;\n      border: none;\n      background-color: #FFC800;\n      color: #111111;\n      font-size: 0.9rem;\n      cursor: pointer;\n      white-space: nowrap;\n    }\n    .clear-logo-btn:hover {\n      background-color: #e0ae00;\n    }\n\n    .mockup-preview {\n      position: relative;\n      border-radius: 1.5rem;\n      background-color: #F5F5F7;\n      padding: 1.5rem;\n      min-height: 220px;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      overflow: hidden;\n    }\n    .mockup-base {\n      max-width: 120%;\n      height: auto;\n      display: block;\n    }\n    .mockup-logo-wrap {\n      position: absolute;\n      top: 55%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      width: 40%;\n      pointer-events: auto;\n      cursor: move;\n      border: 2px solid transparent;\n      border-radius: 4px;\n      box-sizing: border-box;\n    }\n    .mockup-logo-wrap.is-dragging {\n      border-color: #2044A3;\n    }\n    .mockup-logo {\n      width: 100%;\n      height: auto;\n      object-fit: contain;\n      display: block;\n      filter: drop-shadow(0 1px 2px rgba(0,0,0,0.18));\n    }\n\n    .customize-step--quantity {\n      text-align: center;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n    }\n\n    .step-title-top {\n      font-size: 1rem;\n      font-weight: 700;\n      margin-bottom: 1.5rem;\n    }\n\n    .qty-min-text {\n      font-size: 0.85rem;\n      color: #6B7280;\n      margin-top: 0.25rem;\n    }\n\n    \/* === FORZAR ALINEACIÓN PERFECTA DE LA PÍLDORA DE CANTIDAD === *\/\n    .customize-order-section .qty-control {\n      display: inline-flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      border-radius: 9999px !important;\n      border: 1px solid #D4D4D8 !important;\n      overflow: hidden !important;\n      background-color: #ffffff !important;\n      padding: 0 !important;\n      line-height: 0 !important;\n    }\n\n    .customize-order-section .qty-btn {\n      display: inline-flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      width: 60px !important;\n      height: 46px !important;\n      background-color: #FFC800 !important;\n      border: none !important;\n      cursor: pointer !important;\n      color: #111111 !important;\n      font-size: 1.6rem !important;\n      line-height: 1 !important;\n      padding: 0 !important;\n      margin: 0 !important;\n      box-shadow: none !important;\n    }\n\n    .customize-order-section .qty-input {\n      width: 80px !important;\n      height: 46px !important;\n      border: none !important;\n      outline: none !important;\n      text-align: center !important;\n      font-size: 1rem !important;\n      color: #111111 !important;\n      background-color: #ffffff !important;\n      display: flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      padding: 0 !important;\n      margin: 0 !important;\n      box-sizing: border-box !important;\n      line-height: 1 !important;\n    }\n\n    .customize-order-section .qty-btn span,\n    .customize-order-section .qty-btn,\n    .customize-order-section .qty-control * {\n      line-height: 1 !important;\n    }\n\n    \/* BOTÓN WHATSAPP VERDE *\/\n    .customize-order-section .whatsapp-quote-btn {\n      margin-top: 1.25rem;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      align-self: center;\n      padding: 0.9rem 2.5rem;\n      border-radius: 9999px;\n      border: none;\n      background-color: #25D366 !important; \/* Verde WhatsApp *\/\n      color: #ffffff !important;\n      font-size: 1rem;\n      font-weight: 600;\n      cursor: pointer;\n      white-space: nowrap;\n      box-shadow: 0 8px 20px rgba(0,0,0,0.12);\n      gap: 0.5rem; \/* separa icono y texto *\/\n    }\n    .customize-order-section .whatsapp-quote-btn:hover {\n      background-color: #1eb259 !important;\n    }\n\n    \/* Círculo blanco para el ícono *\/\n    .customize-order-section .wa-icon-circle {\n      width: 22px;\n      height: 22px;\n      border-radius: 9999px;\n      background-color: #ffffff;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      overflow: hidden;\n      flex-shrink: 0;\n    }\n\n    \/* Imagen del ícono de WhatsApp *\/\n    .customize-order-section .wa-icon-img {\n      width: 16px;\n      height: 16px;\n      display: block;\n    }\n\n    .customize-order-section .wa-icon-phone,\n    .customize-order-section .wa-icon-phone::after {\n      display: none !important;\n    }\n\n    .customize-steps-row {\n      display: grid;\n      grid-template-columns: repeat(3, minmax(0, 1fr));\n      gap: 2rem;\n      margin-top: 1rem;\n      max-width: 1100px;\n      margin-left: auto;\n      margin-right: auto;\n    }\n    .customize-step-text {\n      text-align:center;\n      display:flex;\n      flex-direction:column;\n      align-items:center;\n    }\n    .step-circle {\n      width: 40px;\n      height: 40px;\n      border-radius: 9999px;\n      border: 2px solid #D4D4D8;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      margin: 0 auto 0.75rem auto;\n      font-weight: 600;\n      color: #111827;\n    }\n    .step-title {\n      font-size: 1rem;\n      font-weight: 700;\n      margin-bottom: 0.5rem;\n    }\n    .step-desc {\n      font-size: 0.875rem;\n      color: #6B7280;\n      line-height: 1.4;\n    }\n\n    @media (max-width: 900px) {\n      .customize-order-grid {\n        grid-template-columns: 1fr;\n      }\n      .customize-steps-row {\n        grid-template-columns: 1fr;\n      }\n      .customize-order-title {\n        text-align: center;\n      }\n      .customize-step--quantity {\n        text-align: center;\n        align-items: center;\n      }\n      .customize-order-section .whatsapp-quote-btn {\n        align-self: center;\n      }\n    }\n  \u003c\/style\u003e\n\n  \u003cscript\u003e\n    document.addEventListener('DOMContentLoaded', function() {\n      var fileInput       = document.getElementById('logo-upload-input');\n      var logoImg         = document.getElementById('mockup-logo-img');\n      var uploadPreview   = document.getElementById('upload-preview-img');\n      var clearBtn        = document.getElementById('clear-logo-btn');\n      var logoDataInput   = document.getElementById('logo-data-input');\n      var plusWrapper     = document.getElementById('upload-plus-wrapper');\n\n      var qtyInput  = document.getElementById('quote-quantity');\n      var qtyHidden = document.getElementById('quote-quantity-input');\n      var btnMinus  = document.getElementById('qty-minus');\n      var btnPlus   = document.getElementById('qty-plus');\n\n      var mockupPreview   = document.querySelector('.mockup-preview');\n      var mockupLogoWrap  = document.getElementById('mockup-logo-wrap');\n\n      if (fileInput \u0026\u0026 logoImg \u0026\u0026 logoDataInput) {\n        fileInput.addEventListener('change', function(event) {\n          var file = event.target.files[0];\n          if (!file) return;\n\n          var maxSizeMB = 2;\n          if (file.size \u003e maxSizeMB * 1024 * 1024) {\n            alert('La imagen es demasiado grande. Tamaño máximo: ' + maxSizeMB + ' MB');\n            fileInput.value = '';\n            return;\n          }\n\n          var reader = new FileReader();\n          reader.onload = function(e) {\n            var dataUrl = e.target.result;\n\n            logoImg.src = dataUrl;\n            logoImg.style.display = 'block';\n\n            if (uploadPreview) {\n              uploadPreview.src = dataUrl;\n              uploadPreview.style.display = 'block';\n            }\n\n            if (plusWrapper) plusWrapper.style.display = 'none';\n\n            logoDataInput.value = dataUrl;\n            clearBtn.style.display = 'inline-flex';\n\n            resetLogoPosition();\n          };\n          reader.readAsDataURL(file);\n        });\n\n        clearBtn.addEventListener('click', function() {\n          fileInput.value = '';\n\n          logoImg.src = '';\n          logoImg.style.display = 'none';\n\n          if (uploadPreview) {\n            uploadPreview.src = '';\n            uploadPreview.style.display = 'none';\n          }\n\n          if (plusWrapper) plusWrapper.style.display = 'flex';\n\n          logoDataInput.value = '';\n          clearBtn.style.display = 'none';\n\n          resetLogoPosition();\n        });\n      }\n\n      function resetLogoPosition() {\n        if (!mockupLogoWrap) return;\n        mockupLogoWrap.style.top = '55%';\n        mockupLogoWrap.style.left = '50%';\n        mockupLogoWrap.style.transform = 'translate(-50%, -50%)';\n        mockupLogoWrap.classList.remove('is-dragging');\n      }\n\n      if (mockupPreview \u0026\u0026 mockupLogoWrap) {\n        var isDragging = false;\n        var startX = 0;\n        var startY = 0;\n        var startLeft = 0;\n        var startTop = 0;\n\n        function getBounds() {\n          return mockupPreview.getBoundingClientRect();\n        }\n\n        function onPointerDown(e) {\n          if (!logoImg || logoImg.style.display === 'none') return;\n\n          isDragging = true;\n          mockupLogoWrap.classList.add('is-dragging');\n\n          var rect = getBounds();\n          var clientX = e.touches ? e.touches[0].clientX : e.clientX;\n          var clientY = e.touches ? e.touches[0].clientY : e.clientY;\n\n          startX = clientX;\n          startY = clientY;\n\n          var wrapRect = mockupLogoWrap.getBoundingClientRect();\n          startLeft = wrapRect.left - rect.left;\n          startTop  = wrapRect.top  - rect.top;\n\n          mockupLogoWrap.style.transform = 'none';\n\n          document.addEventListener('mousemove', onPointerMove);\n          document.addEventListener('mouseup', onPointerUp);\n          document.addEventListener('touchmove', onPointerMove, { passive: false });\n          document.addEventListener('touchend', onPointerUp);\n        }\n\n        function onPointerMove(e) {\n          if (!isDragging) return;\n          e.preventDefault();\n\n          var rect = getBounds();\n          var clientX = e.touches ? e.touches[0].clientX : e.clientX;\n          var clientY = e.touches ? e.touches[0].clientY : e.clientY;\n\n          var deltaX = clientX - startX;\n          var deltaY = clientY - startY;\n\n          var newLeft = startLeft + deltaX;\n          var newTop  = startTop + deltaY;\n\n          var wrapRect  = mockupLogoWrap.getBoundingClientRect();\n          var wrapWidth = wrapRect.width;\n          var wrapHeight = wrapRect.height;\n\n          var minLeft = 0;\n          var minTop  = 0;\n          var maxLeft = rect.width  - wrapWidth;\n          var maxTop  = rect.height - wrapHeight;\n\n          if (newLeft \u003c minLeft) newLeft = minLeft;\n          if (newTop  \u003c minTop)  newTop  = minTop;\n          if (newLeft \u003e maxLeft) newLeft = maxLeft;\n          if (newTop  \u003e maxTop)  newTop  = maxTop;\n\n          mockupLogoWrap.style.left = newLeft + 'px';\n          mockupLogoWrap.style.top  = newTop  + 'px';\n        }\n\n        function onPointerUp() {\n          if (!isDragging) return;\n          isDragging = false;\n          mockupLogoWrap.classList.remove('is-dragging');\n\n          document.removeEventListener('mousemove', onPointerMove);\n          document.removeEventListener('mouseup', onPointerUp);\n          document.removeEventListener('touchmove', onPointerMove);\n          document.removeEventListener('touchend', onPointerUp);\n        }\n\n        mockupLogoWrap.addEventListener('mousedown', onPointerDown);\n        mockupLogoWrap.addEventListener('touchstart', onPointerDown, { passive: true });\n      }\n\n      function sanitizeQty() {\n        if (!qtyInput || !qtyHidden) return;\n\n        var value = qtyInput.value.replace(\/[^0-9]\/g, '');\n        if (!value || Number(value) \u003c 1) {\n          value = '1';\n        }\n        qtyInput.value = value;\n        qtyHidden.value = value;\n      }\n\n      if (qtyInput \u0026\u0026 qtyHidden) {\n        qtyInput.addEventListener('change', sanitizeQty);\n        qtyInput.addEventListener('blur', sanitizeQty);\n      }\n\n      if (btnMinus \u0026\u0026 qtyInput) {\n        btnMinus.addEventListener('click', function() {\n          var current = Number(qtyInput.value || 1);\n          if (current \u003e 1) {\n            qtyInput.value = String(current - 1);\n            sanitizeQty();\n          }\n        });\n      }\n\n      if (btnPlus \u0026\u0026 qtyInput) {\n        btnPlus.addEventListener('click', function() {\n          var current = Number(qtyInput.value || 1);\n          qtyInput.value = String(current + 1);\n          sanitizeQty();\n        });\n      }\n\n      sanitizeQty();\n\n      \/* --- BOTÓN WHATSAPP --- *\/\n      var whatsappBtn    = document.getElementById('custom-whatsapp-btn');\n      var whatsappNumber = '525536684089'; \/\/ tu número sin + ni espacios\n\n      \/\/ EDITA ESTAS DOS LÍNEAS EN CADA PRODUCTO:\n      var productTitle   = \"Bolsa kraft DK20\";\n      var productUrl     = \"https:\/\/acesainter.com\/products\/bolsa-kraft-dk20?utm_source=copyToPasteBoard\u0026utm_medium=product-links\u0026utm_content=web\";\n\n      if (whatsappBtn \u0026\u0026 qtyHidden) {\n        whatsappBtn.addEventListener('click', function() {\n          var qty = parseInt(qtyHidden.value || '1', 10);\n          if (isNaN(qty) || qty \u003c 1) qty = 1;\n\n          var message =\n            \"Hola, quiero cotizar este producto personalizado con mi marca.%0A%0A\" +\n            \"Producto: \" + encodeURIComponent(productTitle) + \"%0A\" +\n            \"Cantidad: \" + encodeURIComponent(qty + \" cajas\") + \"%0A\" +\n            \"URL del producto: \" + encodeURIComponent(productUrl) + \"%0A%0A\" +\n            \"Por favor, confírmenme tiempos de producción, precios y opciones de personalización.\";\n\n          var waUrl = \"https:\/\/wa.me\/\" + whatsappNumber + \"?text=\" + message;\n          window.open(waUrl, \"_blank\");\n        });\n      }\n    });\n  \u003c\/script\u003e\n\u003c\/section\u003e\n","brand":"ACESA INTERABASTO S. A. de C.V.","offers":[{"title":"Default Title","offer_id":48147607519482,"sku":null,"price":10.0,"currency_code":"MXN","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/files\/36.jpg?v=1768505278"},{"product_id":"bolsa-kraft-dk-45","title":"Bolsa kraft DK-45 grande para delivery y despensa 30 x 48 x 15 cm","description":"\u003cp\u003eLa \u003cstrong\u003ebolsa de papel kraft DK-45\u003c\/strong\u003e es una opción \u003cstrong\u003ede gran tamaño\u003c\/strong\u003e, ideal para \u003cstrong\u003eempaques de despensa, pedidos para llevar, alimentos, repostería, combos grandes o múltiples productos\u003c\/strong\u003e. Su \u003cstrong\u003epapel kraft natural\u003c\/strong\u003e ofrece un estilo \u003cstrong\u003eecológico y profesional\u003c\/strong\u003e, muy apreciado por los clientes.\u003c\/p\u003e\n\u003cp\u003eEs \u003cstrong\u003eresistente, ecológica y reciclable\u003c\/strong\u003e, perfecta para \u003cstrong\u003ecafeterías, restaurantes, abarrotes, supermercados pequeños y negocios de delivery\u003c\/strong\u003e que necesitan transportar cargas más voluminosas:\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eMedidas:\u003c\/strong\u003e\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eAltura: \u003cstrong\u003e48 cm\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003cli\u003eAncho: \u003cstrong\u003e30 cm\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003cli\u003eFuelle: \u003cstrong\u003e15 cm\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eCLAVE: \u003cstrong\u003eDK-45\u003c\/strong\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eUso recomendado: despensa, combos grandes, pedidos familiares, delivery\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eMedidas: 30 cm (ancho) x 48 cm (alto) x 15 cm (fuelle)\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eMaterial: papel kraft natural\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eCaracterísticas: ecológica y reciclable\u003c\/p\u003e\n\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003csection class=\"customize-order-section\"\u003e\n  \u003cdiv class=\"customize-order-inner\"\u003e\n    \u003ch2 class=\"customize-order-title\"\u003ePersonaliza tu pedido\u003c\/h2\u003e\n\n    \u003cdiv class=\"customize-order-grid\"\u003e\n      \u003c!-- Columna 1: Subir logo --\u003e\n      \u003cdiv class=\"customize-step\"\u003e\n        \u003clabel for=\"logo-upload-input\" class=\"customize-upload-box\" id=\"upload-box-label\"\u003e\n          \u003cdiv class=\"upload-plus-wrapper\" id=\"upload-plus-wrapper\"\u003e\n            \u003cspan class=\"upload-icon\"\u003e+\u003c\/span\u003e\n          \u003c\/div\u003e\n\n          \u003cdiv class=\"upload-preview-wrapper\"\u003e\n            \u003cimg id=\"upload-preview-img\" src=\"\" alt=\"Vista previa de tu logo\" class=\"upload-preview-img\" style=\"display:none;\"\u003e\n          \u003c\/div\u003e\n        \u003c\/label\u003e\n\n        \u003cinput id=\"logo-upload-input\" type=\"file\" accept=\"image\/png,image\/jpeg,image\/jpg\" class=\"upload-input\"\u003e\n\n        \u003cbutton type=\"button\" id=\"clear-logo-btn\" class=\"clear-logo-btn\" style=\"display:none;\"\u003e\n          Borrar imagen\n        \u003c\/button\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Columna 2: Mockup --\u003e\n      \u003cdiv class=\"customize-step\"\u003e\n        \u003cdiv class=\"mockup-preview\"\u003e\n          \u003cimg src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/files\/BOLSA_KRAFT_DK-45.png?v=1768528015\" alt=\"Vaso personalizado\" class=\"mockup-base\" width=\"800\" height=\"800\"\u003e\n\n          \u003cdiv class=\"mockup-logo-wrap\" id=\"mockup-logo-wrap\"\u003e\n            \u003cimg id=\"mockup-logo-img\" src=\"\" alt=\"Tu logotipo\" class=\"mockup-logo\" style=\"display:none;\" width=\"600\" height=\"600\"\u003e\n          \u003c\/div\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Columna 3: Cantidad + botón WhatsApp --\u003e\n      \u003cdiv class=\"customize-step customize-step--quantity\"\u003e\n        \u003ch3 class=\"step-title step-title-top\"\u003eCantidad de cajas para cotizar\u003c\/h3\u003e\n\n        \u003cdiv class=\"qty-block qty-block-top\"\u003e\n          \u003cdiv class=\"qty-control\"\u003e\n            \u003cbutton type=\"button\" class=\"qty-btn\" id=\"qty-minus\"\u003e−\u003c\/button\u003e\n            \u003cinput type=\"text\" id=\"quote-quantity\" class=\"qty-input\" value=\"1\" inputmode=\"numeric\" pattern=\"[0-9]*\"\u003e\n            \u003cbutton type=\"button\" class=\"qty-btn\" id=\"qty-plus\"\u003e+\u003c\/button\u003e\n          \u003c\/div\u003e\n          \u003cp class=\"qty-min-text\"\u003eTe cotizamos desde una caja\u003c\/p\u003e\n        \u003c\/div\u003e\n\n        \u003c!-- Botón WhatsApp verde con icono (imagen) --\u003e\n        \u003cbutton type=\"button\" id=\"custom-whatsapp-btn\" class=\"whatsapp-quote-btn\"\u003e\n          \u003cspan class=\"wa-icon-circle\"\u003e\n            \u003cimg src=\"https:\/\/upload.wikimedia.org\/wikipedia\/commons\/6\/6b\/WhatsApp.svg\" alt=\"WhatsApp\" class=\"wa-icon-img\"\u003e\n          \u003c\/span\u003e\n          \u003cspan\u003eCotizar Producto\u003c\/span\u003e\n        \u003c\/button\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Fila inferior de pasos --\u003e\n    \u003cdiv class=\"customize-steps-row\"\u003e\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e1\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eAgrega tu logo\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Solo se admiten imágenes en formato .png con fondo transparente. Tamaño máximo: 20 KB.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e2\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eVisualiza cómo se ve\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Esta es una representación digital del producto final. El resultado puede variar ligeramente en color, tamaño o proporciones.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e3\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eHaz tu pedido\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Puedes pedir desde una caja para imprimir tu logo en tu artículo, así de fácil.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Campos ocultos --\u003e\n    \u003cinput type=\"hidden\" id=\"logo-data-input\" name=\"properties[Logo personalizado]\" value=\"\"\u003e\n    \u003cinput type=\"hidden\" id=\"quote-quantity-input\" name=\"properties[Cantidad para cotización]\" value=\"1\"\u003e\n  \u003c\/div\u003e\n\n  \u003cstyle\u003e\n    .customize-order-section {\n      padding: 2.5rem 1.25rem;\n      background-color: #ffffff;\n    }\n    .customize-order-inner {\n      max-width: 1100px;\n      margin: 0 auto;\n    }\n    .customize-order-title {\n      font-size: 1.75rem;\n      font-weight: 700;\n      margin-bottom: 1.75rem;\n      text-align: left;\n      color: #2044A3;\n    }\n\n    .customize-order-grid {\n      display: grid;\n      grid-template-columns: repeat(3, minmax(0, 1fr));\n      gap: 3rem;\n      align-items: flex-start;\n      margin-bottom: 3rem;\n      justify-content: center;\n    }\n    .customize-step {\n      width: 100%;\n      max-width: 300px;\n      margin: 0 auto;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n    }\n\n    .customize-upload-box {\n      border: 2px dashed #D4D4D8;\n      border-radius: 1.5rem;\n      padding: 1.5rem;\n      min-height: 220px;\n      width: 100%;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n      justify-content: center;\n      position: relative;\n      cursor: pointer;\n      box-sizing: border-box;\n    }\n\n    .upload-plus-wrapper {\n      position: absolute;\n      top: 50%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      pointer-events: none;\n    }\n\n    .upload-icon {\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      width: 60px;\n      height: 60px;\n      border-radius: 9999px;\n      border: 2px solid #2044A3;\n      font-size: 1.85rem;\n      font-weight: 600;\n      color: #2044A3;\n      background: #ffffff;\n    }\n\n    .upload-input {\n      display: none;\n    }\n\n    .upload-preview-wrapper {\n      width: 100%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      min-height: 150px;\n    }\n    .upload-preview-img {\n      max-width: 100%;\n      max-height: 160px;\n      object-fit: contain;\n      display: block;\n    }\n\n    .clear-logo-btn {\n      margin-top: 0.75rem;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      align-self: center;\n      padding: 0.6rem 1.6rem;\n      border-radius: 9999px;\n      border: none;\n      background-color: #FFC800;\n      color: #111111;\n      font-size: 0.9rem;\n      cursor: pointer;\n      white-space: nowrap;\n    }\n    .clear-logo-btn:hover {\n      background-color: #e0ae00;\n    }\n\n    .mockup-preview {\n      position: relative;\n      border-radius: 1.5rem;\n      background-color: #F5F5F7;\n      padding: 1.5rem;\n      min-height: 220px;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      overflow: hidden;\n    }\n    .mockup-base {\n      max-width: 120%;\n      height: auto;\n      display: block;\n    }\n    .mockup-logo-wrap {\n      position: absolute;\n      top: 55%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      width: 45%;\n      pointer-events: auto;\n      cursor: move;\n      border: 2px solid transparent;\n      border-radius: 4px;\n      box-sizing: border-box;\n    }\n    .mockup-logo-wrap.is-dragging {\n      border-color: #2044A3;\n    }\n    .mockup-logo {\n      width: 100%;\n      height: auto;\n      object-fit: contain;\n      display: block;\n      filter: drop-shadow(0 1px 2px rgba(0,0,0,0.18));\n    }\n\n    .customize-step--quantity {\n      text-align: center;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n    }\n\n    .step-title-top {\n      font-size: 1rem;\n      font-weight: 700;\n      margin-bottom: 1.5rem;\n    }\n\n    .qty-min-text {\n      font-size: 0.85rem;\n      color: #6B7280;\n      margin-top: 0.25rem;\n    }\n\n    \/* === FORZAR ALINEACIÓN PERFECTA DE LA PÍLDORA DE CANTIDAD === *\/\n    .customize-order-section .qty-control {\n      display: inline-flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      border-radius: 9999px !important;\n      border: 1px solid #D4D4D8 !important;\n      overflow: hidden !important;\n      background-color: #ffffff !important;\n      padding: 0 !important;\n      line-height: 0 !important;\n    }\n\n    .customize-order-section .qty-btn {\n      display: inline-flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      width: 60px !important;\n      height: 46px !important;\n      background-color: #FFC800 !important;\n      border: none !important;\n      cursor: pointer !important;\n      color: #111111 !important;\n      font-size: 1.6rem !important;\n      line-height: 1 !important;\n      padding: 0 !important;\n      margin: 0 !important;\n      box-shadow: none !important;\n    }\n\n    .customize-order-section .qty-input {\n      width: 80px !important;\n      height: 46px !important;\n      border: none !important;\n      outline: none !important;\n      text-align: center !important;\n      font-size: 1rem !important;\n      color: #111111 !important;\n      background-color: #ffffff !important;\n      display: flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      padding: 0 !important;\n      margin: 0 !important;\n      box-sizing: border-box !important;\n      line-height: 1 !important;\n    }\n\n    .customize-order-section .qty-btn span,\n    .customize-order-section .qty-btn,\n    .customize-order-section .qty-control * {\n      line-height: 1 !important;\n    }\n\n    \/* BOTÓN WHATSAPP VERDE *\/\n    .customize-order-section .whatsapp-quote-btn {\n      margin-top: 1.25rem;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      align-self: center;\n      padding: 0.9rem 2.5rem;\n      border-radius: 9999px;\n      border: none;\n      background-color: #25D366 !important; \/* Verde WhatsApp *\/\n      color: #ffffff !important;\n      font-size: 1rem;\n      font-weight: 600;\n      cursor: pointer;\n      white-space: nowrap;\n      box-shadow: 0 8px 20px rgba(0,0,0,0.12);\n      gap: 0.5rem; \/* separa icono y texto *\/\n    }\n    .customize-order-section .whatsapp-quote-btn:hover {\n      background-color: #1eb259 !important;\n    }\n\n    \/* Círculo blanco para el ícono *\/\n    .customize-order-section .wa-icon-circle {\n      width: 22px;\n      height: 22px;\n      border-radius: 9999px;\n      background-color: #ffffff;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      overflow: hidden;\n      flex-shrink: 0;\n    }\n\n    \/* Imagen del ícono de WhatsApp *\/\n    .customize-order-section .wa-icon-img {\n      width: 16px;\n      height: 16px;\n      display: block;\n    }\n\n    .customize-order-section .wa-icon-phone,\n    .customize-order-section .wa-icon-phone::after {\n      display: none !important;\n    }\n\n    .customize-steps-row {\n      display: grid;\n      grid-template-columns: repeat(3, minmax(0, 1fr));\n      gap: 2rem;\n      margin-top: 1rem;\n      max-width: 1100px;\n      margin-left: auto;\n      margin-right: auto;\n    }\n    .customize-step-text {\n      text-align:center;\n      display:flex;\n      flex-direction:column;\n      align-items:center;\n    }\n    .step-circle {\n      width: 40px;\n      height: 40px;\n      border-radius: 9999px;\n      border: 2px solid #D4D4D8;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      margin: 0 auto 0.75rem auto;\n      font-weight: 600;\n      color: #111827;\n    }\n    .step-title {\n      font-size: 1rem;\n      font-weight: 700;\n      margin-bottom: 0.5rem;\n    }\n    .step-desc {\n      font-size: 0.875rem;\n      color: #6B7280;\n      line-height: 1.4;\n    }\n\n    @media (max-width: 900px) {\n      .customize-order-grid {\n        grid-template-columns: 1fr;\n      }\n      .customize-steps-row {\n        grid-template-columns: 1fr;\n      }\n      .customize-order-title {\n        text-align: center;\n      }\n      .customize-step--quantity {\n        text-align: center;\n        align-items: center;\n      }\n      .customize-order-section .whatsapp-quote-btn {\n        align-self: center;\n      }\n    }\n  \u003c\/style\u003e\n\n  \u003cscript\u003e\n    document.addEventListener('DOMContentLoaded', function() {\n      var fileInput       = document.getElementById('logo-upload-input');\n      var logoImg         = document.getElementById('mockup-logo-img');\n      var uploadPreview   = document.getElementById('upload-preview-img');\n      var clearBtn        = document.getElementById('clear-logo-btn');\n      var logoDataInput   = document.getElementById('logo-data-input');\n      var plusWrapper     = document.getElementById('upload-plus-wrapper');\n\n      var qtyInput  = document.getElementById('quote-quantity');\n      var qtyHidden = document.getElementById('quote-quantity-input');\n      var btnMinus  = document.getElementById('qty-minus');\n      var btnPlus   = document.getElementById('qty-plus');\n\n      var mockupPreview   = document.querySelector('.mockup-preview');\n      var mockupLogoWrap  = document.getElementById('mockup-logo-wrap');\n\n      if (fileInput \u0026\u0026 logoImg \u0026\u0026 logoDataInput) {\n        fileInput.addEventListener('change', function(event) {\n          var file = event.target.files[0];\n          if (!file) return;\n\n          var maxSizeMB = 2;\n          if (file.size \u003e maxSizeMB * 1024 * 1024) {\n            alert('La imagen es demasiado grande. Tamaño máximo: ' + maxSizeMB + ' MB');\n            fileInput.value = '';\n            return;\n          }\n\n          var reader = new FileReader();\n          reader.onload = function(e) {\n            var dataUrl = e.target.result;\n\n            logoImg.src = dataUrl;\n            logoImg.style.display = 'block';\n\n            if (uploadPreview) {\n              uploadPreview.src = dataUrl;\n              uploadPreview.style.display = 'block';\n            }\n\n            if (plusWrapper) plusWrapper.style.display = 'none';\n\n            logoDataInput.value = dataUrl;\n            clearBtn.style.display = 'inline-flex';\n\n            resetLogoPosition();\n          };\n          reader.readAsDataURL(file);\n        });\n\n        clearBtn.addEventListener('click', function() {\n          fileInput.value = '';\n\n          logoImg.src = '';\n          logoImg.style.display = 'none';\n\n          if (uploadPreview) {\n            uploadPreview.src = '';\n            uploadPreview.style.display = 'none';\n          }\n\n          if (plusWrapper) plusWrapper.style.display = 'flex';\n\n          logoDataInput.value = '';\n          clearBtn.style.display = 'none';\n\n          resetLogoPosition();\n        });\n      }\n\n      function resetLogoPosition() {\n        if (!mockupLogoWrap) return;\n        mockupLogoWrap.style.top = '55%';\n        mockupLogoWrap.style.left = '50%';\n        mockupLogoWrap.style.transform = 'translate(-50%, -50%)';\n        mockupLogoWrap.classList.remove('is-dragging');\n      }\n\n      if (mockupPreview \u0026\u0026 mockupLogoWrap) {\n        var isDragging = false;\n        var startX = 0;\n        var startY = 0;\n        var startLeft = 0;\n        var startTop = 0;\n\n        function getBounds() {\n          return mockupPreview.getBoundingClientRect();\n        }\n\n        function onPointerDown(e) {\n          if (!logoImg || logoImg.style.display === 'none') return;\n\n          isDragging = true;\n          mockupLogoWrap.classList.add('is-dragging');\n\n          var rect = getBounds();\n          var clientX = e.touches ? e.touches[0].clientX : e.clientX;\n          var clientY = e.touches ? e.touches[0].clientY : e.clientY;\n\n          startX = clientX;\n          startY = clientY;\n\n          var wrapRect = mockupLogoWrap.getBoundingClientRect();\n          startLeft = wrapRect.left - rect.left;\n          startTop  = wrapRect.top  - rect.top;\n\n          mockupLogoWrap.style.transform = 'none';\n\n          document.addEventListener('mousemove', onPointerMove);\n          document.addEventListener('mouseup', onPointerUp);\n          document.addEventListener('touchmove', onPointerMove, { passive: false });\n          document.addEventListener('touchend', onPointerUp);\n        }\n\n        function onPointerMove(e) {\n          if (!isDragging) return;\n          e.preventDefault();\n\n          var rect = getBounds();\n          var clientX = e.touches ? e.touches[0].clientX : e.clientX;\n          var clientY = e.touches ? e.touches[0].clientY : e.clientY;\n\n          var deltaX = clientX - startX;\n          var deltaY = clientY - startY;\n\n          var newLeft = startLeft + deltaX;\n          var newTop  = startTop + deltaY;\n\n          var wrapRect  = mockupLogoWrap.getBoundingClientRect();\n          var wrapWidth = wrapRect.width;\n          var wrapHeight = wrapRect.height;\n\n          var minLeft = 0;\n          var minTop  = 0;\n          var maxLeft = rect.width  - wrapWidth;\n          var maxTop  = rect.height - wrapHeight;\n\n          if (newLeft \u003c minLeft) newLeft = minLeft;\n          if (newTop  \u003c minTop)  newTop  = minTop;\n          if (newLeft \u003e maxLeft) newLeft = maxLeft;\n          if (newTop  \u003e maxTop)  newTop  = maxTop;\n\n          mockupLogoWrap.style.left = newLeft + 'px';\n          mockupLogoWrap.style.top  = newTop  + 'px';\n        }\n\n        function onPointerUp() {\n          if (!isDragging) return;\n          isDragging = false;\n          mockupLogoWrap.classList.remove('is-dragging');\n\n          document.removeEventListener('mousemove', onPointerMove);\n          document.removeEventListener('mouseup', onPointerUp);\n          document.removeEventListener('touchmove', onPointerMove);\n          document.removeEventListener('touchend', onPointerUp);\n        }\n\n        mockupLogoWrap.addEventListener('mousedown', onPointerDown);\n        mockupLogoWrap.addEventListener('touchstart', onPointerDown, { passive: true });\n      }\n\n      function sanitizeQty() {\n        if (!qtyInput || !qtyHidden) return;\n\n        var value = qtyInput.value.replace(\/[^0-9]\/g, '');\n        if (!value || Number(value) \u003c 1) {\n          value = '1';\n        }\n        qtyInput.value = value;\n        qtyHidden.value = value;\n      }\n\n      if (qtyInput \u0026\u0026 qtyHidden) {\n        qtyInput.addEventListener('change', sanitizeQty);\n        qtyInput.addEventListener('blur', sanitizeQty);\n      }\n\n      if (btnMinus \u0026\u0026 qtyInput) {\n        btnMinus.addEventListener('click', function() {\n          var current = Number(qtyInput.value || 1);\n          if (current \u003e 1) {\n            qtyInput.value = String(current - 1);\n            sanitizeQty();\n          }\n        });\n      }\n\n      if (btnPlus \u0026\u0026 qtyInput) {\n        btnPlus.addEventListener('click', function() {\n          var current = Number(qtyInput.value || 1);\n          qtyInput.value = String(current + 1);\n          sanitizeQty();\n        });\n      }\n\n      sanitizeQty();\n\n      \/* --- BOTÓN WHATSAPP --- *\/\n      var whatsappBtn    = document.getElementById('custom-whatsapp-btn');\n      var whatsappNumber = '525536684089'; \/\/ tu número sin + ni espacios\n\n      \/\/ EDITA ESTAS DOS LÍNEAS EN CADA PRODUCTO:\n      var productTitle   = \"Bolsa kraft DK-45 grande\";\n      var productUrl     = \"https:\/\/acesainter.com\/products\/bolsa-kraft-dk-45?utm_source=copyToPasteBoard\u0026utm_medium=product-links\u0026utm_content=web\";\n\n      if (whatsappBtn \u0026\u0026 qtyHidden) {\n        whatsappBtn.addEventListener('click', function() {\n          var qty = parseInt(qtyHidden.value || '1', 10);\n          if (isNaN(qty) || qty \u003c 1) qty = 1;\n\n          var message =\n            \"Hola, quiero cotizar este producto personalizado con mi marca.%0A%0A\" +\n            \"Producto: \" + encodeURIComponent(productTitle) + \"%0A\" +\n            \"Cantidad: \" + encodeURIComponent(qty + \" cajas\") + \"%0A\" +\n            \"URL del producto: \" + encodeURIComponent(productUrl) + \"%0A%0A\" +\n            \"Por favor, confírmenme tiempos de producción, precios y opciones de personalización.\";\n\n          var waUrl = \"https:\/\/wa.me\/\" + whatsappNumber + \"?text=\" + message;\n          window.open(waUrl, \"_blank\");\n        });\n      }\n    });\n  \u003c\/script\u003e\n\u003c\/section\u003e\n","brand":"ACESA INTERABASTO S. A. de C.V.","offers":[{"title":"Default Title","offer_id":48147609223418,"sku":null,"price":10.0,"currency_code":"MXN","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/files\/37.jpg?v=1768505296"},{"product_id":"contenedor-biodegradable-bio-88-8x8","title":"Contenedor biodegradable BIO-88 8x8 fibra de caña de azúcar (caja 250 pzas)","description":"\u003cp\u003eEl \u003cstrong\u003econtenedor BIO-88 8x8\u003c\/strong\u003e está fabricado con \u003cstrong\u003efibra de caña de azúcar\u003c\/strong\u003e, una alternativa biodegradable y compostable que muestra el \u003cstrong\u003ecompromiso ambiental\u003c\/strong\u003e de tu negocio.\u003c\/p\u003e\n\u003cp\u003eSoporta \u003cstrong\u003ealimentos fríos y calientes\u003c\/strong\u003e sin deformarse ni filtrar, manteniendo la comida segura y con buena presentación. Su \u003cstrong\u003ecolor natural beige\u003c\/strong\u003e genera una imagen \u003cstrong\u003elimpia, profesional y sustentable\u003c\/strong\u003e, ideal para \u003cstrong\u003ecafeterías, restaurantes, dark kitchens y negocios de comida para llevar\u003c\/strong\u003e.\u003cbr\u003eSe vende en \u003cstrong\u003ecaja con 250 piezas\u003c\/strong\u003e.\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eCLAVE: \u003cstrong\u003eBIO-88\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003cli\u003eMedida: 8 x 8 (pulgadas)\u003c\/li\u003e\n\u003cli\u003eUso recomendado: platillos para llevar, comida corrida, combos y menús individuales\u003c\/li\u003e\n\u003cli\u003eMaterial: fibra de caña de azúcar\u003c\/li\u003e\n\u003cli\u003eCaracterísticas: resistente, compostable y totalmente ecológico\u003c\/li\u003e\n\u003cli\u003eColor: natural beige\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"ACESA INTERABASTO S. A. de C.V.","offers":[{"title":"Default Title","offer_id":48148159594746,"sku":null,"price":10.0,"currency_code":"MXN","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/files\/46.jpg?v=1768505803"},{"product_id":"contenedor-biodegradable-bio-88-8x8-fibra-de-cana-de-azucar-caja-250-pzas-copia","title":"Contenedor biodegradable BIO-99 9x9 fibra de caña de azúcar (caja 250 pzas)","description":"\u003cp\u003eEl \u003cstrong\u003econtenedor BIO-99 9x9\u003c\/strong\u003e está fabricado con \u003cstrong\u003efibra de caña de azúcar\u003c\/strong\u003e, una alternativa biodegradable y compostable que muestra el \u003cstrong\u003ecompromiso ambiental\u003c\/strong\u003e de tu negocio.\u003c\/p\u003e\n\u003cp\u003eSoporta \u003cstrong\u003ealimentos fríos y calientes\u003c\/strong\u003e sin deformarse ni filtrar, manteniendo la comida segura y con buena presentación. Su \u003cstrong\u003ecolor natural beige\u003c\/strong\u003e genera una imagen \u003cstrong\u003elimpia, profesional y sustentable\u003c\/strong\u003e, ideal para \u003cstrong\u003ecafeterías, restaurantes, dark kitchens y negocios de comida para llevar\u003c\/strong\u003e.\u003cbr\u003eSe vende en \u003cstrong\u003ecaja con 250 piezas\u003c\/strong\u003e.\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eCLAVE: \u003cstrong\u003eBIO-99\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003cli\u003eMedida: 9 x 9 (pulgadas)\u003c\/li\u003e\n\u003cli\u003eUso recomendado: platillos para llevar, comida corrida, combos y menús individuales\u003c\/li\u003e\n\u003cli\u003eMaterial: fibra de caña de azúcar\u003c\/li\u003e\n\u003cli\u003eCaracterísticas: resistente, compostable y totalmente ecológico\u003c\/li\u003e\n\u003cli\u003eColor: natural beige\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"ACESA INTERABASTO S. A. de C.V.","offers":[{"title":"Default Title","offer_id":48148170178810,"sku":null,"price":10.0,"currency_code":"MXN","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/files\/47.jpg?v=1768505803"},{"product_id":"caja-pastel-28x28x6-cj28","title":"Caja para pastel 28x28x6 cm CJ28 cartón kraft blanco natural","description":"\u003cp\u003eLa \u003cstrong\u003ecaja para pastel CJ28 (28x28x6 cm)\u003c\/strong\u003e está fabricada en \u003cstrong\u003ecartón kraft de alta resistencia\u003c\/strong\u003e, diseñada para \u003cstrong\u003emantener tus postres seguros, firmes y bien presentados\u003c\/strong\u003e. Su altura de 6 cm la hace ideal para \u003cstrong\u003epasteles bajos, pays, tartas y repostería fina\u003c\/strong\u003e.\u003c\/p\u003e\n\u003cp\u003ePermite \u003cstrong\u003etransportar pasteles y postres sin riesgo de deformación\u003c\/strong\u003e, ofreciendo un empaque \u003cstrong\u003econfiable, profesional y visualmente atractivo\u003c\/strong\u003e. El \u003cstrong\u003ecolor blanco natural\u003c\/strong\u003e brinda una estética \u003cstrong\u003eelegante y artesanal\u003c\/strong\u003e que realza cualquier creación repostera, ya sea para mostrador o para llevar.\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eCLAVE: \u003cstrong\u003eCJ28\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003cli\u003eMedidas: \u003cstrong\u003e28 cm x 28 cm x 6 cm\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003cli\u003eMaterial: cartón kraft de alta resistencia\u003c\/li\u003e\n\u003cli\u003eUso recomendado: pasteles bajos, pays, tartas, repostería\u003c\/li\u003e\n\u003cli\u003eColor: blanco natural, estética elegante y artesanal\u003c\/li\u003e\n\u003cli\u003eBeneficios: transporte seguro, presentación profesional\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003csection class=\"customize-order-section\"\u003e\n  \u003cdiv class=\"customize-order-inner\"\u003e\n    \u003ch2 class=\"customize-order-title\"\u003ePersonaliza tu pedido\u003c\/h2\u003e\n\n    \u003cdiv class=\"customize-order-grid\"\u003e\n      \u003c!-- Columna 1: Subir logo --\u003e\n      \u003cdiv class=\"customize-step\"\u003e\n        \u003clabel for=\"logo-upload-input\" class=\"customize-upload-box\" id=\"upload-box-label\"\u003e\n          \u003cdiv class=\"upload-plus-wrapper\" id=\"upload-plus-wrapper\"\u003e\n            \u003cspan class=\"upload-icon\"\u003e+\u003c\/span\u003e\n          \u003c\/div\u003e\n\n          \u003cdiv class=\"upload-preview-wrapper\"\u003e\n            \u003cimg id=\"upload-preview-img\" src=\"\" alt=\"Vista previa de tu logo\" class=\"upload-preview-img\" style=\"display:none;\"\u003e\n          \u003c\/div\u003e\n        \u003c\/label\u003e\n\n        \u003cinput id=\"logo-upload-input\" type=\"file\" accept=\"image\/png,image\/jpeg,image\/jpg\" class=\"upload-input\"\u003e\n\n        \u003cbutton type=\"button\" id=\"clear-logo-btn\" class=\"clear-logo-btn\" style=\"display:none;\"\u003e\n          Borrar imagen\n        \u003c\/button\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Columna 2: Mockup --\u003e\n      \u003cdiv class=\"customize-step\"\u003e\n        \u003cdiv class=\"mockup-preview\"\u003e\n          \u003cimg src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/files\/C._28X28X6.png?v=1768528015\" alt=\"Vaso personalizado\" class=\"mockup-base\" width=\"800\" height=\"800\"\u003e\n\n          \u003cdiv class=\"mockup-logo-wrap\" id=\"mockup-logo-wrap\"\u003e\n            \u003cimg id=\"mockup-logo-img\" src=\"\" alt=\"Tu logotipo\" class=\"mockup-logo\" style=\"display:none;\" width=\"600\" height=\"600\"\u003e\n          \u003c\/div\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Columna 3: Cantidad + botón WhatsApp --\u003e\n      \u003cdiv class=\"customize-step customize-step--quantity\"\u003e\n        \u003ch3 class=\"step-title step-title-top\"\u003eCantidad de cajas para cotizar\u003c\/h3\u003e\n\n        \u003cdiv class=\"qty-block qty-block-top\"\u003e\n          \u003cdiv class=\"qty-control\"\u003e\n            \u003cbutton type=\"button\" class=\"qty-btn\" id=\"qty-minus\"\u003e−\u003c\/button\u003e\n            \u003cinput type=\"text\" id=\"quote-quantity\" class=\"qty-input\" value=\"1\" inputmode=\"numeric\" pattern=\"[0-9]*\"\u003e\n            \u003cbutton type=\"button\" class=\"qty-btn\" id=\"qty-plus\"\u003e+\u003c\/button\u003e\n          \u003c\/div\u003e\n          \u003cp class=\"qty-min-text\"\u003eTe cotizamos desde una caja\u003c\/p\u003e\n        \u003c\/div\u003e\n\n        \u003c!-- Botón WhatsApp verde con icono (imagen) --\u003e\n        \u003cbutton type=\"button\" id=\"custom-whatsapp-btn\" class=\"whatsapp-quote-btn\"\u003e\n          \u003cspan class=\"wa-icon-circle\"\u003e\n            \u003cimg src=\"https:\/\/upload.wikimedia.org\/wikipedia\/commons\/6\/6b\/WhatsApp.svg\" alt=\"WhatsApp\" class=\"wa-icon-img\"\u003e\n          \u003c\/span\u003e\n          \u003cspan\u003eCotizar Producto\u003c\/span\u003e\n        \u003c\/button\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Fila inferior de pasos --\u003e\n    \u003cdiv class=\"customize-steps-row\"\u003e\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e1\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eAgrega tu logo\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Solo se admiten imágenes en formato .png con fondo transparente. Tamaño máximo: 20 KB.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e2\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eVisualiza cómo se ve\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Esta es una representación digital del producto final. El resultado puede variar ligeramente en color, tamaño o proporciones.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e3\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eHaz tu pedido\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Puedes pedir desde una caja para imprimir tu logo en tu artículo, así de fácil.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Campos ocultos --\u003e\n    \u003cinput type=\"hidden\" id=\"logo-data-input\" name=\"properties[Logo personalizado]\" value=\"\"\u003e\n    \u003cinput type=\"hidden\" id=\"quote-quantity-input\" name=\"properties[Cantidad para cotización]\" value=\"1\"\u003e\n  \u003c\/div\u003e\n\n  \u003cstyle\u003e\n    .customize-order-section {\n      padding: 2.5rem 1.25rem;\n      background-color: #ffffff;\n    }\n    .customize-order-inner {\n      max-width: 1100px;\n      margin: 0 auto;\n    }\n    .customize-order-title {\n      font-size: 1.75rem;\n      font-weight: 700;\n      margin-bottom: 1.75rem;\n      text-align: left;\n      color: #2044A3;\n    }\n\n    .customize-order-grid {\n      display: grid;\n      grid-template-columns: repeat(3, minmax(0, 1fr));\n      gap: 3rem;\n      align-items: flex-start;\n      margin-bottom: 3rem;\n      justify-content: center;\n    }\n    .customize-step {\n      width: 100%;\n      max-width: 300px;\n      margin: 0 auto;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n    }\n\n    .customize-upload-box {\n      border: 2px dashed #D4D4D8;\n      border-radius: 1.5rem;\n      padding: 1.5rem;\n      min-height: 220px;\n      width: 100%;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n      justify-content: center;\n      position: relative;\n      cursor: pointer;\n      box-sizing: border-box;\n    }\n\n    .upload-plus-wrapper {\n      position: absolute;\n      top: 50%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      pointer-events: none;\n    }\n\n    .upload-icon {\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      width: 60px;\n      height: 60px;\n      border-radius: 9999px;\n      border: 2px solid #2044A3;\n      font-size: 1.85rem;\n      font-weight: 600;\n      color: #2044A3;\n      background: #ffffff;\n    }\n\n    .upload-input {\n      display: none;\n    }\n\n    .upload-preview-wrapper {\n      width: 100%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      min-height: 150px;\n    }\n    .upload-preview-img {\n      max-width: 100%;\n      max-height: 160px;\n      object-fit: contain;\n      display: block;\n    }\n\n    .clear-logo-btn {\n      margin-top: 0.75rem;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      align-self: center;\n      padding: 0.6rem 1.6rem;\n      border-radius: 9999px;\n      border: none;\n      background-color: #FFC800;\n      color: #111111;\n      font-size: 0.9rem;\n      cursor: pointer;\n      white-space: nowrap;\n    }\n    .clear-logo-btn:hover {\n      background-color: #e0ae00;\n    }\n\n    .mockup-preview {\n      position: relative;\n      border-radius: 1.5rem;\n      background-color: #F5F5F7;\n      padding: 1.5rem;\n      min-height: 220px;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      overflow: hidden;\n    }\n    .mockup-base {\n      max-width: 120%;\n      height: auto;\n      display: block;\n    }\n    .mockup-logo-wrap {\n      position: absolute;\n      top: 55%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      width: 40%;\n      pointer-events: auto;\n      cursor: move;\n      border: 2px solid transparent;\n      border-radius: 4px;\n      box-sizing: border-box;\n    }\n    .mockup-logo-wrap.is-dragging {\n      border-color: #2044A3;\n    }\n    .mockup-logo {\n      width: 100%;\n      height: auto;\n      object-fit: contain;\n      display: block;\n      filter: drop-shadow(0 1px 2px rgba(0,0,0,0.18));\n    }\n\n    .customize-step--quantity {\n      text-align: center;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n    }\n\n    .step-title-top {\n      font-size: 1rem;\n      font-weight: 700;\n      margin-bottom: 1.5rem;\n    }\n\n    .qty-min-text {\n      font-size: 0.85rem;\n      color: #6B7280;\n      margin-top: 0.25rem;\n    }\n\n    \/* === FORZAR ALINEACIÓN PERFECTA DE LA PÍLDORA DE CANTIDAD === *\/\n    .customize-order-section .qty-control {\n      display: inline-flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      border-radius: 9999px !important;\n      border: 1px solid #D4D4D8 !important;\n      overflow: hidden !important;\n      background-color: #ffffff !important;\n      padding: 0 !important;\n      line-height: 0 !important;\n    }\n\n    .customize-order-section .qty-btn {\n      display: inline-flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      width: 60px !important;\n      height: 46px !important;\n      background-color: #FFC800 !important;\n      border: none !important;\n      cursor: pointer !important;\n      color: #111111 !important;\n      font-size: 1.6rem !important;\n      line-height: 1 !important;\n      padding: 0 !important;\n      margin: 0 !important;\n      box-shadow: none !important;\n    }\n\n    .customize-order-section .qty-input {\n      width: 80px !important;\n      height: 46px !important;\n      border: none !important;\n      outline: none !important;\n      text-align: center !important;\n      font-size: 1rem !important;\n      color: #111111 !important;\n      background-color: #ffffff !important;\n      display: flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      padding: 0 !important;\n      margin: 0 !important;\n      box-sizing: border-box !important;\n      line-height: 1 !important;\n    }\n\n    .customize-order-section .qty-btn span,\n    .customize-order-section .qty-btn,\n    .customize-order-section .qty-control * {\n      line-height: 1 !important;\n    }\n\n    \/* BOTÓN WHATSAPP VERDE *\/\n    .customize-order-section .whatsapp-quote-btn {\n      margin-top: 1.25rem;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      align-self: center;\n      padding: 0.9rem 2.5rem;\n      border-radius: 9999px;\n      border: none;\n      background-color: #25D366 !important; \/* Verde WhatsApp *\/\n      color: #ffffff !important;\n      font-size: 1rem;\n      font-weight: 600;\n      cursor: pointer;\n      white-space: nowrap;\n      box-shadow: 0 8px 20px rgba(0,0,0,0.12);\n      gap: 0.5rem; \/* separa icono y texto *\/\n    }\n    .customize-order-section .whatsapp-quote-btn:hover {\n      background-color: #1eb259 !important;\n    }\n\n    \/* Círculo blanco para el ícono *\/\n    .customize-order-section .wa-icon-circle {\n      width: 22px;\n      height: 22px;\n      border-radius: 9999px;\n      background-color: #ffffff;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      overflow: hidden;\n      flex-shrink: 0;\n    }\n\n    \/* Imagen del ícono de WhatsApp *\/\n    .customize-order-section .wa-icon-img {\n      width: 16px;\n      height: 16px;\n      display: block;\n    }\n\n    .customize-order-section .wa-icon-phone,\n    .customize-order-section .wa-icon-phone::after {\n      display: none !important;\n    }\n\n    .customize-steps-row {\n      display: grid;\n      grid-template-columns: repeat(3, minmax(0, 1fr));\n      gap: 2rem;\n      margin-top: 1rem;\n      max-width: 1100px;\n      margin-left: auto;\n      margin-right: auto;\n    }\n    .customize-step-text {\n      text-align:center;\n      display:flex;\n      flex-direction:column;\n      align-items:center;\n    }\n    .step-circle {\n      width: 40px;\n      height: 40px;\n      border-radius: 9999px;\n      border: 2px solid #D4D4D8;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      margin: 0 auto 0.75rem auto;\n      font-weight: 600;\n      color: #111827;\n    }\n    .step-title {\n      font-size: 1rem;\n      font-weight: 700;\n      margin-bottom: 0.5rem;\n    }\n    .step-desc {\n      font-size: 0.875rem;\n      color: #6B7280;\n      line-height: 1.4;\n    }\n\n    @media (max-width: 900px) {\n      .customize-order-grid {\n        grid-template-columns: 1fr;\n      }\n      .customize-steps-row {\n        grid-template-columns: 1fr;\n      }\n      .customize-order-title {\n        text-align: center;\n      }\n      .customize-step--quantity {\n        text-align: center;\n        align-items: center;\n      }\n      .customize-order-section .whatsapp-quote-btn {\n        align-self: center;\n      }\n    }\n  \u003c\/style\u003e\n\n  \u003cscript\u003e\n    document.addEventListener('DOMContentLoaded', function() {\n      var fileInput       = document.getElementById('logo-upload-input');\n      var logoImg         = document.getElementById('mockup-logo-img');\n      var uploadPreview   = document.getElementById('upload-preview-img');\n      var clearBtn        = document.getElementById('clear-logo-btn');\n      var logoDataInput   = document.getElementById('logo-data-input');\n      var plusWrapper     = document.getElementById('upload-plus-wrapper');\n\n      var qtyInput  = document.getElementById('quote-quantity');\n      var qtyHidden = document.getElementById('quote-quantity-input');\n      var btnMinus  = document.getElementById('qty-minus');\n      var btnPlus   = document.getElementById('qty-plus');\n\n      var mockupPreview   = document.querySelector('.mockup-preview');\n      var mockupLogoWrap  = document.getElementById('mockup-logo-wrap');\n\n      if (fileInput \u0026\u0026 logoImg \u0026\u0026 logoDataInput) {\n        fileInput.addEventListener('change', function(event) {\n          var file = event.target.files[0];\n          if (!file) return;\n\n          var maxSizeMB = 2;\n          if (file.size \u003e maxSizeMB * 1024 * 1024) {\n            alert('La imagen es demasiado grande. Tamaño máximo: ' + maxSizeMB + ' MB');\n            fileInput.value = '';\n            return;\n          }\n\n          var reader = new FileReader();\n          reader.onload = function(e) {\n            var dataUrl = e.target.result;\n\n            logoImg.src = dataUrl;\n            logoImg.style.display = 'block';\n\n            if (uploadPreview) {\n              uploadPreview.src = dataUrl;\n              uploadPreview.style.display = 'block';\n            }\n\n            if (plusWrapper) plusWrapper.style.display = 'none';\n\n            logoDataInput.value = dataUrl;\n            clearBtn.style.display = 'inline-flex';\n\n            resetLogoPosition();\n          };\n          reader.readAsDataURL(file);\n        });\n\n        clearBtn.addEventListener('click', function() {\n          fileInput.value = '';\n\n          logoImg.src = '';\n          logoImg.style.display = 'none';\n\n          if (uploadPreview) {\n            uploadPreview.src = '';\n            uploadPreview.style.display = 'none';\n          }\n\n          if (plusWrapper) plusWrapper.style.display = 'flex';\n\n          logoDataInput.value = '';\n          clearBtn.style.display = 'none';\n\n          resetLogoPosition();\n        });\n      }\n\n      function resetLogoPosition() {\n        if (!mockupLogoWrap) return;\n        mockupLogoWrap.style.top = '55%';\n        mockupLogoWrap.style.left = '50%';\n        mockupLogoWrap.style.transform = 'translate(-50%, -50%)';\n        mockupLogoWrap.classList.remove('is-dragging');\n      }\n\n      if (mockupPreview \u0026\u0026 mockupLogoWrap) {\n        var isDragging = false;\n        var startX = 0;\n        var startY = 0;\n        var startLeft = 0;\n        var startTop = 0;\n\n        function getBounds() {\n          return mockupPreview.getBoundingClientRect();\n        }\n\n        function onPointerDown(e) {\n          if (!logoImg || logoImg.style.display === 'none') return;\n\n          isDragging = true;\n          mockupLogoWrap.classList.add('is-dragging');\n\n          var rect = getBounds();\n          var clientX = e.touches ? e.touches[0].clientX : e.clientX;\n          var clientY = e.touches ? e.touches[0].clientY : e.clientY;\n\n          startX = clientX;\n          startY = clientY;\n\n          var wrapRect = mockupLogoWrap.getBoundingClientRect();\n          startLeft = wrapRect.left - rect.left;\n          startTop  = wrapRect.top  - rect.top;\n\n          mockupLogoWrap.style.transform = 'none';\n\n          document.addEventListener('mousemove', onPointerMove);\n          document.addEventListener('mouseup', onPointerUp);\n          document.addEventListener('touchmove', onPointerMove, { passive: false });\n          document.addEventListener('touchend', onPointerUp);\n        }\n\n        function onPointerMove(e) {\n          if (!isDragging) return;\n          e.preventDefault();\n\n          var rect = getBounds();\n          var clientX = e.touches ? e.touches[0].clientX : e.clientX;\n          var clientY = e.touches ? e.touches[0].clientY : e.clientY;\n\n          var deltaX = clientX - startX;\n          var deltaY = clientY - startY;\n\n          var newLeft = startLeft + deltaX;\n          var newTop  = startTop + deltaY;\n\n          var wrapRect  = mockupLogoWrap.getBoundingClientRect();\n          var wrapWidth = wrapRect.width;\n          var wrapHeight = wrapRect.height;\n\n          var minLeft = 0;\n          var minTop  = 0;\n          var maxLeft = rect.width  - wrapWidth;\n          var maxTop  = rect.height - wrapHeight;\n\n          if (newLeft \u003c minLeft) newLeft = minLeft;\n          if (newTop  \u003c minTop)  newTop  = minTop;\n          if (newLeft \u003e maxLeft) newLeft = maxLeft;\n          if (newTop  \u003e maxTop)  newTop  = maxTop;\n\n          mockupLogoWrap.style.left = newLeft + 'px';\n          mockupLogoWrap.style.top  = newTop  + 'px';\n        }\n\n        function onPointerUp() {\n          if (!isDragging) return;\n          isDragging = false;\n          mockupLogoWrap.classList.remove('is-dragging');\n\n          document.removeEventListener('mousemove', onPointerMove);\n          document.removeEventListener('mouseup', onPointerUp);\n          document.removeEventListener('touchmove', onPointerMove);\n          document.removeEventListener('touchend', onPointerUp);\n        }\n\n        mockupLogoWrap.addEventListener('mousedown', onPointerDown);\n        mockupLogoWrap.addEventListener('touchstart', onPointerDown, { passive: true });\n      }\n\n      function sanitizeQty() {\n        if (!qtyInput || !qtyHidden) return;\n\n        var value = qtyInput.value.replace(\/[^0-9]\/g, '');\n        if (!value || Number(value) \u003c 1) {\n          value = '1';\n        }\n        qtyInput.value = value;\n        qtyHidden.value = value;\n      }\n\n      if (qtyInput \u0026\u0026 qtyHidden) {\n        qtyInput.addEventListener('change', sanitizeQty);\n        qtyInput.addEventListener('blur', sanitizeQty);\n      }\n\n      if (btnMinus \u0026\u0026 qtyInput) {\n        btnMinus.addEventListener('click', function() {\n          var current = Number(qtyInput.value || 1);\n          if (current \u003e 1) {\n            qtyInput.value = String(current - 1);\n            sanitizeQty();\n          }\n        });\n      }\n\n      if (btnPlus \u0026\u0026 qtyInput) {\n        btnPlus.addEventListener('click', function() {\n          var current = Number(qtyInput.value || 1);\n          qtyInput.value = String(current + 1);\n          sanitizeQty();\n        });\n      }\n\n      sanitizeQty();\n\n      \/* --- BOTÓN WHATSAPP --- *\/\n      var whatsappBtn    = document.getElementById('custom-whatsapp-btn');\n      var whatsappNumber = '525536684089'; \/\/ tu número sin + ni espacios\n\n      \/\/ EDITA ESTAS DOS LÍNEAS EN CADA PRODUCTO:\n      var productTitle   = \"Caja para pastel 28x28x6 cm CJ28\";\n      var productUrl     = \"https:\/\/acesainter.com\/products\/caja-pastel-28x28x6-cj28?utm_source=copyToPasteBoard\u0026utm_medium=product-links\u0026utm_content=web\";\n\n      if (whatsappBtn \u0026\u0026 qtyHidden) {\n        whatsappBtn.addEventListener('click', function() {\n          var qty = parseInt(qtyHidden.value || '1', 10);\n          if (isNaN(qty) || qty \u003c 1) qty = 1;\n\n          var message =\n            \"Hola, quiero cotizar este producto personalizado con mi marca.%0A%0A\" +\n            \"Producto: \" + encodeURIComponent(productTitle) + \"%0A\" +\n            \"Cantidad: \" + encodeURIComponent(qty + \" cajas\") + \"%0A\" +\n            \"URL del producto: \" + encodeURIComponent(productUrl) + \"%0A%0A\" +\n            \"Por favor, confírmenme tiempos de producción, precios y opciones de personalización.\";\n\n          var waUrl = \"https:\/\/wa.me\/\" + whatsappNumber + \"?text=\" + message;\n          window.open(waUrl, \"_blank\");\n        });\n      }\n    });\n  \u003c\/script\u003e\n\u003c\/section\u003e\n","brand":"ACESA INTERABASTO S. A. de C.V.","offers":[{"title":"Default Title","offer_id":48148224180474,"sku":null,"price":10.0,"currency_code":"MXN","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/files\/48.jpg?v=1768505958"},{"product_id":"caja-pastel-28x28x11-cj6","title":"Caja para pastel 28x28x11 cm CJ6 cartón kraft blanco natural","description":"\u003cp\u003eLa \u003cstrong\u003ecaja para pastel CJ6 (28x28x11 cm)\u003c\/strong\u003e está fabricada en \u003cstrong\u003ecartón kraft de alta resistencia\u003c\/strong\u003e, pensada para \u003cstrong\u003epasteles más altos, pays de varias capas y postres voluminosos\u003c\/strong\u003e. Su altura de 11 cm ofrece el espacio necesario para proteger tus creaciones.\u003c\/p\u003e\n\u003cp\u003eProporciona un \u003cstrong\u003etransporte seguro\u003c\/strong\u003e, evitando deformaciones y conservando la \u003cstrong\u003epresentación firme y profesional\u003c\/strong\u003e. El \u003cstrong\u003ecolor blanco natural\u003c\/strong\u003e aporta una imagen \u003cstrong\u003eelegante, limpia y artesanal\u003c\/strong\u003e, ideal para \u003cstrong\u003epastelerías, reposterías y negocios que cuidan su presentación al cliente\u003c\/strong\u003e.\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eCLAVE: \u003cstrong\u003eCJ6\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003cli\u003eMedidas: \u003cstrong\u003e28 cm x 28 cm x 11 cm\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003cli\u003eMaterial: cartón kraft de alta resistencia\u003c\/li\u003e\n\u003cli\u003eUso recomendado: pasteles altos, pays por capas, postres voluminosos\u003c\/li\u003e\n\u003cli\u003eColor: blanco natural\u003c\/li\u003e\n\u003cli\u003eBeneficios: empaque confiable, profesional y atractivo\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003csection class=\"customize-order-section\"\u003e\n  \u003cdiv class=\"customize-order-inner\"\u003e\n    \u003ch2 class=\"customize-order-title\"\u003ePersonaliza tu pedido\u003c\/h2\u003e\n\n    \u003cdiv class=\"customize-order-grid\"\u003e\n      \u003c!-- Columna 1: Subir logo --\u003e\n      \u003cdiv class=\"customize-step\"\u003e\n        \u003clabel for=\"logo-upload-input\" class=\"customize-upload-box\" id=\"upload-box-label\"\u003e\n          \u003cdiv class=\"upload-plus-wrapper\" id=\"upload-plus-wrapper\"\u003e\n            \u003cspan class=\"upload-icon\"\u003e+\u003c\/span\u003e\n          \u003c\/div\u003e\n\n          \u003cdiv class=\"upload-preview-wrapper\"\u003e\n            \u003cimg id=\"upload-preview-img\" src=\"\" alt=\"Vista previa de tu logo\" class=\"upload-preview-img\" style=\"display:none;\"\u003e\n          \u003c\/div\u003e\n        \u003c\/label\u003e\n\n        \u003cinput id=\"logo-upload-input\" type=\"file\" accept=\"image\/png,image\/jpeg,image\/jpg\" class=\"upload-input\"\u003e\n\n        \u003cbutton type=\"button\" id=\"clear-logo-btn\" class=\"clear-logo-btn\" style=\"display:none;\"\u003e\n          Borrar imagen\n        \u003c\/button\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Columna 2: Mockup --\u003e\n      \u003cdiv class=\"customize-step\"\u003e\n        \u003cdiv class=\"mockup-preview\"\u003e\n          \u003cimg src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/files\/C._28X28X11.png?v=1768528015\" alt=\"Vaso personalizado\" class=\"mockup-base\" width=\"800\" height=\"800\"\u003e\n\n          \u003cdiv class=\"mockup-logo-wrap\" id=\"mockup-logo-wrap\"\u003e\n            \u003cimg id=\"mockup-logo-img\" src=\"\" alt=\"Tu logotipo\" class=\"mockup-logo\" style=\"display:none;\" width=\"600\" height=\"600\"\u003e\n          \u003c\/div\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Columna 3: Cantidad + botón WhatsApp --\u003e\n      \u003cdiv class=\"customize-step customize-step--quantity\"\u003e\n        \u003ch3 class=\"step-title step-title-top\"\u003eCantidad de cajas para cotizar\u003c\/h3\u003e\n\n        \u003cdiv class=\"qty-block qty-block-top\"\u003e\n          \u003cdiv class=\"qty-control\"\u003e\n            \u003cbutton type=\"button\" class=\"qty-btn\" id=\"qty-minus\"\u003e−\u003c\/button\u003e\n            \u003cinput type=\"text\" id=\"quote-quantity\" class=\"qty-input\" value=\"1\" inputmode=\"numeric\" pattern=\"[0-9]*\"\u003e\n            \u003cbutton type=\"button\" class=\"qty-btn\" id=\"qty-plus\"\u003e+\u003c\/button\u003e\n          \u003c\/div\u003e\n          \u003cp class=\"qty-min-text\"\u003eTe cotizamos desde una caja\u003c\/p\u003e\n        \u003c\/div\u003e\n\n        \u003c!-- Botón WhatsApp verde con icono (imagen) --\u003e\n        \u003cbutton type=\"button\" id=\"custom-whatsapp-btn\" class=\"whatsapp-quote-btn\"\u003e\n          \u003cspan class=\"wa-icon-circle\"\u003e\n            \u003cimg src=\"https:\/\/upload.wikimedia.org\/wikipedia\/commons\/6\/6b\/WhatsApp.svg\" alt=\"WhatsApp\" class=\"wa-icon-img\"\u003e\n          \u003c\/span\u003e\n          \u003cspan\u003eCotizar Producto\u003c\/span\u003e\n        \u003c\/button\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Fila inferior de pasos --\u003e\n    \u003cdiv class=\"customize-steps-row\"\u003e\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e1\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eAgrega tu logo\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Solo se admiten imágenes en formato .png con fondo transparente. Tamaño máximo: 20 KB.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e2\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eVisualiza cómo se ve\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Esta es una representación digital del producto final. El resultado puede variar ligeramente en color, tamaño o proporciones.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e3\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eHaz tu pedido\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Puedes pedir desde una caja para imprimir tu logo en tu artículo, así de fácil.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Campos ocultos --\u003e\n    \u003cinput type=\"hidden\" id=\"logo-data-input\" name=\"properties[Logo personalizado]\" value=\"\"\u003e\n    \u003cinput type=\"hidden\" id=\"quote-quantity-input\" name=\"properties[Cantidad para cotización]\" value=\"1\"\u003e\n  \u003c\/div\u003e\n\n  \u003cstyle\u003e\n    .customize-order-section {\n      padding: 2.5rem 1.25rem;\n      background-color: #ffffff;\n    }\n    .customize-order-inner {\n      max-width: 1100px;\n      margin: 0 auto;\n    }\n    .customize-order-title {\n      font-size: 1.75rem;\n      font-weight: 700;\n      margin-bottom: 1.75rem;\n      text-align: left;\n      color: #2044A3;\n    }\n\n    .customize-order-grid {\n      display: grid;\n      grid-template-columns: repeat(3, minmax(0, 1fr));\n      gap: 3rem;\n      align-items: flex-start;\n      margin-bottom: 3rem;\n      justify-content: center;\n    }\n    .customize-step {\n      width: 100%;\n      max-width: 300px;\n      margin: 0 auto;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n    }\n\n    .customize-upload-box {\n      border: 2px dashed #D4D4D8;\n      border-radius: 1.5rem;\n      padding: 1.5rem;\n      min-height: 220px;\n      width: 100%;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n      justify-content: center;\n      position: relative;\n      cursor: pointer;\n      box-sizing: border-box;\n    }\n\n    .upload-plus-wrapper {\n      position: absolute;\n      top: 50%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      pointer-events: none;\n    }\n\n    .upload-icon {\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      width: 60px;\n      height: 60px;\n      border-radius: 9999px;\n      border: 2px solid #2044A3;\n      font-size: 1.85rem;\n      font-weight: 600;\n      color: #2044A3;\n      background: #ffffff;\n    }\n\n    .upload-input {\n      display: none;\n    }\n\n    .upload-preview-wrapper {\n      width: 100%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      min-height: 150px;\n    }\n    .upload-preview-img {\n      max-width: 100%;\n      max-height: 160px;\n      object-fit: contain;\n      display: block;\n    }\n\n    .clear-logo-btn {\n      margin-top: 0.75rem;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      align-self: center;\n      padding: 0.6rem 1.6rem;\n      border-radius: 9999px;\n      border: none;\n      background-color: #FFC800;\n      color: #111111;\n      font-size: 0.9rem;\n      cursor: pointer;\n      white-space: nowrap;\n    }\n    .clear-logo-btn:hover {\n      background-color: #e0ae00;\n    }\n\n    .mockup-preview {\n      position: relative;\n      border-radius: 1.5rem;\n      background-color: #F5F5F7;\n      padding: 1.5rem;\n      min-height: 220px;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      overflow: hidden;\n    }\n    .mockup-base {\n      max-width: 120%;\n      height: auto;\n      display: block;\n    }\n    .mockup-logo-wrap {\n      position: absolute;\n      top: 55%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      width: 40%;\n      pointer-events: auto;\n      cursor: move;\n      border: 2px solid transparent;\n      border-radius: 4px;\n      box-sizing: border-box;\n    }\n    .mockup-logo-wrap.is-dragging {\n      border-color: #2044A3;\n    }\n    .mockup-logo {\n      width: 100%;\n      height: auto;\n      object-fit: contain;\n      display: block;\n      filter: drop-shadow(0 1px 2px rgba(0,0,0,0.18));\n    }\n\n    .customize-step--quantity {\n      text-align: center;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n    }\n\n    .step-title-top {\n      font-size: 1rem;\n      font-weight: 700;\n      margin-bottom: 1.5rem;\n    }\n\n    .qty-min-text {\n      font-size: 0.85rem;\n      color: #6B7280;\n      margin-top: 0.25rem;\n    }\n\n    \/* === FORZAR ALINEACIÓN PERFECTA DE LA PÍLDORA DE CANTIDAD === *\/\n    .customize-order-section .qty-control {\n      display: inline-flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      border-radius: 9999px !important;\n      border: 1px solid #D4D4D8 !important;\n      overflow: hidden !important;\n      background-color: #ffffff !important;\n      padding: 0 !important;\n      line-height: 0 !important;\n    }\n\n    .customize-order-section .qty-btn {\n      display: inline-flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      width: 60px !important;\n      height: 46px !important;\n      background-color: #FFC800 !important;\n      border: none !important;\n      cursor: pointer !important;\n      color: #111111 !important;\n      font-size: 1.6rem !important;\n      line-height: 1 !important;\n      padding: 0 !important;\n      margin: 0 !important;\n      box-shadow: none !important;\n    }\n\n    .customize-order-section .qty-input {\n      width: 80px !important;\n      height: 46px !important;\n      border: none !important;\n      outline: none !important;\n      text-align: center !important;\n      font-size: 1rem !important;\n      color: #111111 !important;\n      background-color: #ffffff !important;\n      display: flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      padding: 0 !important;\n      margin: 0 !important;\n      box-sizing: border-box !important;\n      line-height: 1 !important;\n    }\n\n    .customize-order-section .qty-btn span,\n    .customize-order-section .qty-btn,\n    .customize-order-section .qty-control * {\n      line-height: 1 !important;\n    }\n\n    \/* BOTÓN WHATSAPP VERDE *\/\n    .customize-order-section .whatsapp-quote-btn {\n      margin-top: 1.25rem;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      align-self: center;\n      padding: 0.9rem 2.5rem;\n      border-radius: 9999px;\n      border: none;\n      background-color: #25D366 !important; \/* Verde WhatsApp *\/\n      color: #ffffff !important;\n      font-size: 1rem;\n      font-weight: 600;\n      cursor: pointer;\n      white-space: nowrap;\n      box-shadow: 0 8px 20px rgba(0,0,0,0.12);\n      gap: 0.5rem; \/* separa icono y texto *\/\n    }\n    .customize-order-section .whatsapp-quote-btn:hover {\n      background-color: #1eb259 !important;\n    }\n\n    \/* Círculo blanco para el ícono *\/\n    .customize-order-section .wa-icon-circle {\n      width: 22px;\n      height: 22px;\n      border-radius: 9999px;\n      background-color: #ffffff;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      overflow: hidden;\n      flex-shrink: 0;\n    }\n\n    \/* Imagen del ícono de WhatsApp *\/\n    .customize-order-section .wa-icon-img {\n      width: 16px;\n      height: 16px;\n      display: block;\n    }\n\n    .customize-order-section .wa-icon-phone,\n    .customize-order-section .wa-icon-phone::after {\n      display: none !important;\n    }\n\n    .customize-steps-row {\n      display: grid;\n      grid-template-columns: repeat(3, minmax(0, 1fr));\n      gap: 2rem;\n      margin-top: 1rem;\n      max-width: 1100px;\n      margin-left: auto;\n      margin-right: auto;\n    }\n    .customize-step-text {\n      text-align:center;\n      display:flex;\n      flex-direction:column;\n      align-items:center;\n    }\n    .step-circle {\n      width: 40px;\n      height: 40px;\n      border-radius: 9999px;\n      border: 2px solid #D4D4D8;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      margin: 0 auto 0.75rem auto;\n      font-weight: 600;\n      color: #111827;\n    }\n    .step-title {\n      font-size: 1rem;\n      font-weight: 700;\n      margin-bottom: 0.5rem;\n    }\n    .step-desc {\n      font-size: 0.875rem;\n      color: #6B7280;\n      line-height: 1.4;\n    }\n\n    @media (max-width: 900px) {\n      .customize-order-grid {\n        grid-template-columns: 1fr;\n      }\n      .customize-steps-row {\n        grid-template-columns: 1fr;\n      }\n      .customize-order-title {\n        text-align: center;\n      }\n      .customize-step--quantity {\n        text-align: center;\n        align-items: center;\n      }\n      .customize-order-section .whatsapp-quote-btn {\n        align-self: center;\n      }\n    }\n  \u003c\/style\u003e\n\n  \u003cscript\u003e\n    document.addEventListener('DOMContentLoaded', function() {\n      var fileInput       = document.getElementById('logo-upload-input');\n      var logoImg         = document.getElementById('mockup-logo-img');\n      var uploadPreview   = document.getElementById('upload-preview-img');\n      var clearBtn        = document.getElementById('clear-logo-btn');\n      var logoDataInput   = document.getElementById('logo-data-input');\n      var plusWrapper     = document.getElementById('upload-plus-wrapper');\n\n      var qtyInput  = document.getElementById('quote-quantity');\n      var qtyHidden = document.getElementById('quote-quantity-input');\n      var btnMinus  = document.getElementById('qty-minus');\n      var btnPlus   = document.getElementById('qty-plus');\n\n      var mockupPreview   = document.querySelector('.mockup-preview');\n      var mockupLogoWrap  = document.getElementById('mockup-logo-wrap');\n\n      if (fileInput \u0026\u0026 logoImg \u0026\u0026 logoDataInput) {\n        fileInput.addEventListener('change', function(event) {\n          var file = event.target.files[0];\n          if (!file) return;\n\n          var maxSizeMB = 2;\n          if (file.size \u003e maxSizeMB * 1024 * 1024) {\n            alert('La imagen es demasiado grande. Tamaño máximo: ' + maxSizeMB + ' MB');\n            fileInput.value = '';\n            return;\n          }\n\n          var reader = new FileReader();\n          reader.onload = function(e) {\n            var dataUrl = e.target.result;\n\n            logoImg.src = dataUrl;\n            logoImg.style.display = 'block';\n\n            if (uploadPreview) {\n              uploadPreview.src = dataUrl;\n              uploadPreview.style.display = 'block';\n            }\n\n            if (plusWrapper) plusWrapper.style.display = 'none';\n\n            logoDataInput.value = dataUrl;\n            clearBtn.style.display = 'inline-flex';\n\n            resetLogoPosition();\n          };\n          reader.readAsDataURL(file);\n        });\n\n        clearBtn.addEventListener('click', function() {\n          fileInput.value = '';\n\n          logoImg.src = '';\n          logoImg.style.display = 'none';\n\n          if (uploadPreview) {\n            uploadPreview.src = '';\n            uploadPreview.style.display = 'none';\n          }\n\n          if (plusWrapper) plusWrapper.style.display = 'flex';\n\n          logoDataInput.value = '';\n          clearBtn.style.display = 'none';\n\n          resetLogoPosition();\n        });\n      }\n\n      function resetLogoPosition() {\n        if (!mockupLogoWrap) return;\n        mockupLogoWrap.style.top = '55%';\n        mockupLogoWrap.style.left = '50%';\n        mockupLogoWrap.style.transform = 'translate(-50%, -50%)';\n        mockupLogoWrap.classList.remove('is-dragging');\n      }\n\n      if (mockupPreview \u0026\u0026 mockupLogoWrap) {\n        var isDragging = false;\n        var startX = 0;\n        var startY = 0;\n        var startLeft = 0;\n        var startTop = 0;\n\n        function getBounds() {\n          return mockupPreview.getBoundingClientRect();\n        }\n\n        function onPointerDown(e) {\n          if (!logoImg || logoImg.style.display === 'none') return;\n\n          isDragging = true;\n          mockupLogoWrap.classList.add('is-dragging');\n\n          var rect = getBounds();\n          var clientX = e.touches ? e.touches[0].clientX : e.clientX;\n          var clientY = e.touches ? e.touches[0].clientY : e.clientY;\n\n          startX = clientX;\n          startY = clientY;\n\n          var wrapRect = mockupLogoWrap.getBoundingClientRect();\n          startLeft = wrapRect.left - rect.left;\n          startTop  = wrapRect.top  - rect.top;\n\n          mockupLogoWrap.style.transform = 'none';\n\n          document.addEventListener('mousemove', onPointerMove);\n          document.addEventListener('mouseup', onPointerUp);\n          document.addEventListener('touchmove', onPointerMove, { passive: false });\n          document.addEventListener('touchend', onPointerUp);\n        }\n\n        function onPointerMove(e) {\n          if (!isDragging) return;\n          e.preventDefault();\n\n          var rect = getBounds();\n          var clientX = e.touches ? e.touches[0].clientX : e.clientX;\n          var clientY = e.touches ? e.touches[0].clientY : e.clientY;\n\n          var deltaX = clientX - startX;\n          var deltaY = clientY - startY;\n\n          var newLeft = startLeft + deltaX;\n          var newTop  = startTop + deltaY;\n\n          var wrapRect  = mockupLogoWrap.getBoundingClientRect();\n          var wrapWidth = wrapRect.width;\n          var wrapHeight = wrapRect.height;\n\n          var minLeft = 0;\n          var minTop  = 0;\n          var maxLeft = rect.width  - wrapWidth;\n          var maxTop  = rect.height - wrapHeight;\n\n          if (newLeft \u003c minLeft) newLeft = minLeft;\n          if (newTop  \u003c minTop)  newTop  = minTop;\n          if (newLeft \u003e maxLeft) newLeft = maxLeft;\n          if (newTop  \u003e maxTop)  newTop  = maxTop;\n\n          mockupLogoWrap.style.left = newLeft + 'px';\n          mockupLogoWrap.style.top  = newTop  + 'px';\n        }\n\n        function onPointerUp() {\n          if (!isDragging) return;\n          isDragging = false;\n          mockupLogoWrap.classList.remove('is-dragging');\n\n          document.removeEventListener('mousemove', onPointerMove);\n          document.removeEventListener('mouseup', onPointerUp);\n          document.removeEventListener('touchmove', onPointerMove);\n          document.removeEventListener('touchend', onPointerUp);\n        }\n\n        mockupLogoWrap.addEventListener('mousedown', onPointerDown);\n        mockupLogoWrap.addEventListener('touchstart', onPointerDown, { passive: true });\n      }\n\n      function sanitizeQty() {\n        if (!qtyInput || !qtyHidden) return;\n\n        var value = qtyInput.value.replace(\/[^0-9]\/g, '');\n        if (!value || Number(value) \u003c 1) {\n          value = '1';\n        }\n        qtyInput.value = value;\n        qtyHidden.value = value;\n      }\n\n      if (qtyInput \u0026\u0026 qtyHidden) {\n        qtyInput.addEventListener('change', sanitizeQty);\n        qtyInput.addEventListener('blur', sanitizeQty);\n      }\n\n      if (btnMinus \u0026\u0026 qtyInput) {\n        btnMinus.addEventListener('click', function() {\n          var current = Number(qtyInput.value || 1);\n          if (current \u003e 1) {\n            qtyInput.value = String(current - 1);\n            sanitizeQty();\n          }\n        });\n      }\n\n      if (btnPlus \u0026\u0026 qtyInput) {\n        btnPlus.addEventListener('click', function() {\n          var current = Number(qtyInput.value || 1);\n          qtyInput.value = String(current + 1);\n          sanitizeQty();\n        });\n      }\n\n      sanitizeQty();\n\n      \/* --- BOTÓN WHATSAPP --- *\/\n      var whatsappBtn    = document.getElementById('custom-whatsapp-btn');\n      var whatsappNumber = '525536684089'; \/\/ tu número sin + ni espacios\n\n      \/\/ EDITA ESTAS DOS LÍNEAS EN CADA PRODUCTO:\n      var productTitle   = \"Caja para pastel 28x28x11 cm CJ6\";\n      var productUrl     = \"https:\/\/acesainter.com\/products\/caja-pastel-28x28x11-cj6?utm_source=copyToPasteBoard\u0026utm_medium=product-links\u0026utm_content=web\";\n\n      if (whatsappBtn \u0026\u0026 qtyHidden) {\n        whatsappBtn.addEventListener('click', function() {\n          var qty = parseInt(qtyHidden.value || '1', 10);\n          if (isNaN(qty) || qty \u003c 1) qty = 1;\n\n          var message =\n            \"Hola, quiero cotizar este producto personalizado con mi marca.%0A%0A\" +\n            \"Producto: \" + encodeURIComponent(productTitle) + \"%0A\" +\n            \"Cantidad: \" + encodeURIComponent(qty + \" cajas\") + \"%0A\" +\n            \"URL del producto: \" + encodeURIComponent(productUrl) + \"%0A%0A\" +\n            \"Por favor, confírmenme tiempos de producción, precios y opciones de personalización.\";\n\n          var waUrl = \"https:\/\/wa.me\/\" + whatsappNumber + \"?text=\" + message;\n          window.open(waUrl, \"_blank\");\n        });\n      }\n    });\n  \u003c\/script\u003e\n\u003c\/section\u003e\n","brand":"ACESA INTERABASTO S. A. de C.V.","offers":[{"title":"Default Title","offer_id":48148242628858,"sku":null,"price":10.0,"currency_code":"MXN","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/files\/49.jpg?v=1768505958"},{"product_id":"caja-pastel-30x30x11-cj30","title":"Caja para pastel 30x30x11 cm CJ30 cartón kraft blanco natural","description":"\u003cp\u003eLa \u003cstrong\u003ecaja para pastel CJ30 (30x30x11 cm)\u003c\/strong\u003e está elaborada en \u003cstrong\u003ecartón kraft de alta resistencia\u003c\/strong\u003e, ideal para \u003cstrong\u003epasteles medianos, pays grandes y repostería especial\u003c\/strong\u003e. Su tamaño de 30x30 cm y altura de 11 cm proporciona un espacio amplio y seguro para tus creaciones.\u003c\/p\u003e\n\u003cp\u003eAyuda a \u003cstrong\u003etransportar pasteles y postres sin riesgo de deformación\u003c\/strong\u003e, manteniéndolos firmes y bien presentados. El \u003cstrong\u003ecolor blanco natural\u003c\/strong\u003e ofrece una estética \u003cstrong\u003eelegante, artesanal y profesional\u003c\/strong\u003e, perfecta para \u003cstrong\u003epastelerías, reposterías y negocios que buscan un empaque de alta presentación\u003c\/strong\u003e.\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eCLAVE: \u003cstrong\u003eCJ30\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003cli\u003eMedidas: \u003cstrong\u003e30 cm x 30 cm x 11 cm\u003c\/strong\u003e\n\u003c\/li\u003e\n\u003cli\u003eMaterial: cartón kraft de alta resistencia\u003c\/li\u003e\n\u003cli\u003eUso recomendado: pasteles medianos, pays grandes, repostería especial\u003c\/li\u003e\n\u003cli\u003eColor: blanco natural\u003c\/li\u003e\n\u003cli\u003eBeneficios: transporte seguro, presentación premium\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003csection class=\"customize-order-section\"\u003e\n  \u003cdiv class=\"customize-order-inner\"\u003e\n    \u003ch2 class=\"customize-order-title\"\u003ePersonaliza tu pedido\u003c\/h2\u003e\n\n    \u003cdiv class=\"customize-order-grid\"\u003e\n      \u003c!-- Columna 1: Subir logo --\u003e\n      \u003cdiv class=\"customize-step\"\u003e\n        \u003clabel for=\"logo-upload-input\" class=\"customize-upload-box\" id=\"upload-box-label\"\u003e\n          \u003cdiv class=\"upload-plus-wrapper\" id=\"upload-plus-wrapper\"\u003e\n            \u003cspan class=\"upload-icon\"\u003e+\u003c\/span\u003e\n          \u003c\/div\u003e\n\n          \u003cdiv class=\"upload-preview-wrapper\"\u003e\n            \u003cimg id=\"upload-preview-img\" src=\"\" alt=\"Vista previa de tu logo\" class=\"upload-preview-img\" style=\"display:none;\"\u003e\n          \u003c\/div\u003e\n        \u003c\/label\u003e\n\n        \u003cinput id=\"logo-upload-input\" type=\"file\" accept=\"image\/png,image\/jpeg,image\/jpg\" class=\"upload-input\"\u003e\n\n        \u003cbutton type=\"button\" id=\"clear-logo-btn\" class=\"clear-logo-btn\" style=\"display:none;\"\u003e\n          Borrar imagen\n        \u003c\/button\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Columna 2: Mockup --\u003e\n      \u003cdiv class=\"customize-step\"\u003e\n        \u003cdiv class=\"mockup-preview\"\u003e\n          \u003cimg src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/files\/C._30x30x11.png?v=1768528015\" alt=\"Vaso personalizado\" class=\"mockup-base\" width=\"800\" height=\"800\"\u003e\n\n          \u003cdiv class=\"mockup-logo-wrap\" id=\"mockup-logo-wrap\"\u003e\n            \u003cimg id=\"mockup-logo-img\" src=\"\" alt=\"Tu logotipo\" class=\"mockup-logo\" style=\"display:none;\" width=\"600\" height=\"600\"\u003e\n          \u003c\/div\u003e\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003c!-- Columna 3: Cantidad + botón WhatsApp --\u003e\n      \u003cdiv class=\"customize-step customize-step--quantity\"\u003e\n        \u003ch3 class=\"step-title step-title-top\"\u003eCantidad de cajas para cotizar\u003c\/h3\u003e\n\n        \u003cdiv class=\"qty-block qty-block-top\"\u003e\n          \u003cdiv class=\"qty-control\"\u003e\n            \u003cbutton type=\"button\" class=\"qty-btn\" id=\"qty-minus\"\u003e−\u003c\/button\u003e\n            \u003cinput type=\"text\" id=\"quote-quantity\" class=\"qty-input\" value=\"1\" inputmode=\"numeric\" pattern=\"[0-9]*\"\u003e\n            \u003cbutton type=\"button\" class=\"qty-btn\" id=\"qty-plus\"\u003e+\u003c\/button\u003e\n          \u003c\/div\u003e\n          \u003cp class=\"qty-min-text\"\u003eTe cotizamos desde una caja\u003c\/p\u003e\n        \u003c\/div\u003e\n\n        \u003c!-- Botón WhatsApp verde con icono (imagen) --\u003e\n        \u003cbutton type=\"button\" id=\"custom-whatsapp-btn\" class=\"whatsapp-quote-btn\"\u003e\n          \u003cspan class=\"wa-icon-circle\"\u003e\n            \u003cimg src=\"https:\/\/upload.wikimedia.org\/wikipedia\/commons\/6\/6b\/WhatsApp.svg\" alt=\"WhatsApp\" class=\"wa-icon-img\"\u003e\n          \u003c\/span\u003e\n          \u003cspan\u003eCotizar Producto\u003c\/span\u003e\n        \u003c\/button\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Fila inferior de pasos --\u003e\n    \u003cdiv class=\"customize-steps-row\"\u003e\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e1\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eAgrega tu logo\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Solo se admiten imágenes en formato .png con fondo transparente. Tamaño máximo: 20 KB.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e2\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eVisualiza cómo se ve\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Esta es una representación digital del producto final. El resultado puede variar ligeramente en color, tamaño o proporciones.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"customize-step-text\"\u003e\n        \u003cdiv class=\"step-circle\"\u003e3\u003c\/div\u003e\n        \u003ch3 class=\"step-title\"\u003eHaz tu pedido\u003c\/h3\u003e\n        \u003cp class=\"step-desc\"\u003e\n          Puedes pedir desde una caja para imprimir tu logo en tu artículo, así de fácil.\n        \u003c\/p\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- Campos ocultos --\u003e\n    \u003cinput type=\"hidden\" id=\"logo-data-input\" name=\"properties[Logo personalizado]\" value=\"\"\u003e\n    \u003cinput type=\"hidden\" id=\"quote-quantity-input\" name=\"properties[Cantidad para cotización]\" value=\"1\"\u003e\n  \u003c\/div\u003e\n\n  \u003cstyle\u003e\n    .customize-order-section {\n      padding: 2.5rem 1.25rem;\n      background-color: #ffffff;\n    }\n    .customize-order-inner {\n      max-width: 1100px;\n      margin: 0 auto;\n    }\n    .customize-order-title {\n      font-size: 1.75rem;\n      font-weight: 700;\n      margin-bottom: 1.75rem;\n      text-align: left;\n      color: #2044A3;\n    }\n\n    .customize-order-grid {\n      display: grid;\n      grid-template-columns: repeat(3, minmax(0, 1fr));\n      gap: 3rem;\n      align-items: flex-start;\n      margin-bottom: 3rem;\n      justify-content: center;\n    }\n    .customize-step {\n      width: 100%;\n      max-width: 300px;\n      margin: 0 auto;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n    }\n\n    .customize-upload-box {\n      border: 2px dashed #D4D4D8;\n      border-radius: 1.5rem;\n      padding: 1.5rem;\n      min-height: 220px;\n      width: 100%;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n      justify-content: center;\n      position: relative;\n      cursor: pointer;\n      box-sizing: border-box;\n    }\n\n    .upload-plus-wrapper {\n      position: absolute;\n      top: 50%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      pointer-events: none;\n    }\n\n    .upload-icon {\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      width: 60px;\n      height: 60px;\n      border-radius: 9999px;\n      border: 2px solid #2044A3;\n      font-size: 1.85rem;\n      font-weight: 600;\n      color: #2044A3;\n      background: #ffffff;\n    }\n\n    .upload-input {\n      display: none;\n    }\n\n    .upload-preview-wrapper {\n      width: 100%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      min-height: 150px;\n    }\n    .upload-preview-img {\n      max-width: 100%;\n      max-height: 160px;\n      object-fit: contain;\n      display: block;\n    }\n\n    .clear-logo-btn {\n      margin-top: 0.75rem;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      align-self: center;\n      padding: 0.6rem 1.6rem;\n      border-radius: 9999px;\n      border: none;\n      background-color: #FFC800;\n      color: #111111;\n      font-size: 0.9rem;\n      cursor: pointer;\n      white-space: nowrap;\n    }\n    .clear-logo-btn:hover {\n      background-color: #e0ae00;\n    }\n\n    .mockup-preview {\n      position: relative;\n      border-radius: 1.5rem;\n      background-color: #F5F5F7;\n      padding: 1.5rem;\n      min-height: 220px;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      overflow: hidden;\n    }\n    .mockup-base {\n      max-width: 120%;\n      height: auto;\n      display: block;\n    }\n    .mockup-logo-wrap {\n      position: absolute;\n      top: 55%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      width: 40%;\n      pointer-events: auto;\n      cursor: move;\n      border: 2px solid transparent;\n      border-radius: 4px;\n      box-sizing: border-box;\n    }\n    .mockup-logo-wrap.is-dragging {\n      border-color: #2044A3;\n    }\n    .mockup-logo {\n      width: 100%;\n      height: auto;\n      object-fit: contain;\n      display: block;\n      filter: drop-shadow(0 1px 2px rgba(0,0,0,0.18));\n    }\n\n    .customize-step--quantity {\n      text-align: center;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n    }\n\n    .step-title-top {\n      font-size: 1rem;\n      font-weight: 700;\n      margin-bottom: 1.5rem;\n    }\n\n    .qty-min-text {\n      font-size: 0.85rem;\n      color: #6B7280;\n      margin-top: 0.25rem;\n    }\n\n    \/* === FORZAR ALINEACIÓN PERFECTA DE LA PÍLDORA DE CANTIDAD === *\/\n    .customize-order-section .qty-control {\n      display: inline-flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      border-radius: 9999px !important;\n      border: 1px solid #D4D4D8 !important;\n      overflow: hidden !important;\n      background-color: #ffffff !important;\n      padding: 0 !important;\n      line-height: 0 !important;\n    }\n\n    .customize-order-section .qty-btn {\n      display: inline-flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      width: 60px !important;\n      height: 46px !important;\n      background-color: #FFC800 !important;\n      border: none !important;\n      cursor: pointer !important;\n      color: #111111 !important;\n      font-size: 1.6rem !important;\n      line-height: 1 !important;\n      padding: 0 !important;\n      margin: 0 !important;\n      box-shadow: none !important;\n    }\n\n    .customize-order-section .qty-input {\n      width: 80px !important;\n      height: 46px !important;\n      border: none !important;\n      outline: none !important;\n      text-align: center !important;\n      font-size: 1rem !important;\n      color: #111111 !important;\n      background-color: #ffffff !important;\n      display: flex !important;\n      align-items: center !important;\n      justify-content: center !important;\n      padding: 0 !important;\n      margin: 0 !important;\n      box-sizing: border-box !important;\n      line-height: 1 !important;\n    }\n\n    .customize-order-section .qty-btn span,\n    .customize-order-section .qty-btn,\n    .customize-order-section .qty-control * {\n      line-height: 1 !important;\n    }\n\n    \/* BOTÓN WHATSAPP VERDE *\/\n    .customize-order-section .whatsapp-quote-btn {\n      margin-top: 1.25rem;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      align-self: center;\n      padding: 0.9rem 2.5rem;\n      border-radius: 9999px;\n      border: none;\n      background-color: #25D366 !important; \/* Verde WhatsApp *\/\n      color: #ffffff !important;\n      font-size: 1rem;\n      font-weight: 600;\n      cursor: pointer;\n      white-space: nowrap;\n      box-shadow: 0 8px 20px rgba(0,0,0,0.12);\n      gap: 0.5rem; \/* separa icono y texto *\/\n    }\n    .customize-order-section .whatsapp-quote-btn:hover {\n      background-color: #1eb259 !important;\n    }\n\n    \/* Círculo blanco para el ícono *\/\n    .customize-order-section .wa-icon-circle {\n      width: 22px;\n      height: 22px;\n      border-radius: 9999px;\n      background-color: #ffffff;\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      overflow: hidden;\n      flex-shrink: 0;\n    }\n\n    \/* Imagen del ícono de WhatsApp *\/\n    .customize-order-section .wa-icon-img {\n      width: 16px;\n      height: 16px;\n      display: block;\n    }\n\n    .customize-order-section .wa-icon-phone,\n    .customize-order-section .wa-icon-phone::after {\n      display: none !important;\n    }\n\n    .customize-steps-row {\n      display: grid;\n      grid-template-columns: repeat(3, minmax(0, 1fr));\n      gap: 2rem;\n      margin-top: 1rem;\n      max-width: 1100px;\n      margin-left: auto;\n      margin-right: auto;\n    }\n    .customize-step-text {\n      text-align:center;\n      display:flex;\n      flex-direction:column;\n      align-items:center;\n    }\n    .step-circle {\n      width: 40px;\n      height: 40px;\n      border-radius: 9999px;\n      border: 2px solid #D4D4D8;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      margin: 0 auto 0.75rem auto;\n      font-weight: 600;\n      color: #111827;\n    }\n    .step-title {\n      font-size: 1rem;\n      font-weight: 700;\n      margin-bottom: 0.5rem;\n    }\n    .step-desc {\n      font-size: 0.875rem;\n      color: #6B7280;\n      line-height: 1.4;\n    }\n\n    @media (max-width: 900px) {\n      .customize-order-grid {\n        grid-template-columns: 1fr;\n      }\n      .customize-steps-row {\n        grid-template-columns: 1fr;\n      }\n      .customize-order-title {\n        text-align: center;\n      }\n      .customize-step--quantity {\n        text-align: center;\n        align-items: center;\n      }\n      .customize-order-section .whatsapp-quote-btn {\n        align-self: center;\n      }\n    }\n  \u003c\/style\u003e\n\n  \u003cscript\u003e\n    document.addEventListener('DOMContentLoaded', function() {\n      var fileInput       = document.getElementById('logo-upload-input');\n      var logoImg         = document.getElementById('mockup-logo-img');\n      var uploadPreview   = document.getElementById('upload-preview-img');\n      var clearBtn        = document.getElementById('clear-logo-btn');\n      var logoDataInput   = document.getElementById('logo-data-input');\n      var plusWrapper     = document.getElementById('upload-plus-wrapper');\n\n      var qtyInput  = document.getElementById('quote-quantity');\n      var qtyHidden = document.getElementById('quote-quantity-input');\n      var btnMinus  = document.getElementById('qty-minus');\n      var btnPlus   = document.getElementById('qty-plus');\n\n      var mockupPreview   = document.querySelector('.mockup-preview');\n      var mockupLogoWrap  = document.getElementById('mockup-logo-wrap');\n\n      if (fileInput \u0026\u0026 logoImg \u0026\u0026 logoDataInput) {\n        fileInput.addEventListener('change', function(event) {\n          var file = event.target.files[0];\n          if (!file) return;\n\n          var maxSizeMB = 2;\n          if (file.size \u003e maxSizeMB * 1024 * 1024) {\n            alert('La imagen es demasiado grande. Tamaño máximo: ' + maxSizeMB + ' MB');\n            fileInput.value = '';\n            return;\n          }\n\n          var reader = new FileReader();\n          reader.onload = function(e) {\n            var dataUrl = e.target.result;\n\n            logoImg.src = dataUrl;\n            logoImg.style.display = 'block';\n\n            if (uploadPreview) {\n              uploadPreview.src = dataUrl;\n              uploadPreview.style.display = 'block';\n            }\n\n            if (plusWrapper) plusWrapper.style.display = 'none';\n\n            logoDataInput.value = dataUrl;\n            clearBtn.style.display = 'inline-flex';\n\n            resetLogoPosition();\n          };\n          reader.readAsDataURL(file);\n        });\n\n        clearBtn.addEventListener('click', function() {\n          fileInput.value = '';\n\n          logoImg.src = '';\n          logoImg.style.display = 'none';\n\n          if (uploadPreview) {\n            uploadPreview.src = '';\n            uploadPreview.style.display = 'none';\n          }\n\n          if (plusWrapper) plusWrapper.style.display = 'flex';\n\n          logoDataInput.value = '';\n          clearBtn.style.display = 'none';\n\n          resetLogoPosition();\n        });\n      }\n\n      function resetLogoPosition() {\n        if (!mockupLogoWrap) return;\n        mockupLogoWrap.style.top = '55%';\n        mockupLogoWrap.style.left = '50%';\n        mockupLogoWrap.style.transform = 'translate(-50%, -50%)';\n        mockupLogoWrap.classList.remove('is-dragging');\n      }\n\n      if (mockupPreview \u0026\u0026 mockupLogoWrap) {\n        var isDragging = false;\n        var startX = 0;\n        var startY = 0;\n        var startLeft = 0;\n        var startTop = 0;\n\n        function getBounds() {\n          return mockupPreview.getBoundingClientRect();\n        }\n\n        function onPointerDown(e) {\n          if (!logoImg || logoImg.style.display === 'none') return;\n\n          isDragging = true;\n          mockupLogoWrap.classList.add('is-dragging');\n\n          var rect = getBounds();\n          var clientX = e.touches ? e.touches[0].clientX : e.clientX;\n          var clientY = e.touches ? e.touches[0].clientY : e.clientY;\n\n          startX = clientX;\n          startY = clientY;\n\n          var wrapRect = mockupLogoWrap.getBoundingClientRect();\n          startLeft = wrapRect.left - rect.left;\n          startTop  = wrapRect.top  - rect.top;\n\n          mockupLogoWrap.style.transform = 'none';\n\n          document.addEventListener('mousemove', onPointerMove);\n          document.addEventListener('mouseup', onPointerUp);\n          document.addEventListener('touchmove', onPointerMove, { passive: false });\n          document.addEventListener('touchend', onPointerUp);\n        }\n\n        function onPointerMove(e) {\n          if (!isDragging) return;\n          e.preventDefault();\n\n          var rect = getBounds();\n          var clientX = e.touches ? e.touches[0].clientX : e.clientX;\n          var clientY = e.touches ? e.touches[0].clientY : e.clientY;\n\n          var deltaX = clientX - startX;\n          var deltaY = clientY - startY;\n\n          var newLeft = startLeft + deltaX;\n          var newTop  = startTop + deltaY;\n\n          var wrapRect  = mockupLogoWrap.getBoundingClientRect();\n          var wrapWidth = wrapRect.width;\n          var wrapHeight = wrapRect.height;\n\n          var minLeft = 0;\n          var minTop  = 0;\n          var maxLeft = rect.width  - wrapWidth;\n          var maxTop  = rect.height - wrapHeight;\n\n          if (newLeft \u003c minLeft) newLeft = minLeft;\n          if (newTop  \u003c minTop)  newTop  = minTop;\n          if (newLeft \u003e maxLeft) newLeft = maxLeft;\n          if (newTop  \u003e maxTop)  newTop  = maxTop;\n\n          mockupLogoWrap.style.left = newLeft + 'px';\n          mockupLogoWrap.style.top  = newTop  + 'px';\n        }\n\n        function onPointerUp() {\n          if (!isDragging) return;\n          isDragging = false;\n          mockupLogoWrap.classList.remove('is-dragging');\n\n          document.removeEventListener('mousemove', onPointerMove);\n          document.removeEventListener('mouseup', onPointerUp);\n          document.removeEventListener('touchmove', onPointerMove);\n          document.removeEventListener('touchend', onPointerUp);\n        }\n\n        mockupLogoWrap.addEventListener('mousedown', onPointerDown);\n        mockupLogoWrap.addEventListener('touchstart', onPointerDown, { passive: true });\n      }\n\n      function sanitizeQty() {\n        if (!qtyInput || !qtyHidden) return;\n\n        var value = qtyInput.value.replace(\/[^0-9]\/g, '');\n        if (!value || Number(value) \u003c 1) {\n          value = '1';\n        }\n        qtyInput.value = value;\n        qtyHidden.value = value;\n      }\n\n      if (qtyInput \u0026\u0026 qtyHidden) {\n        qtyInput.addEventListener('change', sanitizeQty);\n        qtyInput.addEventListener('blur', sanitizeQty);\n      }\n\n      if (btnMinus \u0026\u0026 qtyInput) {\n        btnMinus.addEventListener('click', function() {\n          var current = Number(qtyInput.value || 1);\n          if (current \u003e 1) {\n            qtyInput.value = String(current - 1);\n            sanitizeQty();\n          }\n        });\n      }\n\n      if (btnPlus \u0026\u0026 qtyInput) {\n        btnPlus.addEventListener('click', function() {\n          var current = Number(qtyInput.value || 1);\n          qtyInput.value = String(current + 1);\n          sanitizeQty();\n        });\n      }\n\n      sanitizeQty();\n\n      \/* --- BOTÓN WHATSAPP --- *\/\n      var whatsappBtn    = document.getElementById('custom-whatsapp-btn');\n      var whatsappNumber = '525536684089'; \/\/ tu número sin + ni espacios\n\n      \/\/ EDITA ESTAS DOS LÍNEAS EN CADA PRODUCTO:\n      var productTitle   = \"Caja para pastel 30x30x11 cm CJ30 \";\n      var productUrl     = \"https:\/\/acesainter.com\/products\/caja-pastel-30x30x11-cj30?utm_source=copyToPasteBoard\u0026utm_medium=product-links\u0026utm_content=web\";\n\n      if (whatsappBtn \u0026\u0026 qtyHidden) {\n        whatsappBtn.addEventListener('click', function() {\n          var qty = parseInt(qtyHidden.value || '1', 10);\n          if (isNaN(qty) || qty \u003c 1) qty = 1;\n\n          var message =\n            \"Hola, quiero cotizar este producto personalizado con mi marca.%0A%0A\" +\n            \"Producto: \" + encodeURIComponent(productTitle) + \"%0A\" +\n            \"Cantidad: \" + encodeURIComponent(qty + \" cajas\") + \"%0A\" +\n            \"URL del producto: \" + encodeURIComponent(productUrl) + \"%0A%0A\" +\n            \"Por favor, confírmenme tiempos de producción, precios y opciones de personalización.\";\n\n          var waUrl = \"https:\/\/wa.me\/\" + whatsappNumber + \"?text=\" + message;\n          window.open(waUrl, \"_blank\");\n        });\n      }\n    });\n  \u003c\/script\u003e\n\u003c\/section\u003e\n","brand":"ACESA INTERABASTO S. A. de C.V.","offers":[{"title":"Default Title","offer_id":48148254654714,"sku":null,"price":10.0,"currency_code":"MXN","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/files\/50.jpg?v=1768505958"}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0794\/9883\/8266\/collections\/Coleccion_Accesorios_para_cafeterias_Accesa_Interabasto_070e3f77-abba-49b5-ba84-a8ecd7cb516b.jpg?v=1766167427","url":"https:\/\/acesainter.com\/collections\/bolsas-y-empaques.oembed?page=2","provider":"ACESA INTERABASTO S. A. de C.V.","version":"1.0","type":"link"}