{"id":245,"date":"2026-06-11T01:39:39","date_gmt":"2026-06-11T01:39:39","guid":{"rendered":"https:\/\/vuelveid.com\/?page_id=245"},"modified":"2026-08-27T00:58:51","modified_gmt":"2026-08-27T00:58:51","slug":"order","status":"publish","type":"page","link":"https:\/\/vuelveid.com\/es\/order\/","title":{"rendered":"Orden"},"content":{"rendered":"\n<!--\n  ============================================================================\n  VUELVE ID \u2014 One-page order configurator (v4, English source)\n  Paste into the WordPress page as a Custom HTML block.\n\n  CHANGES FROM v3\n    REMOVED\n      1. HTML : the \"Reference photo\" section (dachshund on a collar).\n      2. HTML : both <video> demo blocks.\n      3. CSS  : .vsp-demo-item \/ .vsp-demo-video rules (nothing uses them now).\n      4. JS   : the initDemoVideos() IIFE \u2014 dead code once the videos are gone.\n    ADDED\n      5. HTML : \"Inside the tag\" \u2014 the exploded product render. Reuses the\n                existing .vsp-ref-wrap \/ .vsp-ref-img styles, so no new CSS.\n      6. HTML : three screenshot groups (digital profile \/ multi-pet \/ vaccines).\n      7. CSS  : .vsp-shots \u2014 a horizontal scroll-snap carousel, CSS only.\n\n  TRANSLATION NOTE\n    Every string carried over from v3 is byte-identical, so an existing\n    translation keeps matching. Only THREE strings are new:\n      \u00b7 \"Inside the tag\"\n      \u00b7 \"Sealed single piece. It does not open \u2014 no lid and no screw to\n         work loose.\"\n      \u00b7 \"Digital vaccination record\"\n    The other two section headers are reused verbatim from v3.\n\n  CONFIGURE BEFORE GOING LIVE \u2014 see the VSP_CONFIG object at the bottom.\n     - SHIPPING_FLAT : set your real flat shipping cost (or leave null)\n     - WHATSAPP      : the href on .vsp-whatsapp is still a PLACEHOLDER number\n  ============================================================================\n-->\n\n<style>\n.vsp * { box-sizing: border-box; margin: 0; padding: 0; }\n\n.vsp {\n  font-family: Georgia, serif;\n  background: #FFF8F2;\n  max-width: 560px;\n  margin: 0 auto;\n  padding: 0 0 60px;\n}\n\/* When the sticky checkout bar is showing, reserve room so it never\n   covers the trust badges at the bottom of the page. *\/\n.vsp.has-bar { padding-bottom: 130px; }\n\n\/* \u2500\u2500 Section header: reusable label for each structured block \u2500\u2500 *\/\n.vsp-label {\n  font-size: 11px;\n  text-transform: uppercase;\n  letter-spacing: 2px;\n  color: #C97B2E;\n  margin-bottom: 12px;\n  display: block;\n}\n\n\/* \u2500\u2500 Intro paragraph (what Vuelve is) \u2500\u2500 *\/\n.vsp-demo-intro {\n  font-size: 13px;\n  color: #7A5C47;\n  line-height: 1.7;\n  background: #FFFAF5;\n  border: 1.5px solid #F0E0CC;\n  border-radius: 12px;\n  padding: 14px 16px;\n  margin-bottom: 28px;\n}\n\n\/* \u2500\u2500 Product render (was: reference photo) \u2500\u2500 *\/\n.vsp-ref-wrap {\n  position: relative;\n  border-radius: 20px;\n  overflow: hidden;\n  margin-bottom: 12px;\n}\n\n.vsp-ref-img {\n  width: 100%;\n  height: auto;\n  display: block;\n  border-radius: 20px;\n}\n\n\/* Caption under the render. Lives in HTML, not burned into the JPEG, so it\n   scales on any screen, can be selected, and a screen reader can read it. *\/\n.vsp-ref-caption {\n  font-size: 12.5px;\n  color: #7A5C47;\n  line-height: 1.65;\n  text-align: center;\n  margin-bottom: 28px;\n  padding: 0 8px;\n}\n.vsp-ref-caption strong { color: #3D2B1F; }\n\n\/* \u2500\u2500 Screenshot carousel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   Six phone screenshots stacked vertically would add roughly three extra\n   screens of scrolling before the visitor ever reaches the configurator.\n   A horizontal snap-scroller keeps each group to one screen and matches the\n   swipe gesture people already use in a photo gallery.\n\n   scroll-snap-type: x mandatory  \u2192 the scroll always settles ON a shot,\n   never halfway between two. Pure CSS, no JavaScript, no library.\n   https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/scroll-snap-type\n   \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n.vsp-shots {\n  display: flex;\n  align-items: flex-start;\n  gap: 12px;\n  overflow-x: auto;\n  scroll-snap-type: x mandatory;\n  -webkit-overflow-scrolling: touch;  \/* momentum scrolling on older iOS *\/\n  scrollbar-width: none;              \/* Firefox *\/\n  margin-bottom: 28px;\n  padding-bottom: 4px;\n}\n.vsp-shots::-webkit-scrollbar { display: none; }  \/* Chrome \/ Safari *\/\n\n.vsp-shots img {\n  flex: 0 0 auto;         \/* never let flex squeeze a screenshot narrower *\/\n  width: 250px;\n  height: auto;\n  display: block;\n  border-radius: 16px;\n  scroll-snap-align: center;\n  background: #F5E8D8;    \/* placeholder tone while the file loads *\/\n  box-shadow: 0 6px 20px rgba(61,43,31,0.12);\n}\n\n\/* A group with only one screenshot has nothing to swipe through, so center\n   it instead of parking it against the left edge. *\/\n.vsp-shots.single { justify-content: center; }\n\n\/* \u2500\u2500 Product image (lives WITH the selector \u2014 changes on selection) \u2500\u2500 *\/\n.vsp-image-wrap {\n  position: relative;\n  background: #F5E8D8;\n  border-radius: 24px;\n  overflow: hidden;\n  margin-bottom: 16px;\n  aspect-ratio: 1;\n}\n\n.vsp-image-wrap img {\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n  transition: opacity 0.18s ease;\n}\n\n.vsp-image-wrap img.fading { opacity: 0; }\n\n.vsp-badge {\n  position: absolute;\n  top: 16px;\n  left: 16px;\n  background: #3D2B1F;\n  color: #E8A84E;\n  font-size: 11px;\n  letter-spacing: 1.5px;\n  text-transform: uppercase;\n  padding: 6px 14px;\n  border-radius: 20px;\n}\n\n.vsp-title {\n  font-size: 28px;\n  font-weight: 500;\n  color: #3D2B1F;\n  margin-bottom: 4px;\n  line-height: 1.2;\n}\n\n.vsp-subtitle {\n  font-size: 14px;\n  color: #7A5C47;\n  margin-bottom: 20px;\n  font-style: italic;\n}\n\n\/* \u2500\u2500 Benefits strip \u2500\u2500 *\/\n.vsp-benefits {\n  display: flex;\n  gap: 8px;\n  margin-bottom: 28px;\n  overflow-x: auto;\n  scrollbar-width: none;\n  padding-bottom: 4px;\n}\n.vsp-benefits::-webkit-scrollbar { display: none; }\n\n.vsp-benefit {\n  flex: 1 0 auto;\n  min-width: 92px;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  text-align: center;\n  gap: 8px;\n}\n\n.vsp-benefit-icon {\n  width: 64px;\n  height: 64px;\n  border-radius: 50%;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  background: linear-gradient(135deg, #FFF1E0, #F5E8D8);\n  border: 1.5px solid #F0E0CC;\n  transition: transform 0.25s ease, box-shadow 0.25s ease;\n}\n\n.vsp-benefit-icon svg {\n  width: 30px;\n  height: 30px;\n  color: #C97B2E;\n  stroke: currentColor;\n  fill: none;\n  stroke-width: 1.8;\n  stroke-linecap: round;\n  stroke-linejoin: round;\n}\n\n@keyframes vspPop {\n  0%   { transform: scale(0.6); opacity: 0; }\n  70%  { transform: scale(1.08); }\n  100% { transform: scale(1); opacity: 1; }\n}\n.vsp-benefit-icon { animation: vspPop 0.45s ease backwards; }\n.vsp-benefit:nth-child(1) .vsp-benefit-icon { animation-delay: 0.05s; }\n.vsp-benefit:nth-child(2) .vsp-benefit-icon { animation-delay: 0.12s; }\n.vsp-benefit:nth-child(3) .vsp-benefit-icon { animation-delay: 0.19s; }\n.vsp-benefit:nth-child(4) .vsp-benefit-icon { animation-delay: 0.26s; }\n.vsp-benefit:nth-child(5) .vsp-benefit-icon { animation-delay: 0.33s; }\n.vsp-benefit:nth-child(6) .vsp-benefit-icon { animation-delay: 0.40s; }\n\n.vsp-benefit:hover .vsp-benefit-icon {\n  transform: translateY(-4px);\n  box-shadow: 0 8px 20px rgba(201,123,46,0.25);\n}\n.vsp-benefit:hover .vsp-benefit-icon svg { color: #3D2B1F; }\n\n.vsp-benefit-label {\n  font-size: 12px;\n  font-weight: 500;\n  color: #3D2B1F;\n  line-height: 1.25;\n}\n\n\/* \u2500\u2500 Color selector \u2500\u2500 *\/\n.vsp-colors {\n  display: grid;\n  grid-template-columns: repeat(6, 1fr);\n  gap: 10px;\n  margin-bottom: 24px;\n}\n\n.vsp-color-btn {\n  aspect-ratio: 1;\n  border-radius: 12px;\n  border: 2.5px solid transparent;\n  cursor: pointer;\n  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;\n  position: relative;\n  overflow: hidden;\n  background: none;\n  padding: 0;\n}\n\n.vsp-color-btn:hover { transform: translateY(-3px); box-shadow: 0 6px 20px rgba(0,0,0,0.15); }\n.vsp-color-btn:focus-visible { outline: 3px solid #C97B2E; outline-offset: 2px; }\n\n.vsp-color-btn.active {\n  border-color: #3D2B1F;\n  transform: translateY(-3px);\n  box-shadow: 0 6px 20px rgba(0,0,0,0.2);\n}\n\n.vsp-color-btn img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; }\n\n.vsp-color-name {\n  font-size: 12px;\n  color: #7A5C47;\n  text-align: center;\n  margin-top: 6px;\n  font-family: Georgia, serif;\n}\n\n.vsp-color-item { display: flex; flex-direction: column; }\n\n\/* \u2500\u2500 Optional pet-name block (collapsed by default) \u2500\u2500 *\/\n.vsp-name-toggle {\n  width: 100%;\n  background: #FFFAF5;\n  border: 1.5px dashed #E0D0BE;\n  border-radius: 14px;\n  padding: 14px 16px;\n  font-family: Georgia, serif;\n  font-size: 14px;\n  color: #7A5C47;\n  cursor: pointer;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  gap: 8px;\n  transition: border-color 0.2s, color 0.2s;\n}\n.vsp-name-toggle:hover { border-color: #C97B2E; color: #3D2B1F; }\n.vsp-name-toggle:focus-visible { outline: 3px solid #C97B2E; outline-offset: 2px; }\n.vsp-name-toggle strong { color: #C97B2E; }\n\n.vsp-name-panel { display: none; }\n.vsp-name-panel.open { display: block; animation: vspSlideIn 0.25s ease; }\n\n.vsp-name-input {\n  width: 100%;\n  padding: 16px 20px;\n  border: 1.5px solid #E0D0BE;\n  border-radius: 14px;\n  font-size: 18px;\n  font-family: Georgia, serif;\n  background: #fff;\n  color: #3D2B1F;\n  transition: border-color 0.2s;\n  outline: none;\n  text-transform: capitalize;\n}\n\n.vsp-name-input:focus { border-color: #C97B2E; }\n.vsp-name-input::placeholder { color: #D4B89A; font-style: italic; }\n\n.vsp-tip {\n  display: flex;\n  gap: 10px;\n  align-items: flex-start;\n  background: #FFFAF5;\n  border: 1.5px solid #F0E0CC;\n  border-radius: 12px;\n  padding: 12px 16px;\n  margin-top: 10px;\n}\n\n.vsp-tip-icon { font-size: 16px; flex-shrink: 0; margin-top: 1px; }\n.vsp-tip p { font-size: 12px; color: #7A5C47; line-height: 1.6; }\n.vsp-tip strong { color: #C97B2E; }\n\n.vsp-add-btn {\n  width: 100%;\n  background: #3D2B1F;\n  color: #fff;\n  border: none;\n  border-radius: 14px;\n  padding: 16px;\n  font-size: 15px;\n  font-family: Georgia, serif;\n  font-weight: 500;\n  cursor: pointer;\n  transition: background 0.2s, transform 0.2s;\n  margin-top: 14px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  gap: 8px;\n}\n\n.vsp-add-btn:hover { background: #C97B2E; transform: translateY(-1px); }\n.vsp-add-btn:focus-visible { outline: 3px solid #C97B2E; outline-offset: 2px; }\n.vsp-add-btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none; background: #3D2B1F; }\n.vsp-add-btn span { color: #fff; }\n\n\/* \u2500\u2500 Cart \u2500\u2500 *\/\n.vsp-cart { margin-bottom: 20px; display: none; }\n\n.vsp-cart-title {\n  font-size: 11px;\n  text-transform: uppercase;\n  letter-spacing: 2px;\n  color: #C97B2E;\n  margin-bottom: 12px;\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n}\n\n.vsp-cart-item {\n  display: flex;\n  align-items: center;\n  gap: 12px;\n  background: #fff;\n  border: 1.5px solid #F0E0CC;\n  border-radius: 12px;\n  padding: 12px 14px;\n  margin-bottom: 8px;\n  animation: vspSlideIn 0.3s ease;\n}\n\n@keyframes vspSlideIn {\n  from { opacity: 0; transform: translateY(-8px); }\n  to   { opacity: 1; transform: translateY(0); }\n}\n\n.vsp-cart-thumb { width: 44px; height: 44px; border-radius: 8px; object-fit: cover; flex-shrink: 0; }\n.vsp-cart-info { flex: 1; min-width: 0; }\n.vsp-cart-name { font-size: 15px; font-weight: 500; color: #3D2B1F; }\n.vsp-cart-name.no-name { color: #A0866C; font-style: italic; font-size: 14px; }\n.vsp-cart-model { font-size: 12px; color: #999; margin-top: 2px; }\n.vsp-cart-price { font-size: 14px; font-weight: bold; color: #C97B2E; margin-right: 8px; }\n\n.vsp-cart-remove {\n  background: none;\n  border: none;\n  color: #CC3333;\n  font-size: 18px;\n  cursor: pointer;\n  padding: 4px 6px;\n  line-height: 1;\n  opacity: 0.6;\n  transition: opacity 0.2s;\n}\n.vsp-cart-remove:hover { opacity: 1; }\n.vsp-cart-remove:focus-visible { outline: 2px solid #CC3333; outline-offset: 2px; opacity: 1; }\n\n\/* \u2500\u2500 Price breakdown: every cost visible BEFORE checkout \u2500\u2500 *\/\n.vsp-total {\n  background: #3D2B1F;\n  border-radius: 14px;\n  padding: 18px 20px;\n  margin-bottom: 14px;\n  display: none;\n}\n\n.vsp-total-row {\n  display: flex;\n  justify-content: space-between;\n  align-items: baseline;\n  font-size: 13px;\n  color: rgba(255,255,255,0.72);\n  margin-bottom: 8px;\n}\n.vsp-total-row span:last-child { color: rgba(255,255,255,0.9); }\n\n.vsp-total-rule { height: 1px; background: rgba(255,255,255,0.15); margin: 12px 0; }\n\n.vsp-total-final { display: flex; justify-content: space-between; align-items: center; }\n.vsp-total-label { color: rgba(255,255,255,0.7); font-size: 13px; text-transform: uppercase; letter-spacing: 1px; }\n.vsp-total-price { color: #E8A84E; font-size: 24px; font-weight: bold; }\n.vsp-total-note { color: rgba(255,255,255,0.4); font-size: 11px; margin-top: 4px; }\n\n\/* \u2500\u2500 Sticky checkout bar (mobile-first: the CTA is always one tap away) \u2500\u2500 *\/\n.vsp-bar {\n  position: fixed;\n  left: 0; right: 0; bottom: 0;\n  z-index: 9999;\n  background: rgba(255,248,242,0.97);\n  backdrop-filter: blur(8px);\n  border-top: 1.5px solid #F0E0CC;\n  padding: 12px 16px calc(12px + env(safe-area-inset-bottom));\n  transform: translateY(110%);\n  transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1);\n}\n.vsp-bar.visible { transform: translateY(0); }\n\n.vsp-bar-inner {\n  max-width: 560px;\n  margin: 0 auto;\n  display: flex;\n  align-items: center;\n  gap: 12px;\n}\n\n.vsp-bar-info { flex-shrink: 0; line-height: 1.25; }\n.vsp-bar-total { font-family: Georgia, serif; font-size: 20px; font-weight: bold; color: #3D2B1F; }\n.vsp-bar-sub { font-size: 11px; color: #7A5C47; }\n\n.vsp-cta {\n  flex: 1;\n  background: linear-gradient(135deg, #C97B2E, #E8A84E);\n  color: #fff;\n  border: none;\n  border-radius: 14px;\n  padding: 16px;\n  font-size: 16px;\n  font-family: Georgia, serif;\n  font-weight: bold;\n  cursor: pointer;\n  transition: transform 0.2s ease, box-shadow 0.2s ease;\n  box-shadow: 0 6px 24px rgba(201,123,46,0.35);\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  gap: 8px;\n}\n.vsp-cta span { color: #fff; }\n.vsp-cta:hover { transform: translateY(-2px); box-shadow: 0 10px 32px rgba(201,123,46,0.5); }\n.vsp-cta:focus-visible { outline: 3px solid #3D2B1F; outline-offset: 2px; }\n.vsp-cta:disabled { opacity: 0.7; cursor: wait; transform: none; }\n\n\/* \u2500\u2500 Trust \/ payment \/ FAQ \u2500\u2500 *\/\n.vsp-pay {\n  display: flex;\n  flex-wrap: wrap;\n  justify-content: center;\n  gap: 8px;\n  margin-bottom: 16px;\n}\n.vsp-pay-chip {\n  font-family: Georgia, serif;\n  font-size: 12px;\n  color: #3D2B1F;\n  background: #fff;\n  border: 1.5px solid #F0E0CC;\n  border-radius: 20px;\n  padding: 6px 14px;\n}\n\n.vsp-trust {\n  display: flex;\n  justify-content: center;\n  gap: 18px;\n  flex-wrap: wrap;\n  margin-bottom: 18px;\n}\n.vsp-trust-item { display: flex; align-items: center; gap: 5px; font-size: 12px; color: #7A5C47; }\n\n.vsp-whatsapp {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  gap: 8px;\n  width: 100%;\n  background: #fff;\n  border: 1.5px solid #F0E0CC;\n  border-radius: 14px;\n  padding: 14px;\n  font-family: Georgia, serif;\n  font-size: 14px;\n  color: #3D2B1F;\n  text-decoration: none;\n  transition: border-color 0.2s, transform 0.2s;\n}\n.vsp-whatsapp:hover { border-color: #25D366; transform: translateY(-1px); }\n\n.vsp-faq { margin-top: 8px; }\n.vsp-faq details {\n  background: #FFFAF5;\n  border: 1.5px solid #F0E0CC;\n  border-radius: 12px;\n  padding: 12px 16px;\n  margin-bottom: 8px;\n}\n.vsp-faq summary {\n  font-size: 14px;\n  color: #3D2B1F;\n  cursor: pointer;\n  list-style: none;\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n}\n.vsp-faq summary::-webkit-details-marker { display: none; }\n.vsp-faq summary::after { content: '+'; color: #C97B2E; font-size: 18px; }\n.vsp-faq details[open] summary::after { content: '\u2212'; }\n.vsp-faq p { font-size: 13px; color: #7A5C47; line-height: 1.65; margin-top: 10px; }\n\n.vsp-error {\n  background: #FFF4F4;\n  border: 1.5px solid #FFCCCC;\n  border-radius: 10px;\n  padding: 10px 14px;\n  font-size: 13px;\n  color: #CC3333;\n  margin-bottom: 12px;\n  display: none;\n}\n\n@keyframes vsp-spin { to { transform: rotate(360deg); } }\n.vsp-spinner {\n  width: 18px;\n  height: 18px;\n  border: 2px solid rgba(255,255,255,0.4);\n  border-top-color: #fff;\n  border-radius: 50%;\n  animation: vsp-spin 0.6s linear infinite;\n  display: inline-block;\n}\n\n.vsp-divider { height: 1px; background: #F0E0CC; margin: 28px 0; }\n\n\/* Accessibility: honor the OS \"reduce motion\" setting. *\/\n@media (prefers-reduced-motion: reduce) {\n  .vsp *, .vsp *::before, .vsp *::after {\n    animation-duration: 0.001ms !important;\n    animation-iteration-count: 1 !important;\n    transition-duration: 0.001ms !important;\n  }\n}\n<\/style>\n\n<div class=\"vsp\" id=\"vsp-root\">\n\n  <!-- ============ 1. What is Vuelve ============ -->\n  <p class=\"vsp-demo-intro\">\n    <strong>Vuelve ID<\/strong> is a smart pet tag, <strong>designed and built in Puerto Rico<\/strong>. Scan it with QR or NFC and it opens your pet&#8217;s digital profile with your contact information \u2014 so whoever finds them can reach you in seconds.\n    <br><br>\n    If the person scanning agrees to share their location, <strong>you get an email with the exact scan point<\/strong> and a direct link to Google Maps.\n    <br><br>\n    Every tag includes a <strong>digital vaccination record<\/strong> and, if you want it, <strong>your pet&#8217;s name engraved<\/strong>. For cats, the design is <strong>silent and ultralight<\/strong> \u2014 no jingle, no weight on the collar.\n  <\/p>\n\n  <!-- ============ 2. Product render ============\n       Replaces the old reference photo. The render already carries its own\n       cream background, so it blends into the page with no masking. -->\n  <span class=\"vsp-label\">\ud83d\udd0e Inside the tag<\/span>\n  <div class=\"vsp-ref-wrap\">\n    <!-- TODO: re-export as WebP ~900px wide, quality 80. This JPEG is\n         full-resolution feeding a 560px column. -->\n    <img fetchpriority=\"high\" class=\"vsp-ref-img\" width=\"892\" height=\"1200\" decoding=\"async\"\n         src=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/08\/Gemini_Generated_Image_b5ol3nb5ol3nb5ol.jpg\"\n         alt=\"Vuelve ID tag shown from three angles: the front with the pet's name engraved in relief, a cutaway view showing the NFC chip and its copper antenna inside, and the back with the QR code\">\n  <\/div>\n  <p class=\"vsp-ref-caption\">\n    <strong>Sealed single piece.<\/strong>\n    It does not open \u2014 no lid and no screw to work loose.\n  <\/p>\n\n  <!-- ============ 3. Digital profile ============ -->\n  <span class=\"vsp-label\">\ud83d\udcf1 What the digital profile looks like<\/span>\n  <div class=\"vsp-shots\">\n    <!-- width\/height are omitted on purpose: the real pixel dimensions of\n         these screenshots are unknown. Add them once you check the files \u2014\n         the browser can then reserve the right space and the page stops\n         jumping as each shot loads.\n         https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTML\/Element\/img -->\n    <img loading=\"lazy\" decoding=\"async\"\n         src=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/08\/WhatsApp-Image-2026-08-26-at-20.40.42.jpeg\"\n         alt=\"Vuelve ID digital profile, screen 1\">\n    <img loading=\"lazy\" decoding=\"async\"\n         src=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/08\/WhatsApp-Image-2026-08-26-at-20.40.42-1.jpeg\"\n         alt=\"Vuelve ID digital profile, screen 2\">\n    <img loading=\"lazy\" decoding=\"async\"\n         src=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/08\/WhatsApp-Image-2026-08-26-at-20.40.42-2.jpeg\"\n         alt=\"Vuelve ID digital profile, screen 3\">\n  <\/div>\n\n  <!-- ============ 4. Multi-pet management ============ -->\n  <span class=\"vsp-label\">\ud83d\udc3e Several pets in one account<\/span>\n  <div class=\"vsp-shots single\">\n    <img loading=\"lazy\" decoding=\"async\"\n         src=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/08\/WhatsApp-Image-2026-08-26-at-20.40.42-3.jpeg\"\n         alt=\"Vuelve ID account listing several pets\">\n  <\/div>\n\n  <!-- ============ 5. Vaccination record ============ -->\n  <span class=\"vsp-label\">\ud83d\udc89 Digital vaccination record<\/span>\n  <div class=\"vsp-shots\">\n    <img loading=\"lazy\" decoding=\"async\"\n         src=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/08\/vaccines.jpeg\"\n         alt=\"Vuelve ID vaccination record, screen 1\">\n    <img loading=\"lazy\" decoding=\"async\"\n         src=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/08\/WhatsApp-Image-2026-08-26-at-20.40.42-5.jpeg\"\n         alt=\"Vuelve ID vaccination record, screen 2\">\n  <\/div>\n\n  <div class=\"vsp-divider\"><\/div>\n\n  <!-- ============ 6. Benefits ============ -->\n  <span class=\"vsp-label\">Why Vuelve<\/span>\n  <div class=\"vsp-benefits\">\n\n    <div class=\"vsp-benefit\">\n      <span class=\"vsp-benefit-icon\">\n        <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><rect x=\"5\" y=\"2\" width=\"14\" height=\"20\" rx=\"2.5\"\/><circle cx=\"12\" cy=\"8\" r=\"2.2\"\/><path d=\"M8.5 15.5c0-1.9 1.6-3 3.5-3s3.5 1.1 3.5 3\"\/><\/svg>\n      <\/span>\n      <span class=\"vsp-benefit-label\">Digital<br>profile<\/span>\n    <\/div>\n\n    <div class=\"vsp-benefit\">\n      <span class=\"vsp-benefit-icon\">\n        <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M18 2l4 4\"\/><path d=\"M14.5 5.5l4 4\"\/><path d=\"M16.5 7.5L8 16l-2.5.5L5 19l-2-2 2.5-.5L6 14l8.5-8.5\"\/><path d=\"M9 11l2 2\"\/><path d=\"M2 22l3-3\"\/><\/svg>\n      <\/span>\n      <span class=\"vsp-benefit-label\">Vaccination<br>record<\/span>\n    <\/div>\n\n    <div class=\"vsp-benefit\">\n      <span class=\"vsp-benefit-icon\">\n        <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\"\/><rect x=\"5.5\" y=\"5.5\" width=\"2\" height=\"2\" fill=\"currentColor\" stroke=\"none\"\/><rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\"\/><rect x=\"5.5\" y=\"16.5\" width=\"2\" height=\"2\" fill=\"currentColor\" stroke=\"none\"\/><path d=\"M14.5 5a6 6 0 0 1 0 9\"\/><path d=\"M17 2.5a9.5 9.5 0 0 1 0 14\"\/><\/svg>\n      <\/span>\n      <span class=\"vsp-benefit-label\">NFC +<br>QR code<\/span>\n    <\/div>\n\n    <div class=\"vsp-benefit\">\n      <span class=\"vsp-benefit-icon\">\n        <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M12 2l8 3v6c0 5-3.5 8.5-8 10-4.5-1.5-8-5-8-10V5l8-3z\"\/><path d=\"M8.5 12l2.5 2.5L15.5 9.5\"\/><\/svg>\n      <\/span>\n      <span class=\"vsp-benefit-label\">Water<br>resistant<\/span>\n    <\/div>\n\n    <div class=\"vsp-benefit\">\n      <span class=\"vsp-benefit-icon\">\n        <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><rect x=\"2\" y=\"8\" width=\"15\" height=\"9\" rx=\"2\"\/><path d=\"M20 11v3\"\/><path d=\"M3 5l16 14\" stroke-width=\"2\"\/><\/svg>\n      <\/span>\n      <span class=\"vsp-benefit-label\">No<br>batteries<\/span>\n    <\/div>\n\n    <!-- Answers the #1 unasked objection: \"is there a monthly fee?\" -->\n    <div class=\"vsp-benefit\">\n      <span class=\"vsp-benefit-icon\">\n        <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"9\"\/><path d=\"M15 9.5c-.6-1-1.8-1.5-3-1.5-1.7 0-3 .8-3 2s1.3 1.8 3 2 3 .8 3 2-1.3 2-3 2c-1.2 0-2.4-.5-3-1.5\"\/><path d=\"M12 6v12\"\/><\/svg>\n      <\/span>\n      <span class=\"vsp-benefit-label\">No monthly<br>fee<\/span>\n    <\/div>\n\n  <\/div>\n\n  <div class=\"vsp-divider\"><\/div>\n\n  <!-- ============ 7. Configurator ============ -->\n  <span class=\"vsp-label\">Choose your model<\/span>\n\n  <div class=\"vsp-image-wrap\">\n    <img id=\"vsp-main-img\" width=\"600\" height=\"600\" decoding=\"async\"\n         src=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/04\/Untitled-14.png\"\n         alt=\"Vuelve ID Smart Tag, Bosque model\">\n    <span class=\"vsp-badge\">Smart Tag \u00b7 $29.99 each<\/span>\n  <\/div>\n\n  <h1 class=\"vsp-title\" id=\"vsp-title\">Bosque<\/h1>\n  <p class=\"vsp-subtitle\">QR + NFC \u00b7 No batteries \u00b7 Digital profile included<\/p>\n\n  <!-- Swatch <img> and main <img> point at the SAME file on purpose:\n       the browser already has it cached, so switching color is instant. -->\n  <div class=\"vsp-colors\" id=\"vsp-colors\">\n\n    <div class=\"vsp-color-item\">\n      <button type=\"button\" class=\"vsp-color-btn active\" aria-pressed=\"true\" data-id=\"56\" data-name=\"Bosque\" data-img=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/04\/Untitled-14.png\">\n        <img src=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/04\/Untitled-14.png\" alt=\"Bosque\" width=\"120\" height=\"120\" decoding=\"async\">\n      <\/button>\n      <span class=\"vsp-color-name\">Bosque<\/span>\n    <\/div>\n\n    <div class=\"vsp-color-item\">\n      <button type=\"button\" class=\"vsp-color-btn\" aria-pressed=\"false\" data-id=\"51\" data-name=\"Flamenco\" data-img=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/04\/Untitled-17.png\">\n        <img loading=\"lazy\" src=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/04\/Untitled-17.png\" alt=\"Flamenco\" width=\"120\" height=\"120\" decoding=\"async\">\n      <\/button>\n      <span class=\"vsp-color-name\">Flamenco<\/span>\n    <\/div>\n\n    <div class=\"vsp-color-item\">\n      <button type=\"button\" class=\"vsp-color-btn\" aria-pressed=\"false\" data-id=\"52\" data-name=\"Luna\" data-img=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/04\/Untitled-15.png\">\n        <img loading=\"lazy\" src=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/04\/Untitled-15.png\" alt=\"Luna\" width=\"120\" height=\"120\" decoding=\"async\">\n      <\/button>\n      <span class=\"vsp-color-name\">Luna<\/span>\n    <\/div>\n\n    <div class=\"vsp-color-item\">\n      <button type=\"button\" class=\"vsp-color-btn\" aria-pressed=\"false\" data-id=\"54\" data-name=\"Noche\" data-img=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/04\/Untitled-13.png\">\n        <img loading=\"lazy\" src=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/04\/Untitled-13.png\" alt=\"Noche\" width=\"120\" height=\"120\" decoding=\"async\">\n      <\/button>\n      <span class=\"vsp-color-name\">Noche<\/span>\n    <\/div>\n\n    <div class=\"vsp-color-item\">\n      <button type=\"button\" class=\"vsp-color-btn\" aria-pressed=\"false\" data-id=\"53\" data-name=\"Oc\u00e9ano\" data-img=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/04\/Untitled-12.png\">\n        <img loading=\"lazy\" src=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/04\/Untitled-12.png\" alt=\"Oc\u00e9ano\" width=\"120\" height=\"120\" decoding=\"async\">\n      <\/button>\n      <span class=\"vsp-color-name\">Oc\u00e9ano<\/span>\n    <\/div>\n\n    <div class=\"vsp-color-item\">\n      <button type=\"button\" class=\"vsp-color-btn\" aria-pressed=\"false\" data-id=\"55\" data-name=\"Tierra\" data-img=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/04\/Untitled-16.jpeg\">\n        <img loading=\"lazy\" src=\"https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/04\/Untitled-16.jpeg\" alt=\"Tierra\" width=\"120\" height=\"120\" decoding=\"async\">\n      <\/button>\n      <span class=\"vsp-color-name\">Tierra<\/span>\n    <\/div>\n\n  <\/div>\n\n  <!-- Pet name is OPTIONAL and collapsed. Nothing blocks the add-to-order. -->\n  <button type=\"button\" class=\"vsp-name-toggle\" id=\"vsp-name-toggle\"\n          aria-expanded=\"false\" aria-controls=\"vsp-name-panel\">\n    <span>\ud83d\udc3e<\/span>\n    <span id=\"vsp-name-toggle-text\">Engrave my pet&#8217;s name <strong>(optional)<\/strong><\/span>\n  <\/button>\n\n  <div class=\"vsp-name-panel\" id=\"vsp-name-panel\">\n    <input type=\"text\" id=\"vsp-pet-name\" class=\"vsp-name-input\"\n           placeholder=\"e.g. Luna, Max, Coco...\" maxlength=\"20\"\n           autocomplete=\"off\" style=\"margin-top:10px;\">\n    <div class=\"vsp-tip\">\n      <span class=\"vsp-tip-icon\">\ud83d\udc3e<\/span>\n      <p><strong>Tip:<\/strong> trainers recommend names with <strong>one or two syllables<\/strong> ending in a vowel \u2014 like &#8220;Coco&#8221;, &#8220;Luna&#8221; or &#8220;Max&#8221;. They&#8217;re easier for a dog to pick out, so they respond faster. You can leave this blank: the tag ships without engraving and the digital profile works exactly the same.<\/p>\n    <\/div>\n  <\/div>\n\n  <button type=\"button\" class=\"vsp-add-btn\" id=\"vsp-add-btn\">\n    <span>\uff0b<\/span>\n    <span id=\"vsp-add-btn-text\">Add Bosque to my order<\/span>\n  <\/button>\n\n  <div class=\"vsp-error\" id=\"vsp-error\" role=\"alert\" aria-live=\"assertive\"><\/div>\n\n  <div class=\"vsp-divider\"><\/div>\n\n  <!-- Cart -->\n  <div class=\"vsp-cart\" id=\"vsp-cart\">\n    <div class=\"vsp-cart-title\">\n      <span>Your order<\/span>\n      <span id=\"vsp-cart-count\"><\/span>\n    <\/div>\n    <div id=\"vsp-cart-items\"><\/div>\n  <\/div>\n\n  <!-- Full price breakdown BEFORE checkout: no surprise costs at the end -->\n  <div class=\"vsp-total\" id=\"vsp-total\">\n    <div class=\"vsp-total-row\"><span id=\"vsp-sub-label\">Subtotal<\/span><span id=\"vsp-subtotal\">$0.00<\/span><\/div>\n    <div class=\"vsp-total-row\"><span>Sales tax (IVU 11.5%)<\/span><span id=\"vsp-ivu\">$0.00<\/span><\/div>\n    <div class=\"vsp-total-row\"><span>Shipping<\/span><span id=\"vsp-shipping\">\u2014<\/span><\/div>\n    <div class=\"vsp-total-rule\"><\/div>\n    <div class=\"vsp-total-final\">\n      <span class=\"vsp-total-label\">Total<\/span>\n      <span class=\"vsp-total-price\" id=\"vsp-total-price\">$0.00<\/span>\n    <\/div>\n    <div class=\"vsp-total-note\" id=\"vsp-total-note\"><\/div>\n  <\/div>\n\n  <!-- Payment methods: PR buyers look for ATH M\u00f3vil specifically -->\n  <div class=\"vsp-pay\">\n    <span class=\"vsp-pay-chip\">ATH M\u00f3vil<\/span>\n    <span class=\"vsp-pay-chip\">Visa \u00b7 Mastercard<\/span>\n    <span class=\"vsp-pay-chip\">PayPal<\/span>\n  <\/div>\n\n  <div class=\"vsp-trust\">\n    <span class=\"vsp-trust-item\">Made in Puerto Rico<\/span>\n    <span class=\"vsp-trust-item\">\ud83d\udd12 Secure payment<\/span>\n    <span class=\"vsp-trust-item\">\ud83d\udce6 Ships island-wide<\/span>\n  <\/div>\n\n  <!-- TODO: replace 17871234567 with your real WhatsApp number -->\n  <a class=\"vsp-whatsapp\" href=\"https:\/\/wa.me\/17871234567?text=Hi,%20I%20have%20a%20question%20about%20Vuelve%20ID\"\n     target=\"_blank\" rel=\"noopener\">\n    <span>\ud83d\udcac<\/span> <span>Questions? Message us on WhatsApp<\/span>\n  <\/a>\n\n  <!-- The GPS clarification lives here, in a calm tone, instead of as a red\n       alarm above the fold where it killed the pitch before it started. -->\n  <div class=\"vsp-faq\">\n    <details>\n      <summary>Is Vuelve ID a GPS tracker?<\/summary>\n      <p>No. Vuelve ID does not track in real time and carries no battery. You receive a location only when someone scans the tag and agrees to share it \u2014 which is the moment that actually matters: when someone has found your pet.<\/p>\n    <\/details>\n<details>\n      <summary>How do I set up my pet&#8217;s profile?<\/summary>\n      <p>You do it yourself with the first scan. When your tag arrives, scan it with your phone \u2014 it opens Vuelve automatically and walks you through creating your account and your pet&#8217;s profile: photo, contact info, allergies, vaccines. You can edit everything any time from your account. See the full guide at Getting Started.<\/p>\n    <\/details>\n    <details>\n      <summary>Is there a monthly fee?<\/summary>\n      <p>No. You pay for the tag once. The digital profile and the vaccination record are included, with no monthly or annual subscription.<\/p>\n    <\/details>\n    <details>\n      <summary>What if my pet&#8217;s name is already engraved on another tag?<\/summary>\n      <p>The engraving is optional. You can order without a name and edit the digital profile any time from your account.<\/p>\n    <\/details>\n  <\/div>\n\n<\/div>\n\n<!-- Sticky checkout bar: rendered outside .vsp so `position:fixed` isn't\n     trapped by any transform\/filter on the theme's page wrapper. -->\n<div class=\"vsp-bar\" id=\"vsp-bar\">\n  <div class=\"vsp-bar-inner\">\n    <div class=\"vsp-bar-info\">\n      <div class=\"vsp-bar-total\" id=\"vsp-bar-total\">$0.00<\/div>\n      <div class=\"vsp-bar-sub\" id=\"vsp-bar-sub\"><\/div>\n    <\/div>\n    <button type=\"button\" class=\"vsp-cta\" id=\"vsp-btn\">\n      <span id=\"vsp-btn-icon\">\ud83d\uded2<\/span>\n      <span id=\"vsp-btn-text\">Checkout<\/span>\n    <\/button>\n  <\/div>\n<\/div>\n\n<script>\n(function () {\n  'use strict';\n\n  \/* ==========================================================================\n     CONFIG \u2014 the only block you should need to edit.\n     ========================================================================== *\/\n  var VSP_CONFIG = {\n    UNIT_PRICE:    29.99,\n    MAX_TAGS:      4,\n    IVU_RATE:      0.115,   \/\/ 10.5% state + 1.0% municipal\n    SHIPPING_FLAT: null,    \/\/ \u2190 set your real flat rate (e.g. 4.95). null = \"calculated at checkout\"\n    CHECKOUT_URL:  '\/checkout\/',\n    \/\/ WooCommerce's own AJAX router. Faster than admin-ajax.php because it\n    \/\/ skips the wp-admin bootstrap. We fall back to admin-ajax if it 404s.\n    PRIMARY_ENDPOINT:  '\/?wc-ajax=add_to_cart',\n    FALLBACK_ENDPOINT: '\/wp-admin\/admin-ajax.php'\n  };\n\n  \/* ==========================================================================\n     UI STRINGS \u2014 kept in one place so a translation plugin (or a manual\n     Spanish build) only has to touch this object, not the logic below.\n     ========================================================================== *\/\n  var T = {\n    addPrefix:     'Add ',\n    addSuffix:     ' to my order',\n    noName:        'No name engraved',\n    tagSingular:   'tag',\n    tagPlural:     'tags',\n    subtotal:      'Subtotal',\n    shipCalc:      'Calculated at checkout',\n    shipFree:      'Free',\n    noteCalc:      'Shipping is confirmed on the next step.',\n    noteFinal:     'This is your final total. No additional charges.',\n    plusShipping:  ' + shipping',\n    checkout:      'Checkout',\n    working:       'Preparing your order...',\n    maxReached:    'Maximum of 4 tags per order. For more, message us on WhatsApp.',\n    checkoutFail:  'We could not prepare your order. Check your connection and try again, or message us on WhatsApp and we will complete it with you.'\n  };\n\n  \/* ==========================================================================\n     STATE + DOM CACHE\n     Cache every node once at startup instead of calling getElementById on\n     every render \u2014 the cart re-renders on each add\/remove.\n     ========================================================================== *\/\n  var selected = { id: '56', name: 'Bosque', img: 'https:\/\/vuelveid.com\/wp-content\/uploads\/2026\/04\/Untitled-14.png' };\n  var order = [];   \/\/ [{ id, name, img, petName|null }]\n\n  var $ = function (id) { return document.getElementById(id); };\n  var el = {\n    root: $('vsp-root'), mainImg: $('vsp-main-img'), title: $('vsp-title'),\n    colors: $('vsp-colors'), addBtn: $('vsp-add-btn'), addBtnText: $('vsp-add-btn-text'),\n    nameToggle: $('vsp-name-toggle'), namePanel: $('vsp-name-panel'), nameInput: $('vsp-pet-name'),\n    error: $('vsp-error'), cart: $('vsp-cart'), cartItems: $('vsp-cart-items'), cartCount: $('vsp-cart-count'),\n    total: $('vsp-total'), subLabel: $('vsp-sub-label'), subtotal: $('vsp-subtotal'),\n    ivu: $('vsp-ivu'), shipping: $('vsp-shipping'), totalPrice: $('vsp-total-price'), totalNote: $('vsp-total-note'),\n    bar: $('vsp-bar'), barTotal: $('vsp-bar-total'), barSub: $('vsp-bar-sub'),\n    btn: $('vsp-btn'), btnIcon: $('vsp-btn-icon'), btnText: $('vsp-btn-text')\n  };\n\n  var money  = function (n) { return '$' + n.toFixed(2); };\n  var plural = function (n) { return n + ' ' + (n > 1 ? T.tagPlural : T.tagSingular); };\n\n  function showError(msg) {\n    el.error.textContent = msg;\n    el.error.style.display = 'block';\n  }\n  function clearError() { el.error.style.display = 'none'; }\n\n  \/* NOTE: the initDemoVideos() IIFE from v3 was deleted along with the two\n     <video> elements. The screenshot carousels are pure CSS scroll-snap and\n     need no JavaScript at all. *\/\n\n  \/* ==========================================================================\n     COLOR SELECTION \u2014 one delegated listener for all six swatches.\n     ========================================================================== *\/\n  el.colors.addEventListener('click', function (e) {\n    var btn = e.target.closest('.vsp-color-btn');\n    if (!btn) return;\n\n    el.colors.querySelectorAll('.vsp-color-btn').forEach(function (b) {\n      b.classList.remove('active');\n      b.setAttribute('aria-pressed', 'false');\n    });\n    btn.classList.add('active');\n    btn.setAttribute('aria-pressed', 'true');\n\n    selected = { id: btn.dataset.id, name: btn.dataset.name, img: btn.dataset.img };\n    el.title.textContent = selected.name;\n    el.addBtnText.textContent = T.addPrefix + selected.name + T.addSuffix;\n    el.mainImg.alt = 'Vuelve ID Smart Tag, ' + selected.name + ' model';\n\n    swapMainImage(selected.img);\n  });\n\n  \/* Swap the hero image with no flash of an empty box.\n     The old code used a blind setTimeout(150) and hoped the file had loaded.\n     img.decode() resolves only once the bitmap is ready to paint, so the fade\n     out\/in is always in sync with the actual load \u2014 and it's instant when the\n     file is already cached from the swatch. *\/\n  function swapMainImage(src) {\n    var next = new Image();\n    next.src = src;\n    el.mainImg.classList.add('fading');\n\n    var reveal = function () {\n      el.mainImg.src = src;\n      el.mainImg.classList.remove('fading');\n    };\n    if (next.decode) {\n      next.decode().then(reveal).catch(reveal); \/\/ catch \u2192 still swap on decode failure\n    } else {\n      next.onload = reveal;\n      next.onerror = reveal;\n    }\n  }\n\n  \/* ==========================================================================\n     OPTIONAL PET NAME\n     Collapsed by default. The add button never depends on it.\n     ========================================================================== *\/\n  el.nameToggle.addEventListener('click', function () {\n    var open = el.namePanel.classList.toggle('open');\n    el.nameToggle.setAttribute('aria-expanded', String(open));\n    if (open) el.nameInput.focus();\n  });\n\n  \/\/ Auto-capitalize the first letter as they type (engraving is title-case).\n  el.nameInput.addEventListener('input', function () {\n    if (this.value.length > 0) {\n      this.value = this.value.charAt(0).toUpperCase() + this.value.slice(1);\n    }\n  });\n\n  \/\/ Enter inside the name field = add to order.\n  el.nameInput.addEventListener('keydown', function (e) {\n    if (e.key === 'Enter') { e.preventDefault(); addTag(); }\n  });\n\n  \/* ==========================================================================\n     ADD \/ REMOVE\n     ========================================================================== *\/\n  el.addBtn.addEventListener('click', addTag);\n\n  function addTag() {\n    if (order.length >= VSP_CONFIG.MAX_TAGS) {\n      showError(T.maxReached);\n      return;\n    }\n    clearError();\n\n    var petName = el.nameInput.value.trim();\n\n    order.push({\n      id: selected.id,\n      name: selected.name,\n      img: selected.img,\n      petName: petName || null   \/\/ null = no engraving, and that's fine\n    });\n\n    \/\/ Reset the name field and collapse the panel so the next tag starts clean.\n    el.nameInput.value = '';\n    el.namePanel.classList.remove('open');\n    el.nameToggle.setAttribute('aria-expanded', 'false');\n\n    trackPixel('AddToCart', {\n      content_ids: [selected.id],\n      content_type: 'product',\n      content_name: 'Vuelve ID ' + selected.name,\n      value: VSP_CONFIG.UNIT_PRICE,\n      currency: 'USD'\n    });\n\n    render();\n  }\n\n  \/\/ Delegated remove handler \u2014 survives re-renders without rebinding.\n  el.cartItems.addEventListener('click', function (e) {\n    var btn = e.target.closest('.vsp-cart-remove');\n    if (!btn) return;\n    order.splice(Number(btn.dataset.index), 1);\n    clearError();\n    render();\n  });\n\n  \/* ==========================================================================\n     RENDER \u2014 cart, price breakdown, and sticky bar in one pass.\n     ========================================================================== *\/\n  function render() {\n    var count = order.length;\n    var hasItems = count > 0;\n\n    el.cart.style.display  = hasItems ? 'block' : 'none';\n    el.total.style.display = hasItems ? 'block' : 'none';\n    el.bar.classList.toggle('visible', hasItems);\n    el.root.classList.toggle('has-bar', hasItems);\n    el.addBtn.disabled = count >= VSP_CONFIG.MAX_TAGS;\n\n    if (!hasItems) { el.cartItems.textContent = ''; return; }\n\n    el.cartCount.textContent = plural(count);\n\n    \/\/ Build off-DOM, then insert once \u2192 a single reflow instead of N.\n    var frag = document.createDocumentFragment();\n    order.forEach(function (item, i) {\n      var row = document.createElement('div');\n      row.className = 'vsp-cart-item';\n      row.innerHTML =\n        '<img loading=\"lazy\" class=\"vsp-cart-thumb\" src=\"' + item.img + '\" alt=\"\" width=\"44\" height=\"44\" decoding=\"async\">' +\n        '<div class=\"vsp-cart-info\">' +\n          (item.petName\n            ? '<div class=\"vsp-cart-name\">\ud83d\udc3e ' + escapeHtml(item.petName) + '<\/div>'\n            : '<div class=\"vsp-cart-name no-name\">' + T.noName + '<\/div>') +\n          '<div class=\"vsp-cart-model\">' + item.name + '<\/div>' +\n        '<\/div>' +\n        '<span class=\"vsp-cart-price\">' + money(VSP_CONFIG.UNIT_PRICE) + '<\/span>' +\n        '<button type=\"button\" class=\"vsp-cart-remove\" data-index=\"' + i + '\" aria-label=\"Remove this tag\">\u2715<\/button>';\n      frag.appendChild(row);\n    });\n    el.cartItems.textContent = '';\n    el.cartItems.appendChild(frag);\n\n    \/\/ \u2500\u2500 Price breakdown \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    var subtotal = count * VSP_CONFIG.UNIT_PRICE;\n    var ivu      = subtotal * VSP_CONFIG.IVU_RATE;\n    var ship     = VSP_CONFIG.SHIPPING_FLAT;\n    var total    = subtotal + ivu + (ship || 0);\n\n    el.subLabel.textContent  = T.subtotal + ' (' + plural(count) + ')';\n    el.subtotal.textContent  = money(subtotal);\n    el.ivu.textContent       = money(ivu);\n    el.shipping.textContent  = ship === null ? T.shipCalc\n                             : ship === 0    ? T.shipFree\n                             : money(ship);\n    el.totalPrice.textContent = money(total);\n    el.totalNote.textContent  = ship === null ? T.noteCalc : T.noteFinal;\n\n    el.barTotal.textContent = money(total);\n    el.barSub.textContent   = plural(count) + (ship === null ? T.plusShipping : '');\n    el.btnText.textContent  = T.checkout;\n  }\n\n  \/\/ Pet names are user input rendered via innerHTML \u2192 escape before insertion.\n  function escapeHtml(s) {\n    return s.replace(\/[&<>\"']\/g, function (c) {\n      return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' }[c];\n    });\n  }\n\n  \/* ==========================================================================\n     CHECKOUT\n\n     Why this is not Promise.all any more:\n     WooCommerce loads the whole cart from the session, mutates it, and writes\n     it back on every request. The session handler does not lock. Two parallel\n     add_to_cart calls therefore read the same cart and the second write wipes\n     the first \u2192 the customer lands on \/checkout\/ missing items. Sequential\n     requests are the only safe option against the core handler.\n\n     To keep it fast anyway, identical lines (same product + same engraving)\n     are merged into ONE request with quantity N. Ordering 4 unnamed Bosque\n     tags = 1 request, not 4.\n     ========================================================================== *\/\n  el.btn.addEventListener('click', checkout);\n\n  function groupOrder() {\n    var map = new Map();\n    order.forEach(function (item) {\n      var key = item.id + '|' + (item.petName || '');\n      if (map.has(key)) { map.get(key).quantity += 1; }\n      else { map.set(key, { id: item.id, petName: item.petName, quantity: 1 }); }\n    });\n    return Array.from(map.values());\n  }\n\n  async function addToCartRequest(line, endpoint) {\n    var body = new FormData();\n    body.append('action', 'woocommerce_add_to_cart'); \/\/ used by admin-ajax.php\n    body.append('product_id', line.id);\n    body.append('quantity', line.quantity);\n    if (line.petName) body.append('pet_name', line.petName);\n\n    var res = await fetch(endpoint, {\n      method: 'POST',\n      body: body,\n      credentials: 'same-origin',           \/\/ must carry the WC session cookie\n      headers: { 'X-Requested-With': 'XMLHttpRequest' }\n    });\n\n    \/\/ fetch() only rejects on network failure \u2014 a 500 or 404 resolves happily.\n    \/\/ The old code redirected to checkout on those. Check explicitly.\n    if (!res.ok) throw new Error('HTTP ' + res.status);\n\n    var text = await res.text();\n    var data = null;\n    try { data = JSON.parse(text); } catch (e) { \/* some themes return HTML fragments *\/ }\n\n    \/\/ WooCommerce signals a rejected add with { error: true, product_url: ... }\n    if (data && data.error) throw new Error('WC_REJECTED');\n\n    return true;\n  }\n\n  async function checkout() {\n    if (order.length === 0) return;\n\n    setBusy(true);\n    clearError();\n\n    var lines = groupOrder();\n\n    try {\n      for (var i = 0; i < lines.length; i++) {\n        try {\n          await addToCartRequest(lines[i], VSP_CONFIG.PRIMARY_ENDPOINT);\n        } catch (err) {\n          \/\/ The wc-ajax route can be unavailable on some permalink\/cache\n          \/\/ configurations. Retry that line once via admin-ajax before failing.\n          if (err.message === 'WC_REJECTED') throw err;\n          await addToCartRequest(lines[i], VSP_CONFIG.FALLBACK_ENDPOINT);\n        }\n      }\n\n      var subtotal = order.length * VSP_CONFIG.UNIT_PRICE;\n      trackPixel('InitiateCheckout', {\n        content_ids: order.map(function (o) { return o.id; }),\n        content_type: 'product',\n        num_items: order.length,\n        value: subtotal,\n        currency: 'USD'\n      });\n\n      window.location.href = VSP_CONFIG.CHECKOUT_URL;\n\n    } catch (err) {\n      setBusy(false);\n      showError(T.checkoutFail);\n      if (window.console) console.error('[Vuelve] checkout failed:', err);\n    }\n  }\n\n  function setBusy(busy) {\n    el.btn.disabled = busy;\n    el.btnIcon.innerHTML = busy ? '<span class=\"vsp-spinner\"><\/span>' : '\ud83d\uded2';\n    el.btnText.textContent = busy ? T.working : T.checkout;\n  }\n\n  \/* ==========================================================================\n     META PIXEL\n     This cart bypasses WooCommerce's own JS events, so the Facebook for\n     WooCommerce plugin never fires AddToCart \/ InitiateCheckout here.\n     Fire them manually, guarded so a blocked pixel can't break checkout.\n     https:\/\/developers.facebook.com\/docs\/meta-pixel\/reference\n     ========================================================================== *\/\n  function trackPixel(event, params) {\n    try {\n      if (typeof window.fbq === 'function') window.fbq('track', event, params);\n    } catch (e) { \/* ad blockers must never break the purchase flow *\/ }\n  }\n\n  render(); \/\/ initial paint (empty state)\n})();\n<\/script>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Vuelve ID is a smart pet tag, designed and built in Puerto Rico. Scan it with QR or NFC and it opens your pet&#8217;s digital profile with your contact information \u2014 so whoever finds them can reach you in seconds. If the person scanning agrees to share their location, you get an email with the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-245","page","type-page","status-publish","hentry"],"acf":[],"_hostinger_reach_plugin_has_subscription_block":false,"_hostinger_reach_plugin_is_elementor":false,"_links":{"self":[{"href":"https:\/\/vuelveid.com\/es\/wp-json\/wp\/v2\/pages\/245","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vuelveid.com\/es\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/vuelveid.com\/es\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/vuelveid.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vuelveid.com\/es\/wp-json\/wp\/v2\/comments?post=245"}],"version-history":[{"count":11,"href":"https:\/\/vuelveid.com\/es\/wp-json\/wp\/v2\/pages\/245\/revisions"}],"predecessor-version":[{"id":385,"href":"https:\/\/vuelveid.com\/es\/wp-json\/wp\/v2\/pages\/245\/revisions\/385"}],"wp:attachment":[{"href":"https:\/\/vuelveid.com\/es\/wp-json\/wp\/v2\/media?parent=245"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}