{"product_id":"mikes-ssd-selector-work-in-progress","title":"Mike's SSD Selector Widget - CODE\/WORK IN PROGRESS","description":"\u003cdiv class=\"ssd-compact-box\"\u003e\n  \u003cbutton type=\"button\" class=\"ssd-toggle\" id=\"ssd-toggle\"\u003e\n    \u003cspan class=\"ssd-toggle-copy\"\u003e\n      \u003cspan class=\"ssd-pricing-pill\"\u003e\n        \u003cspan class=\"ssd-tag-icon\"\u003e$\u003c\/span\u003e\n        SPECIAL SONNET STORE PRICING\n      \u003c\/span\u003e\n\n      \u003cstrong id=\"ssd-header-title\"\u003eAdd a Western Digital or Kingston M.2 SSD\u003c\/strong\u003e\n      \u003csmall id=\"ssd-header-subtitle\"\u003eSelect one or more SSDs and choose quantities to add with this product.\u003c\/small\u003e\n    \u003c\/span\u003e\n\n    \u003cimg class=\"ssd-group-img\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/your-image-here.png\" alt=\"WD_BLACK and Kingston NVMe M.2 SSDs\"\u003e\n\n    \u003cspan class=\"ssd-toggle-icon\"\u003e+\u003c\/span\u003e\n  \u003c\/button\u003e\n\n  \u003cdiv class=\"ssd-expand-area\" id=\"ssd-expand-area\" style=\"display:none;\"\u003e\n    \u003cdiv class=\"ssd-options\"\u003e\n      \u003cdiv class=\"ssd-option\" data-handle=\"wd_black-sn850x-nvme-ssd-2tb\"\u003e\n        \u003clabel\u003e\u003cinput type=\"checkbox\" class=\"ssd-check\"\u003e\u003cspan\u003e2TB WD_BLACK SN850X \u003cem\u003ePro Performance\u003c\/em\u003e\u003c\/span\u003e\u003c\/label\u003e\n        \u003cdiv class=\"ssd-price\"\u003eLoading...\u003c\/div\u003e\n        \u003cinput type=\"number\" class=\"ssd-qty\" value=\"1\" min=\"1\" max=\"99\" disabled\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"ssd-option\" data-handle=\"wd_black-sn850x-nvme-ssd-4tb\"\u003e\n        \u003clabel\u003e\u003cinput type=\"checkbox\" class=\"ssd-check\"\u003e\u003cspan\u003e4TB WD_BLACK SN850X \u003cem\u003ePro Performance\u003c\/em\u003e\u003c\/span\u003e\u003c\/label\u003e\n        \u003cdiv class=\"ssd-price\"\u003eLoading...\u003c\/div\u003e\n        \u003cinput type=\"number\" class=\"ssd-qty\" value=\"1\" min=\"1\" max=\"99\" disabled\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"ssd-option\" data-handle=\"wd_black-sn850x-nvme-ssd-8tb\"\u003e\n        \u003clabel\u003e\u003cinput type=\"checkbox\" class=\"ssd-check\"\u003e\u003cspan\u003e8TB WD_BLACK SN850X \u003cem\u003ePro Performance\u003c\/em\u003e\u003c\/span\u003e\u003c\/label\u003e\n        \u003cdiv class=\"ssd-price\"\u003eLoading...\u003c\/div\u003e\n        \u003cinput type=\"number\" class=\"ssd-qty\" value=\"1\" min=\"1\" max=\"99\" disabled\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"ssd-option\" data-handle=\"kingston-ssd-1tb\"\u003e\n        \u003clabel\u003e\u003cinput type=\"checkbox\" class=\"ssd-check\"\u003e\u003cspan\u003e1TB Kingston NV3 \u003cem\u003eGeneral Use\u003c\/em\u003e\u003c\/span\u003e\u003c\/label\u003e\n        \u003cdiv class=\"ssd-price\"\u003eLoading...\u003c\/div\u003e\n        \u003cinput type=\"number\" class=\"ssd-qty\" value=\"1\" min=\"1\" max=\"99\" disabled\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"ssd-option\" data-handle=\"kingston-ssd-2tb\"\u003e\n        \u003clabel\u003e\u003cinput type=\"checkbox\" class=\"ssd-check\"\u003e\u003cspan\u003e2TB Kingston NV3 \u003cem\u003eGeneral Use\u003c\/em\u003e\u003c\/span\u003e\u003c\/label\u003e\n        \u003cdiv class=\"ssd-price\"\u003eLoading...\u003c\/div\u003e\n        \u003cinput type=\"number\" class=\"ssd-qty\" value=\"1\" min=\"1\" max=\"99\" disabled\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv class=\"ssd-option\" data-handle=\"kingston-ssd-4tb\"\u003e\n        \u003clabel\u003e\u003cinput type=\"checkbox\" class=\"ssd-check\"\u003e\u003cspan\u003e4TB Kingston NV3 \u003cem\u003eGeneral Use\u003c\/em\u003e\u003c\/span\u003e\u003c\/label\u003e\n        \u003cdiv class=\"ssd-price\"\u003eLoading...\u003c\/div\u003e\n        \u003cinput type=\"number\" class=\"ssd-qty\" value=\"1\" min=\"1\" max=\"99\" disabled\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cdiv id=\"ssd-selection-summary\" class=\"ssd-selection-summary\" style=\"display:none;\"\u003e\u003c\/div\u003e\n  \u003c\/div\u003e\n\u003c\/div\u003e\n\n\u003cstyle\u003e\n.ssd-compact-box {\n  margin: 16px 0 22px;\n  padding: 10px 15px;\n  border: 1px solid #ddd;\n  border-radius: 12px;\n  background: #fafafa;\n  font-family: inherit;\n}\n\n.ssd-toggle {\n  width: 100%;\n  padding: 2px 4px;\n  border: 0;\n  background: transparent;\n  display: grid;\n  grid-template-columns: 1fr auto auto;\n  align-items: center;\n  gap: 16px;\n  text-align: left;\n  cursor: pointer;\n  font-family: inherit;\n}\n\n.ssd-toggle-copy {\n  display: block;\n}\n\n.ssd-pricing-pill {\n  display: inline-flex;\n  align-items: center;\n  gap: 8px;\n  margin-bottom: 10px;\n  padding: 5px 11px;\n  border: 1px solid #9c1c1f;\n  border-radius: 8px;\n  color: #8d171a;\n  background: #fff;\n  font-size: 12px;\n  font-weight: 700;\n  line-height: 1;\n  letter-spacing: .02em;\n}\n\n.ssd-tag-icon {\n  font-size: 13px;\n  font-weight: 700;\n  color: #9c1c1f;\n  line-height: 1;\n}\n\n.ssd-toggle strong {\n  display: block;\n  font-size: 22px;\n  line-height: 1.25;\n  color: #222;\n}\n\n.ssd-toggle small {\n  display: block;\n  margin-top: 4px;\n  font-size: 16px;\n  line-height: 1.4;\n  color: #555;\n}\n\n.ssd-group-img {\n  width: 185px;\n  max-width: 22vw;\n  height: auto;\n  object-fit: contain;\n}\n\n.ssd-toggle-icon {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  width: 34px;\n  height: 34px;\n  border: 1px solid #bbb;\n  border-radius: 50%;\n  background: #fff;\n  color: #666;\n  font-size: 24px;\n  font-weight: 300;\n  line-height: 1;\n  flex-shrink: 0;\n  transition: all .2s ease;\n}\n\n.ssd-toggle:hover .ssd-toggle-icon {\n  border-color: #888;\n  color: #333;\n}\n\n.ssd-expand-area {\n  margin-top: 18px;\n}\n\n.ssd-options {\n  display: grid;\n  gap: 10px;\n}\n\n.ssd-option {\n  display: grid;\n  grid-template-columns: 1fr auto 70px;\n  align-items: center;\n  gap: 12px;\n  padding: 11px 12px;\n  border: 1px solid #ddd;\n  border-radius: 10px;\n  background: #fff;\n  cursor: pointer;\n}\n\n.ssd-option:hover {\n  border-color: #bbb;\n  background: #fcfcfc;\n}\n\n.ssd-option label {\n  display: flex;\n  align-items: center;\n  gap: 10px;\n  margin: 0;\n  cursor: pointer;\n  font-size: 15px;\n  line-height: 1.35;\n  color: #222;\n}\n\n.ssd-option input[type=\"checkbox\"] {\n  width: 18px;\n  height: 18px;\n  margin: 0;\n  cursor: pointer;\n}\n\n.ssd-option em {\n  display: block;\n  margin-top: 2px;\n  font-style: normal;\n  font-size: 13px;\n  color: #666;\n}\n\n.ssd-price {\n  font-size: 15px;\n  font-weight: 700;\n  color: #b12704;\n  white-space: nowrap;\n}\n\n.ssd-price s {\n  margin-right: 6px;\n  color: #888;\n  font-weight: 400;\n}\n\n.ssd-qty {\n  width: 70px;\n  padding: 8px 6px;\n  border: 1px solid #cfcfcf;\n  border-radius: 8px;\n  font-size: 15px;\n  text-align: center;\n  cursor: default;\n}\n\n.ssd-qty:disabled {\n  opacity: .45;\n  cursor: not-allowed;\n}\n\n.ssd-selection-summary {\n  margin-top: 14px;\n}\n\n.ssd-summary-card {\n  padding: 12px 14px;\n  border: 1px solid #d6e6ff;\n  border-radius: 10px;\n  background: #f8fbff;\n  box-shadow: inset 0 1px 0 rgba(255,255,255,.7);\n}\n\n.ssd-summary-top {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  gap: 12px;\n  margin-bottom: 6px;\n}\n\n.ssd-summary-top strong {\n  font-size: 15px;\n  font-weight: 700;\n  color: #0b5fc1;\n}\n\n.ssd-summary-total {\n  font-size: 14px;\n  font-weight: 700;\n  color: #4d6b96;\n  white-space: nowrap;\n}\n\n.ssd-summary-card ul {\n  margin: 0;\n  padding: 0;\n  list-style: none;\n}\n\n.ssd-summary-card li {\n  display: flex;\n  justify-content: space-between;\n  gap: 12px;\n  padding: 7px 0;\n  border-top: 1px solid #e1ecff;\n  font-size: 14px;\n  color: #444;\n}\n\n.ssd-summary-card li:first-child {\n  border-top: 0;\n}\n\n.ssd-summary-check {\n  color: #0b5fc1;\n  font-weight: 700;\n  margin-right: 6px;\n}\n\n.ssd-summary-actions {\n  display: inline-flex;\n  align-items: center;\n  gap: 12px;\n  white-space: nowrap;\n}\n\n.ssd-summary-actions b {\n  color: #555;\n  font-weight: 700;\n}\n\n.ssd-remove-one {\n  padding: 0;\n  border: 0;\n  background: transparent;\n  color: #4d6b96;\n  font-size: 13px;\n  font-family: inherit;\n  text-decoration: underline;\n  cursor: pointer;\n}\n\n.ssd-remove-one:hover {\n  color: #0b5fc1;\n}\n\n@media screen and (max-width: 700px) {\n  .ssd-toggle {\n    grid-template-columns: 1fr auto;\n    gap: 14px;\n  }\n\n  .ssd-group-img {\n    grid-column: 1 \/ -1;\n    grid-row: 1;\n    width: 180px;\n    max-width: 75%;\n    margin-bottom: 8px;\n  }\n\n  .ssd-toggle-copy {\n    grid-column: 1;\n    grid-row: 2;\n  }\n\n  .ssd-toggle-icon {\n    grid-column: 2;\n    grid-row: 2;\n    width: 32px;\n    height: 32px;\n    font-size: 22px;\n  }\n\n  .ssd-toggle strong {\n    font-size: 18px;\n  }\n\n  .ssd-toggle small {\n    font-size: 14px;\n  }\n\n  .ssd-pricing-pill {\n    margin-bottom: 9px;\n    font-size: 11px;\n  }\n\n  .ssd-option {\n    grid-template-columns: 1fr 70px;\n  }\n\n  .ssd-price {\n    grid-column: 1 \/ -1;\n    padding-left: 28px;\n  }\n\n  .ssd-summary-card li {\n    align-items: flex-start;\n  }\n\n  .ssd-summary-actions {\n    flex-direction: column;\n    align-items: flex-end;\n    gap: 3px;\n  }\n}\n\u003c\/style\u003e\n\n\u003cscript\u003e\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n  var box = document.querySelector(\".ssd-compact-box\");\n  var toggle = document.getElementById(\"ssd-toggle\");\n  var expandArea = document.getElementById(\"ssd-expand-area\");\n  var toggleIcon = document.querySelector(\".ssd-toggle-icon\");\n  var headerSubtitle = document.getElementById(\"ssd-header-subtitle\");\n\n  var productForm = document.querySelector('form[action=\"\/cart\/add\"]');\n  var addButton = productForm ? productForm.querySelector('[type=\"submit\"], button[name=\"add\"]') : null;\n  var originalAddButtonText = addButton ? addButton.textContent.trim() : \"Add to Cart\";\n  var originalSubtitle = headerSubtitle ? headerSubtitle.textContent : \"\";\n\n  var options = document.querySelectorAll(\".ssd-option\");\n  var summary = document.getElementById(\"ssd-selection-summary\");\n\n  var selectedSSDItems = [];\n  var isAddingSSD = false;\n\n  function money(cents) {\n    return \"$\" + (cents \/ 100).toFixed(2);\n  }\n\n  function updateCartCount() {\n    fetch(\"\/cart.js\")\n      .then(function (res) { return res.json(); })\n      .then(function (cart) {\n        var count = cart.item_count;\n\n        [\n          \".cart-count\",\n          \".cart-count-bubble\",\n          \".site-header__cart-count\",\n          \"#CartCount\",\n          \"[data-cart-count]\",\n          \".header-cart-count\",\n          \".cart-link__bubble\"\n        ].forEach(function (selector) {\n          document.querySelectorAll(selector).forEach(function (el) {\n            el.textContent = count;\n            el.style.display = count \u003e 0 ? \"\" : \"none\";\n          });\n        });\n      });\n  }\n\n  function getSelectedSSDs() {\n    var selected = [];\n\n    options.forEach(function (option) {\n      var checkbox = option.querySelector(\".ssd-check\");\n      var qtyInput = option.querySelector(\".ssd-qty\");\n\n      if (checkbox.checked \u0026\u0026 option.dataset.variantId) {\n        selected.push({\n          id: Number(option.dataset.variantId),\n          title: option.dataset.shortTitle,\n          price: Number(option.dataset.price || 0),\n          quantity: Math.max(1, Number(qtyInput.value) || 1)\n        });\n      }\n    });\n\n    return selected;\n  }\n\n  function clearSingleSelection(idToRemove) {\n    options.forEach(function (option) {\n      if (String(option.dataset.variantId) === String(idToRemove)) {\n        var checkbox = option.querySelector(\".ssd-check\");\n        var qtyInput = option.querySelector(\".ssd-qty\");\n\n        checkbox.checked = false;\n        qtyInput.value = 1;\n        qtyInput.disabled = true;\n      }\n    });\n\n    updateSummary();\n  }\n\n  function updateSummary() {\n    var selected = getSelectedSSDs();\n\n    var totalQty = selected.reduce(function (sum, item) {\n      return sum + item.quantity;\n    }, 0);\n\n    var totalPrice = selected.reduce(function (sum, item) {\n      return sum + (item.price * item.quantity);\n    }, 0);\n\n    if (selected.length \u003e 0) {\n      if (addButton) addButton.textContent = \"Add to Cart with SSDs\";\n\n      if (headerSubtitle) {\n        headerSubtitle.textContent =\n          totalQty + \" SSD\" + (totalQty \u003e 1 ? \"s\" : \"\") + \" Selected • \" + money(totalPrice);\n      }\n\n      summary.innerHTML =\n        '\u003cdiv class=\"ssd-summary-card\"\u003e' +\n          '\u003cdiv class=\"ssd-summary-top\"\u003e' +\n            '\u003cstrong\u003eSelected SSDs (' + totalQty + ')\u003c\/strong\u003e' +\n            '\u003cspan class=\"ssd-summary-total\"\u003e' + money(totalPrice) + '\u003c\/span\u003e' +\n          '\u003c\/div\u003e' +\n          '\u003cul\u003e' +\n            selected.map(function (item) {\n              return '\u003cli data-ssd-id=\"' + item.id + '\"\u003e' +\n                '\u003cspan\u003e\u003cspan class=\"ssd-summary-check\"\u003e✓\u003c\/span\u003e' + item.title + '\u003c\/span\u003e' +\n                '\u003cspan class=\"ssd-summary-actions\"\u003e' +\n                  '\u003cb\u003eQty ' + item.quantity + '\u003c\/b\u003e' +\n                  '\u003cbutton type=\"button\" class=\"ssd-remove-one\" data-ssd-id=\"' + item.id + '\"\u003eRemove\u003c\/button\u003e' +\n                '\u003c\/span\u003e' +\n              '\u003c\/li\u003e';\n            }).join(\"\") +\n          '\u003c\/ul\u003e' +\n        '\u003c\/div\u003e';\n\n      summary.style.display = \"block\";\n\n      summary.querySelectorAll(\".ssd-remove-one\").forEach(function (btn) {\n        btn.addEventListener(\"click\", function (e) {\n          e.preventDefault();\n          e.stopPropagation();\n          clearSingleSelection(btn.getAttribute(\"data-ssd-id\"));\n        });\n      });\n\n    } else {\n      if (addButton) addButton.textContent = originalAddButtonText;\n      if (headerSubtitle) headerSubtitle.textContent = originalSubtitle;\n      summary.style.display = \"none\";\n    }\n  }\n\n  if (toggle \u0026\u0026 expandArea) {\n    toggle.addEventListener(\"click\", function () {\n      var isOpen = expandArea.style.display === \"block\";\n\n      expandArea.style.display = isOpen ? \"none\" : \"block\";\n      box.classList.toggle(\"is-open\", !isOpen);\n      toggleIcon.textContent = isOpen ? \"+\" : \"−\";\n    });\n  }\n\n  options.forEach(function (option) {\n    var handle = option.getAttribute(\"data-handle\");\n    var priceBox = option.querySelector(\".ssd-price\");\n    var checkbox = option.querySelector(\".ssd-check\");\n    var qtyInput = option.querySelector(\".ssd-qty\");\n    var labelText = option.querySelector(\"label span\");\n\n    fetch(\"\/products\/\" + handle + \".js\")\n      .then(function (res) { return res.json(); })\n      .then(function (product) {\n        var variant = product.variants.find(function (v) {\n          return v.available;\n        });\n\n        option.dataset.shortTitle = labelText ? labelText.childNodes[0].textContent.trim() : product.title;\n\n        if (!variant) {\n          checkbox.disabled = true;\n          qtyInput.disabled = true;\n          priceBox.innerHTML = \"Unavailable\";\n          option.classList.add(\"is-unavailable\");\n          return;\n        }\n\n        option.dataset.variantId = variant.id;\n        option.dataset.price = variant.price;\n\n        if (variant.compare_at_price \u0026\u0026 variant.compare_at_price \u003e variant.price) {\n          priceBox.innerHTML = \"\u003cs\u003e\" + money(variant.compare_at_price) + \"\u003c\/s\u003e\" + money(variant.price);\n        } else {\n          priceBox.innerHTML = money(variant.price);\n        }\n      })\n      .catch(function () {\n        checkbox.disabled = true;\n        qtyInput.disabled = true;\n        priceBox.innerHTML = \"Unavailable\";\n        option.classList.add(\"is-unavailable\");\n      });\n\n    option.addEventListener(\"click\", function (e) {\n      if (\n        e.target.classList.contains(\"ssd-qty\") ||\n        e.target.classList.contains(\"ssd-check\") ||\n        option.classList.contains(\"is-unavailable\")\n      ) {\n        return;\n      }\n\n      checkbox.checked = !checkbox.checked;\n      qtyInput.disabled = !checkbox.checked;\n      updateSummary();\n    });\n\n    checkbox.addEventListener(\"change\", function () {\n      qtyInput.disabled = !checkbox.checked;\n      updateSummary();\n    });\n\n    qtyInput.addEventListener(\"input\", updateSummary);\n  });\n\n  if (productForm) {\n    productForm.addEventListener(\"submit\", function () {\n      selectedSSDItems = getSelectedSSDs();\n\n      if (!selectedSSDItems.length || isAddingSSD) return;\n\n      isAddingSSD = true;\n\n      if (addButton) {\n        addButton.textContent = \"Adding to Cart...\";\n      }\n\n      setTimeout(function () {\n        fetch(\"\/cart\/add.js\", {\n          method: \"POST\",\n          headers: {\n            \"Content-Type\": \"application\/json\"\n          },\n          body: JSON.stringify({\n            items: selectedSSDItems.map(function (ssd) {\n              return {\n                id: ssd.id,\n                quantity: ssd.quantity\n              };\n            })\n          })\n        })\n        .then(function (res) {\n          if (!res.ok) throw new Error(\"SSD add failed\");\n          return res.json();\n        })\n        .then(function () {\n          updateCartCount();\n\n          if (addButton) {\n            addButton.textContent = \"Added to Cart\";\n          }\n\n          setTimeout(function () {\n            isAddingSSD = false;\n            updateSummary();\n          }, 1200);\n        })\n        .catch(function () {\n          isAddingSSD = false;\n\n          if (addButton) {\n            updateSummary();\n          }\n\n          alert(\"The main product was added, but there was an issue adding the SSDs.\");\n        });\n      }, 700);\n    });\n  }\n\n  setTimeout(updateCartCount, 300);\n});\n\u003c\/script\u003e","brand":"Sonnet Online Store","offers":[{"title":"Default Title","offer_id":45981512007878,"sku":"TEST01","price":10000.0,"currency_code":"USD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0847\/8540\/files\/m28x4-prod-hero.png?v=1685790469","url":"https:\/\/www.sonnetstore.com\/products\/mikes-ssd-selector-work-in-progress","provider":"Sonnet Online Store - SONNETTECH","version":"1.0","type":"link"}