{
  "version": 3,
  "sources": ["/cdn/shop/t/1064/assets/__blanksUploadHelper.js?auto=format%2Ccompress"],
  "sourcesContent": ["const apiURL = `https://hpz51rjda5.execute-api.us-east-1.amazonaws.com/production`;\n// const apiURL = `https://7rfb214pth.execute-api.us-east-1.amazonaws.com/production`;\nconst baseAmazonUrl = `s3.amazonaws.com`;\nconst ninjaImgixHost = `ninjauploads-production.imgix.net`;\nconst ninjaS3Host2 = `ninja-services-production-ninjauploadss3bucket-pj1r4ls6dsdh.s3.amazonaws.com`;\nconst ninjaS3Host = `ninjauploads-production.imgix.net`;\n\nlet uploadArea;\nlet fileInput;\nconst productURL = `/products/dtf-transfers`;\nselectedItemNo = 1;\nlet selectedBlockNo = 1;\nvar timeout__;\nconst AI_DAILY_LIMIT = 50;\nconst AI_STATES = {\n  ORIGINAL: \"original\",\n  PROCESSING: \"processing\",\n  RESULT: \"result\",\n  RESULT_ORG: \"result-org\"\n};\nlet designtype = false;\nlet grt_photo_id = '';\nconst imgParamsSettings = [\n  {\n    \"fileType\": \"png\",\n    \"preview\": \"trim=colorUnlessAlpha&w=2000\",\n    \"cart\": \"trim=colorUnlessAlpha&fm=png&auto=compress&q=50&h=150\",\n    \"order\": \"[imgIx]trim=colorUnlessAlpha\",\n    \"bgRemover\": true,\n    \"superRes\": true,\n    \"byDefaultBgRemover\": false,\n    \"byDefaultSuperRes\": false\n  },\n  {\n    \"fileType\": \"jpg\",\n    \"preview\": \"trim=colorUnlessAlpha&fm=png&w=2000\",\n    \"cart\": \"trim=colorUnlessAlpha&fm=png&auto=compress&q=50&h=150\",\n    \"order\": \"[imgIx]trim=colorUnlessAlpha\",\n    \"bgRemover\": true,\n    \"superRes\": true,\n    \"byDefaultBgRemover\": true,\n    \"byDefaultSuperRes\": false\n  },\n  {\n    \"fileType\": \"ai\",\n    \"preview\": \"trim=colorUnlessAlpha&fm=png&w=2000\",\n    \"cart\": \"trim=colorUnlessAlpha&fm=png&auto=compress&q=50&h=150\",\n    \"order\": \"[BOTH_S3]\",\n    \"bgRemover\": false,\n    \"superRes\": false,\n    \"byDefaultBgRemover\": false,\n    \"byDefaultSuperRes\": false\n  },\n  {\n    \"fileType\": \"eps\",\n    \"preview\": \"fm=png&w=2000\",\n    \"cart\": \"trim=colorUnlessAlpha&fm=png&auto=compress&q=50&h=150\",\n    \"order\": \"[BOTH_S3]\",\n    \"bgRemover\": false,\n    \"superRes\": false,\n    \"byDefaultBgRemover\": false,\n    \"byDefaultSuperRes\": false\n  },\n  {\n    \"fileType\": \"pdf\",\n    \"preview\": \"trim=colorUnlessAlpha&fm=png&w=2000\",\n    \"cart\": \"trim=colorUnlessAlpha&fm=png&auto=compress&q=50&h=150\",\n    \"order\": \"[BOTH_S3]\",\n    \"bgRemover\": false,\n    \"superRes\": false,\n    \"byDefaultBgRemover\": false,\n    \"byDefaultSuperRes\": false\n  },\n  {\n    \"fileType\": \"tif\",\n    \"preview\": \"trim=colorUnlessAlpha&w=2000\",\n    \"cart\": \"trim=colorUnlessAlpha&fm=png&auto=compress&q=50&h=150\",\n    \"order\": \"[imgIx]fm=png\",\n    \"bgRemover\": true,\n    \"superRes\": false,\n    \"byDefaultBgRemover\": false,\n    \"byDefaultSuperRes\": false\n  },\n  {\n    \"fileType\": \"svg\",\n    \"preview\": \"trim=colorUnlessAlpha&fm=png&w=2000\",\n    \"cart\": \"trim=colorUnlessAlpha&fm=png&auto=compress&q=50&h=150\",\n    \"order\": \"[BOTH_S3]\",\n    \"bgRemover\": false,\n    \"superRes\": false,\n    \"byDefaultBgRemover\": false,\n    \"byDefaultSuperRes\": false\n  }\n]\n\nfunction initBlanksUploadBox() {\n  /* DELEGATED bindings on `document` so the upload box keeps working after a\n     variant/color change. Changing the shirt color re-renders the product\n     column, which REPLACES the .uploadBox element with a fresh node \u2014 the\n     previous approach bound the click/drag handlers directly to that node, so\n     they were lost on re-render and \"Upload Your Design\" stopped responding.\n     Delegation targets whatever .uploadBox__layout / #fileInput is currently\n     in the DOM, so it survives any number of re-renders. We also refresh the\n     module-level uploadArea/fileInput refs on each interaction so the rest of\n     this file (which resets fileInput.value after processing) acts on the\n     current elements, not stale ones. */\n  if (window.__blanksUploadBoxDelegated) return;\n  window.__blanksUploadBoxDelegated = true;\n\n  /* Click anywhere in the upload box \u2192 open the current file input. */\n  document.addEventListener('click', function (e) {\n    if (!e.target || !e.target.closest) return;\n    var area = e.target.closest('.uploadBox .uploadBox__layout');\n    if (!area) return;\n    uploadArea = area;\n    var fi = document.querySelector('.uploadBox #fileInput');\n    if (fi) { fileInput = fi; fi.click(); }\n  });\n\n  /* A file chosen in the current input \u2192 process it. */\n  document.addEventListener('change', function (e) {\n    if (e.target && e.target.matches && e.target.matches('.uploadBox #fileInput')) {\n      fileInput = e.target;\n      manageFiles(e.target.files);\n    }\n  });\n\n  /* Drag & drop onto the upload box. */\n  document.addEventListener('dragover', function (e) {\n    var area = e.target && e.target.closest && e.target.closest('.uploadBox .uploadBox__layout');\n    if (!area) return;\n    e.preventDefault();\n    area.classList.add('drop-zone--over');\n  });\n  document.addEventListener('dragleave', function (e) {\n    var area = e.target && e.target.closest && e.target.closest('.uploadBox .uploadBox__layout');\n    if (area) area.classList.remove('drop-zone--over');\n  });\n  document.addEventListener('drop', function (e) {\n    var area = e.target && e.target.closest && e.target.closest('.uploadBox .uploadBox__layout');\n    if (!area) return;\n    e.preventDefault();\n    area.classList.remove('drop-zone--over');\n    uploadArea = area;\n    manageFiles(e.dataTransfer.files);\n  });\n}\n\nwindow.initBlanksUploadBox = initBlanksUploadBox;\ninitBlanksUploadBox();\n\n// Bridge: My Designs picker selection \u2192 blanks multi-upload modal.\n// The picker fires `md-picker:use-designs` with `{items: [{file, fileName, id}, ...]}`.\n// We fetch each URL into a File and feed it through the existing\n// multiFilesManage pipeline so designs appear as new blocks alongside\n// any files the user already added \u2014 same UX as a fresh upload.\nif (!window.__blanksMdPickerBridgeBound) {\n  window.__blanksMdPickerBridgeBound = true;\n  document.addEventListener('md-picker:use-designs', async function (e) {\n    try {\n      var items = (e.detail && e.detail.items) || [];\n      if (!items.length) return;\n      if (typeof multiFilesManage !== 'function') return;\n\n      var overlay = document.querySelector('.customTabelPopup__overlay-3');\n      if (overlay) overlay.style.setProperty('display', 'none', 'important');\n\n      // Make sure the multi-upload modal exists (it gets created on first upload).\n      // If user picks designs without uploading first, activateMultiupload sets it up.\n      if (!document.querySelector('body multi-upload-wrapper') && typeof activateMultiupload === 'function') {\n        await activateMultiupload();\n      }\n\n      var filesCounter = $(`multi-upload file-blocks-area uploaded-files-block`).length;\n      var beforeUploadAvailableBlocks = filesCounter;\n\n      for (var i = 0; i < items.length; i++) {\n        var url = (items[i] && items[i].file) ? String(items[i].file) : '';\n        if (!url) continue;\n        if (url.indexOf('?') > -1) url = url.split('?')[0];\n        if (typeof ninjaS3Host2 !== 'undefined' && typeof ninjaS3Host !== 'undefined') {\n          url = url.split(ninjaS3Host2).join(ninjaS3Host);\n        }\n\n        try {\n          var response = await fetch(url);\n          if (!response.ok) continue;\n          var blob = await response.blob();\n          var nameFromUrl = items[i].fileName || url.split('/').pop();\n          if (!nameFromUrl || !nameFromUrl.includes('.')) {\n            nameFromUrl = 'design_' + Date.now() + '.png';\n          }\n          var file = new File([blob], nameFromUrl, { type: blob.type || 'image/png' });\n\n          filesCounter++;\n          await multiFilesManage(file, filesCounter);\n        } catch (err) {\n          console.log('ERROR fetching design from picker', url, err && err.message);\n        }\n      }\n\n      // Scroll the multi-upload modal's scroll container so the first\n      // newly-added block lands at the top of view. Direct scrollTop\n      // animation on `multi-upload upload-area` (the actual scroll\n      // container \u2014 confirmed via getComputedStyle: overflow-y auto,\n      // scrollHeight > clientHeight) is more reliable here than\n      // Element.scrollIntoView, which can no-op inside the fixed-position\n      // modal wrapper.\n      setTimeout(function () {\n        var $newest = $(`multi-upload file-blocks-area uploaded-files-block`).eq(beforeUploadAvailableBlocks);\n        var $ua = $(`multi-upload upload-area`);\n        if ($newest.length && $ua.length) {\n          $ua.animate({ scrollTop: $newest[0].offsetTop }, 500);\n        }\n      }, 500);\n    } catch (err) {\n      console.log('ERROR md-picker:use-designs (blanks)', err && err.message);\n    }\n  });\n}\n\n$(document)\n.ready(function () {\n  $( `#fileInput` ).val(``);\n})\n// ANOTHER UPLOAD START\n.on(`click`, `multi-upload another-upload-multi`, function( e ) {\n  try {\n    // The \"Choose a previously uploaded design\" link lives inside the\n    // dropzone (.access_old_data > .purchase_from_previous). Without\n    // this guard, clicks on that link bubble up to here, get\n    // stopImmediatePropagation()'d, and then fire the file input \u2014\n    // i.e. the user clicks \"previous designs\" and gets the native file\n    // picker instead. Let the link's own handler take the click.\n    if ( e.target.closest( `.access_old_data, .purchase_from_previous` ) ) {\n      return;\n    }\n    e.stopImmediatePropagation();\n    $( `#anotherFileMultiple` ).click();\n  } catch ( err ) {\n    console.log( `ERROR multi-upload another-upload-multi`, err.message );\n  }\n})\n.on(`click`, `.purchase_from_previous`, function( e ) {\n  try {\n    e.preventDefault();\n    e.stopImmediatePropagation();\n    // The Artwork Library v2 modal when the page renders it (__uploadBoxBlock.liquid, blanks,\n    // 2026-09-15): its md-picker:use-designs pick is bridged above exactly like the old\n    // picker's. The old overlay-3 picker stays as the fallback.\n    if ( window.NTArtworkLibrary && typeof window.NTArtworkLibrary.open === `function` && document.querySelector( `[data-alv2-modal]` ) ) {\n      window.NTArtworkLibrary.open();\n      return;\n    }\n    const $overlay = $( `.customTabelPopup__overlay-3` );\n    if ( $overlay.length === 0 ) return;\n    $overlay.attr( `data-type`, $( this ).data( `type` ) || `` );\n    $overlay.fadeIn( 500 );\n  } catch ( err ) {\n    console.log( `ERROR .purchase_from_previous (blanks)`, err.message );\n  }\n})\n.on(`change`, `multi-upload #anotherFileMultiple`, function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    console.log ( 'e', e.target.files );\n    let filesCounter = $( `multi-upload uploaded-files-block` ).length;\n    let beforeUploadAvailableBlocks = filesCounter;\n    for (const file of e.target.files) {\n      filesCounter++;\n      multiFilesManage( file, filesCounter );\n    }\n    setTimeout(() => {\n      setFocusOfMultiUpload( beforeUploadAvailableBlocks );\n    }, 500);\n  } catch ( err ) {\n    console.log( `ERROR multi-upload #anotherFileMultiple`, err.message );\n  }\n})\n.on(`dragover`, `multi-upload another-upload-multi`, function (e) {\n  e.preventDefault();\n  e.stopPropagation();\n  $( this ).addClass( `dragover` );\n})\n.on(`dragleave`, `multi-upload another-upload-multi`, function (e) {\n  e.preventDefault();\n  e.stopPropagation();\n  $( this ).removeClass( `dragover` );\n})\n.on(`drop`, `multi-upload another-upload-multi`, function (e) {\n  e.preventDefault();\n  e.stopPropagation();\n  $( this ).removeClass( `dragover` );\n\n  const files = e.originalEvent.dataTransfer.files;\n  let beforeUploadAvailableBlocks = 0;\n  let filesCounter = 0;\n  if ( files.length ) {\n    filesCounter = $( `multi-upload uploaded-files-block` ).length;\n    beforeUploadAvailableBlocks = filesCounter;\n    console.log ( 'filesCounter', filesCounter );\n    for (const file of files) {\n      filesCounter++;\n      multiFilesManage( file, filesCounter );\n    }\n  }\n  setTimeout(() => {\n    setFocusOfMultiUpload( beforeUploadAvailableBlocks );\n  }, 500);\n})\n// ANOTHER UPLOAD END\n.on(`click`, `multi-upload sizes-blocks .widthHeight__custom.disabled[option-selected]`, function( e ) {\n  // Click-to-reactivate a grayed (inactive-tab) row \u2014 mirror of the DTF\n  // popup engine's handler; the .disabled white ::after overlay intercepts\n  // clicks so inputs can't be focused directly.\n  try {\n    e.stopImmediatePropagation();\n    const rowType = $( this ).attr( `option-selected` );\n    const $block = $( this ).closest( `uploaded-files-block` );\n    selectedBlockNo = $block.attr( `block-no` );\n    selectedItemNo = $( this ).attr( `item` );\n    $block.find( `tab-controls .tabOptionName[value=\"${ rowType }\"]` ).prop( `checked`, true ).trigger( `change` );\n  } catch ( err ) {\n    console.log( `ERROR multi-upload .widthHeight__custom.disabled click`, err.message );\n  }\n})\n.on(`focus`, `multi-upload sizes-blocks .widthHeight__value, multi-upload sizes-blocks .customQtyFile__qty, multi-upload sizes-blocks .popularSizes`, function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    selectedBlockNo = $( this ).closest( `uploaded-files-block` ).attr( `block-no` );\n    selectedItemNo = $( this ).closest( `.widthHeight__custom[item]` ).attr( `item` );\n    const selectedItemOption = $( this ).closest( `.widthHeight__custom[item]` ).attr( `option-selected` );\n    const activeTab = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] tab-controls .tabOptionName:checked` ).val();\n    if ( activeTab == 'custom' && selectedItemOption == 'popular' ) {\n      $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] tab-controls .tabOptionName[value=\"${ selectedItemOption }\"]` ).prop( `checked`, true );\n    } else if ( activeTab == 'popular' && selectedItemOption == 'custom' ) {\n      $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] tab-controls .tabOptionName[value=\"${ selectedItemOption }\"]` ).prop( `checked`, true );\n    }\n    pricesTable();\n    updatePreviewBoxSizes();\n    $( this ).select();\n    setActiveRow();\n  } catch ( err ) {\n    console.log( `ERROR multi-upload sizes-blocks .widthHeight__value, multi-upload sizes-blocks .customQtyFile__qty, multi-upload sizes-blocks .popularSizes`, err.message );\n  }\n})\n// CUSTOM SIZE INCREASE DECREASE START\n.on(`click`, `sizes-blocks .widthHeight__value-minus`, function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    selectedItemNo = $( this ).closest( `.widthHeight__custom` ).attr( `item` );\n    const getVal = $( this ).closest( `.widthHeight__item_inputWrapper` ).find( `.widthHeight__value` ).val() * 1;\n    const getStep = $( this ).closest( `.widthHeight__item_inputWrapper` ).find( `.widthHeight__value` ).attr( `step` ) * 1;\n\n    if ( uploadType == 'multi' ) {\n      selectedBlockNo = $( this ).closest( `uploaded-files-block` ).attr( `block-no` );\n      const activeTab = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] tab-controls .tabOptionName:checked` ).val();\n      if ( activeTab == 'popular' ) {\n        $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] tab-controls .tabOptionName[value=\"custom\"]` ).prop( `checked`, true );\n      }\n    }\n\n    setActiveRow();\n\n    $( this ).closest( `.widthHeight__item_inputWrapper` ).find( `.widthHeight__value` ).val( ( getVal - getStep ).toFixed( 2 ) ).trigger( `keyup` );\n  } catch ( err ) {\n    console.log( `ERROR sizes-blocks .widthHeight__value-minus`, err.message );\n  }\n})\n.on(`click`, `sizes-blocks .widthHeight__value-plus`, function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    selectedItemNo = $( this ).closest( `.widthHeight__custom` ).attr( `item` );\n    const getVal = $( this ).closest( `.widthHeight__item_inputWrapper` ).find( `.widthHeight__value` ).val() * 1;\n    const getStep = $( this ).closest( `.widthHeight__item_inputWrapper` ).find( `.widthHeight__value` ).attr( `step` ) * 1;\n    if ( uploadType == 'multi' ) {\n      selectedBlockNo = $( this ).closest( `uploaded-files-block` ).attr( `block-no` );\n      const activeTab = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] tab-controls .tabOptionName:checked` ).val();\n      if ( activeTab == 'popular' ) {\n        $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] tab-controls .tabOptionName[value=\"custom\"]` ).prop( `checked`, true );\n      }\n    }\n    setActiveRow();\n    $( this ).closest( `.widthHeight__item_inputWrapper` ).find( `.widthHeight__value` ).val( ( getVal + getStep ).toFixed( 2 ) ).trigger( `keyup` );\n  } catch ( err ) {\n    console.log( `ERROR sizes-blocks .widthHeight__value-plus`, err.message );\n  }\n})\n// CUSTOM SIZE INCREASE DECREASE END\n.on(`keyup`, `upload-controls sizes-blocks input[name=\"width__value\"], upload-controls sizes-blocks input[name=\"height__value\"], multi-upload sizes-blocks input[name=\"width__value\"], multi-upload sizes-blocks input[name=\"height__value\"]`,async function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    selectedBlockNo = $( this ).closest( `uploaded-files-block` ).attr( `block-no` );\n    selectedItemNo = $( this ).closest( `.widthHeight__custom[item]` ).attr( `item` );\n    if ( uploadType == 'multi' ) {\n      $( `multi-upload .addToCartGroupItemsMultiple` ).addClass( `disabled` );\n    }\n\n    clearTimeout( timeout__ );\n    timeout__ = setTimeout(() => {\n      let isSizesBlock = $( `upload-controls sizes-blocks` ).length;\n      if ( uploadType == 'multi' ) {\n        isSizesBlock = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] sizes-blocks` ).length;\n      }\n      if ( isSizesBlock > 0 ) {\n        let dpiErr = false;\n        const item = $( this ).closest( `.widthHeight__custom[item]` );\n        const selectedOption__ = item.attr( `option-selected` );\n        let getVal = $( this ).val() * 1;\n        console.log ( 'getVal', getVal );\n        let otherVal = 0;\n        let by = $( this ).closest( `.widthHeight__item` ).attr( `by` );\n        if ( by == 'width' ) {\n          otherVal = $( this ).closest( `.widthHeight__custom` ).find( `.widthHeight__item[by=\"height\"] .widthHeight__value` ).val() * 1;\n        } else if ( by == 'height' ) {\n          otherVal = $( this ).closest( `.widthHeight__custom` ).find( `.widthHeight__item[by=\"width\"] .widthHeight__value` ).val() * 1;\n        }\n        let isWarningErrorActive = item.find( `dpi-warning` ).hasClass( `active` );\n        if ( getVal < definedMinWidth ) {\n          $( this ).val( definedMinWidth ).attr( `value`, definedMinWidth ).addClass( `minError` );\n          getVal = definedMinWidth;\n          if ( isWarningErrorActive ) {\n            item.find( `dpi-warning` ).removeClass( `active` );\n            dpiErr = true;\n          }\n        }\n        let largerDefinedVal;\n        if ( definedMaxWidth == definedMaxHeight ) {\n          largerDefinedVal = definedMaxWidth;\n        } else if ( definedMaxWidth > definedMaxHeight ) {\n          largerDefinedVal = definedMaxWidth;\n        } else if ( definedMaxHeight > definedMaxWidth ) {\n          largerDefinedVal = definedMaxHeight;\n        }\n        if ( getVal == otherVal && getVal > definedMaxWidth ) {\n          console.log ( 'this condition true',  );\n        }\n        if ( by == 'width' && getVal > definedMaxWidth ) {\n          $( this ).val( definedMaxWidth ).addClass( `error` );\n          getVal = definedMaxWidth;\n          if ( isWarningErrorActive ) {\n            item.find( `dpi-warning` ).removeClass( `active` );\n            dpiErr = true;\n          }\n        } else if ( by == 'height' && getVal > definedMaxHeight ) {\n          $( this ).val( definedMaxHeight ).addClass( `error` );\n          getVal = definedMaxHeight;\n          if ( isWarningErrorActive ) {\n            item.find( `dpi-warning` ).removeClass( `active` );\n            dpiErr = true;\n          }\n        }\n        let getRatio;\n        if ( uploadType == 'multi' ) {\n          getRatio = getNewRatio( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] preview-box .fileupload_hero`, by );\n        }\n\n        const newVal = calculateNewWidth_orNewHeight( getRatio, by, getVal );\n\n        console.log ( 'newVal', newVal );\n\n        if ( by == 'height' && newVal > definedMaxWidth ) {\n          item.find( `.widthHeight__item[by=\"width\"] .widthHeight__value` ).val( definedMaxWidth ).attr( `value`, definedMaxWidth ).addClass( `error` );\n\n          let getRatio;\n          if ( uploadType == 'multi' ) {\n            getRatio = getNewRatio( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] preview-box .fileupload_hero`, 'width' );\n          }\n\n          const newVal_ = calculateNewWidth_orNewHeight( getRatio, 'width', definedMaxWidth );\n          console.log ( 'newVal_ H', newVal_ );\n          item.find( `.widthHeight__item[by=\"${ by }\"] .widthHeight__value` ).val( newVal_.toFixed( 2 ) ).attr( `value`, newVal_.toFixed( 2 ) ).addClass( `error` );\n\n          if ( isWarningErrorActive ) {\n            item.find( `dpi-warning` ).removeClass( `active` );\n            dpiErr = true;\n          }\n        } else if ( by == 'width' && newVal > definedMaxHeight ) {\n          item.find( `.widthHeight__item[by=\"height\"] .widthHeight__value` ).val( definedMaxHeight ).attr( `value`, definedMaxHeight ).addClass( `error` );\n          let getRatio;\n          if ( uploadType == 'multi' ) {\n            getRatio = getNewRatio( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] preview-box .fileupload_hero`, 'height' );\n          }\n          const newVal_ = calculateNewWidth_orNewHeight( getRatio, 'height', definedMaxHeight );\n          console.log ( 'newVal_ W', newVal_ );\n          item.find( `.widthHeight__item[by=\"${ by }\"] .widthHeight__value` ).val( newVal_.toFixed( 2 ) ).attr( `value`, newVal_.toFixed( 2 ) ).addClass( `error` );\n\n          if ( isWarningErrorActive ) {\n            item.find( `dpi-warning` ).removeClass( `active` );\n            dpiErr = true;\n          }\n        } else if ( newVal < definedMinWidth ) {\n          if ( by == 'width' ) {\n            item.find( `.widthHeight__item[by=\"height\"] .widthHeight__value` ).val( definedMinWidth ).attr( `value`, definedMinWidth ).addClass( `minError` );\n            let getRatio;\n            if ( uploadType == 'multi' ) {\n              getRatio = getNewRatio( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] preview-box .fileupload_hero`, 'height' );\n            }\n\n            const newVal = calculateNewWidth_orNewHeight( getRatio, 'height', definedMinWidth );\n            item.find( `.widthHeight__item[by=\"${ by }\"] .widthHeight__value` ).val( newVal.toFixed( 2 ) ).attr( `value`, newVal.toFixed( 2 ) ).addClass( `minError` );\n\n            if ( isWarningErrorActive ) {\n              item.find( `dpi-warning` ).removeClass( `active` );\n              dpiErr = true;\n            }\n          } else if ( by == 'height' ) {\n            item.find( `.widthHeight__item[by=\"width\"] .widthHeight__value` ).val( definedMinWidth ).attr( `value`, definedMinWidth ).addClass( `minError` );\n            let getRatio;\n            if ( uploadType == 'multi' ) {\n              getRatio = getNewRatio( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] preview-box .fileupload_hero`, 'width' );\n            }\n            const newVal = calculateNewWidth_orNewHeight( getRatio, 'width', definedMinWidth );\n            item.find( `.widthHeight__item[by=\"${ by }\"] .widthHeight__value` ).val( newVal.toFixed( 2 ) ).attr( `value`, newVal.toFixed( 2 ) ).addClass( `minError` );\n\n            if ( isWarningErrorActive ) {\n              item.find( `dpi-warning` ).removeClass( `active` );\n              dpiErr = true;\n            }\n          }\n        } else {\n          if ( by == 'width' ) {\n            item.find( `.widthHeight__item[by=\"height\"] .widthHeight__value` ).val( newVal.toFixed( 2 ) ).attr( `value`, newVal.toFixed( 2 ) );\n          } else if ( by == 'height' ) {\n            item.find( `.widthHeight__item[by=\"width\"] .widthHeight__value` ).val( newVal.toFixed( 2 ) ).attr( `value`, newVal.toFixed( 2 ) );\n          }\n        }\n\n        setTimeout(() => {\n          let updatedWidth, updatedHeight;\n          if ( uploadType == 'multi' ) {\n            updatedWidth = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] sizes-blocks .widthHeight__custom[item=\"${ selectedItemNo }\"] input[name=\"width__value\"]` ).val();\n            updatedHeight = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] sizes-blocks .widthHeight__custom[item=\"${ selectedItemNo }\"] input[name=\"height__value\"]` ).val();\n          }\n\n          if ( typeof updatedWidth !== 'undefined' && updatedWidth && typeof updatedHeight !== 'undefined' && updatedHeight ) {\n            let fileDetails = getFileDetailsFunction( selectedBlockNo );\n            if ( typeof fileDetails !== 'undefined' && fileDetails ) {\n              fileDetails.currentWidth = updatedWidth,\n              fileDetails.currentHeight = updatedHeight\n\n              if ( typeof fileDetails.vector_currentWidth !== 'undefined' && fileDetails.vector_currentWidth && typeof fileDetails.vector_currentHeight !== 'undefined' && fileDetails.vector_currentHeight ) {\n                fileDetails.vector_currentWidth = updatedWidth\n                fileDetails.vector_currentHeight = updatedHeight\n              }\n\n              const matchedVariant = getMatchingVariant( fileDetails, selectedBlockNo );\n              console.log ( 'matchedVariant', matchedVariant );\n              matched_variant = matchedVariant;\n              if ( typeof matchedVariant !== 'undefined' && matchedVariant ) {\n                applyImgToPreviewBox( fileDetails, matchedVariant, false, selectedBlockNo, `no` );\n              }\n            }\n            console.log ( 'fileDetails', fileDetails );\n            if ( uploadType == 'multi' ) {\n              $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] sizes-blocks .widthHeight__custom[item=\"${ selectedItemNo }\"]` ).attr({\n                \"w\": updatedWidth,\n                \"h\": updatedHeight,\n                \"size\": `${ updatedWidth }x${ updatedHeight }`\n              });\n            }\n          }\n\n          console.log ( 'updatedWidth', updatedWidth );\n          console.log ( 'updatedHeight', updatedHeight );\n\n          calculateDPILineItem( selectedBlockNo )\n        }, 500);\n\n        setTimeout(() => {\n          item.find( `.widthHeight__item .widthHeight__value` ).removeClass( `error minError` );\n          if ( dpiErr ) {\n            item.find( `dpi-warning` ).addClass( `active` );\n            dpiErr = false;\n          }\n        }, 1500);\n      }\n      if ( uploadType == 'multi' ) {\n        $( `multi-upload .addToCartGroupItemsMultiple` ).removeClass( `disabled` );\n      }\n      setActiveRow();\n    }, 300);\n  } catch ( err ) {\n    console.log( `ERROR upload-controls input[name=\"width__value\"], upload-controls input[name=\"height__value\"]`, err.message );\n  }\n})\n.on(`keyup`, `upload-controls sizes-blocks .customQtyFile__qty, multi-upload sizes-blocks .customQtyFile__qty`, function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    selectedBlockNo = $( this ).closest( `uploaded-files-block` ).attr( `block-no` );\n    selectedItemNo = $( this ).closest( `.widthHeight__custom[item]` ).attr( `item` );\n    if ( uploadType == 'multi' ) {\n      $( `multi-upload .addToCartGroupItemsMultiple` ).addClass( `disabled` );\n    }\n    clearTimeout( timeout__ );\n    timeout__ = setTimeout(() => {\n      const getVal = $( this ).val() * 1;\n      var pattern = /^[0-9]+$/;\n      let isError = false;\n      let setQty = 0;\n      if ( pattern.test( getVal ) ) {\n        if ( getVal < definedMinQty ) {\n          isError = true;\n          setQty = definedMinQty;\n        } else {\n          setQty = getVal;\n        }\n      } else {\n        isError = true;\n        setQty = definedMinQty;\n      }\n      if ( isError ) {\n        $( this ).closest( `.widthHeight__custom` ).attr( `qty`, setQty );\n        $( this ).val( setQty ).addClass( `error` );\n      } else {\n        $( this ).closest( `.widthHeight__custom` ).attr( `qty`, setQty );\n        $( this ).removeClass( `error` );\n        calculatePrices();\n      }\n      calculateTotalQty();\n      setTimeout(() => {\n        $( this ).removeClass( `error` );\n      }, 1500);\n      if ( uploadType == 'multi' ) {\n        $( `multi-upload .addToCartGroupItemsMultiple` ).removeClass( `disabled` );\n      }\n      setActiveRow();\n    }, 300);\n  } catch ( err ) {\n    console.log( `ERROR upload-controls sizes-blocks .customQtyFile__qty`, err.message );\n  }\n})\n.on(`change`, `multi-upload tab-controls .tabOptionName`,async function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    selectedBlockNo = $( this ).closest( `uploaded-files-block` ).attr( `block-no` );\n    console.log ( 'selectedBlockNo', selectedBlockNo );\n    const isAdded = await checkAndAddNewSizeRow( selectedBlockNo );\n    console.log ( 'isAdded', isAdded );\n    let activeOption = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] tab-controls .tabOptionName:checked` ).val();\n    if ( isAdded ) {\n      let fileDetails = getFileDetailsFunction( selectedBlockNo );\n      if ( typeof fileDetails !== 'undefined' && fileDetails ) {\n        const matchedVariant = getMatchingVariant( fileDetails, selectedBlockNo );\n        if ( typeof matchedVariant !== 'undefined' && matchedVariant ) {\n          applyImgToPreviewBox( fileDetails, matchedVariant, false, selectedBlockNo );\n\n          if ( activeOption == 'custom' ) {\n            updateLineItemData( fileDetails.currentWidth, fileDetails.currentHeight, selectedBlockNo )\n          } else if ( activeOption == 'popular' ) {\n            const getDimension = getWidthHeight_popularSize( matchedVariant.option1_converted );\n            updateLineItemData( getDimension.width, getDimension.height, selectedBlockNo );\n          }\n        }\n      }\n    }\n    // let isRowSelected = false;\n    if ( activeOption == 'custom' ) {\n      const isAvailable = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] sizes-blocks line-items-custom .widthHeight__custom` ).length;\n      if ( isAvailable > 0 ) {\n        selectedItemNo = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] sizes-blocks line-items-custom .widthHeight__custom` ).last().attr( `item` );\n      }\n    } else if ( activeOption == 'popular' ) {\n      const isAvailable = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] sizes-blocks line-items-popular .widthHeight__custom` ).length;\n      if ( isAvailable > 0 ) {\n        selectedItemNo = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] sizes-blocks line-items-popular .widthHeight__custom` ).last().attr( `item` );\n      }\n    }\n\n    // pricesTable();\n    updatePreviewBoxSizes();\n    setActiveRow();\n    // console.log ( 'selectedItemNo', selectedItemNo );\n  } catch ( err ) {\n    console.log( `ERROR multi-upload tab-controls .tabOptionName`, err.message );\n  }\n})\n.on(`change`, `multi-upload sizes-blocks .popularSizes`,async function( e ) {\n  try {\n    e.stopPropagation();\n    console.clear();\n\n    console.log ( 'chaaaaaaa',  );\n\n    const selectedVal = $(this).val();\n    if (!selectedVal) return;\n\n    selectedBlockNo = $( this ).closest( `uploaded-files-block` ).attr( `block-no` );\n    selectedItemNo = $( this ).closest( `.widthHeight__custom[item]` ).attr( `item` );\n\n    console.log ( 'selectedBlockNo', selectedBlockNo );\n    console.log ( 'selectedItemNo', selectedItemNo );\n\n    const $row      = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] sizes-blocks .widthHeight__custom[item=\"${ selectedItemNo }\"]` );\n\n    // let activeOption = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] tab-controls .tabOptionName:checked` ).val();\n    let fileDetails = getFileDetailsFunction( selectedBlockNo );\n    if ( typeof fileDetails !== 'undefined' && fileDetails ) {\n      let largerIs = Math.ceil(fileDetails.fileWidth) >= Math.ceil(fileDetails.fileHeight) ? 'width' : 'height';\n      // let largerIs =fileDetails.fileHeight ? 'width' : 'height';\n\n      console.log ( 'fileDetails', fileDetails );\n\n      console.log ( 'largerIs', largerIs );\n\n      const matchedVariant = getMatchingVariant( fileDetails, selectedBlockNo );\n\n      if ( typeof matchedVariant !== 'undefined' && matchedVariant ) {\n        console.log ( 'matchedVariant', matchedVariant );\n\n        if ( typeof smartSizing !== 'undefined' && smartSizing ) {\n          console.log ( 'yes it is',  );\n          let width  = 0;\n          let height = 0;\n          if ( matchedVariant && matchedVariant.option1_converted ) {\n            const dim = getWidthHeight_popularSize( matchedVariant.option1_converted );\n            if (dim) {\n              width  = dim.width;\n              height = dim.height;\n            }\n          }\n\n          console.log ( 'width', width, 'height', height );\n\n          let updatedDim = {};\n\n          if ( largerIs == 'width' ) {\n            console.log ( 'its by width', Math.ceil(fileDetails.fileWidth), Math.ceil(fileDetails.fileHeight) );\n            updatedDim = getProportionalSize( width, 'width', Math.ceil(fileDetails.fileWidth), Math.ceil(fileDetails.fileHeight) );\n          } else {\n            console.log ( 'its by height', Math.ceil(fileDetails.fileWidth), Math.ceil(fileDetails.fileHeight) );\n            updatedDim = getProportionalSize( height, 'height', Math.ceil(fileDetails.fileWidth), Math.ceil(fileDetails.fileHeight) );\n          }\n\n          width = updatedDim.width;\n          height = updatedDim.height;\n\n          console.log ( 'updatedDim', updatedDim );\n\n          const $select = $(this);\n\n          resetPopularOptionLabels($select);\n\n          const $option = $select.find('option:selected');\n          const originalLabel = $option.data('original-label') || $.trim($option.text());\n\n          console.log ( 'originalLabel', originalLabel );\n\n          if (!$option.data('original-label')) {\n            $option.data('original-label', originalLabel);\n          }\n\n          const parts = originalLabel.split('-');\n          const desc  = parts.length > 1 ? '-' + parts.slice(1).join('-') : '';\n\n          const wLabel = formatInchesValue(width);\n          const hLabel = formatInchesValue(height);\n\n          const newLabel = `${wLabel}\" x ${hLabel}\" ${desc}`;\n          $option.text(newLabel);\n\n          fileDetails.currentWidth  = width;\n          fileDetails.currentHeight = height;\n\n          const matchedPricingVariant = getVariantForSmartSize(width, height);\n\n          console.log ( 'matchedPricingVariant', matchedPricingVariant );\n\n          if (matchedPricingVariant) {\n            $row.attr({\n              \"title\": matchedPricingVariant.title,\n              \"vid\": matchedPricingVariant.id,\n              \"dpi-warning\": '',\n              \"price\": matchedPricingVariant.price,\n              \"media-id\": matchedPricingVariant.media_id,\n              \"w\": width,\n              \"h\": height,\n              \"size\": `${ width }x${ height }`\n            });\n          }\n\n          applyImgToPreviewBox( fileDetails, matchedPricingVariant, false, selectedBlockNo, `no` );\n          updateLineItemData( width, height, selectedBlockNo );\n        } else {\n          applyImgToPreviewBox( fileDetails, matchedVariant, false, selectedBlockNo, `no` );\n          const getDimension = getWidthHeight_popularSize( matchedVariant.option1_converted );\n          if ( typeof getDimension !== 'undefined' && getDimension ) {\n            updateLineItemData( getDimension.width, getDimension.height, selectedBlockNo );\n          }\n        }\n      }\n    }\n    calculateDPILineItem( selectedBlockNo );\n    updatePreviewBoxSizes();\n    setActiveRow();\n  } catch ( err ) {\n    console.log( `ERROR upload-controls tab-controls .tabOptionName`, err.message );\n  }\n})\n// ADD SIZES ROW START\n.on(`click`, `multi-upload .addmore_size`,async function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    if ( uploadType == 'multi' ) {\n      selectedBlockNo = $( this ).closest( `uploaded-files-block` ).attr( `block-no` );\n      let activeOption = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] tab-controls .tabOptionName:checked` ).val();\n      $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] sizes-blocks line-items-${ activeOption }` )\n        .append( $( `#multiUploadTemplates template[data-multi-id=\"${ activeOption }\"]` ).html() )\n        .addClass( `rowAdded` );\n      await applyItemNo( activeOption, selectedBlockNo );\n\n      let fileDetails = getFileDetailsFunction( selectedBlockNo );\n      if ( typeof fileDetails !== 'undefined' && fileDetails ) {\n\n        const matchedVariant = getMatchingVariant( null, selectedBlockNo );\n        console.log ( 'matchedVariant', matchedVariant );\n        if ( typeof matchedVariant !== 'undefined' && matchedVariant ) {\n          applyImgToPreviewBox( fileDetails, matchedVariant, false, selectedBlockNo, 'no' );\n          if ( activeOption == 'custom' ) {\n            updateLineItemData( fileDetails.currentWidth, fileDetails.currentHeight, selectedBlockNo )\n          } else if ( activeOption == 'popular' ) {\n            const getDimension = getWidthHeight_popularSize( matchedVariant.option1_converted );\n            updateLineItemData( getDimension.width, getDimension.height, selectedBlockNo );\n            console.log ( 'getDimension.height added new size', getDimension.height );\n            updatePreviewSizeOnly( getDimension.width, getDimension.height, selectedBlockNo );\n          }\n        }\n      }\n    }\n    setActiveRow();\n  } catch ( err ) {\n    console.log( `ERROR upload-controls .addmore_size, multi-upload .addmore_size`, err.message );\n  }\n})\n// ADD SIZES ROW END\n// REMOVE ITEM START\n.on(`click`, `multi-upload sizes-blocks .del_item_cta`, async function(e) {\n  try {\n    e.stopImmediatePropagation();\n\n    selectedBlockNo = $(this).closest(`uploaded-files-block`).attr(`block-no`) || 1;\n\n    $(this).closest(`.widthHeight__custom`).remove();\n    const type = $(this).closest(`line-items-popular`).length ? `popular` : `custom`;\n    await applyItemNo(type, selectedBlockNo);\n\n    await selectAvailableTier(selectedBlockNo);\n\n    await calculateTotalQty();\n    await calculatePrices(null, null, selectedBlockNo);\n    if (uploadType == 'multi') {\n      let totalPrice = 0;\n      $(`multi-upload line-items sizes-blocks .widthHeight__custom[item]`).each(function() {\n        const qty = $(this).find(`precut-unit-logic .precut-unit-logic__qty .customQtyFile__qty`).val() * 1;\n        let unitPrice = $(this).attr(`price`) * 1;\n        totalPrice += qty * unitPrice;\n      });\n      shippingBarData(totalPrice);\n    }\n  } catch (err) {\n    console.log(`ERROR del_item_cta`, err.message);\n  }\n})\n// REMOVE ITEM END\n.on(`click`, `multi-upload preview-box a[removefile], multi-upload item-no .itemNo__action a`, function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    selectedBlockNo = $( this ).closest( `uploaded-files-block` ).attr( `block-no` );\n    const fileRemoveHTML = $( `template[data-multi-id=\"fileRemove\"]` ).html();\n    $( `body` ).append( fileRemoveHTML );\n  } catch ( err ) {\n    console.log( `ERROR preview-box a[fileremove], multi-upload item-no .itemNo__action a`, err.message );\n  }\n})\n.on(`click`, `file-remove-wrapper .fileRemoveBlock__removeFile, file-remove-wrapper-multi .fileRemoveBlock__removeFile`,async function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    if ( uploadType == 'multi' ) {\n      const totalBlocks = $( `multi-upload uploaded-files-block` ).length;\n      if ( totalBlocks == 1 ) {\n        $( `multi-upload-wrapper` ).remove();\n        $( `file-remove-wrapper-multi` ).remove();\n        uploadType = '';\n        /* last design removed -> reload to a clean PDP (real user clicks only) */\n        if ( e.isTrusted ) setTimeout( function () { window.location.reload(); }, 50 );\n      } else {\n        $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"]` ).remove();\n        resetItemNo();\n        applyItemNo( 'custom', selectedBlockNo );\n        $( `file-remove-wrapper-multi` ).remove();\n      }\n    }\n  } catch ( err ) {\n    console.log( `ERROR file-remove-wrapper .fileRemoveBlock__removeFile, file-remove-wrapper-multi .fileRemoveBlock__removeFile`, err.message );\n  }\n})\n.on(`click`, `file-remove-wrapper-multi .fileRemoveBlock__close, file-remove-wrapper-multi .fileRemoveBlock__cancle`, function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    $( this ).closest( `file-remove-wrapper-multi` ).remove();\n  } catch ( err ) {\n    console.log( `ERROR file-remove-wrapper-multi .fileRemoveBlock__close, file-remove-wrapper-multi .fileRemoveBlock__cancle`, err.message );\n  }\n})\n.on(`click`, `multi-upload .multiUpload__close`, function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    let fileRemoveHTML = $( `template[data-multi-id=\"fileRemove\"]` ).html();\n    fileRemoveHTML = fileRemoveHTML.replace( `fileRemoveBlock__removeFile`, `removeAllBlocks` );\n    $( `body` ).append( fileRemoveHTML );\n  } catch ( err ) {\n    console.log( `ERROR multi-upload .multiUpload__close`, err.message );\n  }\n})\n.on(`click`, `file-remove-wrapper-multi .removeAllBlocks`, function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    $( `multi-upload-wrapper` ).remove();\n    $( `file-remove-wrapper-multi` ).remove();\n    /* schedule reload FIRST so it fires even if fileInput is unset (the fileInput.value\n       line below can throw, which would otherwise skip the reload). Clean PDP on close. */\n    setTimeout( function () { window.location.reload(); }, 50 );\n    try { fileInput.value = ''; } catch ( e ) {}\n    uploadType = '';\n  } catch ( err ) {\n    console.log( `ERROR file-remove-wrapper-multi .removeAllBlocks`, err.message );\n  }\n})\n.on(`click`, `precut .openmodalbox`, function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    const precutHTML = $( `template[data-id=\"precutModal\"]` ).html();\n    $( `body` ).prepend( precutHTML );\n  } catch ( err ) {\n    console.log( `ERROR precut .openmodalbox`, err.message );\n  }\n})\n.on(`click`, `multi-upload prices-table .pricesTable__table_viewAll`, function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    const isShowAll = $( this ).closest( `.pricesTable__items` ).hasClass( `showAll` );\n    if ( isShowAll ) {\n      $( this ).closest( `.pricesTable__items` ).removeClass( `showAll` );\n      $( this ).addClass( `view` );\n    } else {\n      $( this ).closest( `.pricesTable__items` ).addClass( `showAll` );\n      $( this ).removeClass( `view` );\n    }\n  } catch ( err ) {\n    console.log( `ERROR multi-upload prices-table .pricesTable__table_viewAll`, err.message );\n  }\n})\n.on(`change`, `multi-upload toggle-options .toggleOption`,async function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    selectedBlockNo = $( this ).closest( `uploaded-files-block` ).attr( `block-no` );\n    if ( uploadType == 'multi' ) {\n      await selectAvailableTier( selectedBlockNo );\n      $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] file-preview preview-block.easyzoom` ).addClass( `image-loading` );\n      await updatePreviewImgAndLineItems( selectedBlockNo );\n      updatePreviewBoxSizes();\n\n      /* REINFORCE SIZE START */\n      $( `line-items-custom .widthHeight__custom[item=\"${ selectedItemNo }\"] .widthHeight__item[by=\"height\"] input[name=\"height__value\"]` ).trigger('keyup');\n      /* REINFORCE SIZE END */\n\n      $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] file-preview preview-block.easyzoom` ).removeClass( `image-loading` );\n    }\n  } catch ( err ) {\n    console.log( `ERROR multi-upload toggle-options .toggleOption`, err.message );\n  }\n})\n.on(`click`, `.edit-with-ai`, function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    /* Bind to the whole .edit-with-ai BUTTON, not the inner .edit-with-aiFlex span.\n       The .ai-ring styling pads the button ~8-9px larger than the span on every\n       side, so clicks on that padding ring matched NEITHER this handler nor the\n       span's inline onclick \u2014 the button \"didn't always trigger\" (intermittent by\n       click position). Opening the overlay here (it was an inline onclick on the\n       span) makes a ring click open the editor too. */\n    const _aiOverlay = document.querySelector('.customTabelPopup__overlay-ai');\n    if ( _aiOverlay ) _aiOverlay.style.display = 'grid';\n    const $uploadedBlock = $(this).closest('uploaded-files-block');\n\n    if ( uploadType == 'multi' ) {\n      selectedBlockNo = $uploadedBlock.attr('block-no') || 1;   // fallback \u2014 guards a dropped block-no attr (parity with the size-delete handler)\n\n      const $customItem = $uploadedBlock\n        .find('line-items-custom .widthHeight__custom')\n        .first();\n\n      if ($customItem.length > 0) {\n        selectedItemNo = $customItem.attr('item');\n      } else {\n        selectedItemNo = $uploadedBlock\n          .find('line-items-popular .widthHeight__custom')\n          .first()\n          .attr('item');\n      }\n\n      if (!canUseAiRequest()) {\n        showRedToast('You have reached your AI generation limit for today.');\n        return;\n      }\n      $(\"body\").addClass(\"lock-page\");\n\n      const imgUrl = getCurrentPreviewImageUrl();\n      console.log('imgUrl', imgUrl);\n\n      // Set base image preview\n      if (imgUrl) {\n        $('#customer_image_preview').attr('src', imgUrl);\n      } else {\n        $('#customer_image_preview').attr('src', '');\n      }\n\n      // Reset AI result & status each time popup opens\n      $('#ai_image_preview').attr('src', '');\n      $('#ai_prompt_2').val('');\n      $('#ai_status_message').hide().text('');\n\n      // 1) Reset result container and success class\n      $('.ai_result_output').hide();           // keep it hidden by default\n      $('.ai-container').removeClass('_success');\n\n      // 2) Reset Generate button (enable again for fresh run)\n      const $btn = $('#ai_generate_image_2');\n      $btn.prop('disabled', false);\n      $btn.data('busy', '0');\n      // const originalBtnText = decodeHTML($btn.data('original-text')) || 'Edit Image';\n      // $btn.html(originalBtnText);\n      setAIState(AI_STATES.ORIGINAL);\n    }\n  } catch ( err ) {\n    console.log( `ERROR .edit-with-ai .edit-with-aiFlex`, err.message );\n  }\n})\n.on('click', '#ai_generate_image_2', async function () {\n  if (!canUseAiRequest()) {\n    showRedToast('You have reached your AI generation limit for today.');\n    return;\n  }\n  const $btn = $(this);\n  const $aiPrompt_2 = $('#ai_prompt_2');\n  const $status = $('#ai_status_message');\n  let isSuccess = false;\n  $('.ai-container').removeClass('_success');\n  setAIState(AI_STATES.PROCESSING);\n  try {\n    // LOCK POPUP\n    $('.customTabelPopup__overlay-ai').addClass('ai-overlay-locked');\n    $('.customTabelPopup__overlay-ai').addClass('processing-ai');\n    const baseImageUrl = $('#customer_image_preview').attr('src');\n\n    if (!baseImageUrl) {\n      alert('No base image found. Please upload an image first.');\n      return;\n    }\n\n    // PROMPT VALIDATION\n    let promptText = ($('#ai_prompt_2').val() || '').trim();\n    if (!promptText) {\n      $status.show().text('Please enter a prompt to describe how you want to edit the image.');\n      $('#ai_prompt_2').focus();\n      return;\n    }\n\n    // UI: set loading state\n    $btn.prop('disabled', true);\n    $aiPrompt_2.prop('disabled', true);\n    $btn.data('busy', '1');\n\n    $status.hide().text('');\n\n    // Clear previous AI preview\n    $('#ai_image_preview').attr('src', '');\n\n    // CALL AI EDIT (Gram edit-lite via the bg-removal proxy Lambda)\n    const newImageUrl = await nbEditRequest(baseImageUrl, promptText);\n\n    // Update preview\n    $('#ai_image_preview').attr('src', newImageUrl);\n    setAIState(AI_STATES.RESULT);\n\n    isSuccess = true;\n  } catch (err) {\n    console.log('ERROR #ai_generate_image_2 click', err);\n    $status.show().text('Error: ' + (err.message || 'Something went wrong while generating the image.'));\n  } finally {\n    // UNLOCK POPUP\n    $('.customTabelPopup__overlay-ai').removeClass('ai-overlay-locked');\n    $('.customTabelPopup__overlay-ai').removeClass('processing-ai');\n\n    if (!isSuccess) {\n      $btn.prop('disabled', false);\n      $aiPrompt_2.prop('disabled', false);\n      $btn.data('busy', '0');\n    } else {\n      $btn.prop('disabled', true);\n      $aiPrompt_2.prop('disabled', false);\n      $btn.data('busy', '0');\n    }\n  }\n})\n.on('click', '#use_ai_image', async function () {\n  const $btn = $(this);\n  const $status = $('#ai_status_message');\n  let isSuccess = false;\n\n  console.log ( 'uploadtype', uploadType, 'selectedBlockNo', selectedBlockNo);\n\n  try {\n    $('.customTabelPopup__overlay-ai').addClass('ai-overlay-locked');\n\n    const aiImageUrl = $('#ai_image_preview').attr('src');\n    if (!aiImageUrl) {\n      return;\n    }\n\n    const originalBtnText = $btn.data('original-text') || $btn.html();\n    $btn.data('original-text', originalBtnText);\n    $btn.prop('disabled', true);\n    $btn.html('Applying...');\n\n    if ( typeof uploadType !== 'undefined' && uploadType === 'multi') {\n      if ( typeof selectedBlockNo !== 'undefined' && selectedBlockNo ) {\n        if ( $( `uploaded-files-block[block-no=\"${ selectedBlockNo }\"] toggle-options[show-bg-option=\"true\"] .bgRemover .toggleOption` ).length > 0 ) {\n          $( `uploaded-files-block[block-no=\"${ selectedBlockNo }\"] toggle-options[show-bg-option=\"true\"] .bgRemover .toggleOption` ).prop( 'checked', true );\n          await addDelay( 200 );\n        }\n        const uploaded = await processFileOrUrl(aiImageUrl, selectedBlockNo);\n        console.log ( 'uploaded', uploaded );\n\n        const fileDetail = {\n          originalFile: uploaded.originalFile || aiImageUrl,        // keep S3 here for internal stuff\n          imgIxFile: uploaded.imgIxFile || uploaded.originalFile || aiImageUrl,\n          file_crc: uploaded.file_crc,\n          fileName: uploaded.fileName || 'ai-image.png',\n          fileURL: uploaded.originalFile || aiImageUrl,\n          isAIEdit: true,\n          aiOriginalUrl: aiImageUrl                                // \uD83D\uDC49 AI edit result URL\n        };\n\n        const getFileDetail = getFileDetailsFunction( selectedBlockNo );\n\n        const updatedObject = {...getFileDetail, ...fileDetail};\n\n        const isUpdate = updateFileDetailsFunction( updatedObject, selectedBlockNo );\n        if ( isUpdate ) {\n          console.log ( 'Successfully Update' );\n          $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] toggle-options .toggleOption` ).trigger( `change` );\n        } else {\n          console.log ( 'Unable to Update FileDetails' );\n        }\n      }\n    }\n\n  } catch (err) {\n    console.log('ERROR #use_ai_image click', err);\n    $status.show().text('Error: ' + (err.message || 'Something went wrong while applying the AI image.'));\n  } finally {\n    $('.customTabelPopup__overlay-ai').removeClass('ai-overlay-locked');\n    $('.customTabelPopup__overlay-ai').hide();\n    if (!isSuccess) {\n      $btn.prop('disabled', false);\n    } else {\n      $btn.prop('disabled', true);\n    }\n    $btn.prop('disabled', false);\n\n    const originalBtnText = $btn.data('original-text') || 'Apply AI Edit';\n    $btn.html(originalBtnText);\n    $(\"body\").removeClass(\"lock-page\");\n  }\n})\n/* AI Edit / Original compare tabs. These click handlers were MISSING on the blanks\n   engine \u2014 they existed only in the portal copy (portal-multiupload.liquid), so the\n   tabs did nothing and \"Original\" was a dead click. setAIState already implements both\n   views (RESULT = AI result, RESULT_ORG = original); guard on a present AI result so\n   the toggle only acts in the compare state. */\n.on(`click`, `.ai-tab[data-tab=\"ai\"]`, function () {\n  if ( $('#ai_image_preview').attr('src') ) setAIState( AI_STATES.RESULT );\n})\n.on(`click`, `.ai-tab[data-tab=\"original\"]`, function () {\n  if ( $('#ai_image_preview').attr('src') ) setAIState( AI_STATES.RESULT_ORG );\n})\n.on(`click`, `upload-controls .zoom_image, multi-upload .zoom_image`, function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    if ( uploadType == 'multi' ) {\n      $( `.customTabelPopup__overlay-5 img` ).attr( `src`, `` );\n      selectedBlockNo = $( this ).closest( `uploaded-files-block` ).attr( `block-no` );\n      let optionParams = getToggleOptionParams( selectedBlockNo );\n      let fileDetail = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] file-preview file-details` ).text();\n      fileDetail = JSON.parse( fileDetail );\n      $( `.customTabelPopup__overlay-5 img` ).attr( `src`, `${ fileDetail.imgIxFile }?${ fileDetail.preview }${ typeof optionParams !== 'undefined' && optionParams ? optionParams : `` }` );\n      $( `.customTabelPopup__overlay-5` ).show();\n    }\n  } catch ( err ) {\n    console.log( `ERROR upload-controls .zoom_image, multi-upload .zoom_image`, err.message );\n  }\n})\n// ADD TO CART START\n.on(`click`, `multi-upload proceed-to-checkout .addToCartGroupItemsMultiple`,async function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    if ( uploadType == 'multi' ) {\n      $( this ).addClass( `working` );\n      const items = await multiFilesAddToCart();\n      $( this ).removeClass( `working` );\n    }\n  } catch ( err ) {\n    console.log( `ERROR multi-upload proceed-to-checkout .addToCartGroupItemsMultiple`, err.message );\n  }\n})\n// ADD TO CART END\n.on(`change`, `multi-upload #preCutOption_multi`, function( e ) {\n  try {\n    e.stopImmediatePropagation();\n    const isPreCutActive = $( this ).is( `:checked` );\n    if ( isPreCutActive ) {\n      $( `multi-upload sizes-blocks .widthHeight__custom` ).attr( `precut`, `Yes` );\n    } else {\n      $( `multi-upload sizes-blocks .widthHeight__custom` ).attr( `precut`, `` );\n    }\n  } catch ( err ) {\n    console.log( `ERROR multi-upload #preCutOption_multi`, err.message );\n  }\n})\n;\nasync function multiFilesAddToCart() {\n  try {\n    let items = [];\n    const uploadControl = $( `multi-upload` );\n    const discountInputProperty = uploadControl.find( `prices-table discount-properties` ).attr( `discount-input` );\n    const discountNameProperty = uploadControl.find( `prices-table discount-properties` ).attr( `discount-name` );\n    $($( `multi-upload sizes-blocks .widthHeight__custom[item]` ).get().reverse()).each(function( i ) {\n      const blockNo = $( this ).closest( `uploaded-files-block` ).attr( `block-no` );\n      const fileDetail = getFileDetailsFunction( blockNo );\n      const VID = $( this ).attr( `vid` ) * 1;\n      const qty = $( this ).attr( `qty` ) * 1;\n      const option = $( this ).attr( `option-selected` );\n      const dpi = $( this ).attr( `dpi-warning` );\n      const precut = $( this ).attr( `precut` );\n      const width = $( this ).attr( `w` );\n      const height = $( this ).attr( `h` );\n      const size = $( this ).attr( `size` );\n      const bgRemover = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] toggle-options .bgRemover .toggleOption` ).is( `:checked` );\n      const superRes = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] toggle-options .superRes .toggleOption` ).is( `:checked` );\n      // The legacy <designer-notes> .designNotes textarea was replaced by the\n      // .nt-design-note collapsible (name=\"properties[Design Notes]\"). Read THIS\n      // block's new field first, fall back to THIS block's legacy one, default ''\n      // so .trim() never runs on undefined (that TypeError silently aborted the\n      // cart-add, leaving the button dead with no error).\n      // FIX (per-block notes): both reads are scoped to block-no. A previous\n      // GLOBAL `.nt-design-note textarea`.first() fallback sat between them, so a\n      // block with an EMPTY note inherited the FIRST block's note at cart-add\n      // (e.g. an empty design 2 picked up design 1's \"test\"). Removed \u2014 an empty\n      // note now stays empty. Verified live: block-2 buggy \"test\" \u2192 fixed \"\".\n      const designNote = (\n        $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] .nt-design-note textarea[name=\"properties[Design Notes]\"]` ).val()\n        || $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] designer-notes .designNotes` ).val()\n        || ''\n      ).trim();\n      const properties = {};\n\n      const orderProperty = parseOrderString( fileDetail.imgIxFile, fileDetail.originalFile, fileDetail.order, fileDetail.currentOptions );\n      if ( typeof orderProperty !== 'undefined' && orderProperty ) {\n        if ( orderProperty.imgIx ) {\n          properties['Upload (Vector Files Preferred)'] = `${ orderProperty.imgIx_params != '' ? orderProperty.imgIx_params : `` }`;\n          console.log(\"designtype: \",designtype, \" :grt_photo_id:\",grt_photo_id);\n          if(designtype && grt_photo_id != \"\"){\n            properties['design re-used'] = `${grt_photo_id}`;\n          }\n          if(designtype == 1 && ordername != \"\"){\n            properties['design re-used'] = `previously on order # ${ordername}`;\n          }\n        }\n        if ( orderProperty.s3 ) {\n          if ( typeof fileDetail.isReadyToPress !== 'undefined' && fileDetail.isReadyToPress == 'Yes' ) {\n            properties['Upload (Vector Files Preferred)'] = `${ orderProperty.s3_params != '' ? orderProperty.s3_params : `` }`;\n            console.log(\"designtype: \",designtype, \" :grt_photo_id:\",grt_photo_id);\n            if(designtype && grt_photo_id != \"\"){\n              properties['design re-used'] = `${grt_photo_id}`;\n            }\n            if(designtype == 1 && ordername != \"\"){\n              properties['design re-used'] = `previously on order # ${ordername}`;\n            }\n          } else {\n            properties['_Original Image'] = `${ orderProperty.s3_params != '' ? orderProperty.s3_params : `` }`;\n          }\n        }\n      }\n\n      properties['_cartImg'] = `${ fileDetail.imgIxFile }?${ fileDetail.cart }${ typeof fileDetail.currentOptions !== 'undefined' && fileDetail.currentOptions ? fileDetail.currentOptions : `` }`;\n      if ( typeof bgRemover !== 'undefined' && bgRemover ) {\n        properties['Remove Background'] = 'Yes';\n      }\n      if ( typeof superRes !== 'undefined' && superRes ) {\n        properties['Super Resolution'] = 'Yes';\n      }\n      if ( typeof designNote !== 'undefined' && designNote ) {\n        properties['Design Notes'] = designNote;\n      }\n      if ( dpi != '' ) {\n        properties[`DPI Warning`] = dpi;\n      }\n      if ( precut != '' ) {\n        properties['Precut'] = precut;\n      }\n      if ( option == 'custom' ) {\n        properties['_width'] = width;\n        properties['_height'] = height;\n      } else {\n        if ( typeof width !== 'undefined' && width ) {\n          properties['_width'] = width;\n        }\n        if ( typeof height !== 'undefined' && height ) {\n          properties['_height'] = height;\n        }\n      }\n      properties['_Size'] = size;\n\n      if ( typeof discountInputProperty !== 'undefined' && discountInputProperty ) {\n        properties['_discount_input'] = discountInputProperty;\n      }\n      if ( typeof discountNameProperty !== 'undefined' && discountNameProperty ) {\n        properties['_discount_name'] = discountNameProperty;\n      }\n      if ( typeof fileDetail.isReadyToPress !== 'undefined' && fileDetail.isReadyToPress == 'Yes' ) {\n        properties['_Ready to Press'] = fileDetail.isReadyToPress;\n      }\n      if ( typeof fileDetail.isAIImage !== 'undefined' && fileDetail.isAIImage ) {\n        properties['AI Created'] = 'Yes';\n      }\n\n      if ( typeof fileDetail.isAIEdit !== 'undefined' && fileDetail.isAIEdit ) {\n        properties['AI Edit'] = 'Yes';\n      }\n\n      items.push({\n        id: VID,\n        quantity: qty,\n        properties\n      });\n    })\n\n    if ( items.length > 0 ) {\n      console.log ( 'items', items );\n      const attributes = '';\n      // $( `body` )\n      // .append( `\n      //   <div class=\"loadingScreen__\">\n      //     <img src=\"${ loaderGif }\">\n      //   </div>\n      // ` );\n      const getData = await fetch(window.Shopify.routes.root + 'cart/add.js', {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n        },\n        body: JSON.stringify({ items, attributes }),\n      })\n      .then((response) => {\n        toast('', 'Added to cart Successfully');\n        return response.json();\n      })\n      .catch((error) => {\n        console.error('Error:', error);\n      });\n      refreshCart();\n      updateCartItemCount();\n      loadCartItemsCount();\n      flushSingleFileData();\n\n      // location.href = `/cart`;\n      await addDelay( 3000 );\n      $( `.loadingScreen__` ).remove();\n    }\n  } catch ( err ) {\n    console.log( `ERROR multiFilesAddToCart()`, err.message );\n  }\n}\nasync function flushSingleFileData() {\n  try {\n    uploadType = '';\n    // `fileInput` is undefined until the customer touches the file input (it's\n    // only assigned on .uploadBox #fileInput click/change). When designs come in\n    // via \"Previous Designs\", it stays undefined \u2014 so `fileInput.value = ''` threw\n    // here, and because this function has its own try/catch the error was\n    // swallowed and the modal-remove on the next line never ran, leaving the\n    // upload modal open after Add to Cart (the slider cart still opened). Guard it.\n    if ( fileInput ) fileInput.value = '';\n    $( `multi-upload-wrapper` ).remove();\n    $( `upload-controls next-element` ).addClass( `hidden` );\n    $( `\n      upload-controls preview-box preview-block .fileupload_hero,\n      upload-controls preview-box preview-block .viewer-box img\n    ` ).attr( `src`, transpareImg );\n    $( `upload-controls preview-box preview-block .horizontal_direction` ).attr( `x-is`, `` );\n    $( `upload-controls preview-box preview-block .verticle_direction` ).attr( `y-is`, `` );\n    $( `upload-controls preview-box file-details` ).empty();\n    $( `upload-controls sizes-blocks` )\n      .attr({\"total-items\": 1, \"total-qty\": 1})\n      .find( `line-items-custom, line-items-popular` )\n      .removeClass( `rowAdded` )\n      .empty();\n    $( `upload-controls toggle-options .toggleOption, upload-controls designer-notes #designerNotes` ).prop( `checked`, false );\n    $( `upload-controls tab-controls #customSizeTabOption` ).prop( `checked`, true );\n    $( `upload-controls master-upload, upload-controls file-progress` ).removeClass( `hidden` );\n    $( `upload-controls file-progress .loadingPercent__counter` ).text( `0%` );\n    $( `upload-controls file-progress .fileProgress__bar` ).css( `width`, `0%` );\n    $( `upload-controls designer-notes .designNotes` ).val( `` );\n    $( `file-remove-wrapper` ).remove();\n    $( `#generative-ai-area` ).removeAttr( `style` ).removeClass( `hidden` );\n    $( `.generative-ai-area` ).removeClass( `hidden` );\n    grt_photo_id = '';\n  } catch ( err ) {\n    console.log( `ERROR `, err.message );\n  }\n}\nfunction updateCartItemCount() {\n  try {\n    $.get(`/cart?view=cartItemsCount`, function ( res ) {\n      $( `.header-container .area--cart` ).html( res );\n    });\n  } catch ( err ) {\n    console.log( `ERROR updateCartItemCount()`, err.message );\n  }\n}\nfunction parseOrderString( imgIxURL, s3URL, order, selectedOptions = `` ) {\n  const result = {\n    imgIx: false,\n    imgIx_params: \"\",\n    s3: false,\n    s3_params: \"\"\n  };\n\n  const parts = order.split( `&&` );\n\n  // Normalize selectedOptions (remove leading ? or &)\n  selectedOptions = selectedOptions.replace(/^[?&]+/, \"\");\n\n  // Helper to normalize part like [imgIx]trim=true -> [imgIx]?trim=true\n  const normalizePart = ( part ) => {\n    return part.replace(/^(\\[(?:imgIx|s3|both_imgix|both_s3)\\])([^?].+)/i, '$1?$2');\n  };\n\n  // Helper to build full URL\n  const buildUrl = ( baseURL, rawParams, appendSelected ) => {\n    let url = baseURL;\n\n    if ( rawParams ) {\n      url += rawParams;\n    }\n\n    if ( appendSelected && selectedOptions ) {\n      if ( rawParams.includes( `?` ) ) {\n        url += `&` + selectedOptions;\n      } else {\n        url += `?` + selectedOptions;\n      }\n    }\n\n    return url;\n  };\n\n  parts.forEach(rawPart => {\n    const part = normalizePart( rawPart.trim() );\n    const match = part.match(/\\[(imgIx|s3|both_imgix|both_s3)\\](\\?[^\\s]*)?/i);\n    if ( match ) {\n      const key = match[1].toLowerCase();\n      const rawParams = match[2]?.trim() || \"\";\n\n      if ( key === `imgix` ) {\n        result.imgIx = true;\n        result.imgIx_params = buildUrl(imgIxURL, rawParams, true);\n      } else if ( key === `s3` ) {\n        result.s3 = true;\n        result.s3_params = buildUrl(s3URL, rawParams, false);\n      } else if ( key === `both_imgix` ) {\n        result.imgIx = true;\n        result.s3 = true;\n        result.imgIx_params = buildUrl(imgIxURL, rawParams, true);\n        result.s3_params = buildUrl(imgIxURL, rawParams, true);\n      } else if ( key === `both_s3` ) {\n        result.imgIx = true;\n        result.s3 = true;\n        result.imgIx_params = buildUrl(s3URL, rawParams, false);\n        result.s3_params = buildUrl(s3URL, rawParams, false);\n      }\n    }\n  });\n\n  return result;\n}\n\nfunction updateFileDetailsFunction( fileDetails, blockNo ) {\n  try {\n    if ( typeof uploadType === 'undefined' || uploadType == 'multi' ) {\n      $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] preview-box file-preview file-details` ).text( JSON.stringify( fileDetails ) );\n      return true;\n    }\n    return false;\n  } catch ( err ) {\n    console.log( `ERROR `, err.message );\n  }\n}\nasync function processFileOrUrl(fileOrUrl, blockNo) {\n  let file;\n\n  if (fileOrUrl instanceof File) {\n    file = fileOrUrl;\n  } else if (typeof fileOrUrl === \"string\") {\n    const url = fileOrUrl;\n\n    if (url.includes(\"amazonaws.com\")) {\n      return {\n        originalFile: url,\n        imgIxFile: url.replace(ninjaS3Host2, ninjaImgixHost),\n        file_crc: null,\n        fileName: url.split(\"/\").pop().split(\"?\")[0]\n      };\n    }\n\n    const response = await fetch(url);\n    if (!response.ok) throw new Error(\"Failed to fetch external file\");\n\n    const blob = await response.blob();\n\n    const urlParts = url.split(\"/\");\n    let nameFromUrl = urlParts[urlParts.length - 1].split(\"?\")[0];\n    if (!nameFromUrl.includes(\".\")) {\n      nameFromUrl = \"file_\" + Date.now() + \".jpg\";\n    }\n\n    file = new File([blob], nameFromUrl, { type: blob.type || \"application/octet-stream\" });\n  } else {\n    throw new Error(\"Invalid input: must be File or URL string\");\n  }\n\n  let rtn = null;\n  const fileReader = new FileReader();\n  const fileType = file.type;\n  const fileSize = file.size;\n\n  const nameOnly = file.name\n    .split(\".\")[0]\n    .toLowerCase()\n    .replace(/[^a-z0-9]/gi, \"-\")\n    .replace(/-+/g, \"-\")\n    .replace(/^-|-$/g, \"\");\n\n  // Dotless/garbage filenames: a bare split(\".\").pop() returns the WHOLE name as\n  // the \"extension\" (spaces included) \u2014 imgix still serves it (MIME-based), but\n  // the production API rejects extensions >10 chars. Keep a valid dotted ext;\n  // else derive from the MIME type; else png. (2026-08-18)\n  const extension = /\\.[a-z0-9]{1,5}$/i.test(file.name) ? file.name.split(\".\").pop() : ({ \"image/png\": \"png\", \"image/jpeg\": \"jpg\", \"image/webp\": \"webp\", \"image/gif\": \"gif\", \"image/svg+xml\": \"svg\", \"application/pdf\": \"pdf\", \"application/postscript\": \"eps\" }[file.type] || \"png\");\n  const randomName = `${nameOnly}____image_${Date.now()}_${Math.floor(Math.random() * 1000)}.${extension}`;\n\n  const presignData = await getPresignedUploadUrl(randomName, file.type);\n\n  if (presignData && presignData.url) {\n    fileProcessBar(`start`);\n    if (uploadType == \"multi\") {\n      progressMove(`multi-upload uploaded-files-block[block-no=\"${blockNo}\"] file-progress`, ``, fileSize);\n    }\n\n    const originalUploadedFileURL = presignData.sourceUrl;\n    const response = await fetch(presignData.url, {\n      method: \"PUT\",\n      body: file,\n    });\n\n    if (response.status == 200) {\n      let filePath = `https://${ninjaImgixHost}/${randomName}`;\n      const file_crc = await makeCRC(file);\n\n      fileReader.readAsDataURL(file);\n      rtn = {\n        originalFile: originalUploadedFileURL,\n        imgIxFile: filePath,\n        file_crc: file_crc,\n        fileName: randomName,\n      };\n    }\n  }\n  return rtn;\n}\nasync function nbEditRequest(imageUrl, promptText) {\n  aiJobCancelled = false;\n  console.log ( 'promptText', promptText );\n  aiJobAbortController = new AbortController();\n\n  // Gram edit-lite via the bg-removal proxy Lambda\n  const resp = await fetch('https://ruhg140mmf.execute-api.us-east-1.amazonaws.com/', {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify({\n      model: 'gram-edit-45g',\n      imageUrl: imageUrl,\n      prompt: promptText,\n      transparency: 'AUTO'\n    }),\n    signal: aiJobAbortController.signal\n  });\n\n  if (!resp.ok) {\n    const txt = await resp.text().catch(() => '');\n    throw new Error('AI edit request failed (' + resp.status + '): ' + txt.slice(0, 200));\n  }\n\n  if (aiJobCancelled) {\n    throw new Error(\"AI request cancelled by user\");\n  }\n\n  const data = await resp.json();\n  if (!data || !data.url) throw new Error('AI edit response missing url');\n\n  return data.url;\n}\nfunction setAIState(state) {\n  const $box = $(\".ai-preview-box\");\n\n  $box.addClass(\"ai-fade\");\n  setTimeout(() => $box.removeClass(\"ai-fade\"), 250);\n\n  $( `\n    #customer_image_preview,\n    #ai_image_preview,\n    .ai-processing,\n    .ai-prompt-box,\n    .ai-action-box,\n    .black-bg,\n    .ai-action-box .button\n  ` ).hide();\n  $( `.ai-tabs, .ai-tab`).removeClass( `active` );\n  $( `.ai-modal` ).removeClass( `ai-is-processing` );\n\n  if ( state === AI_STATES.ORIGINAL ) {\n    $( `.ai-tab[data-tab=\"original\"]` ).addClass( `active` );\n    $( `#customer_image_preview, .ai-prompt-box` ).show();\n  }\n\n  if ( state === AI_STATES.PROCESSING ) {\n    $( `.ai-processing` ).show();\n    $( `.ai-modal` ).addClass( `ai-is-processing` );\n  }\n\n  if ( state === AI_STATES.RESULT ) {\n    $( `.ai-tabs, .ai-tab[data-tab=\"ai\"]` ).addClass( `active` );\n    $( `#ai_image_preview, .ai-action-box, .ai-action-box .button#use_ai_image` ).show();\n  }\n\n  if ( state === AI_STATES.RESULT_ORG ) {\n    $( `.ai-tabs, .ai-tab[data-tab=\"original\"]` ).addClass( `active` );\n    $( `#customer_image_preview, .ai-action-box, .ai-action-box .button:not(#use_ai_image)` ).show();\n    $( `.black-bg` ).hide();\n  }\n}\nfunction getCurrentPreviewImageUrl() {\n  try {\n    if ( typeof uploadType !== 'undefined' && uploadType === 'multi' ) {\n      if ( typeof selectedBlockNo !== 'undefined' && selectedBlockNo ) {\n        const src3 = $(`multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] preview-box .fileupload_hero`).attr('src');\n        if ( src3 ) return src3;\n      }\n    }\n    return '';\n  } catch (err) {\n    console.log('ERROR getCurrentPreviewImageUrl()', err.message);\n    return '';\n  }\n}\nfunction canUseAiRequest() {\n  const usage = getAiUsage();\n  return usage.count < AI_DAILY_LIMIT;\n}\nfunction getAiUsage() {\n  const day = getLocalDayKey();\n  const raw = (localStorage.getItem('nbUsage') || localStorage.getItem('nanoBananaUsage'));\n  let obj = {};\n  try { obj = raw ? JSON.parse(raw) : {}; } catch (e) { obj = {}; }\n\n  if (!obj || obj.day !== day) obj = { day, count: 0 };\n  return obj;\n}\nfunction getLocalDayKey() {\n  // YYYY-MM-DD in USER'S local timezone\n  const d = new Date();\n  const year  = d.getFullYear();\n  const month = String(d.getMonth() + 1).padStart(2, '0');\n  const day   = String(d.getDate()).padStart(2, '0');\n  return `${year}-${month}-${day}`;\n}\nfunction setFocusOfMultiUpload( beforeUploadAvailableBlocks ) {\n  try {\n    console.clear();\n    console.log ( 'beforeUploadAvailableBlocks', beforeUploadAvailableBlocks );\n    if ( beforeUploadAvailableBlocks == 0 ) {\n      $( `multi-upload upload-area` ).animate({scrollTop: 0}, 500);\n      return;\n    }\n    let actualTop = 0;\n    $( `multi-upload file-blocks-area uploaded-files-block` ).each(function( i ) {\n      const j = i + 1;\n      if ( i < beforeUploadAvailableBlocks ) {\n        const getBlockHeight = $( this ).outerHeight() + 20;\n        actualTop = actualTop + getBlockHeight;\n      }\n    })\n    $( `multi-upload upload-area` ).animate({scrollTop: ( actualTop )}, 500);\n  } catch ( err ) {\n    console.log( `ERROR setFocusOfMultiUpload( beforeUploadAvailableBlocks )`, err.message );\n  }\n}\nasync function resetItemNo() {\n  try {\n    $( `multi-upload uploaded-files-block` ).each(function(i) {\n      const j = i + 1;\n      setIndexNoToBlock( $( this ), j );\n    })\n  } catch ( err ) {\n    console.log( `ERROR resetItemNo()`, err.message );\n  }\n}\nasync function selectAvailableTier( blockNo ) {\n  try {\n    if ( uploadType == 'multi' && blockNo ) {\n      const activeTab = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] tab-controls .tabOptionName:checked` ).val();\n      if ( activeTab == 'custom' ) {\n        const isCustomTierAvailable = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] line-items-custom .widthHeight__custom` ).length;\n        if ( isCustomTierAvailable > 0 ) {\n          selectedItemNo = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] line-items-custom .widthHeight__custom` ).last().attr( `item` );\n        } else {\n          selectedItemNo = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] line-items-popular .widthHeight__custom` ).last().attr( `item` );\n        }\n      } else if ( activeTab == 'popular' ) {\n        const isPopularTierAvailable = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] line-items-popular .widthHeight__custom` ).length;\n        if ( isPopularTierAvailable > 0 ) {\n          selectedItemNo = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] line-items-popular .widthHeight__custom` ).last().attr( `item` );\n        } else {\n          selectedItemNo = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] line-items-custom .widthHeight__custom` ).last().attr( `item` );\n        }\n      }\n    }\n  } catch ( err ) {\n    console.log( `ERROR updatePreviewSizeOnly( width, height, blockNo )`, err.message );\n  }\n}\nfunction getVariantForSmartSize(width, height) {\n  try {\n    let totalInches = parseFloat(width) * parseFloat(height);\n\n    if (totalInches < 1) {\n      totalInches = 1;\n    }\n    totalInches = Math.ceil(totalInches);\n\n    const customVariants = bySizeVariants.filter(style => style.isCustom);\n    if (!customVariants.length) return null;\n\n    const highestMaxInches = Math.max(...customVariants.map(style => style.maxInches));\n\n    if (totalInches > highestMaxInches) {\n      // fall back to largest style\n      return customVariants.reduce((maxObj, current) =>\n        current.maxInches > maxObj.maxInches ? current : maxObj\n      );\n    }\n\n    // find style whose min/max range contains this area\n    return (\n      customVariants\n        .slice()\n        .reverse()\n        .find(\n          (obj) => totalInches >= obj.minInches && totalInches <= obj.maxInches\n        ) || null\n    );\n  } catch (err) {\n    console.log('ERROR getVariantForSmartSize', err.message);\n    return null;\n  }\n}\nfunction formatInchesValue(value) {\n  try {\n    const num = parseFloat(value);\n    if (isNaN(num)) return value;\n    return parseFloat(num.toFixed(2)).toString().replace(/\\.00$/, '');\n  } catch (err) {\n    console.log('ERROR formatInchesValue', err.message);\n    return value;\n  }\n}\nfunction resetPopularOptionLabels($select) {\n  try {\n    $select.find('option').each(function() {\n      const $opt = $(this);\n      const originalLabel = $opt.data('original-label');\n      if (originalLabel) {\n        $opt.text(originalLabel);\n      }\n    });\n  } catch (err) {\n    console.log(\"ERROR resetPopularOptionLabels\", err.message);\n  }\n}\nfunction getProportionalSize(size, by, uploadedWidth, uploadedHeight) {\n  let width, height, widthIn, heightIn;\n\n  if (by === \"width\") {\n    const ratio = size / uploadedWidth;\n    width = size;\n    height = parseFloat((uploadedHeight * ratio).toFixed(2));\n  } else {\n    const ratio = size / uploadedHeight;\n    height = size;\n    width = parseFloat((uploadedWidth * ratio).toFixed(2));\n  }\n  widthIn = (width/300).toFixed(2);\n  heightIn = (height/300).toFixed(2);\n\n  return { width, height, widthIn, heightIn };\n}\nfunction updateLineItemData( w, h, blockNo ) {\n  try {\n    if ( uploadType == 'multi' ) {\n      $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] sizes-blocks .widthHeight__custom[item=\"${ selectedItemNo }\"]` ).attr({\n        \"w\": w,\n        \"h\": h,\n        \"size\": `${ w }x${ h }`\n      });\n    }\n  } catch ( err ) {\n    console.log( `ERROR updateLineItemData( w, h )`, err.message );\n  }\n}\nfunction getWidthHeight_popularSize( value ) {\n  try {\n    // Match formats like: 3^ x 2^, 3\"x2.5, 3.5^x6.15\", etc.\n    const match = value.match(/^([\\d.]+)[\\^\"]?\\s*x\\s*([\\d.]+)[\\^\"]?$/i);\n    if (match) {\n      const width = parseFloat(match[1]);\n      const height = parseFloat(match[2]);\n      return { width, height };\n    }\n    return null; // return null if pattern doesn't match\n  } catch ( err ) {\n    console.log( `ERROR getWidthHeight_popularSize()`, err.message );\n  }\n}\nfunction calculateDPILineItem( blockNo ) {\n  if ( uploadType == 'multi' ) {\n    const fileDetail = getFileDetailsFunction( blockNo );\n\n    if ( fileDetail.fileType == 'png' || fileDetail.fileType == 'jpg' || fileDetail.fileType == 'jpeg' ) {\n      const uploadedWidth = fileDetail.fileWidth;\n      const uploadedHeight = fileDetail.fileHeight;\n      $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] sizes-blocks .widthHeight__custom` ).each(function() {\n        const width = $( this ).attr( `w` ) * 1;\n        const height = $( this ).attr( `h` ) * 1;\n\n        const rowType = $( this ).attr( `option-selected` );\n\n        let makeSqInchesForPopular, makeSqInchesForCustom, currentSqInches = 0;\n        if ( rowType == 'custom' ) {\n          makeSqInchesForCustom = (uploadedWidth * uploadedHeight) / 72;\n          currentSqInches = ( width * height ) * 72;\n        } else if ( rowType == 'popular' ) {\n          makeSqInchesForPopular = width * height;\n        }\n\n        if ( rowType == 'custom' ) {\n          if ( makeSqInchesForCustom < 288 ) {\n            $( this ).find( `dpi-warning` ).addClass( `active` );\n            $( this ).attr( `dpi-warning`, `Yes` );\n          } else if ( makeSqInchesForCustom > 288 && makeSqInchesForCustom > currentSqInches ) {\n            $( this ).find( `dpi-warning` ).removeClass( `active` );\n            $( this ).attr( `dpi-warning`, `` );\n          } else {\n            $( this ).find( `dpi-warning` ).addClass( `active` );\n            $( this ).attr( `dpi-warning`, `Yes` );\n          }\n        } else if ( rowType == 'popular' ) {\n          const recommendedSqInches = ((uploadedWidth / 72) * (uploadedHeight / 72));\n          if ( recommendedSqInches < 4 ) {\n            $( this ).find( `dpi-warning` ).addClass( `active` );\n            $( this ).attr( `dpi-warning`, `Yes` );\n          } else if ( makeSqInchesForPopular < recommendedSqInches ) {\n            $( this ).find( `dpi-warning` ).removeClass( `active` );\n            $( this ).attr( `dpi-warning`, `` );\n          } else {\n            $( this ).find( `dpi-warning` ).addClass( `active` );\n            $( this ).attr( `dpi-warning`, `Yes` );\n          }\n        }\n      })\n    }\n  }\n}\n\nfunction updatePreviewBoxSizes() {\n  try {\n    if ( uploadType == 'multi' ) {\n      let activeTab = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] tab-controls .tabOptionName:checked` ).val();\n      const isRowAvailable = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] sizes-blocks .widthHeight__custom[option-selected=\"${ activeTab }\"]` ).length;\n      if ( isRowAvailable > 0 ) {\n        const w = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] sizes-blocks .widthHeight__custom[item=\"${ selectedItemNo }\"]` ).attr( `w` );\n        let h = $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] sizes-blocks .widthHeight__custom[item=\"${ selectedItemNo }\"]` ).attr( `h` );\n        if ( activeTab == 'custom' ) {\n          h = `${ h }\"`;\n        } else if ( activeTab == 'popular' ) {\n          if ( typeof h == 'undefined' ) {\n            h = `Proportional Height`;\n          } else {\n            h = `${ h }\"`;\n          }\n          // h = `Proportional Height`;\n        }\n        $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] preview-box .horizontal_direction` ).attr( `x-is`, w );\n        $( `multi-upload uploaded-files-block[block-no=\"${ selectedBlockNo }\"] preview-box .verticle_direction` ).attr( `y-is`, h );\n      }\n    }\n  } catch ( err ) {\n    console.log( `ERROR updatePreviewBoxSizes()`, err.message );\n  }\n}\nasync function manageFiles(files) {\n  console.clear();\n  console.log ( 'files', files.length );\n  // if ( files.length > 1 ) {\n  await activateMultiupload();\n  // }\n  let filesCounter = 1;\n  for (const file of files) {\n    multiFilesManage( file, filesCounter );\n    filesCounter++;\n  }\n}\n\nasync function multiFilesManage( file, fileIndex ) {\n  try {\n    uploadType = 'multi';\n    selectedItemNo = '1-1';\n    console.log ( 'MULTI FILES',  );\n    const fileBlockHTML = $( `template[data-multi-id=\"fileBlock\"]` ).html();\n    $( `multi-upload file-blocks-area` ).append( fileBlockHTML );\n    const lastAddedBlock = $( `multi-upload file-blocks-area uploaded-files-block` ).last();\n    await setIndexNoToBlock( lastAddedBlock, fileIndex );\n\n    const isValidFile = fileValidate( file.type, file.size, file );\n    if ( isValidFile ) {\n      const fileExt = getFileExt( file.name );\n      const selectedParamsObject = imgPreviewBox( `active`, fileExt, fileIndex );\n      if ( typeof hideToggleForVectors !== 'undefined' && hideToggleForVectors && ( fileExt == 'ai' || fileExt == 'eps' || fileExt == 'pdf' || fileExt == 'svg' ) ) {\n        console.log ( 'selectedParamsObject before', selectedParamsObject );\n        selectedParamsObject.bgRemover = false;\n        selectedParamsObject.superRes = false;\n        selectedParamsObject.byDefaultBgRemover = false;\n        selectedParamsObject.byDefaultSuperRes = false;\n        console.log ( 'selectedParamsObject after', selectedParamsObject );\n\n        $( `multi-upload uploaded-files-block[block-no=\"${ fileIndex }\"] toggle-options` ).attr({\n          \"show-bg-option\": false,\n          \"show-superres-option\": false\n        });\n      }\n      let svgFileStatus = false;\n      if ( fileExt == 'svg' ) {\n        svgFileStatus = preDeterminedSVGDimension( file );\n      }\n      const getFileDetails = await processFile( file, fileIndex );\n      // console.log ( 'getFileDetails', getFileDetails );\n      if ( typeof selectedParamsObject !== 'undefined' && selectedParamsObject && typeof getFileDetails !== 'undefined' && getFileDetails ) {\n        getFileDetails['fileExt'] = fileExt;\n        getFileDetails['currentOptions'] = '';\n        if ( typeof file.isAIImage !== 'undefined' && file.isAIImage ) {\n          getFileDetails.isAIImage = file.isAIImage;\n        }\n        if ( typeof file.isAIEdit !== 'undefined' && file.isAIEdit ) {\n          getFileDetails.isAIEdit = file.isAIEdit;\n        }\n        let fileDetails = { ...selectedParamsObject, ...getFileDetails };\n        console.log ( 'fileDetails', fileDetails );\n        const dimensionDetails = await fileDimensions( fileDetails );\n        if ( typeof dimensionDetails !== 'undefined' && dimensionDetails ) {\n          fileDetails = { ...fileDetails, ...dimensionDetails };\n          console.log ( 'fileDetails after dimensions', fileDetails );\n          await applyClassByDimension( fileDetails, fileIndex );\n          const matchedVariant = getMatchingVariant( fileDetails, fileIndex );\n          if ( typeof matchedVariant !== 'undefined' && matchedVariant ) {\n            console.log ( 'matchedVariant', matchedVariant );\n            await checkAndAddNewSizeRow( fileIndex );\n            await toggleOptionActiveWhileFileProcessing( fileDetails, fileIndex );\n            await applyImgToPreviewBox( fileDetails, matchedVariant, true, fileIndex, `yes` );\n\n            await updatePreviewImgAndLineItems( fileIndex );\n\n            saveFileToUser( fileIndex );\n          }\n\n          if (\n              typeof fileDetails.fileExt !== 'undefined' &&\n              ['pdf', 'ai', 'eps'].includes( fileDetails.fileExt )\n            ) {\n              console.log ( 'ext found',  );\n            await addDelay( 1000 * fileIndex );\n            $( `multi-upload uploaded-files-block[block-no=\"${ fileIndex }\"] .widthHeight__item[by=\"width\"] .widthHeight__value` ).trigger( `keyup` );\n          } else {\n            await addDelay( 1000 * fileIndex );\n            $( `multi-upload uploaded-files-block[block-no=\"${ fileIndex }\"] .widthHeight__item[by=\"width\"] .widthHeight__value` ).trigger( `keyup` );\n          }\n        }\n      }\n      setActiveRow();\n    } else {\n      lastAddedBlock.addClass( `drop-disabled-type` );\n      // setTimeout(function(){\n      //   lastAddedBlock.find( `preview-box preview-block` ).removeClass( `drop-disabled-type` );\n      // },2000);\n    }\n    console.log ( 'lastAddedBlock', lastAddedBlock );\n  } catch ( err ) {\n    console.log( `ERROR multiFilesManage( file )`, err.message );\n  }\n}\nasync function saveFileToUser( blockNo ) {\n  try {\n    if ( typeof CUSTOMER_ID !== 'undefined' && CUSTOMER_ID ) {\n      let fileDetails;\n      if ( uploadType == 'multi' ) {\n        fileDetails = getFileDetailsFunction( blockNo );\n      }\n\n      if ( typeof fileDetails !== 'undefined' && fileDetails\n        && typeof fileDetails.file_crc !== 'undefined' && fileDetails.file_crc\n        && typeof fileDetails.fileName !== 'undefined' && fileDetails.fileName\n        && typeof fileDetails.fileWidth_inch !== 'undefined' && fileDetails.fileWidth_inch\n        && typeof fileDetails.fileHeight_inch !== 'undefined' && fileDetails.fileHeight_inch\n        && typeof fileDetails.imgIxFile !== 'undefined' && fileDetails.imgIxFile\n      ) {\n        $.ajax({\n          url: `${ apiURL }/uploads/saveData`,\n          method: \"post\",\n          dataType: \"json\",\n          data: JSON.stringify([{\n            \"variant_title\":  `${ fileDetails.fileWidth_inch }x${ fileDetails.fileHeight_inch }`,\n            \"file\": fileDetails.imgIxFile,\n            \"customer_id\": CUSTOMER_ID,\n            \"file_name\": fileDetails.fileName,\n            \"file_crc\": fileDetails.file_crc,\n            \"product_id\": PRODUCT_ID,\n            \"gangsheet\": isGangPage\n          }])\n        });\n      }\n    }\n  } catch ( err ) {\n    console.log( `ERROR saveFileToUser( blockNo )`, err.message );\n  }\n}\n\nasync function updatePreviewImgAndLineItems( blockNo ) {\n  try {\n    if ( uploadType == 'multi' ) {\n      const optionParams = getToggleOptionParams( blockNo );\n      const fileDetails = getFileDetailsFunction( blockNo );\n      $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] file-preview preview-block .fileupload_hero` ).attr( `src`, `${ fileDetails.imgIxFile }?${ fileDetails.preview }${ typeof optionParams !== 'undefined' && optionParams ? optionParams : `` }` );\n      const isImageLoaded =  await imgLoaded( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] file-preview preview-block .fileupload_hero` );\n      if ( typeof isImageLoaded !== 'undefined' && isImageLoaded ) {\n        $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] file-preview preview-block .viewer-box > img` ).attr( `src`, `${ fileDetails.imgIxFile }?${ fileDetails.preview }${ typeof optionParams !== 'undefined' && optionParams ? optionParams : `` }` );\n        console.log ( 'image loaded', isImageLoaded );\n\n        const previewParams_withoutWidthHeight = removeWandHParams( fileDetails.preview );\n        const getImgDimensions = await getImageSizeFromUrl( `${ fileDetails.imgIxFile }?${ previewParams_withoutWidthHeight }${ typeof optionParams !== 'undefined' && optionParams ? optionParams : `` }` );\n        let getActualWidth = null;\n        let getActualHeight = null;\n        if ( typeof getImgDimensions !== 'undefined' && getImgDimensions ) {\n          getActualWidth = getImgDimensions.width;\n          getActualHeight = getImgDimensions.height;\n        }\n        const newRatio = getNewRatio( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] file-preview preview-block .fileupload_hero`, 'width', getActualWidth, getActualHeight );\n        const getNewHeight = calculateNewWidth_orNewHeight( newRatio, `width`, fileDetails.fileWidth );\n        fileDetails.fileHeight = Math.ceil( getNewHeight );\n        fileDetails.fileHeight_inch = ( getNewHeight / 300 ).toFixed( 2 );\n        fileDetails.currentHeight = ( getNewHeight / 300 ).toFixed( 2 );\n\n        fileDetails.currentOptions = `${ typeof optionParams !== 'undefined' && optionParams ? optionParams : `` }`;\n\n        await applyClassByDimension( fileDetails, blockNo );\n\n        $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] file-preview file-details` ).html( JSON.stringify( fileDetails ) );\n\n        $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] sizes-blocks line-items-custom .widthHeight__custom` ).each(function() {\n          const w = $( this ).find( `.widthHeight__item[by=\"width\"] .widthHeight__value` ).val() * 1;\n          const h = calculateNewWidth_orNewHeight( newRatio, `width`, w );\n          const fileDetail = fileDetails;\n          fileDetail.currentWidth = w.toFixed( 2 );\n          fileDetail.currentHeight = h.toFixed( 2 );\n          const totalInches = Math.ceil( w * h );\n          const matchedVariant = allVariants.slice().reverse().find(obj =>\n            obj.isCustom &&\n            totalInches >= obj.minInches &&\n            totalInches <= obj.maxInches\n          );\n\n          $( this ).find( `.widthHeight__item[by=\"height\"] .widthHeight__value` ).val( h.toFixed( 2 ) );\n\n          if ( typeof matchedVariant !== 'undefined' && matchedVariant ) {\n            $( this ).attr({\n              \"vid\": matchedVariant.id,\n              \"media-id\": matchedVariant.media_id,\n              \"title\": matchedVariant.title,\n              \"price\": matchedVariant.price,\n              \"w\": w.toFixed( 2 ),\n              \"h\": h.toFixed( 2 ),\n              \"size\": `${ w.toFixed( 2 ) }x${ h.toFixed( 2 ) }`\n            });\n          }\n          console.log ( '----- matchedVariant', matchedVariant );\n        })\n\n        calculatePrices();\n        $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] file-preview preview-block.easyzoom` ).removeClass( `image-loading` );\n      }\n    }\n  } catch ( err ) {\n    console.log( `ERROR getToggleOptionParams()`, err.message );\n  }\n}\nfunction calculateNewWidth_orNewHeight(ratio, by, widthOrHeight) {\n  if ( by == 'width' ) {\n    const [ratioWidth, ratioHeight] = ratio.split(':').map(Number);\n    const newWidth = (widthOrHeight * ratioWidth) / ratioHeight;\n    return newWidth;\n  } else if ( by == 'height' ) {\n    const [ratioHeight, ratioWidth] = ratio.split(':').map(Number);\n    const newWHeight = (widthOrHeight * ratioHeight) / ratioWidth;\n    return newWHeight;\n  }\n}\nfunction getNewRatio( selector, by, width, height ) {\n  let getWidth = $( selector ).width() * 1;\n  let getHeight = $( selector ).height() * 1;\n\n  if ( width && height ) {\n    getWidth = width;\n    getHeight = height;\n  }\n\n  let getRatio;\n  if ( by == 'height' ) {\n    getRatio = getRatioFunc( getWidth, getHeight );\n  } else if ( by == 'width' ) {\n    getRatio = getRatioFunc( getHeight, getWidth );\n  } else {\n    getRatio = null;\n  }\n  return getRatio;\n}\nfunction getRatioFunc(height, width) {\n  function gcd(x, y) {\n      return y === 0 ? x : gcd(y, x % y);\n  }\n  const greatestCommonDivisor = gcd(height, width);\n  const ratioHeight = height / greatestCommonDivisor;\n  const ratioWidth = width / greatestCommonDivisor;\n\n  return `${ratioHeight}:${ratioWidth}`;\n}\nasync function getImageSizeFromUrl( url ) {\n  return new Promise((resolve, reject) => {\n    const img = new Image();\n    img.onload = function () {\n      resolve({\n        width: img.naturalWidth,\n        height: img.naturalHeight\n      });\n    };\n    img.onerror = function () {\n      reject(new Error('Failed to load image: ' + url));\n    };\n    img.src = url;\n  });\n}\nasync function imgLoaded(selector) {\n  try {\n    await waitForImageLoad(selector);\n    console.log('\u2705 Image loaded successfully');\n    return true;\n  } catch (err) {\n    console.error('\u274C Image failed to load', err);\n    return false;\n  } finally {\n    console.log('\uD83C\uDFAF Done checking image, moving forward');\n    $(\"next-element\").addClass(\"enablereward\");\n  }\n}\nasync function waitForImageLoad(imgSelector, maxRetries = 5, retryDelay = 3000, attemptTimeout = 10000) {\n  const img = document.querySelector(imgSelector);\n  if (!img) {\n    throw new Error(`No image found with selector \"${imgSelector}\"`);\n  }\n\n  const ignoredSrc = '//cdn.shopify.com/s/files/1/0558/0265/8899/files/transparent.png';\n  if (img.src.includes(ignoredSrc)) {\n    console.log('Image is transparent placeholder \u2013 skipping load check.');\n    return null;\n  }\n\n  function tryLoadImage(attempt) {\n    return new Promise((resolve, reject) => {\n      if (img.complete && img.naturalWidth !== 0) {\n        return resolve(img);\n      }\n\n      let settled = false;\n      const timeoutId = setTimeout(() => {\n        if (!settled) {\n          settled = true;\n          cleanup();\n          console.warn(`Attempt ${attempt + 1}: image load timed out after ${attemptTimeout}ms`);\n          if (attempt < maxRetries) {\n            setTimeout(() => {\n              tryLoadImage(attempt + 1).then(resolve).catch(reject);\n            }, retryDelay);\n          } else {\n            reject(new Error(`Image timed out after ${maxRetries} attempts.`));\n          }\n        }\n      }, attemptTimeout);\n\n      const onLoad = () => {\n        if (!settled) {\n          settled = true;\n          cleanup();\n          clearTimeout(timeoutId);\n          resolve(img);\n        }\n      };\n\n      const onError = () => {\n        if (!settled) {\n          settled = true;\n          cleanup();\n          clearTimeout(timeoutId);\n          if (attempt < maxRetries) {\n            console.warn(`Attempt ${attempt + 1}: image failed to load. Retrying...`);\n            setTimeout(() => {\n              tryLoadImage(attempt + 1).then(resolve).catch(reject);\n            }, retryDelay);\n          } else {\n            reject(new Error(`Image failed to load after ${maxRetries} attempts.`));\n          }\n        }\n      };\n\n      function cleanup() {\n        img.removeEventListener('load', onLoad);\n        img.removeEventListener('error', onError);\n      }\n\n      img.addEventListener('load', onLoad);\n      img.addEventListener('error', onError);\n    });\n  }\n\n  return tryLoadImage(0);\n}\nasync function applyImgToPreviewBox( fileDetails, matchedVariant, updateImg = false, blockNo, isFileUploading = 'no' ) {\n  try {\n    if ( uploadType == 'multi' ) {\n      if ( updateImg ) {\n        const optionParams = getToggleOptionParams( blockNo );\n        $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] file-preview preview-block .fileupload_hero` ).attr( `src`, `${ fileDetails.imgIxFile }?${ fileDetails.preview }${ typeof optionParams !== 'undefined' && optionParams ? optionParams : `` }` );\n        const isImageLoaded =  await imgLoaded( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] file-preview preview-block .fileupload_hero` );\n        if ( typeof isImageLoaded !== 'undefined' && isImageLoaded ) {\n          $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] file-preview preview-block .viewer-box > img` ).attr( `src`, `${ fileDetails.imgIxFile }?${ fileDetails.preview }` );\n          console.log ( 'image loaded', isImageLoaded );\n\n          const previewParams_withoutWidthHeight = removeWandHParams( fileDetails.preview );\n          const getImgDimensions = await getImageSizeFromUrl( `${ fileDetails.imgIxFile }?${ previewParams_withoutWidthHeight }${ typeof optionParams !== 'undefined' && optionParams ? optionParams : `` }` );\n          if ( typeof getImgDimensions !== 'undefined' && getImgDimensions ) {\n            if (\n              typeof fileDetails.fileExt !== 'undefined' &&\n              ['pdf', 'ai', 'eps'].includes( fileDetails.fileExt ) &&\n              typeof fileDetails.vector_fileWidth !== 'undefined' &&\n              fileDetails.vector_fileWidth &&\n              typeof fileDetails.vector_fileHeight !== 'undefined' &&\n              fileDetails.vector_fileHeight\n            ) {\n              // console.log ( 'getImgDimensions', getImgDimensions );\n              fileDetails.fileWidth = fileDetails.vector_fileWidth;\n              fileDetails.fileHeight = fileDetails.vector_fileHeight;\n              fileDetails.fileWidth_inch = (fileDetails.vector_fileWidth / 300).toFixed(2);\n              fileDetails.fileHeight_inch = (fileDetails.vector_fileHeight / 300).toFixed(2);\n              fileDetails.ratioBy_width = `${ fileDetails.vector_fileWidth / fileDetails.vector_fileHeight }`;\n              fileDetails.ratioBy_height = `${ fileDetails.vector_fileHeight / fileDetails.vector_fileWidth }`;\n              fileDetails.currentWidth = (fileDetails.vector_fileWidth / 300).toFixed(2);\n              fileDetails.currentHeight = (fileDetails.vector_fileHeight / 300).toFixed(2);\n\n              delete fileDetails.vector_fileWidth;\n              delete fileDetails.vector_fileHeight;\n              delete fileDetails.vector_fileWidth_inch;\n              delete fileDetails.vector_fileHeight_inch;\n              delete fileDetails.vector_ratioBy_width;\n              delete fileDetails.vector_ratioBy_height;\n              delete fileDetails.vector_currentWidth;\n              delete fileDetails.vector_currentHeight;\n            } else {\n              console.log ( 'getImgDimensions', getImgDimensions );\n              fileDetails.fileWidth = getImgDimensions.width;\n              fileDetails.fileHeight = getImgDimensions.height;\n              fileDetails.fileWidth_inch = (getImgDimensions.width / 300).toFixed(2);\n              fileDetails.fileHeight_inch = (getImgDimensions.height / 300).toFixed(2);\n              fileDetails.ratioBy_width = `${ getImgDimensions.width / getImgDimensions.height }`;\n              fileDetails.ratioBy_height = `${ getImgDimensions.height / getImgDimensions.width }`;\n              fileDetails.currentWidth = (getImgDimensions.width / 300).toFixed(2);\n              fileDetails.currentHeight = (getImgDimensions.height / 300).toFixed(2);\n            }\n          }\n\n          $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] file-preview file-details` ).html( JSON.stringify( fileDetails ) );\n\n          await applySizes( fileDetails, matchedVariant, blockNo, isFileUploading );\n          await calculatePrices( fileDetails, matchedVariant );\n          $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] file-preview preview-block.easyzoom` ).removeClass( `image-loading` );\n          $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] file-progress` ).addClass( `hidden` );\n        }\n      } else {\n        await applySizes( fileDetails, matchedVariant, blockNo, isFileUploading );\n        await calculatePrices( fileDetails, matchedVariant, blockNo );\n      }\n    }\n  } catch ( err ) {\n    console.log( `ERROR applyImgToPreviewBox( fileDetails, matchedVariant )`, err.message );\n  }\n}\n/* ------------------------------------------------------------------\n   Ninja Cash / cashback crest for the blanks multi-upload modal.\n\n   The dtf-transfers modal shows a \"X% BACK \u00B7 You'll earn $Y back on\n   this item\" crest under Add to Cart. That is driven by bySize.css +\n   multiupload.css + a product render of reward-point-info.liquid \u2014 none\n   of which load on blanks. So we reproduce it here: __uploadBoxBlock.liquid\n   bakes the customer's belt tier into the .multiupload-rewards-slice\n   container as data-* attributes, and this fn computes the live dollar\n   amount from the modal's running total (paid = total \u00D7 (1 \u2212 discount)).\n\n   The markup/classes mirror reward-point-info.liquid exactly, so the\n   `.reward-crest*` CSS already on the page (from the cart crest render)\n   styles it 1:1 \u2014 no extra CSS needed. The inner wrapper carries\n   id=\"__reward_info\" purely so the grey-pill container rule applies; it\n   is selected by its .nt-reward-info class to stay clear of the cart\n   crest's same-id node. Hidden until the order total is > $0, mirroring\n   the dtf modal's \"enablereward\" gating. */\nfunction updateBlanksReward( totalPrice, discountPercent ) {\n  try {\n    var slices = document.querySelectorAll( '.multiupload-rewards-slice[data-nt-reward]' );\n    if ( !slices.length ) return;\n    var pct  = parseFloat( discountPercent ) || 0;\n    var paid = ( parseFloat( totalPrice ) || 0 ) * ( 1 - pct / 100 );\n    if ( isNaN( paid ) || paid < 0 ) paid = 0;\n    for ( var s = 0; s < slices.length; s++ ) {\n      ( function( slice ) {\n        var signedIn  = slice.getAttribute( 'data-signed-in' ) === 'true';\n        var slug      = slice.getAttribute( 'data-tier-slug' ) || 'white';\n        var name      = slice.getAttribute( 'data-tier-name' ) || 'White Belt';\n        var tierPct   = slice.getAttribute( 'data-tier-pct' ) || '2';\n        var rate      = parseFloat( slice.getAttribute( 'data-rate' ) ) || 0.02;\n        var itemOrder = slice.getAttribute( 'data-item-or-order' ) || 'on this item';\n        var learnHref = slice.getAttribute( 'data-learn-href' ) || '/pages/ninja-rewards';\n        var money     = '$' + ( paid * rate ).toFixed( 2 );\n        var info;\n        if ( signedIn ) {\n          info = \"<div class='reward-crest__swatch reward-crest__swatch--\" + slug + \"'>\"\n               +   \"<div class='reward-crest__rate'>\" + tierPct + \"%</div>\"\n               +   \"<div class='reward-crest__rate-sub'>BACK</div>\"\n               + \"</div>\"\n               + \"<div class='reward-crest__body'>\"\n               +   \"<span class='reward-crest__eyebrow'>\" + name + \" Cashback</span>\"\n               +   \"<span class='reward-crest__copy'><span class='rc-lead'>You'll </span><span class='rc-verb-full'>earn</span><span class='rc-verb-short'>Earn</span> <strong>\" + money + \"</strong> back<span class='rc-tail'> \" + itemOrder + \"</span></span>\"\n               + \"</div>\";\n        } else {\n          info = \"<div class='reward-crest__swatch reward-crest__swatch--guest'>\"\n               +   \"<div class='reward-crest__rate-pre'>Up to</div>\"\n               +   \"<div class='reward-crest__rate'>10%</div>\"\n               +   \"<div class='reward-crest__rate-sub'>BACK</div>\"\n               + \"</div>\"\n               + \"<div class='reward-crest__body'>\"\n               +   \"<span class='reward-crest__eyebrow-row'><span class='reward-crest__eyebrow'>Ninja Rewards Cashback</span><span class='reward-crest__eyebrow-sep'>&middot;</span><a href='\" + learnHref + \"' target='_blank' rel='noopener' class='reward-crest__signin'>Learn more</a></span>\"\n               +   \"<span class='reward-crest__copy'>Earn up to <strong>\" + money + \"</strong> back \" + itemOrder + \"</span>\"\n               + \"</div>\";\n        }\n        var crest = slice.querySelector( '.reward-point-block' );\n        if ( !crest ) {\n          // Ninja Cash Balance card \u2014 mirrors reward-point-info.liquid (which doesn't render on\n          // blanks). Balance is fixed for the session, so build it once at crest creation; the\n          // shared .nt-nc-balance-card / .multiupload-rewards-slice CSS handles the layout.\n          var ncBalance = parseInt( slice.getAttribute( 'data-nc-balance' ) || '0', 10 );\n          var showNc = signedIn && ncBalance > 0;\n          crest = document.createElement( 'div' );\n          crest.className = 'reward-point-block reward-crest reward-crest--' + slug + ' __product-page' + ( showNc ? ' nt-has-nc-balance' : '' );\n          var infoWrap = document.createElement( 'div' );\n          infoWrap.id = '__reward_info';\n          infoWrap.className = 'nt-reward-info';\n          crest.appendChild( infoWrap );\n          if ( showNc ) {\n            var ncMoney = '$' + ( ncBalance / 100 ).toFixed( 2 );\n            var ncCard = document.createElement( 'div' );\n            ncCard.className = 'nt-nc-balance-card';\n            ncCard.setAttribute( 'aria-label', 'Ninja Cash Balance' );\n            ncCard.innerHTML = \"<span class='nt-nc-balance-card__icon' aria-hidden='true'>$</span>\"\n              + \"<span class='nt-nc-balance-card__text'>\"\n              +   \"<span class='nt-nc-balance-card__label'><span class='rc-bal-full'>Ninja Cash</span><span class='rc-bal-short'>Ninja Cash</span></span>\"\n              +   \"<span class='nt-nc-balance-card__amount'>\" + ncMoney + \"</span>\"\n              + \"</span>\";\n            crest.appendChild( ncCard );\n          }\n          slice.appendChild( crest );\n        }\n        crest.querySelector( '.nt-reward-info' ).innerHTML = info;\n        /* .reward-point-block has a base display:none (reward-point-info.liquid); the dtf engine's\n           reward func flips it to flex, but that doesn't run for the blanks crest \u2014 so reveal it\n           here. Without this the crest stayed hidden on mobile (desktop happened to be shown by\n           the PDP reward func), leaving the pinned bar button-only. */\n        crest.style.display = 'flex';\n        /* Always visible (Justin 2026-06-16) \u2014 hiding at $0 left the mobile\n           pinned bar button-only until a size was picked, and the scroll\n           clearance sized for the full bar showed as a white gap. */\n        slice.style.display = 'flex';\n        slice.style.justifyContent = 'center';\n      } )( slices[ s ] );\n    }\n  } catch ( err ) {\n    console.log( 'ERROR updateBlanksReward( totalPrice, discountPercent )', err.message );\n  }\n}\nasync function calculatePrices( fileDetails = null, matchedVariant = null, blockNo ) {\n  try {\n    if ( uploadType == 'multi' ) {\n      await pricesTable();\n      const selectedIndex = $( `multi-upload prices-table .pricesTable__items .pricesTable__item.selected` ).attr( `index` );\n      console.log ( 'selectedIndex', selectedIndex );\n      let getDiscountPercent = $( `multi-upload prices-table .pricesTable__items .pricesTable__item.selected` ).attr( `off` );\n      console.log ( 'getDiscountPercent', getDiscountPercent );\n      let discountText = '';\n      if ( getDiscountPercent == '' || getDiscountPercent == '0' ) {\n        getDiscountPercent = 0;\n      } else {\n        discountText = `${ getDiscountPercent }% off`;\n      }\n\n      let totalPrice = 0;\n      $( `multi-upload line-items sizes-blocks .widthHeight__custom[item]` ).each(function() {\n        const qty = $( this ).find( `precut-unit-logic .precut-unit-logic__qty .customQtyFile__qty` ).val() * 1;\n        let unitPrice = $( this ).attr( `price` ) * 1;\n\n        // Shopify-parity: the cart tier discount floors the per-unit discount to whole cents; mirror it so the PDP quotes what checkout charges\n        let unitDiscountPrice = Math.floor( ( Math.round( unitPrice * 100 ) * getDiscountPercent ) / 100 ) / 100;\n        unitDiscountPrice = unitPrice - unitDiscountPrice;\n\n        $( this ).attr( `discount`, getDiscountPercent );\n        $( this ).find( `precut-unit-logic .precut-unit-logic__price .__originalPrice` ).text( `$${ unitPrice.toFixed( 2 ) }` );\n        $( this ).find( `precut-unit-logic .precut-unit-logic__price .__discountedPrice` ).html( Number.isNaN(unitDiscountPrice) ? '$0.00<span>ea</span>' : `$${unitDiscountPrice.toFixed(2)}<span>ea</span>` );\n\n        $( this ).find( `precut-unit-logic .precut-unit-logic__total .__originalPrice` ).text( `$${ (unitPrice * qty).toFixed(2) }` );\n        // $( this ).find( `precut-unit-logic .precut-unit-logic__total .__discountedPrice` ).text( `$${ (unitDiscountPrice * qty).toFixed(2) }` );\n        $( this ).find( `precut-unit-logic .precut-unit-logic__total .__discountedPrice` ).text( Number.isNaN(unitDiscountPrice) ? '$0.00' : `$${ (unitDiscountPrice * qty).toFixed(2) }` );\n        $( this ).find( `precut-unit-logic .precut-unit-logic__discount > span` ).text( discountText );\n\n        const total = qty * unitPrice;\n\n        totalPrice = totalPrice + total;\n      })\n      console.log ( 'totalPrice', totalPrice );\n      shippingBarData( totalPrice );\n      // Keep the Ninja Cash / cashback crest in sync with the running total.\n      updateBlanksReward( totalPrice, getDiscountPercent );\n    }\n  } catch ( err ) {\n    console.log( `ERROR calculatePrices( fileDetails, matchedVariant = null )`, err.message );\n  }\n}\nasync function shippingBarData( total ) {\n  try {\n    console.log ( 'total', total );\n    await fetch( `/cart?view=shipping-bar&price=${ total }` )\n      .then(response => {\n        return response.text()\n      })\n      .then(html => {\n        $( `multi-upload multi-shipping-bar` ).html( html.replaceAll(`[AMOUNT]`,`$75`) )\n      })\n  } catch ( err ) {\n    console.log( `ERROR shippingBarData( total )`, err.message );\n  }\n}\nasync function pricesTable() {\n  try {\n    console.log ( 'pricesTable()' );\n    if ( uploadType == 'multi' ) {\n      // Mirror of bySize_popular.js's popup fix (2026-07-01): the popup's\n      // Price column was CSS-hidden historically, so this branch was left\n      // empty and the tier cells rendered a bare \"$ ea\". Same source of\n      // truth as DTF: the ACTIVE line item's per-unit `price` attr (set by\n      // applySizes from matchedVariant), discounted per tier row.\n      const unitPriceMulti = $( `multi-upload sizes-blocks .widthHeight__custom[item=\"${ selectedItemNo }\"]` ).attr( `price` ) * 1;\n      $( `multi-upload prices-table .pricesTable__items .pricesTable__item` ).each(function(i) {\n        let offPercent = $( this ).attr( `off` ) * 1;\n        let getOff = 1;\n        if ( offPercent == '' || offPercent == 0 ) {\n          offPercent = 1;\n        } else {\n          getOff = ( 100 - offPercent ) / 100;\n        }\n        if (Number.isNaN(unitPriceMulti)) {\n          $( this ).find( `.pricesTable__item_2 discount` ).text( `0.00` );\n        } else {\n          // Shopify-parity: floor the per-unit discount to whole cents like the cart does\n          $( this ).find( `.pricesTable__item_2 discount` ).text( ( getOff == 1 ? unitPriceMulti : ( Math.round( unitPriceMulti * 100 ) - Math.floor( ( Math.round( unitPriceMulti * 100 ) * offPercent ) / 100 ) ) / 100 ).toFixed( 2 ) );\n        }\n      })\n    }\n  } catch ( err ) {\n    console.log( `ERROR pricesTable()`, err.message );\n  }\n}\nasync function applySizes( fileDetails, matchedVariant = null, blockNo, isFileUploading ) {\n  try {\n    if ( uploadType == 'multi' ) {\n      $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] file-preview .horizontal_direction` ).attr( `x-is`, `${ fileDetails.currentWidth }` );\n      $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] file-preview .verticle_direction` ).attr( `y-is`, `${ fileDetails.currentHeight }\"` );\n      let getSelectedTier;\n      if ( isFileUploading == 'yes' ) {\n        getSelectedTier = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] sizes-blocks .widthHeight__custom[item=\"${ blockNo }-1\"]` );\n      } else {\n        getSelectedTier = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] sizes-blocks .widthHeight__custom[item=\"${ selectedItemNo }\"]` );\n      }\n\n      if (\n        typeof fileDetails.fileExt !== 'undefined' &&\n        ['pdf', 'ai', 'eps'].includes( fileDetails.fileExt ) &&\n        typeof fileDetails.vector_currentWidth !== 'undefined' &&\n        fileDetails.vector_currentWidth\n      ) {\n        getSelectedTier.find( `.widthHeight__item[by=\"width\"] .widthHeight__value` ).val( fileDetails.vector_currentWidth );\n        getSelectedTier.find( `.widthHeight__item[by=\"height\"] .widthHeight__value` ).val( fileDetails.vector_currentHeight );\n      } else {\n        getSelectedTier.find( `.widthHeight__item[by=\"width\"] .widthHeight__value` ).val( fileDetails.currentWidth );\n        getSelectedTier.find( `.widthHeight__item[by=\"height\"] .widthHeight__value` ).val( fileDetails.currentHeight );\n      }\n\n      if ( typeof matchedVariant !== 'undefined' && matchedVariant ) {\n        getSelectedTier.attr({\n          \"title\": matchedVariant.title,\n          \"vid\": matchedVariant.id,\n          \"dpi-warning\": '',\n          \"price\": matchedVariant.price,\n          \"media-id\": matchedVariant.media_id,\n          \"w\": fileDetails.currentWidth,\n          \"h\": fileDetails.currentHeight,\n          \"size\": `${ fileDetails.currentWidth }x${ fileDetails.currentHeight }`\n        });\n      }\n    }\n  } catch ( err ) {\n    console.log( `ERROR applySizeToPreviewBox( fileDetails )`, err.message );\n  }\n}\n\nfunction removeWandHParams( query ) {\n  try {\n    let params = new URLSearchParams(query);\n    // Delete 'w' and 'h' if they exist\n    params.delete('w');\n    params.delete('h');\n\n    // Get the updated query string\n    return params.toString();\n  } catch ( err ) {\n    console.log( `ERROR removeWandHParams( url )`, err.message );\n  }\n}\nfunction getToggleOptionParams( blockNo ) {\n  try {\n    let bgRemoveState = false;\n    let superResState = false;\n    if ( uploadType == 'multi' ) {\n      bgRemoveState = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] toggle-options .bgRemover .toggleOption` ).is( `:checked` );\n      superResState = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] toggle-options .superRes .toggleOption` ).is( `:checked` );\n    }\n    if ( bgRemoveState || superResState ) {\n      let optionParams = ``;\n      if ( bgRemoveState ) {\n        optionParams += bgRemoveState ? `&bg-remove=true` : ``;\n      }\n      if ( superResState ) {\n        optionParams += superResState ? `&upscale=true` : ``;\n      }\n      return optionParams\n    } else {\n      return null;\n    }\n  } catch ( err ) {\n    console.log( `ERROR getToggleOptionParams()`, err.message );\n  }\n}\nasync function toggleOptionActiveWhileFileProcessing( fileDetails, blockNo ) {\n  try {\n    if ( uploadType == 'multi' ) {\n      let collectCurrentOptions = ``;\n      if ( fileDetails.bgRemover && fileDetails.byDefaultBgRemover ) {\n        $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] toggle-options .bgRemover .toggleOption` ).prop( `checked`, true );\n        collectCurrentOptions = `&bg-remove=true`;\n      }\n      const getTotalPixels = ( fileDetails.fileWidth * fileDetails.fileHeight );\n      if ( fileDetails.superRes && fileDetails.byDefaultSuperRes && typeof isEnabledPixelsValidation !== 'undefined' && isEnabledPixelsValidation && definedMaxPixelsForSuperRes > getTotalPixels ) {\n        $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] toggle-options .superRes .toggleOption` ).prop( `checked`, true );\n        collectCurrentOptions = `${ collectCurrentOptions }&upscale=true`;\n      }\n      if (  typeof isEnabledPixelsValidation !== 'undefined' && isEnabledPixelsValidation && definedMaxPixelsForSuperRes < getTotalPixels ) {\n        $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] toggle-options` ).attr( `show-superres-option`, false );\n      }\n      if ( collectCurrentOptions != '' ) {\n        fileDetails.currentOptions = collectCurrentOptions;\n        $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] preview-box file-details` ).text( JSON.stringify( fileDetails ) );\n      }\n    }\n  } catch ( err ) {\n    console.log( `ERROR toggleOptionActiveWhileFileProcessing( blockNo )`, err.message );\n  }\n}\nasync function checkAndAddNewSizeRow( blockNo ) {\n  try {\n    let rtn = false;\n    if ( uploadType == 'multi' ) {\n      let activeOption = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] tab-controls .tabOptionName:checked` ).val();\n      const isActiveTierAvailable = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] sizes-blocks line-items-${ activeOption }` ).hasClass( `rowAdded` );\n      if ( isActiveTierAvailable == false ) {\n        $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] sizes-blocks line-items-${ activeOption }:not(.rowAdded)` )\n          .append( $( `#multiUploadTemplates template[data-multi-id=\"${ activeOption }\"]` ).html() )\n          .addClass( `rowAdded`, activeOption );\n\n        await applyItemNo( activeOption, blockNo );\n        rtn = true;\n      }\n    }\n    return rtn;\n  } catch ( err ) {\n    console.log( `ERROR checkAndAddNewSizeRow( selector )`, err.message );\n  }\n}\nasync function applyItemNo( type, blockNo ) {\n  try {\n    if ( uploadType == 'multi' ) {\n      let totalQty = 0;\n      $( `multi-upload file-blocks-area uploaded-files-block` ).each(function( main_i ) {\n        let blockCountNo = 0;\n        const newMain_index = main_i + 1;\n        $( this ).find( `sizes-blocks line-items-custom .widthHeight__custom` ).each(function( i ) {\n          const j = i + 1;\n          $( this ).attr({\n            \"item\": `${ newMain_index }-${ j }`\n          });\n          blockCountNo = j;\n        })\n        let secondCountNo = blockCountNo;\n        $( this ).find( `sizes-blocks line-items-popular .widthHeight__custom` ).each(function( i ) {\n          const j = blockCountNo + ( i + 1 );\n          $( this ).attr({\n            \"item\": `${ newMain_index }-${ j }`\n          });\n          secondCountNo = j;\n        })\n        $( this ).find( `sizes-blocks` ).attr( `total-items`, secondCountNo );\n        totalQty = totalQty + secondCountNo;\n      })\n      selectedItemNo = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] sizes-blocks line-items-${ type } .widthHeight__custom` ).last().attr( `item` );\n      let precut = $( `multi-upload precut #preCutOption_multi` ).is( `:checked` );\n      if ( typeof precut !== 'undefined' && precut ) {\n        precut = 'Yes';\n      } else {\n        precut = '';\n      }\n      $( `multi-upload file-blocks-area` ).attr( `total-qty`, totalQty );\n      $( `multi-upload sizes-blocks .widthHeight__custom` ).attr( `precut`, precut );\n      calculateTotalQty();\n    }\n  } catch ( err ) {\n    console.log( `ERROR applyItemNo( selector )`, err.message );\n  }\n}\nasync function calculateTotalQty() {\n  try {\n    console.log ( 'calculateTotalQty();',  );\n    if ( uploadType == 'multi' ) {\n      let totalQty = 0;\n      $( `multi-upload file-blocks-area uploaded-files-block` ).each(function( main_i ) {\n        let blockQty = 0;\n        $( this ).find( `sizes-blocks line-items-custom .widthHeight__custom` ).each(function( i ) {\n          const q = $( this ).attr( `qty` ) * 1;\n          totalQty = totalQty + q;\n          blockQty = blockQty + q;\n        })\n\n        $( this ).find( `sizes-blocks line-items-popular .widthHeight__custom` ).each(function( i ) {\n          const q = $( this ).attr( `qty` ) * 1;\n          totalQty = totalQty + q;\n          blockQty = blockQty + q;\n        })\n        $( this ).find( `line-items sizes-blocks` ).attr( `total-qty`, blockQty );\n      })\n      $( `multi-upload file-blocks-area, multi-upload prices-table` ).attr( `total-qty`, totalQty );\n      const cartQty = $( `multi-upload prices-table` ).attr( `already-in-cart` ) * 1;\n      $( `multi-upload prices-table` ).attr( `current-qty-plus-cart-qty`, `${ totalQty + cartQty }` );\n\n      pricesTableSelectedBar();\n    }\n  } catch ( err ) {\n    console.log( `ERROR calculateTotalQty()`, err.message );\n  }\n}\nfunction pricesTableSelectedBar() {\n  try {\n    console.log ( 'pricesTableSelectedBar()',  );\n    if ( uploadType == 'multi' ) {\n      var $table = $( `multi-upload prices-table` );\n      var totalQty = parseInt($table.attr( `current-qty-plus-cart-qty` ), 10);\n      let selectedIndex;\n\n      console.log ( 'totalQty', totalQty );\n\n      $table.find( `.pricesTable__items .pricesTable__item` ).each(function () {\n        const min     = $( this ).attr( `min` ) * 1;\n        const max     = $( this ).attr( `max` ) * 1;\n        const indexNo = $( this ).attr( `index` ) * 1;\n        if ( totalQty >= min && totalQty <= max ) {\n          selectedIndex = indexNo;\n        }\n      });\n      if ( typeof selectedIndex !== 'undefined' && selectedIndex ) {\n        $table.find( `.pricesTable__items .pricesTable__item` ).removeClass( `selected` );\n        $table.find( `.pricesTable__items .pricesTable__item[index=\"${ selectedIndex }\"]` ).addClass( `selected` );\n      }\n\n      const lastIndexNo = $table.find( `.pricesTable__items .pricesTable__item` ).last().attr( `index` ) * 1;\n      const isLastMinumum = $table.find( `.pricesTable__items .pricesTable__item` ).last().attr( `min` ) * 1;\n\n      if ( lastIndexNo == selectedIndex ) {\n        const maxQtyMsg = $table.attr( `max-qty-msg` );\n        $table.find( `.pricesTable__items .pricesTable__item[index=\"${ selectedIndex }\"] .pricesTable__item__msg` ).html( maxQtyMsg );\n      } else {\n        let rowMsg = $table.attr( `items-msg` );\n        const CumulativeQty = getCumulativeQty();\n        if ( rowMsg.includes( `[QTY]` ) ) {\n          rowMsg = rowMsg.replace( `[QTY]`, CumulativeQty );\n        }\n        if ( rowMsg.includes( `[NEXT_DISCOUNT]` ) ) {\n          const nextOff = $table.find( `.pricesTable__items .pricesTable__item[index=\"${ selectedIndex }\"]` ).attr( `next-off` );\n          if ( typeof nextOff !== 'undefined' && nextOff ) {\n            rowMsg = rowMsg.replace( `[NEXT_DISCOUNT]`, `${ nextOff }% off` );\n          }\n        }\n        console.log ( 'CumulativeQty', CumulativeQty, `isLastMinumum`, isLastMinumum );\n        $table.find( `.pricesTable__items .pricesTable__item[index=\"${ selectedIndex }\"] .pricesTable__item__msg` ).html( rowMsg );\n      }\n    }\n  } catch ( err ) {\n    console.log( `ERROR pricesTableSelectedBar()`, err.message );\n  }\n}\nfunction getCumulativeQty() {\n  try {\n    if ( uploadType == 'multi' ) {\n      const pageQty = $( `multi-upload prices-table` ).attr( `total-qty` ) * 1;\n      const cartQty = $( `multi-upload prices-table` ).attr( `already-in-cart` ) * 1;\n      const max = $( `multi-upload prices-table .pricesTable__items .pricesTable__item.selected` ).attr( `max` ) * 1;\n\n      let cartState =  cartQty + pageQty;\n      let x = max - cartState;\n      if ( pageQty === 1 ) return (max + 2) - cartState;\n      if(x === 0 ) return 1;\n      x = max - cartState;\n      return x + 1\n    }\n  } catch ( err ) {\n    console.log( `ERROR getCumulativeQty()`, err.message );\n  }\n}\n\n\n\nfunction getMatchingVariant( fileDetail = null, blockNo ) {\n  try {\n    if ( uploadType == 'multi' ) {\n      let activeTab = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] tab-controls .tabOptionName:checked` ).val();\n      console.log ( 'fileDetail', fileDetail );\n      let fileDetails = fileDetail;\n      if ( fileDetail == null ) {\n        fileDetails = getFileDetailsFunction( blockNo );\n      }\n      if ( activeTab == `custom` ) {\n        let totalInches = parseFloat(fileDetails.currentWidth) * parseFloat(fileDetails.currentHeight);\n        if ( totalInches < 1 ) {\n          totalInches = 1;\n        }\n        totalInches = Math.ceil( totalInches );\n\n        const highestMaxInches = Math.max(...bySizeVariants.filter(style => style.isCustom).map(style => style.maxInches));\n        if ( totalInches > highestMaxInches ) {\n          const highestObject = bySizeVariants.filter(style => style.isCustom).reduce((maxObj, current) => {\n            return current.maxInches > maxObj.maxInches ? current : maxObj;\n          });\n          // console.log('Object with highest maxInches:', highestObject);\n          return highestObject;\n        } else {\n          const matchedStyle = bySizeVariants.slice().reverse().find(obj =>\n            obj.isCustom &&\n            totalInches >= obj.minInches &&\n            totalInches <= obj.maxInches\n          );\n          return matchedStyle ?? null;\n        }\n      } else if ( activeTab == 'popular' ) {\n        const getVal = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] sizes-blocks .widthHeight__custom[item=\"${ selectedItemNo }\"] .popularSizes` ).val();\n        const matchedVariant = findObjectByKey( bySizeVariants, `option1_converted`, getVal );\n        return matchedVariant ?? null;\n      }\n    }\n  } catch ( err ) {\n    console.log( `ERROR getMatchingVariant( fileDetails )`, err.message );\n  }\n}\nfunction getFileDetailsFunction( blockNo ) {\n  try {\n    let fileDetails = '';\n    if ( uploadType == 'multi' ) {\n      fileDetails = $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] preview-box file-preview file-details` ).text();\n    }\n    if ( typeof fileDetails !== 'undefined' && fileDetails ) {\n      fileDetails = JSON.parse( fileDetails );\n      return fileDetails;\n    } else {\n      return null;\n    }\n  } catch ( err ) {\n    console.log( `ERROR getFileDetailsFunction()`, err.message );\n  }\n}\n\nfunction setActiveRow() {\n  try {\n    if ( uploadType == 'multi' ) {\n      $( `multi-upload .widthHeight__custom` ).removeClass( `active` );\n      $( `multi-upload .widthHeight__custom[item=\"${ selectedItemNo }\"]` ).addClass( `active` );\n      // Mirrors of the DTF popup engine (bySize_popular.js, 2026-07-01):\n      // keep the pricing-table Price column in sync with the active row,\n      // and gray out the INACTIVE tab's rows per block (.disabled white\n      // overlay from transferBySize.css; click-to-reactivate handler below).\n      pricesTable();\n      $( `multi-upload uploaded-files-block` ).each(function() {\n        const blockTab = $( this ).find( `tab-controls .tabOptionName:checked` ).val();\n        $( this ).find( `sizes-blocks .widthHeight__custom[item][option-selected=\"custom\"]` ).toggleClass( `disabled`, blockTab === 'popular' );\n        $( this ).find( `sizes-blocks .widthHeight__custom[item][option-selected=\"popular\"]` ).toggleClass( `disabled`, blockTab === 'custom' );\n      });\n    }\n\n    // console.log(\"typeof _qtyupdate:\",typeof _qtyupdate)\n    if(typeof _qtyupdate == \"function\"){\n      _qtyupdate();\n      $(\".grt_payment_icons\").removeClass(\"hide\");\n    }\n  } catch ( err ) {\n    console.log( `ERROR `, err.message );\n  }\n}\nasync function fileDimensions( fileDetails ) {\n  try {\n    let getApiResponse, file_width, file_height;\n    if ( fileDetails.fileExt == 'psd' || fileDetails.fileExt == 'eps' || fileDetails.fileExt == 'ai' ) {\n      if ( fileDetails.fileExt == 'eps' || fileDetails.fileExt == 'ai' ) {\n        getApiResponse  =   await sendApiRequest( `${ fileDetails.imgIxFile }?trim=colorUnlessAlpha` );\n      } else {\n        getApiResponse  =   await sendApiRequest( `${ fileDetails.imgIxFile }`, true );\n      }\n      if ( typeof getApiResponse !== 'undefined' && getApiResponse.success === true ) {\n        console.log ( 'getApiResponse', getApiResponse );\n        if ( typeof getApiResponse.data.dimensions !== 'undefined' && getApiResponse.data.dimensions ) {\n          if ( fileDetails.fileExt == 'eps' || fileDetails.fileExt == 'ai' ) {\n            file_width  =   getApiResponse.data.dimensions.width;\n            file_height =   getApiResponse.data.dimensions.height;\n\n            file_width  =   file_width * 4.167;\n            file_height =   file_height * 4.167;\n\n            file_width  =   file_width * 300;\n            file_height =   file_height * 300;\n          } else {\n            file_width  =   getApiResponse.data.dimensions.width * 300;\n            file_height =   getApiResponse.data.dimensions.height * 300;\n          }\n        }\n\n        return {\n          \"vector_fileWidth\": file_width,\n          \"vector_fileHeight\": file_height,\n          \"vector_fileWidth_inch\": (file_width / 300).toFixed(2),\n          \"vector_fileHeight_inch\": (file_height / 300).toFixed(2),\n          \"vector_ratioBy_width\": `${ file_width / file_height }`,\n          \"vector_ratioBy_height\": `${ file_height / file_width }`,\n          \"vector_currentWidth\": (file_width / 300).toFixed(2),\n          \"vector_currentHeight\": (file_height / 300).toFixed(2),\n\n          \"fileWidth\": file_width,\n          \"fileHeight\": file_height,\n          \"fileWidth_inch\": (file_width / 300).toFixed(2),\n          \"fileHeight_inch\": (file_height / 300).toFixed(2),\n          \"ratioBy_width\": `${ file_width / file_height }`,\n          \"ratioBy_height\": `${ file_height / file_width }`,\n          \"currentWidth\": (file_width / 300).toFixed(2),\n          \"currentHeight\": (file_height / 300).toFixed(2)\n        }\n      } else {\n        file_width  =   300;\n        file_height =   300;\n      }\n      return {\n        \"fileWidth\": file_width,\n        \"fileHeight\": file_height,\n        \"fileWidth_inch\": (file_width / 300).toFixed(2),\n        \"fileHeight_inch\": (file_height / 300).toFixed(2),\n        \"ratioBy_width\": `${ file_width / file_height }`,\n        \"ratioBy_height\": `${ file_height / file_width }`,\n        \"currentWidth\": (file_width / 300).toFixed(2),\n        \"currentHeight\": (file_height / 300).toFixed(2)\n      }\n    } else {\n      let setFileURL = fileDetails.imgIxFile;\n      if ( fileDetails.fileExt == 'pdf' ) {\n        setFileURL = `${ setFileURL }?trim=colorUnlessAlpha&fm=png`;\n        console.log ( 'setFileURL', setFileURL );\n        getApiResponse  =   await sendApiRequest( setFileURL, fileDetails.fileName );\n      }\n\n      const dimensions = await getImageDimensions( setFileURL );\n      console.log('Image dimensions:', dimensions);\n\n\n      if ( fileDetails.fileExt == 'svg' ) {\n        if ( typeof noWidthAndHeightForSVG !== 'undefined' && noWidthAndHeightForSVG ) {\n          const getUnitForMultiple = 2480 / dimensions.width;\n          file_width = dimensions.width * getUnitForMultiple;\n          file_height = dimensions.height * getUnitForMultiple;\n        } else {\n          file_width = dimensions.width * 4.168067226890756;\n          file_height = dimensions.height * 4.168067226890756;\n        }\n      } else if ( fileDetails.fileExt == 'pdf' && typeof getApiResponse !== 'undefined' && getApiResponse ) {\n        if ( typeof getApiResponse.data !== 'undefined' && getApiResponse.data && typeof getApiResponse.data.dimensions !== 'undefined' && getApiResponse.data.dimensions && typeof getApiResponse.data.dimensions.width !== 'undefined' && getApiResponse.data.dimensions.width && typeof getApiResponse.data.dimensions.height !== 'undefined' && getApiResponse.data.dimensions.height ) {\n          file_width = getApiResponse.data.dimensions.width;\n          file_height = getApiResponse.data.dimensions.height;\n\n          return {\n            \"vector_fileWidth\": ( file_width * 300),\n            \"vector_fileHeight\": ( file_height * 300 ),\n            \"vector_fileWidth_inch\": file_width,\n            \"vector_fileHeight_inch\": file_height,\n            \"vector_ratioBy_width\": `${ file_width / file_height }`,\n            \"vector_ratioBy_height\": `${ file_height / file_width }`,\n            \"vector_currentWidth\": file_width,\n            \"vector_currentHeight\": file_height,\n            \"fileWidth\": file_width,\n            \"fileHeight\": file_height,\n            \"fileWidth_inch\": file_width,\n            \"fileHeight_inch\": file_height,\n            \"ratioBy_width\": `${ file_width / file_height }`,\n            \"ratioBy_height\": `${ file_height / file_width }`,\n            \"currentWidth\": file_width,\n            \"currentHeight\": file_height\n          }\n        } else {\n          if ( getApiResponse.data.dimensions.width > getApiResponse.data.dimensions.height ) {\n            let makeMultiplier = getApiResponse.data.dimensions.height / ( dimensions.height / 300 );\n\n            file_width = dimensions.width * makeMultiplier;\n            file_height = dimensions.height * makeMultiplier;\n          } else {\n            let makeMultiplier = getApiResponse.data.dimensions.width / ( dimensions.width / 300 );\n\n            file_width = dimensions.width * makeMultiplier;\n            file_height = dimensions.height * makeMultiplier;\n          }\n        }\n      } else {\n        file_width = dimensions.width;\n        file_height = dimensions.height;\n      }\n      $(\".dtf_body_image_labels\").css({\"opacity\":0});\n      calculateRatio( file_width, file_height);\n      return {\n        \"fileWidth\": file_width,\n        \"fileHeight\": file_height,\n        \"fileWidth_inch\": (file_width / 300).toFixed(2),\n        \"fileHeight_inch\": (file_height / 300).toFixed(2),\n        \"ratioBy_width\": `${ file_width / file_height }`,\n        \"ratioBy_height\": `${ file_height / file_width }`,\n        \"currentWidth\": (file_width / 300).toFixed(2),\n        \"currentHeight\": (file_height / 300).toFixed(2)\n      }\n    }\n  } catch ( err ) {\n    console.log( `ERROR fileDimensions( fileDetails )`, err.message );\n  }\n}\nasync function sendApiRequest(file_url, s3Key ) {\n  try {\n    if ( s3Key ) {\n      let rtn;\n      const endCode = encodeURI( s3Key );\n      await $.get(`${ apiURL + \"/calculateInches?s3Key=\" + endCode }`, function ( res ) {\n        rtn   =   res;\n      });\n      return rtn;\n    }\n    else if ( file_url ) {\n      let rtn;\n      const endCode = encodeURI( file_url );\n      await $.get(`${ apiURL + \"/calculateInches?url=\" + endCode }`, function ( res ) {\n        rtn   =   res;\n      });\n      return rtn;\n    }\n  } catch ( err ) {\n    console.log( `ERROR sendApiRequest`, err.message );\n  }\n}\nfunction calculateRatio( num_1, num_2 ) {\n  num_1 = num_1 * 1;\n  num_2 = num_2 * 1;\n\n  for(num=num_2; num>1; num--) {\n    if((num_1 % num) == 0 && (num_2 % num) == 0) {\n      num_1=num_1/num;\n      num_2=num_2/num;\n    }\n  }\n  ratio_width   =   num_1 * 1;\n  ratio_height  =   num_2 * 1;\n  console.log(\"ratio_width=ratio_height\",ratio_width,ratio_height);\n}\nasync function getImageDimensions(url) {\n  return new Promise((resolve, reject) => {\n    const img = new Image();\n    img.onload = () => {\n      resolve({\n        width: img.width,\n        height: img.height\n      });\n    };\n    img.onerror = () => {\n      reject(new Error('Failed to load image.'));\n    };\n    img.src = url;\n  });\n}\nasync function setIndexNoToBlock( selector, indexNo ) {\n  try {\n    selector.attr( `block-no`, indexNo );\n    selector.find( `item-no .itemNo__name` ).text( `Upload ${ indexNo }` );\n    selector.find( `preview-box file-preview` ).attr( `id`, `filePreview_${ indexNo }` );\n\n    selector.find( `toggle-options .bgRemover .toggleOption` ).attr( `id`, `bgRemover_${ indexNo }` );\n    selector.find( `toggle-options .bgRemover` ).attr( `for`, `bgRemover_${ indexNo }` );\n    selector.find( `toggle-options .superRes .toggleOption` ).attr( `id`, `superRes_${ indexNo }` );\n    selector.find( `toggle-options .superRes` ).attr( `for`, `superRes_${ indexNo }` );\n\n    selector.find( `tab-controls .tabOptionName` ).attr( `name`, `tabOptionName_${ indexNo }` );\n    selector.find( `tab-controls .tabOptionName[value=\"custom\"]` ).attr( `id`, `tabOptionCustom_${ indexNo }` );\n    selector.find( `tab-controls .tabLink[for*=\"tabOptionCustom_\"]` ).attr( `for`, `tabOptionCustom_${ indexNo }` );\n    selector.find( `tab-controls .tabOptionName[value=\"popular\"]` ).attr( `id`, `tabOptionPopular_${ indexNo }` );\n    selector.find( `tab-controls .tabLink[for*=\"tabOptionPopular_\"]` ).attr( `for`, `tabOptionPopular_${ indexNo }` );\n    selector.find( `designer-notes .popupinput` ).attr( `id`, `designerNotes_${ indexNo }` );\n    selector.find( `designer-notes label` ).attr( `for`, `designerNotes_${ indexNo }` );\n  } catch ( err ) {\n    console.log( `ERROR setIndexNoToBlock( selector, indexNo )`, err.message );\n  }\n}\n\nasync function activateMultiupload( files ) {\n  try {\n    $( `body multi-upload-wrapper` ).remove();\n    const multiUploadHTML = $( `template[data-multi-id=\"main\"]` ).html();\n    $( `body` ).append( multiUploadHTML );\n    loadCartItemsCount();\n    /* Render the cashback crest immediately (like the dtf modal) \u2014 before\n       the first calculatePrices() the slice was empty, so the mobile pinned\n       bar showed only Add-to-Cart (Justin 2026-06-16). Live total updates\n       overwrite this on every calc. */\n    updateBlanksReward( 0, 0 );\n\n  } catch ( err ) {\n    console.log( `ERROR activateMultiupload( files )`, err.message );\n  }\n}\nasync function loadCartItemsCount() {\n  try {\n    const res = await getRequest( `${ productURL }?view=itemsInCart__cumulative` );\n    if ( typeof res !== 'undefined' && res ) {\n      if ( uploadType == 'multi' ) {\n        $( `multi-upload prices-table` ).attr( `already-in-cart`, `${ res.count }` );\n      }\n    }\n  } catch ( err ) {\n    console.log( `ERROR loadCartItemsCount()`, err.message );\n  }\n}\n\nasync function applyClassByDimension( fileDetails = null, blockNo ) {\n  try {\n    if ( typeof fileDetails !== 'undefined' && fileDetails ) {\n      let classByDimension = '';\n      if ( fileDetails.fileWidth == fileDetails.fileHeight ) {\n        classByDimension = `img_square`;\n      } else if ( fileDetails.fileWidth > fileDetails.fileHeight ) {\n        classByDimension = `img_wide`;\n      } else if ( fileDetails.fileWidth < fileDetails.fileHeight ) {\n        classByDimension = `img_tall`;\n      }\n      if ( uploadType == 'multi' ) {\n        $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] preview-box file-preview` ).removeClass( `img_square img_wide img_tall` );\n        $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] preview-box file-preview` ).addClass( classByDimension );\n      }\n    }\n  } catch ( err ) {\n    console.log( `ERROR applyClassByDimension( fileDetails = null )`, err.message );\n  }\n}\nfunction fileValidate(fileType, fileSize, file) {\n  let isImage = imagesTypesNew.filter((type) => fileType.indexOf(`${type}`) !== -1);\n  // If The Uploaded File Is An Image\n  if (isImage.length !== 0 ) {\n    // Check, If File Size Is 2MB or Less\n    if (fileSize <= 5368709120) { // 2MB :)\n      return true;\n    } else { // Else File Size\n      return false;\n    };\n  } else { // Else File Type\n    return false\n  }\n}\nfunction getFileExt( fileName ) {\n  try {\n    let fileExt = fileName.split('.').pop();\n    fileExt = fileExt.toLowerCase();\n    if ( fileExt == 'jpeg' ) {\n      fileExt = 'jpg';\n    } else if ( fileExt == 'tiff' ) {\n      fileExt = 'tif';\n    }\n    return fileExt;\n  } catch ( err ) {\n    console.log( `ERROR getFileExt( fileName )`, err.message );\n  }\n}\nfunction imgPreviewBox( act, fileExt, blockNo ) {\n  try {\n    if ( act == 'active' ) {\n      if ( uploadType == 'multi' ) {\n        if ( fileExt ) {\n          $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] preview-box file-preview preview-block` ).addClass( `image-loading` );\n          const selectedParamsObject = findObjectByKey( imgParamsSettings, `fileType`, fileExt );\n          $( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] preview-box toggle-options` ).attr({\n            \"show-bg-option\": selectedParamsObject.bgRemover,\n            \"show-superres-option\": selectedParamsObject.superRes\n          });\n          return selectedParamsObject;\n        }\n      }\n\n    } else if ( act == 'inactive' ) {\n    }\n  } catch ( err ) {\n    console.log( `ERROR imgPreviewBox( act )`, err.message );\n  }\n}\n\nasync function preDeterminedSVGDimension( file ) {\n  try {\n    console.log ( 'file', file );\n    if ( typeof file.fileURL !== 'undefined' && file.fileURL ) {\n      noWidthAndHeightForSVG = true;\n      return noWidthAndHeightForSVG;\n    } else {\n      const reader = new FileReader();\n      reader.onload = function(e) {\n        const parser = new DOMParser();\n        const svgDoc = parser.parseFromString(e.target.result, 'image/svg+xml');\n        const svgElement = svgDoc.documentElement;\n        const width = svgElement.getAttribute('width');\n        const height = svgElement.getAttribute('height');\n        if ( width == null && height == null ) {\n          noWidthAndHeightForSVG = true;\n        } else {\n          noWidthAndHeightForSVG = false;\n        }\n        // console.log ( 'SVG', `Width: ${width}, Height: ${height}` );\n      };\n      reader.readAsText(file);\n      return noWidthAndHeightForSVG;\n    }\n  } catch ( err ) {\n    console.log( `ERROR preDeterminedSVGDimension( file )`, err.message );\n  }\n}\n\nasync function processFile( file, blockNo ) {\n  let rtn = null;\n  const fileReader = new FileReader();\n  const fileType = file.type;\n  const fileSize = file.size;\n\n  // const randomName = file.name.split('.')[0].replace(/[^a-z0-9\\s]/gi, '').replace(/[_\\s]/g, '-')+\"____\"+'image_' + Date.now() + '_' + Math.floor(Math.random() * 1000) + '.' + file.name.split('.').pop();\n\n  const nameOnly = file.name.split('.')[0]\n  .toLowerCase()\n  .replace(/[^a-z0-9]/gi, '-')        // Replace all non-alphanumerics with dash\n  .replace(/-+/g, '-')                // Collapse multiple dashes\n  .replace(/^-|-$/g, '');             // Trim leading/trailing dashes\n\n  // Dotless/garbage filenames: a bare split(\".\").pop() returns the WHOLE name as\n  // the \"extension\" (spaces included) \u2014 imgix still serves it (MIME-based), but\n  // the production API rejects extensions >10 chars. Keep a valid dotted ext;\n  // else derive from the MIME type; else png. (2026-08-18)\n  const extension = /\\.[a-z0-9]{1,5}$/i.test(file.name) ? file.name.split('.').pop() : ({ 'image/png': 'png', 'image/jpeg': 'jpg', 'image/webp': 'webp', 'image/gif': 'gif', 'image/svg+xml': 'svg', 'application/pdf': 'pdf', 'application/postscript': 'eps' }[file.type] || 'png');\n\n  const randomName = `${ nameOnly }____image_${ Date.now() }_${ Math.floor( Math.random() * 1000 ) }.${ extension }`;\n\n\n  const presignData = await getPresignedUploadUrl( randomName, file.type );\n\n  if ( typeof presignData !== 'undefined' && presignData && typeof presignData.url !== 'undefined' && presignData.url ) {\n    fileProcessBar( `start` );\n    if ( uploadType == 'multi' ) {\n      progressMove( `multi-upload uploaded-files-block[block-no=\"${ blockNo }\"] file-progress`, ``, fileSize );\n    }\n    const originalUploadedFileURL = presignData.sourceUrl;\n    const response = await fetch(presignData.url, {\n      method: 'PUT',\n      body: file\n    });\n\n    if ( typeof response !== 'undefined' && response.status == 200 ) {\n      let filePath = `https://${ ninjaImgixHost }/${ randomName }`;\n\n      const file_crc = await makeCRC( file );\n\n      fileReader.readAsDataURL( file );\n      rtn = {\n        \"originalFile\": originalUploadedFileURL,\n        \"imgIxFile\": filePath,\n        \"file_crc\": file_crc,\n        \"fileName\": randomName\n      }\n    }\n  }\n  return rtn;\n}\nasync function getPresignedUploadUrl( file_name, file_type ) {\n  /* LAST-GATE extension guard (2026-08-19): builders that derive the extension\n     with split(\".\").pop() turn a DOTLESS original filename into\n     \"<slug>____image_<ts>_<n>.<whole original name>\" \u2014 imgix still serves it\n     (MIME-based) but the production API rejects extensions >10 chars. This is\n     the final hop before S3, so normalizing HERE covers every upload path,\n     including any builder not individually patched. */\n  if (!/\\.[a-z0-9]{1,5}$/i.test(String(file_name || ''))) {\n    var _ntDot = String(file_name || 'design').lastIndexOf('.');\n    file_name = (_ntDot > 0 ? String(file_name).slice(0, _ntDot) : String(file_name || 'design')) + '.' +\n      ({ 'image/png': 'png', 'image/jpeg': 'jpg', 'image/webp': 'webp', 'image/gif': 'gif', 'image/svg+xml': 'svg', 'application/pdf': 'pdf', 'application/postscript': 'eps' }[String(file_type || '').toLowerCase().split(';')[0].trim()] || 'png');\n  }\n  try {\n    let rtn;\n    await $.get(`${ apiURL }/uploads/getPresignedUploadUrl?file_name=${ encodeURIComponent( file_name ) }&file_type=${ encodeURIComponent( file_type ) }`, function ( res ) {\n      rtn   =   res;\n    });\n    return rtn;\n  } catch ( err ) {\n    console.log( `ERROR getPresignedUploadUrl`, err.message );\n  }\n}\n\nfunction fileProcessBar( act ) {\n  try {\n    if ( act == 'start' ) {\n    } else if ( act == 'reset' ) {\n      $( `#fileupload_custom` ).hide();\n      $( `upload-controls file-preview #fileupload_hero, file-preview .viewer-box` ).attr( `src`, transpareImg );\n      uploadArea.classList.remove('upload-area--open');\n      loadingText.style.display = `block`;\n      fileDetails.classList.remove('file-details--open');\n      uploadedFile.classList.remove('uploaded-file--open');\n      uploadedFileInfo.classList.remove('uploaded-file__info--active');\n      uploadArea.classList.remove( `hidden` );\n      // aiImgGenerator.classList.remove( `hidden` );\n    }\n  } catch ( err ) {\n    console.log( `ERROR fileProcessBar()`, err.message );\n  }\n}\nasync function progressMove( selector, filePath, fileSize = 550 ) {\n  let counter = 0;\n  if ( fileSize > 9000000 ) {\n    fileSize = 250;\n  } else if ( fileSize > 7000000 ) {\n    fileSize = 150;\n  } else if ( fileSize > 5000000 ) {\n    fileSize = 120;\n  } else if ( fileSize > 3000000 ) {\n    fileSize = 90;\n  } else if ( fileSize > 1000000 ) {\n    fileSize = 80;\n  } else {\n    fileSize = 70;\n  }\n  fileSize = 50;\n  if(filePath == \"quick\"){\n    counter = 50\n  }\n\n  let counterIncrease = setInterval(() => {\n    if (counter === 100) {\n      let isCompleted;\n      if ( uploadType == 'multi' ) {\n        isCompleted = $( selector ).closest( `uploaded-files-block` ).find( `preview-box .easyzoom` ).hasClass( `image-loading` );\n        if ( isCompleted == false ) {\n          clearInterval( counterIncrease );\n          return 'completed';\n        }\n      }\n    } else {\n      if ( uploadType == 'multi' ) {\n        counter = counter + 1;\n        $( selector ).find( `.fileProgress__bar` ).css({\n          \"width\": `${ counter }%`\n        });\n        $( selector ).find( `.loadingPercent__counter` ).text( `${ counter }%` );\n      }\n    }\n  }, fileSize);\n};\nasync function getAsByteArray(file) {\n  return new Uint8Array(await readFile(file));\n}\nasync function makeCRC( file ) {\n  try {\n    const byteArr = await getAsByteArray( file );\n    file_crc = (CRC32.buf(byteArr)>>>0).toString(16);\n    return file_crc;\n  }\n  catch (error) {\n    console.log(\"Unable to calculate file crc: \" + error)\n  }\n}\nfunction readFile(file) {\n  return new Promise((resolve, reject) => {\n    let reader = new FileReader();\n    reader.addEventListener(\"loadend\", (e) => resolve(e.target.result));\n    reader.addEventListener(\"error\", reject);\n    reader.readAsArrayBuffer(file);\n  });\n}\n\n/* \u2500\u2500 Blanks zoom preview: close on click OUTSIDE the image \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   The zoom modal (.customTabelPopup__overlay-5) is opened/handled in\n   pdp_transferBySize.js, whose backdrop-close only fires for clicks OUTSIDE\n   the .customTabelPopup card. On the blanks layout the card is 75vw\u00D775vh, so\n   clicking beside the image (inside the card's padding/letterbox) never closes\n   it \u2014 only the \u00D7 button does. This blanks-scoped handler (this file loads on\n   blanks only) closes the modal on any overlay click that isn't the image\n   itself or an interactive control. Reuses pdp_transferBySize.js's\n   window.__closePreviewZoom when present (also unlocks body scroll). */\n(function () {\n  if (typeof window.jQuery === \"undefined\") return;\n  window.jQuery(document).on(\"click\", \".customTabelPopup__overlay-5\", function (e) {\n    var t = e.target;\n    if (t && t.closest && t.closest(\".zoomed-in-image, .customTabelPopup__close, a, button, input, textarea, select, label\")) return;\n    if (typeof window.__closePreviewZoom === \"function\") {\n      window.__closePreviewZoom();\n    } else {\n      var o = document.querySelector(\".customTabelPopup__overlay-5\");\n      if (o) { o.style.display = \"none\"; o.classList.remove(\"is-loading\"); }\n    }\n  });\n})();\n\n/* \u2500\u2500 Blanks: \"or choose a previous design\" link under the upload button \u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   Logged-in customers get a blue link beneath the \"Upload Your Design\" button\n   that opens the existing previous-design picker. Clicking it is handled by the\n   `.purchase_from_previous` click handler above (fades in the picker overlay-3);\n   the \"My Designs picker \u2192 blanks multi-upload\" bridge above then loads the\n   selected design(s) \u2014 one OR many \u2014 into the blanks modal. The upload box is\n   rendered by the over-limit main-product.liquid (unpushable), so the link is\n   injected here (deploy-around). Gate = body.customer-logged-in (theme.liquid\n   adds it via {% if customer %}); per Justin we show it to any logged-in\n   customer (the picker itself surfaces \"no designs\" when empty). */\n(function () {\n  if (!document.body.classList.contains(\"customer-logged-in\")) return; // logged-in only\n  if (!document.getElementById(\"nt-blanks-choose-prev-style\")) {\n    var st = document.createElement(\"style\");\n    st.id = \"nt-blanks-choose-prev-style\";\n    /* inline styles can't do :hover, so the underline-on-hover lives here.\n       display:block + text-align:inherit (no fixed width / auto margins) makes\n       the link follow the upload box's text-align exactly like the button\n       (inline-flex) does, so it sits directly under the button at every width. */\n    st.textContent =\n      \".nt-blanks-choose-prev{display:block;margin:10px 0 6px;text-align:inherit;color:#019AFF;\" +\n      \"font-size:14px;font-weight:400;line-height:1.2;text-decoration:none;cursor:pointer;}\" +\n      \".nt-blanks-choose-prev:hover{text-decoration:underline;}\";\n    document.head.appendChild(st);\n  }\n  function inject() {\n    var btn = document.querySelector(\".uploadBox__contentButton\");\n    if (!btn) return;\n    var next = btn.nextElementSibling;\n    if (next && next.classList && next.classList.contains(\"nt-blanks-choose-prev\")) return; // already injected\n    var a = document.createElement(\"a\");\n    a.href = \"#\";\n    a.className = \"purchase_from_previous nt-blanks-choose-prev\";\n    a.setAttribute(\"data-type\", \"first_upload\");\n    a.textContent = \"or choose a previous design\";\n    /* No own click handler needed: the theme's delegated\n       `.on('click', '.purchase_from_previous')` handler (this file) already\n       does e.preventDefault() + opens the picker (overlay-3) + reads data-type,\n       exactly as for every other previous-design trigger. We just match its\n       class + data-type so the existing flow runs unchanged. */\n    btn.insertAdjacentElement(\"afterend\", a);\n  }\n  if (document.readyState === \"loading\") {\n    document.addEventListener(\"DOMContentLoaded\", inject);\n  } else {\n    inject();\n  }\n  /* the upload box re-renders on reset (after removing a file) \u2014 re-inject */\n  var obs = new MutationObserver(function () { inject(); });\n  obs.observe(document.documentElement, { childList: true, subtree: true });\n})();\n\n"],
  "mappings": "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",
  "names": ["getRatio", "newVal", "fileDetails", "file_crc", "num"]
}
