{"title":"Menos de $2000","description":"","products":[{"product_id":"corazon-radiante","title":"RADIANT HEART","description":"\u003cp\u003e\u003cspan data-mce-fragment=\"1\"\u003eMaterial:\u003cbr\u003e\u003cbr\u003e- Cadena acero inoxidable\u003cbr\u003e\u003cbr\u003e- Dijes acero y aleación\u003cbr\u003e\u003cbr\u003eLargo 45cm regulable\u003c\/span\u003e\u003c\/p\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":44277069906086,"sku":null,"price":1490.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/WhatsAppImage2023-07-20at21.34.54.jpg?v=1765408719"},{"product_id":"choker-cristal-heart","title":"CRYSTAL HEART HARMONY","description":"\u003cul\u003e\n\u003cli\u003eCollar quíntuple combinado\u003c\/li\u003e\n\u003cli\u003eCadenas acero quirúrgico inoxidable\u003c\/li\u003e\n\u003cli\u003ePerlas de vidrio esmaltadas\u003c\/li\u003e\n\u003cli\u003eDijes en acero y aleación metálica\u003c\/li\u003e\n\u003cli\u003eCorazón de vidrio\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":44426817634470,"sku":null,"price":1990.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_1102.jpg?v=1776463154"},{"product_id":"estrella-radiante","title":"RADIANT STAR","description":"\u003cp\u003e\u003cspan\u003eMaterial:\u003c\/span\u003e\u003cbr\u003e\u003cbr\u003e\u003cspan\u003e- Cadena acero inoxidable\u003c\/span\u003e\u003cbr\u003e\u003cbr\u003e\u003cspan\u003e- Dijes acero y aleación\u003c\/span\u003e\u003cbr\u003e\u003cbr\u003e\u003cspan\u003eLargo 45cm regulable\u003c\/span\u003e\u003c\/p\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":44588818333862,"sku":null,"price":1490.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/5B3B8DE7-04CF-4048-92F9-737ADDF9295C.jpg?v=1724933923"},{"product_id":"eternal-gothic-cross","title":"ETERNAL GOTHIC CROSS","description":"\u003cp\u003eMaterial:\u003cbr\u003e\u003cbr\u003e-cadena acero quirúrgico\u003cbr\u003e\u003cbr\u003e-dijes aleación\u003c\/p\u003e\n\u003c!----\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":45440700612774,"sku":"","price":1490.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/71962BA1-6EED-4573-BD8E-8CF4E92B536F.jpg?v=1724933731"},{"product_id":"light-crucifix-chain","title":"LIGHT CRUCIFIX CHAIN","description":"\u003cp\u003eMaterial:\u003cbr\u003e\u003cbr\u003e- Perlas de vidrio esmaltadas y cristales\u003cbr\u003e- Cadenas acero inoxidable\u003cbr\u003e- Dijes acero y aleación\u003cbr\u003e\u003cbr\u003eLargo 40cm regulable\u003c\/p\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":45691751694502,"sku":null,"price":1790.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_0785.jpg?v=1724933974"},{"product_id":"black-charm-cross","title":"BLACK CHARM CROSS","description":"\u003cp\u003eMaterial :\u003cbr\u003e\u003cbr\u003e-Cadena acero inoxidable\u003cbr\u003e\u003cbr\u003e-Dijes aleación y acero inoxidable\u003c\/p\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":45879056105638,"sku":null,"price":1490.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_0179_f3516ae5-bd8b-4fc0-8ff7-857b51850019.jpg?v=1728884463"},{"product_id":"lockdown-chain","title":"LOCKDOWN CHAIN","description":"\u003cp\u003eMaterial :\u003c\/p\u003e\n\u003cp\u003e- Cadena acero quirúrgico \u003c\/p\u003e\n\u003cp\u003e- Dijes acero quirúrgico \u003c\/p\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":45888166985894,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/9DDF0894-BB7F-4FF7-9DB6-6577BF5C90C8.jpg?v=1748219309"},{"product_id":"studded-star-pendant","title":"STUDDED STAR PENDANT","description":"\u003cp\u003eMateriales:\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eCadena en acero quirúrgico inoxidable, piercings de acero y dije estrella en acero\u003c\/li\u003e\n\u003cli\u003eLargo: 40cm \/\/ regulable\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":46525397860518,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_0836.jpg?v=1753154384"},{"product_id":"chained-crucifixion","title":"CHAINED CRUCIFIXION","description":"\u003cul\u003e\n\u003cli\u003eCadena acero quirúrgico hipoalergénico, dijes cruces de acero y aleación\u003c\/li\u003e\n\u003cli\u003eLargo 40cm regulable\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":46525421748390,"sku":null,"price":1490.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_1544.jpg?v=1753155740"},{"product_id":"gothic-oval-ring","title":"GOTHIC OVAL RING","description":"\u003cbody\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eAleación de 60% Cobre y 30% Zinc con un 10% de Acabado Metálico de alta resistencia.\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eAcabado envejecido y textura marcada\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eEvitá mojarlo o exponerlo a humedad\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003cmeta charset=\"UTF-8\"\u003e\n\u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003e\n\u003ctitle\u003eJUST VERO — medí tu talle de anillo\u003c\/title\u003e\n\u003cstyle\u003e\n  #jv-ring-sizer{\n    --jv-black:#111111;\n    --jv-white:#ffffff;\n    --jv-brown:#3F352B;\n    --jv-tan:#BCA08A;\n    --jv-line:#dcd6cd;\n    font-family:Helvetica, Arial, sans-serif;\n    color:var(--jv-black);\n    background:var(--jv-white);\n    max-width:520px;\n    margin:0 auto;\n    padding:24px 18px 40px;\n    line-height:1.45;\n    -webkit-text-size-adjust:100%;\n  }\n  #jv-ring-sizer *{box-sizing:border-box;}\n  #jv-ring-sizer h2{\n    font-size:15px;\n    font-weight:700;\n    letter-spacing:0.08em;\n    text-transform:uppercase;\n    margin:0 0 6px;\n  }\n  #jv-ring-sizer p{\n    font-size:13px;\n    color:var(--jv-brown);\n    margin:0 0 14px;\n  }\n  #jv-ring-sizer .step{\n    display:none;\n    border-top:1px solid var(--jv-line);\n    padding-top:20px;\n    margin-top:18px;\n  }\n  #jv-ring-sizer .step.active{display:block;}\n  #jv-ring-sizer .tag{\n    display:inline-block;\n    font-size:10px;\n    letter-spacing:0.12em;\n    text-transform:uppercase;\n    color:var(--jv-white);\n    background:var(--jv-black);\n    padding:3px 8px;\n    margin-bottom:10px;\n  }\n\n  \/* ---- calibration ---- *\/\n  #jv-ring-sizer .calarea{\n    position:relative;\n    margin:16px 0 10px;\n    min-height:120px;\n  }\n  #jv-ring-sizer .calcard{\n    position:relative;\n    border:2px solid var(--jv-black);\n    border-bottom:2px dashed var(--jv-line);\n    border-radius:6px 6px 0 0;\n    background:\n      linear-gradient(to right, rgba(188,160,138,0.10), rgba(188,160,138,0.02));\n  }\n  #jv-ring-sizer .calcard .corner{\n    position:absolute;\n    top:-2px;\n    left:-2px;\n    width:16px;\n    height:16px;\n    border-top:4px solid var(--jv-black);\n    border-left:4px solid var(--jv-black);\n  }\n  #jv-ring-sizer .calcard .cardlbl{\n    position:absolute;\n    bottom:6px;\n    left:0;\n    right:0;\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.06em;\n    text-transform:uppercase;\n    color:var(--jv-tan);\n  }\n  #jv-ring-sizer .calrow{\n    display:flex;\n    align-items:center;\n    gap:10px;\n    margin:14px 0 4px;\n  }\n  #jv-ring-sizer .calrow input[type=range]{\n    flex:1;\n    accent-color:var(--jv-black);\n    min-width:0;\n  }\n  #jv-ring-sizer .nudge{\n    width:34px;\n    min-width:34px;\n    padding:6px 0;\n    font-size:14px;\n    line-height:1;\n  }\n\n  \/* ---- buttons ---- *\/\n  #jv-ring-sizer button{\n    font-family:Helvetica, Arial, sans-serif;\n    background:var(--jv-black);\n    color:var(--jv-white);\n    border:none;\n    padding:12px 18px;\n    font-size:12px;\n    letter-spacing:0.08em;\n    text-transform:uppercase;\n    cursor:pointer;\n    width:100%;\n    margin-top:8px;\n  }\n  #jv-ring-sizer button:focus-visible{\n    outline:2px solid var(--jv-tan);\n    outline-offset:2px;\n  }\n\n  \/* ---- tabs ---- *\/\n  #jv-ring-sizer .tabs{\n    display:flex;\n    margin-bottom:16px;\n    border:1px solid var(--jv-black);\n  }\n  #jv-ring-sizer .tabs button{\n    flex:1;\n    background:var(--jv-white);\n    color:var(--jv-black);\n    margin:0;\n    padding:11px 6px;\n    font-size:11px;\n  }\n  #jv-ring-sizer .tabs button[aria-selected=\"true\"]{\n    background:var(--jv-black);\n    color:var(--jv-white);\n  }\n  #jv-ring-sizer .panel{display:none;}\n  #jv-ring-sizer .panel.on{display:block;}\n\n  \/* ---- rings ---- *\/\n  #jv-ring-sizer .rings{\n    display:grid;\n    gap:16px 10px;\n    justify-items:center;\n    margin:16px 0 4px;\n  }\n  #jv-ring-sizer .ringwrap{\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.04em;\n    text-transform:uppercase;\n    color:var(--jv-brown);\n  }\n  #jv-ring-sizer .ring{\n    border:1.5px solid var(--jv-black);\n    border-radius:50%;\n    margin:0 auto 5px;\n  }\n\n  \/* ---- vertical ruler ---- *\/\n  #jv-ring-sizer .rulerwrap{\n    position:relative;\n    margin:18px 0 8px;\n  }\n  #jv-ring-sizer .ruler{\n    position:relative;\n    border-left:2px solid var(--jv-black);\n    margin-left:2px;\n  }\n  #jv-ring-sizer .tick{\n    position:absolute;\n    left:0;\n    height:0;\n    border-top:1px solid var(--jv-brown);\n    width:5px;\n  }\n  #jv-ring-sizer .tick.mid{width:10px;}\n  #jv-ring-sizer .tick.major{\n    width:17px;\n    border-top:1.5px solid var(--jv-black);\n  }\n  #jv-ring-sizer .tick .lbl{\n    position:absolute;\n    left:21px;\n    top:-6px;\n    font-size:9px;\n    color:var(--jv-black);\n    white-space:nowrap;\n  }\n  #jv-ring-sizer .mark{\n    position:absolute;\n    left:0;\n    height:0;\n    border-top:1px dashed var(--jv-tan);\n  }\n  #jv-ring-sizer .mark .lbl{\n    position:absolute;\n    top:-6px;\n    font-size:10px;\n    color:var(--jv-brown);\n    white-space:nowrap;\n    background:var(--jv-white);\n    padding:0 3px;\n  }\n\n  \/* ---- table + notes ---- *\/\n  #jv-ring-sizer table{\n    width:100%;\n    border-collapse:collapse;\n    font-size:12px;\n    margin-top:14px;\n  }\n  #jv-ring-sizer th, #jv-ring-sizer td{\n    border-bottom:1px solid var(--jv-line);\n    padding:7px 4px;\n    text-align:center;\n  }\n  #jv-ring-sizer th{\n    text-transform:uppercase;\n    font-size:10px;\n    letter-spacing:0.06em;\n    color:var(--jv-brown);\n    font-weight:700;\n  }\n  #jv-ring-sizer .note{\n    font-size:11px;\n    color:var(--jv-tan);\n    margin:10px 0 0;\n  }\n  #jv-ring-sizer .rule-note{\n    font-size:12px;\n    color:var(--jv-black);\n    border-left:2px solid var(--jv-black);\n    padding:2px 0 2px 10px;\n    margin:16px 0 0;\n  }\n  #jv-ring-sizer .check{\n    margin:18px 0 0;\n    font-size:11px;\n    color:var(--jv-brown);\n  }\n  #jv-ring-sizer .checkbar{\n    height:8px;\n    border:1px solid var(--jv-black);\n    border-top:none;\n    margin-top:3px;\n  }\n  #jv-ring-sizer .warn{\n    font-size:12px;\n    background:#f6f2ec;\n    border-left:2px solid var(--jv-tan);\n    padding:9px 10px;\n    margin:0 0 14px;\n    color:var(--jv-brown);\n    display:none;\n  }\n  #jv-ring-sizer .warn.on{display:block;}\n  #jv-ring-sizer .recal{\n    display:block;\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.06em;\n    text-transform:uppercase;\n    text-decoration:underline;\n    color:var(--jv-brown);\n    background:none;\n    border:none;\n    width:auto;\n    margin:22px auto 0;\n    padding:6px;\n  }\n  #jv-ring-sizer .sr{\n    position:absolute;\n    width:1px;height:1px;\n    padding:0;margin:-1px;\n    overflow:hidden;\n    clip:rect(0,0,0,0);\n    white-space:nowrap;border:0;\n  }\n\u003c\/style\u003e\n\n\n\u003cdiv id=\"jv-ring-sizer\"\u003e\n\n  \u003ch2\u003emedí tu talle de anillo\u003c\/h2\u003e\n  \u003cp\u003ecalibrá la pantalla una vez. después medís desde el celular o la computadora.\u003c\/p\u003e\n\n  \u003c!-- ============ PASO 1 · CALIBRACIÓN ============ --\u003e\n  \u003cdiv class=\"step\" id=\"step-cal\"\u003e\n    \u003cspan class=\"tag\"\u003epaso 1 · calibración\u003c\/span\u003e\n    \u003cp\u003eapoyá una tarjeta sobre la pantalla — crédito, débito o la cédula. en vertical, alineada\n       con la esquina de arriba a la izquierda. movés el control hasta que el ancho del rectángulo\n       coincida con el ancho de la tarjeta.\u003c\/p\u003e\n\n    \u003cdiv class=\"calarea\" id=\"calArea\"\u003e\n      \u003cdiv class=\"calcard\" id=\"calCard\"\u003e\n        \u003cspan class=\"corner\"\u003e\u003c\/span\u003e\n        \u003cspan class=\"cardlbl\"\u003eancho de la tarjeta\u003c\/span\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"calrow\"\u003e\n      \u003cbutton class=\"nudge\" id=\"calDown\" aria-label=\"reducir el ancho\"\u003e−\u003c\/button\u003e\n      \u003cinput type=\"range\" id=\"calSlider\" aria-label=\"ajustar el ancho del rectángulo hasta que coincida con la tarjeta\"\u003e\n      \u003cbutton class=\"nudge\" id=\"calUp\" aria-label=\"aumentar el ancho\"\u003e+\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003cbutton id=\"calConfirm\"\u003econfirmar\u003c\/button\u003e\n    \u003cp class=\"note\"\u003eel zoom del navegador tiene que estar al 100%. si tenés activado el zoom de\n       accesibilidad o el modo lupa, la medida no va a dar.\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003c!-- ============ PASO 2 · HERRAMIENTA ============ --\u003e\n  \u003cdiv class=\"step\" id=\"step-tool\"\u003e\n\n    \u003cdiv class=\"warn\" id=\"dprWarn\"\u003e\n      cambió el zoom o la pantalla desde la última vez que calibraste. conviene recalibrar antes de medir.\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"tabs\" role=\"tablist\" aria-label=\"método de medición\"\u003e\n      \u003cbutton role=\"tab\" id=\"tabA\" aria-selected=\"true\" aria-controls=\"panelA\"\u003ecomparar un anillo\u003c\/button\u003e\n      \u003cbutton role=\"tab\" id=\"tabB\" aria-selected=\"false\" aria-controls=\"panelB\"\u003emedir el dedo\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- opción A --\u003e\n    \u003cdiv class=\"panel on\" id=\"panelA\" role=\"tabpanel\" aria-labelledby=\"tabA\"\u003e\n      \u003cspan class=\"tag\"\u003eopción a\u003c\/span\u003e\n      \u003cp\u003eapoyá un anillo que ya te calce bien sobre los círculos. el talle es el círculo cuyo\n         borde exterior queda justo por dentro del anillo.\u003c\/p\u003e\n      \u003cdiv class=\"rings\" id=\"ringsGrid\"\u003e\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- opción B --\u003e\n    \u003cdiv class=\"panel\" id=\"panelB\" role=\"tabpanel\" aria-labelledby=\"tabB\"\u003e\n      \u003cspan class=\"tag\"\u003eopción b\u003c\/span\u003e\n      \u003cp\u003eenvolvé una tira de papel o un hilo en la base del dedo, donde va a quedar el anillo.\n         marcá el punto donde se superpone. después estirá la tira sobre la regla, arrancando\n         desde el cero.\u003c\/p\u003e\n      \u003cdiv class=\"rulerwrap\"\u003e\n        \u003cdiv class=\"ruler\" id=\"ruler\"\u003e\u003c\/div\u003e\n      \u003c\/div\u003e\n      \u003cp class=\"note\"\u003elas líneas punteadas son la circunferencia de cada talle.\u003c\/p\u003e\n    \u003c\/div\u003e\n\n    \u003ctable\u003e\n      \u003ccaption class=\"sr\"\u003etalles disponibles con su diámetro y circunferencia\u003c\/caption\u003e\n      \u003cthead\u003e\u003ctr\u003e\n\u003cth scope=\"col\"\u003etalle\u003c\/th\u003e\n\u003cth scope=\"col\"\u003ediámetro\u003c\/th\u003e\n\u003cth scope=\"col\"\u003ecircunferencia\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n      \u003ctbody id=\"refBody\"\u003e\u003c\/tbody\u003e\n    \u003c\/table\u003e\n\n    \u003cp class=\"rule-note\"\u003esi te queda entre dos talles, elegí el mayor.\u003c\/p\u003e\n\n    \u003cdiv class=\"check\"\u003e\n      control: esta línea mide 50 mm. si tenés una regla a mano, verificá.\n      \u003cdiv class=\"checkbar\" id=\"checkBar\"\u003e\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cp class=\"note\"\u003ees una medida aproximada — sirve para orientarte, no es exacta al milímetro.\n       el dedo cambia de grosor con el calor y la hora del día.\u003c\/p\u003e\n\n    \u003cbutton class=\"recal\" id=\"recalBtn\"\u003erecalibrar pantalla\u003c\/button\u003e\n  \u003c\/div\u003e\n\n\u003c\/div\u003e\n\n\u003cscript\u003e\n(function(){\n  'use strict';\n\n  var STORAGE_KEY = 'jv_ring_sizer_cal_v2';\n\n  \/\/ ISO\/IEC 7810 ID-1 — short side. The long side (85.6mm) is wider than most\n  \/\/ phone screens, so calibration has to happen on the short side.\n  var CARD_SHORT_MM = 53.98;\n  var CARD_LONG_MM  = 85.60;\n  var CARD_MAX_H_PX = 190;\n\n  var MIN_PPM = 1.6;   \/\/ absolute plausibility floor\n  var MAX_PPM = 22;    \/\/ absolute plausibility ceiling\n  var BASE_PPM = 96 \/ 25.4;\n\n  var SIZES = [\n    {size:6,  d:16.5},\n    {size:7,  d:17.3},\n    {size:8,  d:18.1},\n    {size:9,  d:19.0},\n    {size:10, d:19.8},\n    {size:11, d:20.6}\n  ];\n  SIZES.forEach(function(s){ s.c = s.d * Math.PI; });\n\n  var RULER_MAX_MM = 72;   \/\/ clears size 11 (~64.7mm) with room to read\n\n  var root      = document.getElementById('jv-ring-sizer');\n  var stepCal   = root.querySelector('#step-cal');\n  var stepTool  = root.querySelector('#step-tool');\n  var calArea   = root.querySelector('#calArea');\n  var calCard   = root.querySelector('#calCard');\n  var calSlider = root.querySelector('#calSlider');\n  var calUp     = root.querySelector('#calUp');\n  var calDown   = root.querySelector('#calDown');\n  var calConfirm= root.querySelector('#calConfirm');\n  var recalBtn  = root.querySelector('#recalBtn');\n  var dprWarn   = root.querySelector('#dprWarn');\n  var tabA      = root.querySelector('#tabA');\n  var tabB      = root.querySelector('#tabB');\n  var panelA    = root.querySelector('#panelA');\n  var panelB    = root.querySelector('#panelB');\n  var ringsGrid = root.querySelector('#ringsGrid');\n  var ruler     = root.querySelector('#ruler');\n  var refBody   = root.querySelector('#refBody');\n  var checkBar  = root.querySelector('#checkBar');\n\n  var pxPerMm = null;\n\n  \/* ---------- storage (may throw in partitioned\/blocked contexts) ---------- *\/\n  function readCal(){\n    try{\n      var raw = window.localStorage.getItem(STORAGE_KEY);\n      if(!raw) return null;\n      var o = JSON.parse(raw);\n      var p = parseFloat(o \u0026\u0026 o.ppm);\n      if(!isFinite(p) || p \u003c MIN_PPM || p \u003e MAX_PPM) return null;\n      return {ppm:p, dpr:parseFloat(o.dpr) || null};\n    }catch(e){ return null; }\n  }\n  function writeCal(ppm){\n    try{\n      window.localStorage.setItem(STORAGE_KEY, JSON.stringify({\n        ppm:ppm, dpr:window.devicePixelRatio || 1, ts:Date.now()\n      }));\n    }catch(e){ \/* sin persistencia: la calibración vale para esta sesión *\/ }\n  }\n  function clearCal(){\n    try{ window.localStorage.removeItem(STORAGE_KEY); }catch(e){}\n  }\n\n  \/* ---------- available width ---------- *\/\n  function availWidth(){\n    var w = calArea.clientWidth || root.clientWidth || 320;\n    return Math.max(120, w);\n  }\n\n  \/* ---------- calibration step ---------- *\/\n  function sliderBounds(){\n    \/\/ Cap so the calibration rectangle can never overflow its container.\n    var maxPpm = availWidth() \/ CARD_SHORT_MM;\n    var minPpm = MIN_PPM;\n    if(maxPpm \u003c minPpm + 0.5) maxPpm = minPpm + 0.5;\n    return {min:minPpm, max:maxPpm};\n  }\n\n  function drawCalCard(ppm){\n    var w = CARD_SHORT_MM * ppm;\n    var h = Math.min(CARD_LONG_MM * ppm, CARD_MAX_H_PX);\n    calCard.style.width  = w + 'px';\n    calCard.style.height = h + 'px';\n  }\n\n  function setupCalStep(){\n    var b = sliderBounds();\n    var current = parseFloat(calSlider.value);\n    var start = (isFinite(current) \u0026\u0026 current \u003e= b.min \u0026\u0026 current \u003c= b.max)\n      ? current\n      : Math.min(Math.max(pxPerMm || BASE_PPM, b.min), b.max);\n\n    calSlider.min = b.min.toFixed(3);\n    calSlider.max = b.max.toFixed(3);\n    calSlider.step = '0.005';\n    calSlider.value = start;\n    drawCalCard(start);\n  }\n\n  function nudge(delta){\n    var b = sliderBounds();\n    var v = Math.min(Math.max(parseFloat(calSlider.value) + delta, b.min), b.max);\n    calSlider.value = v;\n    drawCalCard(v);\n  }\n\n  calSlider.addEventListener('input', function(){\n    drawCalCard(parseFloat(calSlider.value));\n  });\n  calUp.addEventListener('click',   function(){ nudge(0.02); });\n  calDown.addEventListener('click', function(){ nudge(-0.02); });\n\n  calConfirm.addEventListener('click', function(){\n    var v = parseFloat(calSlider.value);\n    if(!isFinite(v) || v \u003c MIN_PPM || v \u003e MAX_PPM) return;\n    pxPerMm = v;\n    writeCal(pxPerMm);\n    dprWarn.classList.remove('on');\n    renderTool();\n    stepTool.scrollIntoView({block:'start'});\n  });\n\n  recalBtn.addEventListener('click', function(){\n    clearCal();\n    showStep('cal');\n    setupCalStep();\n    stepCal.scrollIntoView({block:'start'});\n  });\n\n  \/* ---------- tabs ---------- *\/\n  function switchTab(which){\n    var isA = (which === 'A');\n    tabA.setAttribute('aria-selected', isA ? 'true' : 'false');\n    tabB.setAttribute('aria-selected', isA ? 'false' : 'true');\n    panelA.classList.toggle('on', isA);\n    panelB.classList.toggle('on', !isA);\n  }\n  tabA.addEventListener('click', function(){ switchTab('A'); });\n  tabB.addEventListener('click', function(){ switchTab('B'); });\n  [tabA, tabB].forEach(function(t){\n    t.addEventListener('keydown', function(e){\n      if(e.key === 'ArrowRight'){ switchTab('B'); tabB.focus(); }\n      if(e.key === 'ArrowLeft'){ switchTab('A'); tabA.focus(); }\n    });\n  });\n\n  function showStep(which){\n    stepCal.classList.toggle('active', which === 'cal');\n    stepTool.classList.toggle('active', which === 'tool');\n  }\n\n  \/* ---------- render: rings ---------- *\/\n  function renderRings(){\n    ringsGrid.innerHTML = '';\n    var maxPx = 0;\n    SIZES.forEach(function(s){ maxPx = Math.max(maxPx, s.d * pxPerMm); });\n\n    \/\/ Columns must fit the largest circle, otherwise rings overflow their cell.\n    var avail = availWidth();\n    var cols = Math.max(1, Math.floor((avail + 10) \/ (maxPx + 10)));\n    cols = Math.min(cols, SIZES.length);\n    ringsGrid.style.gridTemplateColumns = 'repeat(' + cols + ', 1fr)';\n\n    SIZES.forEach(function(s){\n      var px = s.d * pxPerMm;\n      var wrap = document.createElement('div');\n      wrap.className = 'ringwrap';\n      var ring = document.createElement('div');\n      ring.className = 'ring';\n      ring.style.width  = px + 'px';\n      ring.style.height = px + 'px';\n      wrap.appendChild(ring);\n      wrap.appendChild(document.createTextNode('talle ' + s.size));\n      ringsGrid.appendChild(wrap);\n    });\n  }\n\n  \/* ---------- render: vertical ruler ---------- *\/\n  function renderRuler(){\n    ruler.innerHTML = '';\n    ruler.style.height = (RULER_MAX_MM * pxPerMm) + 'px';\n\n    for(var mm = 0; mm \u003c= RULER_MAX_MM; mm++){\n      var tick = document.createElement('div');\n      var cls = 'tick';\n      if(mm % 10 === 0) cls += ' major';\n      else if(mm % 5 === 0) cls += ' mid';\n      tick.className = cls;\n      tick.style.top = (mm * pxPerMm) + 'px';\n      if(mm % 10 === 0){\n        var lbl = document.createElement('span');\n        lbl.className = 'lbl';\n        lbl.textContent = mm + ' mm';\n        tick.appendChild(lbl);\n      }\n      ruler.appendChild(tick);\n    }\n\n    \/\/ Size marks stagger across two columns: consecutive sizes are ~2.5mm apart,\n    \/\/ which is under 10px on a low-density screen — too tight for one column.\n    var cols = [86, 210];\n    SIZES.forEach(function(s, i){\n      var mark = document.createElement('div');\n      mark.className = 'mark';\n      mark.style.top = (s.c * pxPerMm) + 'px';\n      mark.style.width = (cols[i % 2] + 60) + 'px';\n      var lbl = document.createElement('span');\n      lbl.className = 'lbl';\n      lbl.style.left = cols[i % 2] + 'px';\n      lbl.textContent = 'talle ' + s.size + ' · ' + fmt(s.c) + ' mm';\n      mark.appendChild(lbl);\n      ruler.appendChild(mark);\n    });\n  }\n\n  \/* ---------- render: table + check bar ---------- *\/\n  function fmt(n){ return n.toFixed(1).replace('.', ','); }\n\n  function renderTable(){\n    refBody.innerHTML = '';\n    SIZES.forEach(function(s){\n      var tr = document.createElement('tr');\n      var cells = [String(s.size), fmt(s.d) + ' mm', fmt(s.c) + ' mm'];\n      cells.forEach(function(txt){\n        var td = document.createElement('td');\n        td.textContent = txt;\n        tr.appendChild(td);\n      });\n      refBody.appendChild(tr);\n    });\n  }\n\n  function renderCheck(){\n    checkBar.style.width = (50 * pxPerMm) + 'px';\n  }\n\n  function renderTool(){\n    renderRings();\n    renderRuler();\n    renderTable();\n    renderCheck();\n    showStep('tool');\n  }\n\n  \/* ---------- resize \/ orientation ---------- *\/\n  var rt;\n  window.addEventListener('resize', function(){\n    clearTimeout(rt);\n    rt = setTimeout(function(){\n      if(stepCal.classList.contains('active')) setupCalStep();\n      else if(pxPerMm) renderRings();\n    }, 150);\n  });\n\n  \/* ---------- init ---------- *\/\n  var saved = readCal();\n  if(saved){\n    pxPerMm = saved.ppm;\n    \/\/ A changed devicePixelRatio usually means the browser zoom changed,\n    \/\/ which invalidates the stored calibration.\n    var dprNow = window.devicePixelRatio || 1;\n    if(saved.dpr \u0026\u0026 Math.abs(saved.dpr - dprNow) \u003e 0.01){\n      dprWarn.classList.add('on');\n    }\n    renderTool();\n  }else{\n    showStep('cal');\n    setupCalStep();\n  }\n})();\n\u003c\/script\u003e\n\u003c\/body\u003e","brand":"Just Vero","offers":[{"title":"8","offer_id":56236578603174,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":false},{"title":"9","offer_id":46567026655398,"sku":null,"price":1390.0,"currency_code":"UYU","in_stock":false},{"title":"10","offer_id":46567026688166,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_2441.jpg?v=1754516083"},{"product_id":"cemetery-ring","title":"CEMETERY RING","description":"\u003cbody\u003e\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eAleación de 60% Cobre y 30% Zinc con un 10% de Acabado Metálico de alta resistencia.\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eAcabado envejecido y textura marcada\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eEvitá mojarlo o exponerlo a humedad\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cmeta charset=\"UTF-8\"\u003e\n\u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003e\n\u003ctitle\u003eJUST VERO — medí tu talle de anillo\u003c\/title\u003e\n\u003cstyle\u003e\n  #jv-ring-sizer{\n    --jv-black:#111111;\n    --jv-white:#ffffff;\n    --jv-brown:#3F352B;\n    --jv-tan:#BCA08A;\n    --jv-line:#dcd6cd;\n    font-family:Helvetica, Arial, sans-serif;\n    color:var(--jv-black);\n    background:var(--jv-white);\n    max-width:520px;\n    margin:0 auto;\n    padding:24px 18px 40px;\n    line-height:1.45;\n    -webkit-text-size-adjust:100%;\n  }\n  #jv-ring-sizer *{box-sizing:border-box;}\n  #jv-ring-sizer h2{\n    font-size:15px;\n    font-weight:700;\n    letter-spacing:0.08em;\n    text-transform:uppercase;\n    margin:0 0 6px;\n  }\n  #jv-ring-sizer p{\n    font-size:13px;\n    color:var(--jv-brown);\n    margin:0 0 14px;\n  }\n  #jv-ring-sizer .step{\n    display:none;\n    border-top:1px solid var(--jv-line);\n    padding-top:20px;\n    margin-top:18px;\n  }\n  #jv-ring-sizer .step.active{display:block;}\n  #jv-ring-sizer .tag{\n    display:inline-block;\n    font-size:10px;\n    letter-spacing:0.12em;\n    text-transform:uppercase;\n    color:var(--jv-white);\n    background:var(--jv-black);\n    padding:3px 8px;\n    margin-bottom:10px;\n  }\n\n  \/* ---- calibration ---- *\/\n  #jv-ring-sizer .calarea{\n    position:relative;\n    margin:16px 0 10px;\n    min-height:120px;\n  }\n  #jv-ring-sizer .calcard{\n    position:relative;\n    border:2px solid var(--jv-black);\n    border-bottom:2px dashed var(--jv-line);\n    border-radius:6px 6px 0 0;\n    background:\n      linear-gradient(to right, rgba(188,160,138,0.10), rgba(188,160,138,0.02));\n  }\n  #jv-ring-sizer .calcard .corner{\n    position:absolute;\n    top:-2px;\n    left:-2px;\n    width:16px;\n    height:16px;\n    border-top:4px solid var(--jv-black);\n    border-left:4px solid var(--jv-black);\n  }\n  #jv-ring-sizer .calcard .cardlbl{\n    position:absolute;\n    bottom:6px;\n    left:0;\n    right:0;\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.06em;\n    text-transform:uppercase;\n    color:var(--jv-tan);\n  }\n  #jv-ring-sizer .calrow{\n    display:flex;\n    align-items:center;\n    gap:10px;\n    margin:14px 0 4px;\n  }\n  #jv-ring-sizer .calrow input[type=range]{\n    flex:1;\n    accent-color:var(--jv-black);\n    min-width:0;\n  }\n  #jv-ring-sizer .nudge{\n    width:34px;\n    min-width:34px;\n    padding:6px 0;\n    font-size:14px;\n    line-height:1;\n  }\n\n  \/* ---- buttons ---- *\/\n  #jv-ring-sizer button{\n    font-family:Helvetica, Arial, sans-serif;\n    background:var(--jv-black);\n    color:var(--jv-white);\n    border:none;\n    padding:12px 18px;\n    font-size:12px;\n    letter-spacing:0.08em;\n    text-transform:uppercase;\n    cursor:pointer;\n    width:100%;\n    margin-top:8px;\n  }\n  #jv-ring-sizer button:focus-visible{\n    outline:2px solid var(--jv-tan);\n    outline-offset:2px;\n  }\n\n  \/* ---- tabs ---- *\/\n  #jv-ring-sizer .tabs{\n    display:flex;\n    margin-bottom:16px;\n    border:1px solid var(--jv-black);\n  }\n  #jv-ring-sizer .tabs button{\n    flex:1;\n    background:var(--jv-white);\n    color:var(--jv-black);\n    margin:0;\n    padding:11px 6px;\n    font-size:11px;\n  }\n  #jv-ring-sizer .tabs button[aria-selected=\"true\"]{\n    background:var(--jv-black);\n    color:var(--jv-white);\n  }\n  #jv-ring-sizer .panel{display:none;}\n  #jv-ring-sizer .panel.on{display:block;}\n\n  \/* ---- rings ---- *\/\n  #jv-ring-sizer .rings{\n    display:grid;\n    gap:16px 10px;\n    justify-items:center;\n    margin:16px 0 4px;\n  }\n  #jv-ring-sizer .ringwrap{\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.04em;\n    text-transform:uppercase;\n    color:var(--jv-brown);\n  }\n  #jv-ring-sizer .ring{\n    border:1.5px solid var(--jv-black);\n    border-radius:50%;\n    margin:0 auto 5px;\n  }\n\n  \/* ---- vertical ruler ---- *\/\n  #jv-ring-sizer .rulerwrap{\n    position:relative;\n    margin:18px 0 8px;\n  }\n  #jv-ring-sizer .ruler{\n    position:relative;\n    border-left:2px solid var(--jv-black);\n    margin-left:2px;\n  }\n  #jv-ring-sizer .tick{\n    position:absolute;\n    left:0;\n    height:0;\n    border-top:1px solid var(--jv-brown);\n    width:5px;\n  }\n  #jv-ring-sizer .tick.mid{width:10px;}\n  #jv-ring-sizer .tick.major{\n    width:17px;\n    border-top:1.5px solid var(--jv-black);\n  }\n  #jv-ring-sizer .tick .lbl{\n    position:absolute;\n    left:21px;\n    top:-6px;\n    font-size:9px;\n    color:var(--jv-black);\n    white-space:nowrap;\n  }\n  #jv-ring-sizer .mark{\n    position:absolute;\n    left:0;\n    height:0;\n    border-top:1px dashed var(--jv-tan);\n  }\n  #jv-ring-sizer .mark .lbl{\n    position:absolute;\n    top:-6px;\n    font-size:10px;\n    color:var(--jv-brown);\n    white-space:nowrap;\n    background:var(--jv-white);\n    padding:0 3px;\n  }\n\n  \/* ---- table + notes ---- *\/\n  #jv-ring-sizer table{\n    width:100%;\n    border-collapse:collapse;\n    font-size:12px;\n    margin-top:14px;\n  }\n  #jv-ring-sizer th, #jv-ring-sizer td{\n    border-bottom:1px solid var(--jv-line);\n    padding:7px 4px;\n    text-align:center;\n  }\n  #jv-ring-sizer th{\n    text-transform:uppercase;\n    font-size:10px;\n    letter-spacing:0.06em;\n    color:var(--jv-brown);\n    font-weight:700;\n  }\n  #jv-ring-sizer .note{\n    font-size:11px;\n    color:var(--jv-tan);\n    margin:10px 0 0;\n  }\n  #jv-ring-sizer .rule-note{\n    font-size:12px;\n    color:var(--jv-black);\n    border-left:2px solid var(--jv-black);\n    padding:2px 0 2px 10px;\n    margin:16px 0 0;\n  }\n  #jv-ring-sizer .check{\n    margin:18px 0 0;\n    font-size:11px;\n    color:var(--jv-brown);\n  }\n  #jv-ring-sizer .checkbar{\n    height:8px;\n    border:1px solid var(--jv-black);\n    border-top:none;\n    margin-top:3px;\n  }\n  #jv-ring-sizer .warn{\n    font-size:12px;\n    background:#f6f2ec;\n    border-left:2px solid var(--jv-tan);\n    padding:9px 10px;\n    margin:0 0 14px;\n    color:var(--jv-brown);\n    display:none;\n  }\n  #jv-ring-sizer .warn.on{display:block;}\n  #jv-ring-sizer .recal{\n    display:block;\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.06em;\n    text-transform:uppercase;\n    text-decoration:underline;\n    color:var(--jv-brown);\n    background:none;\n    border:none;\n    width:auto;\n    margin:22px auto 0;\n    padding:6px;\n  }\n  #jv-ring-sizer .sr{\n    position:absolute;\n    width:1px;height:1px;\n    padding:0;margin:-1px;\n    overflow:hidden;\n    clip:rect(0,0,0,0);\n    white-space:nowrap;border:0;\n  }\n\u003c\/style\u003e\n\n\n\u003cdiv id=\"jv-ring-sizer\"\u003e\n\n  \u003ch2\u003emedí tu talle de anillo\u003c\/h2\u003e\n  \u003cp\u003ecalibrá la pantalla una vez. después medís desde el celular o la computadora.\u003c\/p\u003e\n\n  \u003c!-- ============ PASO 1 · CALIBRACIÓN ============ --\u003e\n  \u003cdiv class=\"step\" id=\"step-cal\"\u003e\n    \u003cspan class=\"tag\"\u003epaso 1 · calibración\u003c\/span\u003e\n    \u003cp\u003eapoyá una tarjeta sobre la pantalla — crédito, débito o la cédula. en vertical, alineada\n       con la esquina de arriba a la izquierda. movés el control hasta que el ancho del rectángulo\n       coincida con el ancho de la tarjeta.\u003c\/p\u003e\n\n    \u003cdiv class=\"calarea\" id=\"calArea\"\u003e\n      \u003cdiv class=\"calcard\" id=\"calCard\"\u003e\n        \u003cspan class=\"corner\"\u003e\u003c\/span\u003e\n        \u003cspan class=\"cardlbl\"\u003eancho de la tarjeta\u003c\/span\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"calrow\"\u003e\n      \u003cbutton class=\"nudge\" id=\"calDown\" aria-label=\"reducir el ancho\"\u003e−\u003c\/button\u003e\n      \u003cinput type=\"range\" id=\"calSlider\" aria-label=\"ajustar el ancho del rectángulo hasta que coincida con la tarjeta\"\u003e\n      \u003cbutton class=\"nudge\" id=\"calUp\" aria-label=\"aumentar el ancho\"\u003e+\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003cbutton id=\"calConfirm\"\u003econfirmar\u003c\/button\u003e\n    \u003cp class=\"note\"\u003eel zoom del navegador tiene que estar al 100%. si tenés activado el zoom de\n       accesibilidad o el modo lupa, la medida no va a dar.\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003c!-- ============ PASO 2 · HERRAMIENTA ============ --\u003e\n  \u003cdiv class=\"step\" id=\"step-tool\"\u003e\n\n    \u003cdiv class=\"warn\" id=\"dprWarn\"\u003e\n      cambió el zoom o la pantalla desde la última vez que calibraste. conviene recalibrar antes de medir.\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"tabs\" role=\"tablist\" aria-label=\"método de medición\"\u003e\n      \u003cbutton role=\"tab\" id=\"tabA\" aria-selected=\"true\" aria-controls=\"panelA\"\u003ecomparar un anillo\u003c\/button\u003e\n      \u003cbutton role=\"tab\" id=\"tabB\" aria-selected=\"false\" aria-controls=\"panelB\"\u003emedir el dedo\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- opción A --\u003e\n    \u003cdiv class=\"panel on\" id=\"panelA\" role=\"tabpanel\" aria-labelledby=\"tabA\"\u003e\n      \u003cspan class=\"tag\"\u003eopción a\u003c\/span\u003e\n      \u003cp\u003eapoyá un anillo que ya te calce bien sobre los círculos. el talle es el círculo cuyo\n         borde exterior queda justo por dentro del anillo.\u003c\/p\u003e\n      \u003cdiv class=\"rings\" id=\"ringsGrid\"\u003e\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- opción B --\u003e\n    \u003cdiv class=\"panel\" id=\"panelB\" role=\"tabpanel\" aria-labelledby=\"tabB\"\u003e\n      \u003cspan class=\"tag\"\u003eopción b\u003c\/span\u003e\n      \u003cp\u003eenvolvé una tira de papel o un hilo en la base del dedo, donde va a quedar el anillo.\n         marcá el punto donde se superpone. después estirá la tira sobre la regla, arrancando\n         desde el cero.\u003c\/p\u003e\n      \u003cdiv class=\"rulerwrap\"\u003e\n        \u003cdiv class=\"ruler\" id=\"ruler\"\u003e\u003c\/div\u003e\n      \u003c\/div\u003e\n      \u003cp class=\"note\"\u003elas líneas punteadas son la circunferencia de cada talle.\u003c\/p\u003e\n    \u003c\/div\u003e\n\n    \u003ctable\u003e\n      \u003ccaption class=\"sr\"\u003etalles disponibles con su diámetro y circunferencia\u003c\/caption\u003e\n      \u003cthead\u003e\u003ctr\u003e\n\u003cth scope=\"col\"\u003etalle\u003c\/th\u003e\n\u003cth scope=\"col\"\u003ediámetro\u003c\/th\u003e\n\u003cth scope=\"col\"\u003ecircunferencia\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n      \u003ctbody id=\"refBody\"\u003e\u003c\/tbody\u003e\n    \u003c\/table\u003e\n\n    \u003cp class=\"rule-note\"\u003esi te queda entre dos talles, elegí el mayor.\u003c\/p\u003e\n\n    \u003cdiv class=\"check\"\u003e\n      control: esta línea mide 50 mm. si tenés una regla a mano, verificá.\n      \u003cdiv class=\"checkbar\" id=\"checkBar\"\u003e\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cp class=\"note\"\u003ees una medida aproximada — sirve para orientarte, no es exacta al milímetro.\n       el dedo cambia de grosor con el calor y la hora del día.\u003c\/p\u003e\n\n    \u003cbutton class=\"recal\" id=\"recalBtn\"\u003erecalibrar pantalla\u003c\/button\u003e\n  \u003c\/div\u003e\n\n\u003c\/div\u003e\n\n\u003cscript\u003e\n(function(){\n  'use strict';\n\n  var STORAGE_KEY = 'jv_ring_sizer_cal_v2';\n\n  \/\/ ISO\/IEC 7810 ID-1 — short side. The long side (85.6mm) is wider than most\n  \/\/ phone screens, so calibration has to happen on the short side.\n  var CARD_SHORT_MM = 53.98;\n  var CARD_LONG_MM  = 85.60;\n  var CARD_MAX_H_PX = 190;\n\n  var MIN_PPM = 1.6;   \/\/ absolute plausibility floor\n  var MAX_PPM = 22;    \/\/ absolute plausibility ceiling\n  var BASE_PPM = 96 \/ 25.4;\n\n  var SIZES = [\n    {size:6,  d:16.5},\n    {size:7,  d:17.3},\n    {size:8,  d:18.1},\n    {size:9,  d:19.0},\n    {size:10, d:19.8},\n    {size:11, d:20.6}\n  ];\n  SIZES.forEach(function(s){ s.c = s.d * Math.PI; });\n\n  var RULER_MAX_MM = 72;   \/\/ clears size 11 (~64.7mm) with room to read\n\n  var root      = document.getElementById('jv-ring-sizer');\n  var stepCal   = root.querySelector('#step-cal');\n  var stepTool  = root.querySelector('#step-tool');\n  var calArea   = root.querySelector('#calArea');\n  var calCard   = root.querySelector('#calCard');\n  var calSlider = root.querySelector('#calSlider');\n  var calUp     = root.querySelector('#calUp');\n  var calDown   = root.querySelector('#calDown');\n  var calConfirm= root.querySelector('#calConfirm');\n  var recalBtn  = root.querySelector('#recalBtn');\n  var dprWarn   = root.querySelector('#dprWarn');\n  var tabA      = root.querySelector('#tabA');\n  var tabB      = root.querySelector('#tabB');\n  var panelA    = root.querySelector('#panelA');\n  var panelB    = root.querySelector('#panelB');\n  var ringsGrid = root.querySelector('#ringsGrid');\n  var ruler     = root.querySelector('#ruler');\n  var refBody   = root.querySelector('#refBody');\n  var checkBar  = root.querySelector('#checkBar');\n\n  var pxPerMm = null;\n\n  \/* ---------- storage (may throw in partitioned\/blocked contexts) ---------- *\/\n  function readCal(){\n    try{\n      var raw = window.localStorage.getItem(STORAGE_KEY);\n      if(!raw) return null;\n      var o = JSON.parse(raw);\n      var p = parseFloat(o \u0026\u0026 o.ppm);\n      if(!isFinite(p) || p \u003c MIN_PPM || p \u003e MAX_PPM) return null;\n      return {ppm:p, dpr:parseFloat(o.dpr) || null};\n    }catch(e){ return null; }\n  }\n  function writeCal(ppm){\n    try{\n      window.localStorage.setItem(STORAGE_KEY, JSON.stringify({\n        ppm:ppm, dpr:window.devicePixelRatio || 1, ts:Date.now()\n      }));\n    }catch(e){ \/* sin persistencia: la calibración vale para esta sesión *\/ }\n  }\n  function clearCal(){\n    try{ window.localStorage.removeItem(STORAGE_KEY); }catch(e){}\n  }\n\n  \/* ---------- available width ---------- *\/\n  function availWidth(){\n    var w = calArea.clientWidth || root.clientWidth || 320;\n    return Math.max(120, w);\n  }\n\n  \/* ---------- calibration step ---------- *\/\n  function sliderBounds(){\n    \/\/ Cap so the calibration rectangle can never overflow its container.\n    var maxPpm = availWidth() \/ CARD_SHORT_MM;\n    var minPpm = MIN_PPM;\n    if(maxPpm \u003c minPpm + 0.5) maxPpm = minPpm + 0.5;\n    return {min:minPpm, max:maxPpm};\n  }\n\n  function drawCalCard(ppm){\n    var w = CARD_SHORT_MM * ppm;\n    var h = Math.min(CARD_LONG_MM * ppm, CARD_MAX_H_PX);\n    calCard.style.width  = w + 'px';\n    calCard.style.height = h + 'px';\n  }\n\n  function setupCalStep(){\n    var b = sliderBounds();\n    var current = parseFloat(calSlider.value);\n    var start = (isFinite(current) \u0026\u0026 current \u003e= b.min \u0026\u0026 current \u003c= b.max)\n      ? current\n      : Math.min(Math.max(pxPerMm || BASE_PPM, b.min), b.max);\n\n    calSlider.min = b.min.toFixed(3);\n    calSlider.max = b.max.toFixed(3);\n    calSlider.step = '0.005';\n    calSlider.value = start;\n    drawCalCard(start);\n  }\n\n  function nudge(delta){\n    var b = sliderBounds();\n    var v = Math.min(Math.max(parseFloat(calSlider.value) + delta, b.min), b.max);\n    calSlider.value = v;\n    drawCalCard(v);\n  }\n\n  calSlider.addEventListener('input', function(){\n    drawCalCard(parseFloat(calSlider.value));\n  });\n  calUp.addEventListener('click',   function(){ nudge(0.02); });\n  calDown.addEventListener('click', function(){ nudge(-0.02); });\n\n  calConfirm.addEventListener('click', function(){\n    var v = parseFloat(calSlider.value);\n    if(!isFinite(v) || v \u003c MIN_PPM || v \u003e MAX_PPM) return;\n    pxPerMm = v;\n    writeCal(pxPerMm);\n    dprWarn.classList.remove('on');\n    renderTool();\n    stepTool.scrollIntoView({block:'start'});\n  });\n\n  recalBtn.addEventListener('click', function(){\n    clearCal();\n    showStep('cal');\n    setupCalStep();\n    stepCal.scrollIntoView({block:'start'});\n  });\n\n  \/* ---------- tabs ---------- *\/\n  function switchTab(which){\n    var isA = (which === 'A');\n    tabA.setAttribute('aria-selected', isA ? 'true' : 'false');\n    tabB.setAttribute('aria-selected', isA ? 'false' : 'true');\n    panelA.classList.toggle('on', isA);\n    panelB.classList.toggle('on', !isA);\n  }\n  tabA.addEventListener('click', function(){ switchTab('A'); });\n  tabB.addEventListener('click', function(){ switchTab('B'); });\n  [tabA, tabB].forEach(function(t){\n    t.addEventListener('keydown', function(e){\n      if(e.key === 'ArrowRight'){ switchTab('B'); tabB.focus(); }\n      if(e.key === 'ArrowLeft'){ switchTab('A'); tabA.focus(); }\n    });\n  });\n\n  function showStep(which){\n    stepCal.classList.toggle('active', which === 'cal');\n    stepTool.classList.toggle('active', which === 'tool');\n  }\n\n  \/* ---------- render: rings ---------- *\/\n  function renderRings(){\n    ringsGrid.innerHTML = '';\n    var maxPx = 0;\n    SIZES.forEach(function(s){ maxPx = Math.max(maxPx, s.d * pxPerMm); });\n\n    \/\/ Columns must fit the largest circle, otherwise rings overflow their cell.\n    var avail = availWidth();\n    var cols = Math.max(1, Math.floor((avail + 10) \/ (maxPx + 10)));\n    cols = Math.min(cols, SIZES.length);\n    ringsGrid.style.gridTemplateColumns = 'repeat(' + cols + ', 1fr)';\n\n    SIZES.forEach(function(s){\n      var px = s.d * pxPerMm;\n      var wrap = document.createElement('div');\n      wrap.className = 'ringwrap';\n      var ring = document.createElement('div');\n      ring.className = 'ring';\n      ring.style.width  = px + 'px';\n      ring.style.height = px + 'px';\n      wrap.appendChild(ring);\n      wrap.appendChild(document.createTextNode('talle ' + s.size));\n      ringsGrid.appendChild(wrap);\n    });\n  }\n\n  \/* ---------- render: vertical ruler ---------- *\/\n  function renderRuler(){\n    ruler.innerHTML = '';\n    ruler.style.height = (RULER_MAX_MM * pxPerMm) + 'px';\n\n    for(var mm = 0; mm \u003c= RULER_MAX_MM; mm++){\n      var tick = document.createElement('div');\n      var cls = 'tick';\n      if(mm % 10 === 0) cls += ' major';\n      else if(mm % 5 === 0) cls += ' mid';\n      tick.className = cls;\n      tick.style.top = (mm * pxPerMm) + 'px';\n      if(mm % 10 === 0){\n        var lbl = document.createElement('span');\n        lbl.className = 'lbl';\n        lbl.textContent = mm + ' mm';\n        tick.appendChild(lbl);\n      }\n      ruler.appendChild(tick);\n    }\n\n    \/\/ Size marks stagger across two columns: consecutive sizes are ~2.5mm apart,\n    \/\/ which is under 10px on a low-density screen — too tight for one column.\n    var cols = [86, 210];\n    SIZES.forEach(function(s, i){\n      var mark = document.createElement('div');\n      mark.className = 'mark';\n      mark.style.top = (s.c * pxPerMm) + 'px';\n      mark.style.width = (cols[i % 2] + 60) + 'px';\n      var lbl = document.createElement('span');\n      lbl.className = 'lbl';\n      lbl.style.left = cols[i % 2] + 'px';\n      lbl.textContent = 'talle ' + s.size + ' · ' + fmt(s.c) + ' mm';\n      mark.appendChild(lbl);\n      ruler.appendChild(mark);\n    });\n  }\n\n  \/* ---------- render: table + check bar ---------- *\/\n  function fmt(n){ return n.toFixed(1).replace('.', ','); }\n\n  function renderTable(){\n    refBody.innerHTML = '';\n    SIZES.forEach(function(s){\n      var tr = document.createElement('tr');\n      var cells = [String(s.size), fmt(s.d) + ' mm', fmt(s.c) + ' mm'];\n      cells.forEach(function(txt){\n        var td = document.createElement('td');\n        td.textContent = txt;\n        tr.appendChild(td);\n      });\n      refBody.appendChild(tr);\n    });\n  }\n\n  function renderCheck(){\n    checkBar.style.width = (50 * pxPerMm) + 'px';\n  }\n\n  function renderTool(){\n    renderRings();\n    renderRuler();\n    renderTable();\n    renderCheck();\n    showStep('tool');\n  }\n\n  \/* ---------- resize \/ orientation ---------- *\/\n  var rt;\n  window.addEventListener('resize', function(){\n    clearTimeout(rt);\n    rt = setTimeout(function(){\n      if(stepCal.classList.contains('active')) setupCalStep();\n      else if(pxPerMm) renderRings();\n    }, 150);\n  });\n\n  \/* ---------- init ---------- *\/\n  var saved = readCal();\n  if(saved){\n    pxPerMm = saved.ppm;\n    \/\/ A changed devicePixelRatio usually means the browser zoom changed,\n    \/\/ which invalidates the stored calibration.\n    var dprNow = window.devicePixelRatio || 1;\n    if(saved.dpr \u0026\u0026 Math.abs(saved.dpr - dprNow) \u003e 0.01){\n      dprWarn.classList.add('on');\n    }\n    renderTool();\n  }else{\n    showStep('cal');\n    setupCalStep();\n  }\n})();\n\u003c\/script\u003e\n\u003c\/ul\u003e\u003c\/body\u003e","brand":"Just Vero","offers":[{"title":"6","offer_id":56449952481446,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":false},{"title":"7","offer_id":56449952448678,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":false},{"title":"8","offer_id":56449952415910,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":true},{"title":"9","offer_id":46629785796774,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":true},{"title":"10","offer_id":46629785764006,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_2446.jpg?v=1766017132"},{"product_id":"vine-cross","title":"VINE CROSS","description":"\u003cul data-end=\"424\" data-start=\"180\"\u003e\n\u003cli data-end=\"210\" data-start=\"180\"\u003e\n\u003cp data-end=\"210\" data-start=\"182\"\u003eDije en Aleación de 60% Cobre y 30% Zinc con un 10% de Acabado Metálico de alta resistencia.\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli data-end=\"210\" data-start=\"180\"\u003e\n\u003cp data-end=\"210\" data-start=\"182\"\u003eCadena acero inoxidable\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli data-end=\"288\" data-start=\"248\"\u003e\n\u003cp data-end=\"288\" data-start=\"250\"\u003eAcabado envejecido y textura marcada\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli data-end=\"296\" data-start=\"257\"\u003e\n\u003cp data-end=\"296\" data-start=\"259\"\u003eEvita mojarlo o exponerlo a humedad\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":46567020363942,"sku":null,"price":1990.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_2510.jpg?v=1762304446"},{"product_id":"crossroad-ring","title":"CROSSROAD RING","description":"\u003cbody\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eAleación de 60% Cobre y 30% Zinc con un 10% de Acabado Metálico de alta resistencia.\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eAcabado envejecido y textura marcada\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eEvitá mojarlo o exponerlo a humedad\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003cmeta charset=\"UTF-8\"\u003e\n\u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003e\n\u003ctitle\u003eJUST VERO — medí tu talle de anillo\u003c\/title\u003e\n\u003cstyle\u003e\n  #jv-ring-sizer{\n    --jv-black:#111111;\n    --jv-white:#ffffff;\n    --jv-brown:#3F352B;\n    --jv-tan:#BCA08A;\n    --jv-line:#dcd6cd;\n    font-family:Helvetica, Arial, sans-serif;\n    color:var(--jv-black);\n    background:var(--jv-white);\n    max-width:520px;\n    margin:0 auto;\n    padding:24px 18px 40px;\n    line-height:1.45;\n    -webkit-text-size-adjust:100%;\n  }\n  #jv-ring-sizer *{box-sizing:border-box;}\n  #jv-ring-sizer h2{\n    font-size:15px;\n    font-weight:700;\n    letter-spacing:0.08em;\n    text-transform:uppercase;\n    margin:0 0 6px;\n  }\n  #jv-ring-sizer p{\n    font-size:13px;\n    color:var(--jv-brown);\n    margin:0 0 14px;\n  }\n  #jv-ring-sizer .step{\n    display:none;\n    border-top:1px solid var(--jv-line);\n    padding-top:20px;\n    margin-top:18px;\n  }\n  #jv-ring-sizer .step.active{display:block;}\n  #jv-ring-sizer .tag{\n    display:inline-block;\n    font-size:10px;\n    letter-spacing:0.12em;\n    text-transform:uppercase;\n    color:var(--jv-white);\n    background:var(--jv-black);\n    padding:3px 8px;\n    margin-bottom:10px;\n  }\n\n  \/* ---- calibration ---- *\/\n  #jv-ring-sizer .calarea{\n    position:relative;\n    margin:16px 0 10px;\n    min-height:120px;\n  }\n  #jv-ring-sizer .calcard{\n    position:relative;\n    border:2px solid var(--jv-black);\n    border-bottom:2px dashed var(--jv-line);\n    border-radius:6px 6px 0 0;\n    background:\n      linear-gradient(to right, rgba(188,160,138,0.10), rgba(188,160,138,0.02));\n  }\n  #jv-ring-sizer .calcard .corner{\n    position:absolute;\n    top:-2px;\n    left:-2px;\n    width:16px;\n    height:16px;\n    border-top:4px solid var(--jv-black);\n    border-left:4px solid var(--jv-black);\n  }\n  #jv-ring-sizer .calcard .cardlbl{\n    position:absolute;\n    bottom:6px;\n    left:0;\n    right:0;\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.06em;\n    text-transform:uppercase;\n    color:var(--jv-tan);\n  }\n  #jv-ring-sizer .calrow{\n    display:flex;\n    align-items:center;\n    gap:10px;\n    margin:14px 0 4px;\n  }\n  #jv-ring-sizer .calrow input[type=range]{\n    flex:1;\n    accent-color:var(--jv-black);\n    min-width:0;\n  }\n  #jv-ring-sizer .nudge{\n    width:34px;\n    min-width:34px;\n    padding:6px 0;\n    font-size:14px;\n    line-height:1;\n  }\n\n  \/* ---- buttons ---- *\/\n  #jv-ring-sizer button{\n    font-family:Helvetica, Arial, sans-serif;\n    background:var(--jv-black);\n    color:var(--jv-white);\n    border:none;\n    padding:12px 18px;\n    font-size:12px;\n    letter-spacing:0.08em;\n    text-transform:uppercase;\n    cursor:pointer;\n    width:100%;\n    margin-top:8px;\n  }\n  #jv-ring-sizer button:focus-visible{\n    outline:2px solid var(--jv-tan);\n    outline-offset:2px;\n  }\n\n  \/* ---- tabs ---- *\/\n  #jv-ring-sizer .tabs{\n    display:flex;\n    margin-bottom:16px;\n    border:1px solid var(--jv-black);\n  }\n  #jv-ring-sizer .tabs button{\n    flex:1;\n    background:var(--jv-white);\n    color:var(--jv-black);\n    margin:0;\n    padding:11px 6px;\n    font-size:11px;\n  }\n  #jv-ring-sizer .tabs button[aria-selected=\"true\"]{\n    background:var(--jv-black);\n    color:var(--jv-white);\n  }\n  #jv-ring-sizer .panel{display:none;}\n  #jv-ring-sizer .panel.on{display:block;}\n\n  \/* ---- rings ---- *\/\n  #jv-ring-sizer .rings{\n    display:grid;\n    gap:16px 10px;\n    justify-items:center;\n    margin:16px 0 4px;\n  }\n  #jv-ring-sizer .ringwrap{\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.04em;\n    text-transform:uppercase;\n    color:var(--jv-brown);\n  }\n  #jv-ring-sizer .ring{\n    border:1.5px solid var(--jv-black);\n    border-radius:50%;\n    margin:0 auto 5px;\n  }\n\n  \/* ---- vertical ruler ---- *\/\n  #jv-ring-sizer .rulerwrap{\n    position:relative;\n    margin:18px 0 8px;\n  }\n  #jv-ring-sizer .ruler{\n    position:relative;\n    border-left:2px solid var(--jv-black);\n    margin-left:2px;\n  }\n  #jv-ring-sizer .tick{\n    position:absolute;\n    left:0;\n    height:0;\n    border-top:1px solid var(--jv-brown);\n    width:5px;\n  }\n  #jv-ring-sizer .tick.mid{width:10px;}\n  #jv-ring-sizer .tick.major{\n    width:17px;\n    border-top:1.5px solid var(--jv-black);\n  }\n  #jv-ring-sizer .tick .lbl{\n    position:absolute;\n    left:21px;\n    top:-6px;\n    font-size:9px;\n    color:var(--jv-black);\n    white-space:nowrap;\n  }\n  #jv-ring-sizer .mark{\n    position:absolute;\n    left:0;\n    height:0;\n    border-top:1px dashed var(--jv-tan);\n  }\n  #jv-ring-sizer .mark .lbl{\n    position:absolute;\n    top:-6px;\n    font-size:10px;\n    color:var(--jv-brown);\n    white-space:nowrap;\n    background:var(--jv-white);\n    padding:0 3px;\n  }\n\n  \/* ---- table + notes ---- *\/\n  #jv-ring-sizer table{\n    width:100%;\n    border-collapse:collapse;\n    font-size:12px;\n    margin-top:14px;\n  }\n  #jv-ring-sizer th, #jv-ring-sizer td{\n    border-bottom:1px solid var(--jv-line);\n    padding:7px 4px;\n    text-align:center;\n  }\n  #jv-ring-sizer th{\n    text-transform:uppercase;\n    font-size:10px;\n    letter-spacing:0.06em;\n    color:var(--jv-brown);\n    font-weight:700;\n  }\n  #jv-ring-sizer .note{\n    font-size:11px;\n    color:var(--jv-tan);\n    margin:10px 0 0;\n  }\n  #jv-ring-sizer .rule-note{\n    font-size:12px;\n    color:var(--jv-black);\n    border-left:2px solid var(--jv-black);\n    padding:2px 0 2px 10px;\n    margin:16px 0 0;\n  }\n  #jv-ring-sizer .check{\n    margin:18px 0 0;\n    font-size:11px;\n    color:var(--jv-brown);\n  }\n  #jv-ring-sizer .checkbar{\n    height:8px;\n    border:1px solid var(--jv-black);\n    border-top:none;\n    margin-top:3px;\n  }\n  #jv-ring-sizer .warn{\n    font-size:12px;\n    background:#f6f2ec;\n    border-left:2px solid var(--jv-tan);\n    padding:9px 10px;\n    margin:0 0 14px;\n    color:var(--jv-brown);\n    display:none;\n  }\n  #jv-ring-sizer .warn.on{display:block;}\n  #jv-ring-sizer .recal{\n    display:block;\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.06em;\n    text-transform:uppercase;\n    text-decoration:underline;\n    color:var(--jv-brown);\n    background:none;\n    border:none;\n    width:auto;\n    margin:22px auto 0;\n    padding:6px;\n  }\n  #jv-ring-sizer .sr{\n    position:absolute;\n    width:1px;height:1px;\n    padding:0;margin:-1px;\n    overflow:hidden;\n    clip:rect(0,0,0,0);\n    white-space:nowrap;border:0;\n  }\n\u003c\/style\u003e\n\n\n\u003cdiv id=\"jv-ring-sizer\"\u003e\n\n  \u003ch2\u003emedí tu talle de anillo\u003c\/h2\u003e\n  \u003cp\u003ecalibrá la pantalla una vez. después medís desde el celular o la computadora.\u003c\/p\u003e\n\n  \u003c!-- ============ PASO 1 · CALIBRACIÓN ============ --\u003e\n  \u003cdiv class=\"step\" id=\"step-cal\"\u003e\n    \u003cspan class=\"tag\"\u003epaso 1 · calibración\u003c\/span\u003e\n    \u003cp\u003eapoyá una tarjeta sobre la pantalla — crédito, débito o la cédula. en vertical, alineada\n       con la esquina de arriba a la izquierda. movés el control hasta que el ancho del rectángulo\n       coincida con el ancho de la tarjeta.\u003c\/p\u003e\n\n    \u003cdiv class=\"calarea\" id=\"calArea\"\u003e\n      \u003cdiv class=\"calcard\" id=\"calCard\"\u003e\n        \u003cspan class=\"corner\"\u003e\u003c\/span\u003e\n        \u003cspan class=\"cardlbl\"\u003eancho de la tarjeta\u003c\/span\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"calrow\"\u003e\n      \u003cbutton class=\"nudge\" id=\"calDown\" aria-label=\"reducir el ancho\"\u003e−\u003c\/button\u003e\n      \u003cinput type=\"range\" id=\"calSlider\" aria-label=\"ajustar el ancho del rectángulo hasta que coincida con la tarjeta\"\u003e\n      \u003cbutton class=\"nudge\" id=\"calUp\" aria-label=\"aumentar el ancho\"\u003e+\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003cbutton id=\"calConfirm\"\u003econfirmar\u003c\/button\u003e\n    \u003cp class=\"note\"\u003eel zoom del navegador tiene que estar al 100%. si tenés activado el zoom de\n       accesibilidad o el modo lupa, la medida no va a dar.\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003c!-- ============ PASO 2 · HERRAMIENTA ============ --\u003e\n  \u003cdiv class=\"step\" id=\"step-tool\"\u003e\n\n    \u003cdiv class=\"warn\" id=\"dprWarn\"\u003e\n      cambió el zoom o la pantalla desde la última vez que calibraste. conviene recalibrar antes de medir.\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"tabs\" role=\"tablist\" aria-label=\"método de medición\"\u003e\n      \u003cbutton role=\"tab\" id=\"tabA\" aria-selected=\"true\" aria-controls=\"panelA\"\u003ecomparar un anillo\u003c\/button\u003e\n      \u003cbutton role=\"tab\" id=\"tabB\" aria-selected=\"false\" aria-controls=\"panelB\"\u003emedir el dedo\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- opción A --\u003e\n    \u003cdiv class=\"panel on\" id=\"panelA\" role=\"tabpanel\" aria-labelledby=\"tabA\"\u003e\n      \u003cspan class=\"tag\"\u003eopción a\u003c\/span\u003e\n      \u003cp\u003eapoyá un anillo que ya te calce bien sobre los círculos. el talle es el círculo cuyo\n         borde exterior queda justo por dentro del anillo.\u003c\/p\u003e\n      \u003cdiv class=\"rings\" id=\"ringsGrid\"\u003e\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- opción B --\u003e\n    \u003cdiv class=\"panel\" id=\"panelB\" role=\"tabpanel\" aria-labelledby=\"tabB\"\u003e\n      \u003cspan class=\"tag\"\u003eopción b\u003c\/span\u003e\n      \u003cp\u003eenvolvé una tira de papel o un hilo en la base del dedo, donde va a quedar el anillo.\n         marcá el punto donde se superpone. después estirá la tira sobre la regla, arrancando\n         desde el cero.\u003c\/p\u003e\n      \u003cdiv class=\"rulerwrap\"\u003e\n        \u003cdiv class=\"ruler\" id=\"ruler\"\u003e\u003c\/div\u003e\n      \u003c\/div\u003e\n      \u003cp class=\"note\"\u003elas líneas punteadas son la circunferencia de cada talle.\u003c\/p\u003e\n    \u003c\/div\u003e\n\n    \u003ctable\u003e\n      \u003ccaption class=\"sr\"\u003etalles disponibles con su diámetro y circunferencia\u003c\/caption\u003e\n      \u003cthead\u003e\u003ctr\u003e\n\u003cth scope=\"col\"\u003etalle\u003c\/th\u003e\n\u003cth scope=\"col\"\u003ediámetro\u003c\/th\u003e\n\u003cth scope=\"col\"\u003ecircunferencia\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n      \u003ctbody id=\"refBody\"\u003e\u003c\/tbody\u003e\n    \u003c\/table\u003e\n\n    \u003cp class=\"rule-note\"\u003esi te queda entre dos talles, elegí el mayor.\u003c\/p\u003e\n\n    \u003cdiv class=\"check\"\u003e\n      control: esta línea mide 50 mm. si tenés una regla a mano, verificá.\n      \u003cdiv class=\"checkbar\" id=\"checkBar\"\u003e\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cp class=\"note\"\u003ees una medida aproximada — sirve para orientarte, no es exacta al milímetro.\n       el dedo cambia de grosor con el calor y la hora del día.\u003c\/p\u003e\n\n    \u003cbutton class=\"recal\" id=\"recalBtn\"\u003erecalibrar pantalla\u003c\/button\u003e\n  \u003c\/div\u003e\n\n\u003c\/div\u003e\n\n\u003cscript\u003e\n(function(){\n  'use strict';\n\n  var STORAGE_KEY = 'jv_ring_sizer_cal_v2';\n\n  \/\/ ISO\/IEC 7810 ID-1 — short side. The long side (85.6mm) is wider than most\n  \/\/ phone screens, so calibration has to happen on the short side.\n  var CARD_SHORT_MM = 53.98;\n  var CARD_LONG_MM  = 85.60;\n  var CARD_MAX_H_PX = 190;\n\n  var MIN_PPM = 1.6;   \/\/ absolute plausibility floor\n  var MAX_PPM = 22;    \/\/ absolute plausibility ceiling\n  var BASE_PPM = 96 \/ 25.4;\n\n  var SIZES = [\n    {size:6,  d:16.5},\n    {size:7,  d:17.3},\n    {size:8,  d:18.1},\n    {size:9,  d:19.0},\n    {size:10, d:19.8},\n    {size:11, d:20.6}\n  ];\n  SIZES.forEach(function(s){ s.c = s.d * Math.PI; });\n\n  var RULER_MAX_MM = 72;   \/\/ clears size 11 (~64.7mm) with room to read\n\n  var root      = document.getElementById('jv-ring-sizer');\n  var stepCal   = root.querySelector('#step-cal');\n  var stepTool  = root.querySelector('#step-tool');\n  var calArea   = root.querySelector('#calArea');\n  var calCard   = root.querySelector('#calCard');\n  var calSlider = root.querySelector('#calSlider');\n  var calUp     = root.querySelector('#calUp');\n  var calDown   = root.querySelector('#calDown');\n  var calConfirm= root.querySelector('#calConfirm');\n  var recalBtn  = root.querySelector('#recalBtn');\n  var dprWarn   = root.querySelector('#dprWarn');\n  var tabA      = root.querySelector('#tabA');\n  var tabB      = root.querySelector('#tabB');\n  var panelA    = root.querySelector('#panelA');\n  var panelB    = root.querySelector('#panelB');\n  var ringsGrid = root.querySelector('#ringsGrid');\n  var ruler     = root.querySelector('#ruler');\n  var refBody   = root.querySelector('#refBody');\n  var checkBar  = root.querySelector('#checkBar');\n\n  var pxPerMm = null;\n\n  \/* ---------- storage (may throw in partitioned\/blocked contexts) ---------- *\/\n  function readCal(){\n    try{\n      var raw = window.localStorage.getItem(STORAGE_KEY);\n      if(!raw) return null;\n      var o = JSON.parse(raw);\n      var p = parseFloat(o \u0026\u0026 o.ppm);\n      if(!isFinite(p) || p \u003c MIN_PPM || p \u003e MAX_PPM) return null;\n      return {ppm:p, dpr:parseFloat(o.dpr) || null};\n    }catch(e){ return null; }\n  }\n  function writeCal(ppm){\n    try{\n      window.localStorage.setItem(STORAGE_KEY, JSON.stringify({\n        ppm:ppm, dpr:window.devicePixelRatio || 1, ts:Date.now()\n      }));\n    }catch(e){ \/* sin persistencia: la calibración vale para esta sesión *\/ }\n  }\n  function clearCal(){\n    try{ window.localStorage.removeItem(STORAGE_KEY); }catch(e){}\n  }\n\n  \/* ---------- available width ---------- *\/\n  function availWidth(){\n    var w = calArea.clientWidth || root.clientWidth || 320;\n    return Math.max(120, w);\n  }\n\n  \/* ---------- calibration step ---------- *\/\n  function sliderBounds(){\n    \/\/ Cap so the calibration rectangle can never overflow its container.\n    var maxPpm = availWidth() \/ CARD_SHORT_MM;\n    var minPpm = MIN_PPM;\n    if(maxPpm \u003c minPpm + 0.5) maxPpm = minPpm + 0.5;\n    return {min:minPpm, max:maxPpm};\n  }\n\n  function drawCalCard(ppm){\n    var w = CARD_SHORT_MM * ppm;\n    var h = Math.min(CARD_LONG_MM * ppm, CARD_MAX_H_PX);\n    calCard.style.width  = w + 'px';\n    calCard.style.height = h + 'px';\n  }\n\n  function setupCalStep(){\n    var b = sliderBounds();\n    var current = parseFloat(calSlider.value);\n    var start = (isFinite(current) \u0026\u0026 current \u003e= b.min \u0026\u0026 current \u003c= b.max)\n      ? current\n      : Math.min(Math.max(pxPerMm || BASE_PPM, b.min), b.max);\n\n    calSlider.min = b.min.toFixed(3);\n    calSlider.max = b.max.toFixed(3);\n    calSlider.step = '0.005';\n    calSlider.value = start;\n    drawCalCard(start);\n  }\n\n  function nudge(delta){\n    var b = sliderBounds();\n    var v = Math.min(Math.max(parseFloat(calSlider.value) + delta, b.min), b.max);\n    calSlider.value = v;\n    drawCalCard(v);\n  }\n\n  calSlider.addEventListener('input', function(){\n    drawCalCard(parseFloat(calSlider.value));\n  });\n  calUp.addEventListener('click',   function(){ nudge(0.02); });\n  calDown.addEventListener('click', function(){ nudge(-0.02); });\n\n  calConfirm.addEventListener('click', function(){\n    var v = parseFloat(calSlider.value);\n    if(!isFinite(v) || v \u003c MIN_PPM || v \u003e MAX_PPM) return;\n    pxPerMm = v;\n    writeCal(pxPerMm);\n    dprWarn.classList.remove('on');\n    renderTool();\n    stepTool.scrollIntoView({block:'start'});\n  });\n\n  recalBtn.addEventListener('click', function(){\n    clearCal();\n    showStep('cal');\n    setupCalStep();\n    stepCal.scrollIntoView({block:'start'});\n  });\n\n  \/* ---------- tabs ---------- *\/\n  function switchTab(which){\n    var isA = (which === 'A');\n    tabA.setAttribute('aria-selected', isA ? 'true' : 'false');\n    tabB.setAttribute('aria-selected', isA ? 'false' : 'true');\n    panelA.classList.toggle('on', isA);\n    panelB.classList.toggle('on', !isA);\n  }\n  tabA.addEventListener('click', function(){ switchTab('A'); });\n  tabB.addEventListener('click', function(){ switchTab('B'); });\n  [tabA, tabB].forEach(function(t){\n    t.addEventListener('keydown', function(e){\n      if(e.key === 'ArrowRight'){ switchTab('B'); tabB.focus(); }\n      if(e.key === 'ArrowLeft'){ switchTab('A'); tabA.focus(); }\n    });\n  });\n\n  function showStep(which){\n    stepCal.classList.toggle('active', which === 'cal');\n    stepTool.classList.toggle('active', which === 'tool');\n  }\n\n  \/* ---------- render: rings ---------- *\/\n  function renderRings(){\n    ringsGrid.innerHTML = '';\n    var maxPx = 0;\n    SIZES.forEach(function(s){ maxPx = Math.max(maxPx, s.d * pxPerMm); });\n\n    \/\/ Columns must fit the largest circle, otherwise rings overflow their cell.\n    var avail = availWidth();\n    var cols = Math.max(1, Math.floor((avail + 10) \/ (maxPx + 10)));\n    cols = Math.min(cols, SIZES.length);\n    ringsGrid.style.gridTemplateColumns = 'repeat(' + cols + ', 1fr)';\n\n    SIZES.forEach(function(s){\n      var px = s.d * pxPerMm;\n      var wrap = document.createElement('div');\n      wrap.className = 'ringwrap';\n      var ring = document.createElement('div');\n      ring.className = 'ring';\n      ring.style.width  = px + 'px';\n      ring.style.height = px + 'px';\n      wrap.appendChild(ring);\n      wrap.appendChild(document.createTextNode('talle ' + s.size));\n      ringsGrid.appendChild(wrap);\n    });\n  }\n\n  \/* ---------- render: vertical ruler ---------- *\/\n  function renderRuler(){\n    ruler.innerHTML = '';\n    ruler.style.height = (RULER_MAX_MM * pxPerMm) + 'px';\n\n    for(var mm = 0; mm \u003c= RULER_MAX_MM; mm++){\n      var tick = document.createElement('div');\n      var cls = 'tick';\n      if(mm % 10 === 0) cls += ' major';\n      else if(mm % 5 === 0) cls += ' mid';\n      tick.className = cls;\n      tick.style.top = (mm * pxPerMm) + 'px';\n      if(mm % 10 === 0){\n        var lbl = document.createElement('span');\n        lbl.className = 'lbl';\n        lbl.textContent = mm + ' mm';\n        tick.appendChild(lbl);\n      }\n      ruler.appendChild(tick);\n    }\n\n    \/\/ Size marks stagger across two columns: consecutive sizes are ~2.5mm apart,\n    \/\/ which is under 10px on a low-density screen — too tight for one column.\n    var cols = [86, 210];\n    SIZES.forEach(function(s, i){\n      var mark = document.createElement('div');\n      mark.className = 'mark';\n      mark.style.top = (s.c * pxPerMm) + 'px';\n      mark.style.width = (cols[i % 2] + 60) + 'px';\n      var lbl = document.createElement('span');\n      lbl.className = 'lbl';\n      lbl.style.left = cols[i % 2] + 'px';\n      lbl.textContent = 'talle ' + s.size + ' · ' + fmt(s.c) + ' mm';\n      mark.appendChild(lbl);\n      ruler.appendChild(mark);\n    });\n  }\n\n  \/* ---------- render: table + check bar ---------- *\/\n  function fmt(n){ return n.toFixed(1).replace('.', ','); }\n\n  function renderTable(){\n    refBody.innerHTML = '';\n    SIZES.forEach(function(s){\n      var tr = document.createElement('tr');\n      var cells = [String(s.size), fmt(s.d) + ' mm', fmt(s.c) + ' mm'];\n      cells.forEach(function(txt){\n        var td = document.createElement('td');\n        td.textContent = txt;\n        tr.appendChild(td);\n      });\n      refBody.appendChild(tr);\n    });\n  }\n\n  function renderCheck(){\n    checkBar.style.width = (50 * pxPerMm) + 'px';\n  }\n\n  function renderTool(){\n    renderRings();\n    renderRuler();\n    renderTable();\n    renderCheck();\n    showStep('tool');\n  }\n\n  \/* ---------- resize \/ orientation ---------- *\/\n  var rt;\n  window.addEventListener('resize', function(){\n    clearTimeout(rt);\n    rt = setTimeout(function(){\n      if(stepCal.classList.contains('active')) setupCalStep();\n      else if(pxPerMm) renderRings();\n    }, 150);\n  });\n\n  \/* ---------- init ---------- *\/\n  var saved = readCal();\n  if(saved){\n    pxPerMm = saved.ppm;\n    \/\/ A changed devicePixelRatio usually means the browser zoom changed,\n    \/\/ which invalidates the stored calibration.\n    var dprNow = window.devicePixelRatio || 1;\n    if(saved.dpr \u0026\u0026 Math.abs(saved.dpr - dprNow) \u003e 0.01){\n      dprWarn.classList.add('on');\n    }\n    renderTool();\n  }else{\n    showStep('cal');\n    setupCalStep();\n  }\n})();\n\u003c\/script\u003e\n\u003c\/body\u003e","brand":"Just Vero","offers":[{"title":"6","offer_id":56430528888998,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":false},{"title":"7","offer_id":56430528921766,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":false},{"title":"8","offer_id":46656463077542,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":true},{"title":"9","offer_id":46656463044774,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":true},{"title":"10","offer_id":46826543218854,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_2464.jpg?v=1765408134"},{"product_id":"dark-crown","title":"DARK CROWN","description":"\u003cul\u003e\n\u003cli\u003eCadena acero quirúrgico hipoalergénico, Dijes aleación baño plateado, cristales cz\u003c\/li\u003e\n\u003cli\u003eLargo 42cm regulable\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":46584410112166,"sku":null,"price":1490.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_2761_dd5db685-1e4f-46d4-b87c-10a91d718c4c.jpg?v=1755265819"},{"product_id":"relic-drop","title":"RELIC DROP","description":"\u003cul\u003e\n\u003cli\u003eCadena acero quirúrgico hipoalergénico\u003c\/li\u003e\n\u003cli\u003eDijes mix aleación y acero\u003c\/li\u003e\n\u003cli\u003eLargo 40cm regulable\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":46733846446246,"sku":null,"price":1490.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_4319.jpg?v=1759966705"},{"product_id":"fleur","title":"FLEUR","description":"\u003cbody\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eAleación con baño plateado\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eMetal resistente\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eAcabado envejecido y textura marcada\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eEvitá mojarlo o exponerlo a humedad\u003cbr\u003e\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003cmeta charset=\"UTF-8\"\u003e\n\u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003e\n\u003ctitle\u003eJUST VERO — medí tu talle de anillo\u003c\/title\u003e\n\u003cstyle\u003e\n  #jv-ring-sizer{\n    --jv-black:#111111;\n    --jv-white:#ffffff;\n    --jv-brown:#3F352B;\n    --jv-tan:#BCA08A;\n    --jv-line:#dcd6cd;\n    font-family:Helvetica, Arial, sans-serif;\n    color:var(--jv-black);\n    background:var(--jv-white);\n    max-width:520px;\n    margin:0 auto;\n    padding:24px 18px 40px;\n    line-height:1.45;\n    -webkit-text-size-adjust:100%;\n  }\n  #jv-ring-sizer *{box-sizing:border-box;}\n  #jv-ring-sizer h2{\n    font-size:15px;\n    font-weight:700;\n    letter-spacing:0.08em;\n    text-transform:uppercase;\n    margin:0 0 6px;\n  }\n  #jv-ring-sizer p{\n    font-size:13px;\n    color:var(--jv-brown);\n    margin:0 0 14px;\n  }\n  #jv-ring-sizer .step{\n    display:none;\n    border-top:1px solid var(--jv-line);\n    padding-top:20px;\n    margin-top:18px;\n  }\n  #jv-ring-sizer .step.active{display:block;}\n  #jv-ring-sizer .tag{\n    display:inline-block;\n    font-size:10px;\n    letter-spacing:0.12em;\n    text-transform:uppercase;\n    color:var(--jv-white);\n    background:var(--jv-black);\n    padding:3px 8px;\n    margin-bottom:10px;\n  }\n\n  \/* ---- calibration ---- *\/\n  #jv-ring-sizer .calarea{\n    position:relative;\n    margin:16px 0 10px;\n    min-height:120px;\n  }\n  #jv-ring-sizer .calcard{\n    position:relative;\n    border:2px solid var(--jv-black);\n    border-bottom:2px dashed var(--jv-line);\n    border-radius:6px 6px 0 0;\n    background:\n      linear-gradient(to right, rgba(188,160,138,0.10), rgba(188,160,138,0.02));\n  }\n  #jv-ring-sizer .calcard .corner{\n    position:absolute;\n    top:-2px;\n    left:-2px;\n    width:16px;\n    height:16px;\n    border-top:4px solid var(--jv-black);\n    border-left:4px solid var(--jv-black);\n  }\n  #jv-ring-sizer .calcard .cardlbl{\n    position:absolute;\n    bottom:6px;\n    left:0;\n    right:0;\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.06em;\n    text-transform:uppercase;\n    color:var(--jv-tan);\n  }\n  #jv-ring-sizer .calrow{\n    display:flex;\n    align-items:center;\n    gap:10px;\n    margin:14px 0 4px;\n  }\n  #jv-ring-sizer .calrow input[type=range]{\n    flex:1;\n    accent-color:var(--jv-black);\n    min-width:0;\n  }\n  #jv-ring-sizer .nudge{\n    width:34px;\n    min-width:34px;\n    padding:6px 0;\n    font-size:14px;\n    line-height:1;\n  }\n\n  \/* ---- buttons ---- *\/\n  #jv-ring-sizer button{\n    font-family:Helvetica, Arial, sans-serif;\n    background:var(--jv-black);\n    color:var(--jv-white);\n    border:none;\n    padding:12px 18px;\n    font-size:12px;\n    letter-spacing:0.08em;\n    text-transform:uppercase;\n    cursor:pointer;\n    width:100%;\n    margin-top:8px;\n  }\n  #jv-ring-sizer button:focus-visible{\n    outline:2px solid var(--jv-tan);\n    outline-offset:2px;\n  }\n\n  \/* ---- tabs ---- *\/\n  #jv-ring-sizer .tabs{\n    display:flex;\n    margin-bottom:16px;\n    border:1px solid var(--jv-black);\n  }\n  #jv-ring-sizer .tabs button{\n    flex:1;\n    background:var(--jv-white);\n    color:var(--jv-black);\n    margin:0;\n    padding:11px 6px;\n    font-size:11px;\n  }\n  #jv-ring-sizer .tabs button[aria-selected=\"true\"]{\n    background:var(--jv-black);\n    color:var(--jv-white);\n  }\n  #jv-ring-sizer .panel{display:none;}\n  #jv-ring-sizer .panel.on{display:block;}\n\n  \/* ---- rings ---- *\/\n  #jv-ring-sizer .rings{\n    display:grid;\n    gap:16px 10px;\n    justify-items:center;\n    margin:16px 0 4px;\n  }\n  #jv-ring-sizer .ringwrap{\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.04em;\n    text-transform:uppercase;\n    color:var(--jv-brown);\n  }\n  #jv-ring-sizer .ring{\n    border:1.5px solid var(--jv-black);\n    border-radius:50%;\n    margin:0 auto 5px;\n  }\n\n  \/* ---- vertical ruler ---- *\/\n  #jv-ring-sizer .rulerwrap{\n    position:relative;\n    margin:18px 0 8px;\n  }\n  #jv-ring-sizer .ruler{\n    position:relative;\n    border-left:2px solid var(--jv-black);\n    margin-left:2px;\n  }\n  #jv-ring-sizer .tick{\n    position:absolute;\n    left:0;\n    height:0;\n    border-top:1px solid var(--jv-brown);\n    width:5px;\n  }\n  #jv-ring-sizer .tick.mid{width:10px;}\n  #jv-ring-sizer .tick.major{\n    width:17px;\n    border-top:1.5px solid var(--jv-black);\n  }\n  #jv-ring-sizer .tick .lbl{\n    position:absolute;\n    left:21px;\n    top:-6px;\n    font-size:9px;\n    color:var(--jv-black);\n    white-space:nowrap;\n  }\n  #jv-ring-sizer .mark{\n    position:absolute;\n    left:0;\n    height:0;\n    border-top:1px dashed var(--jv-tan);\n  }\n  #jv-ring-sizer .mark .lbl{\n    position:absolute;\n    top:-6px;\n    font-size:10px;\n    color:var(--jv-brown);\n    white-space:nowrap;\n    background:var(--jv-white);\n    padding:0 3px;\n  }\n\n  \/* ---- table + notes ---- *\/\n  #jv-ring-sizer table{\n    width:100%;\n    border-collapse:collapse;\n    font-size:12px;\n    margin-top:14px;\n  }\n  #jv-ring-sizer th, #jv-ring-sizer td{\n    border-bottom:1px solid var(--jv-line);\n    padding:7px 4px;\n    text-align:center;\n  }\n  #jv-ring-sizer th{\n    text-transform:uppercase;\n    font-size:10px;\n    letter-spacing:0.06em;\n    color:var(--jv-brown);\n    font-weight:700;\n  }\n  #jv-ring-sizer .note{\n    font-size:11px;\n    color:var(--jv-tan);\n    margin:10px 0 0;\n  }\n  #jv-ring-sizer .rule-note{\n    font-size:12px;\n    color:var(--jv-black);\n    border-left:2px solid var(--jv-black);\n    padding:2px 0 2px 10px;\n    margin:16px 0 0;\n  }\n  #jv-ring-sizer .check{\n    margin:18px 0 0;\n    font-size:11px;\n    color:var(--jv-brown);\n  }\n  #jv-ring-sizer .checkbar{\n    height:8px;\n    border:1px solid var(--jv-black);\n    border-top:none;\n    margin-top:3px;\n  }\n  #jv-ring-sizer .warn{\n    font-size:12px;\n    background:#f6f2ec;\n    border-left:2px solid var(--jv-tan);\n    padding:9px 10px;\n    margin:0 0 14px;\n    color:var(--jv-brown);\n    display:none;\n  }\n  #jv-ring-sizer .warn.on{display:block;}\n  #jv-ring-sizer .recal{\n    display:block;\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.06em;\n    text-transform:uppercase;\n    text-decoration:underline;\n    color:var(--jv-brown);\n    background:none;\n    border:none;\n    width:auto;\n    margin:22px auto 0;\n    padding:6px;\n  }\n  #jv-ring-sizer .sr{\n    position:absolute;\n    width:1px;height:1px;\n    padding:0;margin:-1px;\n    overflow:hidden;\n    clip:rect(0,0,0,0);\n    white-space:nowrap;border:0;\n  }\n\u003c\/style\u003e\n\n\n\u003cdiv id=\"jv-ring-sizer\"\u003e\n\n  \u003ch2\u003emedí tu talle de anillo\u003c\/h2\u003e\n  \u003cp\u003ecalibrá la pantalla una vez. después medís desde el celular o la computadora.\u003c\/p\u003e\n\n  \u003c!-- ============ PASO 1 · CALIBRACIÓN ============ --\u003e\n  \u003cdiv class=\"step\" id=\"step-cal\"\u003e\n    \u003cspan class=\"tag\"\u003epaso 1 · calibración\u003c\/span\u003e\n    \u003cp\u003eapoyá una tarjeta sobre la pantalla — crédito, débito o la cédula. en vertical, alineada\n       con la esquina de arriba a la izquierda. movés el control hasta que el ancho del rectángulo\n       coincida con el ancho de la tarjeta.\u003c\/p\u003e\n\n    \u003cdiv class=\"calarea\" id=\"calArea\"\u003e\n      \u003cdiv class=\"calcard\" id=\"calCard\"\u003e\n        \u003cspan class=\"corner\"\u003e\u003c\/span\u003e\n        \u003cspan class=\"cardlbl\"\u003eancho de la tarjeta\u003c\/span\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"calrow\"\u003e\n      \u003cbutton class=\"nudge\" id=\"calDown\" aria-label=\"reducir el ancho\"\u003e−\u003c\/button\u003e\n      \u003cinput type=\"range\" id=\"calSlider\" aria-label=\"ajustar el ancho del rectángulo hasta que coincida con la tarjeta\"\u003e\n      \u003cbutton class=\"nudge\" id=\"calUp\" aria-label=\"aumentar el ancho\"\u003e+\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003cbutton id=\"calConfirm\"\u003econfirmar\u003c\/button\u003e\n    \u003cp class=\"note\"\u003eel zoom del navegador tiene que estar al 100%. si tenés activado el zoom de\n       accesibilidad o el modo lupa, la medida no va a dar.\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003c!-- ============ PASO 2 · HERRAMIENTA ============ --\u003e\n  \u003cdiv class=\"step\" id=\"step-tool\"\u003e\n\n    \u003cdiv class=\"warn\" id=\"dprWarn\"\u003e\n      cambió el zoom o la pantalla desde la última vez que calibraste. conviene recalibrar antes de medir.\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"tabs\" role=\"tablist\" aria-label=\"método de medición\"\u003e\n      \u003cbutton role=\"tab\" id=\"tabA\" aria-selected=\"true\" aria-controls=\"panelA\"\u003ecomparar un anillo\u003c\/button\u003e\n      \u003cbutton role=\"tab\" id=\"tabB\" aria-selected=\"false\" aria-controls=\"panelB\"\u003emedir el dedo\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- opción A --\u003e\n    \u003cdiv class=\"panel on\" id=\"panelA\" role=\"tabpanel\" aria-labelledby=\"tabA\"\u003e\n      \u003cspan class=\"tag\"\u003eopción a\u003c\/span\u003e\n      \u003cp\u003eapoyá un anillo que ya te calce bien sobre los círculos. el talle es el círculo cuyo\n         borde exterior queda justo por dentro del anillo.\u003c\/p\u003e\n      \u003cdiv class=\"rings\" id=\"ringsGrid\"\u003e\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- opción B --\u003e\n    \u003cdiv class=\"panel\" id=\"panelB\" role=\"tabpanel\" aria-labelledby=\"tabB\"\u003e\n      \u003cspan class=\"tag\"\u003eopción b\u003c\/span\u003e\n      \u003cp\u003eenvolvé una tira de papel o un hilo en la base del dedo, donde va a quedar el anillo.\n         marcá el punto donde se superpone. después estirá la tira sobre la regla, arrancando\n         desde el cero.\u003c\/p\u003e\n      \u003cdiv class=\"rulerwrap\"\u003e\n        \u003cdiv class=\"ruler\" id=\"ruler\"\u003e\u003c\/div\u003e\n      \u003c\/div\u003e\n      \u003cp class=\"note\"\u003elas líneas punteadas son la circunferencia de cada talle.\u003c\/p\u003e\n    \u003c\/div\u003e\n\n    \u003ctable\u003e\n      \u003ccaption class=\"sr\"\u003etalles disponibles con su diámetro y circunferencia\u003c\/caption\u003e\n      \u003cthead\u003e\u003ctr\u003e\n\u003cth scope=\"col\"\u003etalle\u003c\/th\u003e\n\u003cth scope=\"col\"\u003ediámetro\u003c\/th\u003e\n\u003cth scope=\"col\"\u003ecircunferencia\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n      \u003ctbody id=\"refBody\"\u003e\u003c\/tbody\u003e\n    \u003c\/table\u003e\n\n    \u003cp class=\"rule-note\"\u003esi te queda entre dos talles, elegí el mayor.\u003c\/p\u003e\n\n    \u003cdiv class=\"check\"\u003e\n      control: esta línea mide 50 mm. si tenés una regla a mano, verificá.\n      \u003cdiv class=\"checkbar\" id=\"checkBar\"\u003e\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cp class=\"note\"\u003ees una medida aproximada — sirve para orientarte, no es exacta al milímetro.\n       el dedo cambia de grosor con el calor y la hora del día.\u003c\/p\u003e\n\n    \u003cbutton class=\"recal\" id=\"recalBtn\"\u003erecalibrar pantalla\u003c\/button\u003e\n  \u003c\/div\u003e\n\n\u003c\/div\u003e\n\n\u003cscript\u003e\n(function(){\n  'use strict';\n\n  var STORAGE_KEY = 'jv_ring_sizer_cal_v2';\n\n  \/\/ ISO\/IEC 7810 ID-1 — short side. The long side (85.6mm) is wider than most\n  \/\/ phone screens, so calibration has to happen on the short side.\n  var CARD_SHORT_MM = 53.98;\n  var CARD_LONG_MM  = 85.60;\n  var CARD_MAX_H_PX = 190;\n\n  var MIN_PPM = 1.6;   \/\/ absolute plausibility floor\n  var MAX_PPM = 22;    \/\/ absolute plausibility ceiling\n  var BASE_PPM = 96 \/ 25.4;\n\n  var SIZES = [\n    {size:6,  d:16.5},\n    {size:7,  d:17.3},\n    {size:8,  d:18.1},\n    {size:9,  d:19.0},\n    {size:10, d:19.8},\n    {size:11, d:20.6}\n  ];\n  SIZES.forEach(function(s){ s.c = s.d * Math.PI; });\n\n  var RULER_MAX_MM = 72;   \/\/ clears size 11 (~64.7mm) with room to read\n\n  var root      = document.getElementById('jv-ring-sizer');\n  var stepCal   = root.querySelector('#step-cal');\n  var stepTool  = root.querySelector('#step-tool');\n  var calArea   = root.querySelector('#calArea');\n  var calCard   = root.querySelector('#calCard');\n  var calSlider = root.querySelector('#calSlider');\n  var calUp     = root.querySelector('#calUp');\n  var calDown   = root.querySelector('#calDown');\n  var calConfirm= root.querySelector('#calConfirm');\n  var recalBtn  = root.querySelector('#recalBtn');\n  var dprWarn   = root.querySelector('#dprWarn');\n  var tabA      = root.querySelector('#tabA');\n  var tabB      = root.querySelector('#tabB');\n  var panelA    = root.querySelector('#panelA');\n  var panelB    = root.querySelector('#panelB');\n  var ringsGrid = root.querySelector('#ringsGrid');\n  var ruler     = root.querySelector('#ruler');\n  var refBody   = root.querySelector('#refBody');\n  var checkBar  = root.querySelector('#checkBar');\n\n  var pxPerMm = null;\n\n  \/* ---------- storage (may throw in partitioned\/blocked contexts) ---------- *\/\n  function readCal(){\n    try{\n      var raw = window.localStorage.getItem(STORAGE_KEY);\n      if(!raw) return null;\n      var o = JSON.parse(raw);\n      var p = parseFloat(o \u0026\u0026 o.ppm);\n      if(!isFinite(p) || p \u003c MIN_PPM || p \u003e MAX_PPM) return null;\n      return {ppm:p, dpr:parseFloat(o.dpr) || null};\n    }catch(e){ return null; }\n  }\n  function writeCal(ppm){\n    try{\n      window.localStorage.setItem(STORAGE_KEY, JSON.stringify({\n        ppm:ppm, dpr:window.devicePixelRatio || 1, ts:Date.now()\n      }));\n    }catch(e){ \/* sin persistencia: la calibración vale para esta sesión *\/ }\n  }\n  function clearCal(){\n    try{ window.localStorage.removeItem(STORAGE_KEY); }catch(e){}\n  }\n\n  \/* ---------- available width ---------- *\/\n  function availWidth(){\n    var w = calArea.clientWidth || root.clientWidth || 320;\n    return Math.max(120, w);\n  }\n\n  \/* ---------- calibration step ---------- *\/\n  function sliderBounds(){\n    \/\/ Cap so the calibration rectangle can never overflow its container.\n    var maxPpm = availWidth() \/ CARD_SHORT_MM;\n    var minPpm = MIN_PPM;\n    if(maxPpm \u003c minPpm + 0.5) maxPpm = minPpm + 0.5;\n    return {min:minPpm, max:maxPpm};\n  }\n\n  function drawCalCard(ppm){\n    var w = CARD_SHORT_MM * ppm;\n    var h = Math.min(CARD_LONG_MM * ppm, CARD_MAX_H_PX);\n    calCard.style.width  = w + 'px';\n    calCard.style.height = h + 'px';\n  }\n\n  function setupCalStep(){\n    var b = sliderBounds();\n    var current = parseFloat(calSlider.value);\n    var start = (isFinite(current) \u0026\u0026 current \u003e= b.min \u0026\u0026 current \u003c= b.max)\n      ? current\n      : Math.min(Math.max(pxPerMm || BASE_PPM, b.min), b.max);\n\n    calSlider.min = b.min.toFixed(3);\n    calSlider.max = b.max.toFixed(3);\n    calSlider.step = '0.005';\n    calSlider.value = start;\n    drawCalCard(start);\n  }\n\n  function nudge(delta){\n    var b = sliderBounds();\n    var v = Math.min(Math.max(parseFloat(calSlider.value) + delta, b.min), b.max);\n    calSlider.value = v;\n    drawCalCard(v);\n  }\n\n  calSlider.addEventListener('input', function(){\n    drawCalCard(parseFloat(calSlider.value));\n  });\n  calUp.addEventListener('click',   function(){ nudge(0.02); });\n  calDown.addEventListener('click', function(){ nudge(-0.02); });\n\n  calConfirm.addEventListener('click', function(){\n    var v = parseFloat(calSlider.value);\n    if(!isFinite(v) || v \u003c MIN_PPM || v \u003e MAX_PPM) return;\n    pxPerMm = v;\n    writeCal(pxPerMm);\n    dprWarn.classList.remove('on');\n    renderTool();\n    stepTool.scrollIntoView({block:'start'});\n  });\n\n  recalBtn.addEventListener('click', function(){\n    clearCal();\n    showStep('cal');\n    setupCalStep();\n    stepCal.scrollIntoView({block:'start'});\n  });\n\n  \/* ---------- tabs ---------- *\/\n  function switchTab(which){\n    var isA = (which === 'A');\n    tabA.setAttribute('aria-selected', isA ? 'true' : 'false');\n    tabB.setAttribute('aria-selected', isA ? 'false' : 'true');\n    panelA.classList.toggle('on', isA);\n    panelB.classList.toggle('on', !isA);\n  }\n  tabA.addEventListener('click', function(){ switchTab('A'); });\n  tabB.addEventListener('click', function(){ switchTab('B'); });\n  [tabA, tabB].forEach(function(t){\n    t.addEventListener('keydown', function(e){\n      if(e.key === 'ArrowRight'){ switchTab('B'); tabB.focus(); }\n      if(e.key === 'ArrowLeft'){ switchTab('A'); tabA.focus(); }\n    });\n  });\n\n  function showStep(which){\n    stepCal.classList.toggle('active', which === 'cal');\n    stepTool.classList.toggle('active', which === 'tool');\n  }\n\n  \/* ---------- render: rings ---------- *\/\n  function renderRings(){\n    ringsGrid.innerHTML = '';\n    var maxPx = 0;\n    SIZES.forEach(function(s){ maxPx = Math.max(maxPx, s.d * pxPerMm); });\n\n    \/\/ Columns must fit the largest circle, otherwise rings overflow their cell.\n    var avail = availWidth();\n    var cols = Math.max(1, Math.floor((avail + 10) \/ (maxPx + 10)));\n    cols = Math.min(cols, SIZES.length);\n    ringsGrid.style.gridTemplateColumns = 'repeat(' + cols + ', 1fr)';\n\n    SIZES.forEach(function(s){\n      var px = s.d * pxPerMm;\n      var wrap = document.createElement('div');\n      wrap.className = 'ringwrap';\n      var ring = document.createElement('div');\n      ring.className = 'ring';\n      ring.style.width  = px + 'px';\n      ring.style.height = px + 'px';\n      wrap.appendChild(ring);\n      wrap.appendChild(document.createTextNode('talle ' + s.size));\n      ringsGrid.appendChild(wrap);\n    });\n  }\n\n  \/* ---------- render: vertical ruler ---------- *\/\n  function renderRuler(){\n    ruler.innerHTML = '';\n    ruler.style.height = (RULER_MAX_MM * pxPerMm) + 'px';\n\n    for(var mm = 0; mm \u003c= RULER_MAX_MM; mm++){\n      var tick = document.createElement('div');\n      var cls = 'tick';\n      if(mm % 10 === 0) cls += ' major';\n      else if(mm % 5 === 0) cls += ' mid';\n      tick.className = cls;\n      tick.style.top = (mm * pxPerMm) + 'px';\n      if(mm % 10 === 0){\n        var lbl = document.createElement('span');\n        lbl.className = 'lbl';\n        lbl.textContent = mm + ' mm';\n        tick.appendChild(lbl);\n      }\n      ruler.appendChild(tick);\n    }\n\n    \/\/ Size marks stagger across two columns: consecutive sizes are ~2.5mm apart,\n    \/\/ which is under 10px on a low-density screen — too tight for one column.\n    var cols = [86, 210];\n    SIZES.forEach(function(s, i){\n      var mark = document.createElement('div');\n      mark.className = 'mark';\n      mark.style.top = (s.c * pxPerMm) + 'px';\n      mark.style.width = (cols[i % 2] + 60) + 'px';\n      var lbl = document.createElement('span');\n      lbl.className = 'lbl';\n      lbl.style.left = cols[i % 2] + 'px';\n      lbl.textContent = 'talle ' + s.size + ' · ' + fmt(s.c) + ' mm';\n      mark.appendChild(lbl);\n      ruler.appendChild(mark);\n    });\n  }\n\n  \/* ---------- render: table + check bar ---------- *\/\n  function fmt(n){ return n.toFixed(1).replace('.', ','); }\n\n  function renderTable(){\n    refBody.innerHTML = '';\n    SIZES.forEach(function(s){\n      var tr = document.createElement('tr');\n      var cells = [String(s.size), fmt(s.d) + ' mm', fmt(s.c) + ' mm'];\n      cells.forEach(function(txt){\n        var td = document.createElement('td');\n        td.textContent = txt;\n        tr.appendChild(td);\n      });\n      refBody.appendChild(tr);\n    });\n  }\n\n  function renderCheck(){\n    checkBar.style.width = (50 * pxPerMm) + 'px';\n  }\n\n  function renderTool(){\n    renderRings();\n    renderRuler();\n    renderTable();\n    renderCheck();\n    showStep('tool');\n  }\n\n  \/* ---------- resize \/ orientation ---------- *\/\n  var rt;\n  window.addEventListener('resize', function(){\n    clearTimeout(rt);\n    rt = setTimeout(function(){\n      if(stepCal.classList.contains('active')) setupCalStep();\n      else if(pxPerMm) renderRings();\n    }, 150);\n  });\n\n  \/* ---------- init ---------- *\/\n  var saved = readCal();\n  if(saved){\n    pxPerMm = saved.ppm;\n    \/\/ A changed devicePixelRatio usually means the browser zoom changed,\n    \/\/ which invalidates the stored calibration.\n    var dprNow = window.devicePixelRatio || 1;\n    if(saved.dpr \u0026\u0026 Math.abs(saved.dpr - dprNow) \u003e 0.01){\n      dprWarn.classList.add('on');\n    }\n    renderTool();\n  }else{\n    showStep('cal');\n    setupCalStep();\n  }\n})();\n\u003c\/script\u003e\n\u003c\/body\u003e","brand":"Just Vero","offers":[{"title":"8","offer_id":46806453059750,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":true},{"title":"9","offer_id":46806453092518,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/E2C93677-DAF0-48A0-A3B7-43FAAEE73430.jpg?v=1766017237"},{"product_id":"chaos-spell","title":"CHAOS SPELL","description":"\u003cp\u003eMateriales:\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eCadenas acero quirúrgico hipoalergénico\u003c\/li\u003e\n\u003cli\u003eCharms mixtos de aleación y acero\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":55964657615014,"sku":null,"price":1790.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_6180.jpg?v=1764287907"},{"product_id":"star-hook-crush","title":"STAR HOOK CRUSH","description":"\u003cp\u003eCadena de pantalón con cristales incrustados en aros entrelazados y dijes de estrella\u003cbr\u003e\u003cbr\u003eMateriales:\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eCadenas acero quirúrgico\u003c\/li\u003e\n\u003cli\u003eCristales checos\u003c\/li\u003e\n\u003cli\u003eDijes acero y aleación\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":55965852860582,"sku":null,"price":1890.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/292B9B6A-42C0-433E-ADD6-EE8288EC8996.jpg?v=1764294351"},{"product_id":"basic-steel-stack","title":"Basic Steel Set","description":"\u003cul\u003e\n\u003cli\u003eCadenas acero quirúrgico inoxidable \u003c\/li\u003e\n\u003cli\u003ePerlas plateadas de hematita\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":56320521830566,"sku":null,"price":1990.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/9C12EECD-0568-4C5D-8960-4EF8E0E769C9.jpg?v=1774381798"},{"product_id":"pinned-emotion","title":"PINNED EMOTION","description":"\u003cul\u003e\n\u003cli\u003eCadena regulable de acero inoxidable\u003c\/li\u003e\n\u003cli\u003ePiercings acero \u003c\/li\u003e\n\u003cli\u003eCorazón en aleación\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":56335039824038,"sku":null,"price":1550.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_1447_JPG.jpg?v=1774972752"},{"product_id":"crystal-heart-chaos","title":"CRYSTAL HEART CHAOS","description":"\u003cul\u003e\n\u003cli\u003eGargantilla choker combinada\u003c\/li\u003e\n\u003cli\u003e5 strands distintos\u003c\/li\u003e\n\u003cli\u003ePerlas hematite\u003c\/li\u003e\n\u003cli\u003ePerlas esmaltada\u003c\/li\u003e\n\u003cli\u003eCadenas acero quirúrgico\u003c\/li\u003e\n\u003cli\u003eDijes aleación y acero quirúrgico\u003c\/li\u003e\n\u003cli\u003eCorazón de cristal transparente\u003c\/li\u003e\n\u003cli\u003eLargo 40cm \/\/ 10cm cadena regulable\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":56407512645798,"sku":null,"price":1790.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_2638_JPG.jpg?v=1776917961"},{"product_id":"midnight-devotion","title":"Midnight Devotion","description":"\u003cp\u003eSet dos collares rosario y choker\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eCadena regulable de acero quirúrgico inoxidable\u003c\/li\u003e\n\u003cli\u003ePerlas de vidrio esmaltadas matte\u003c\/li\u003e\n\u003cli\u003eDijes en aleación y acero\u003c\/li\u003e\n\u003cli\u003eLargo choker 45cm regulable \/\/ Largo rosario 70cm regulable \u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"con brillos","offer_id":56408326111398,"sku":null,"price":1990.0,"currency_code":"UYU","in_stock":false},{"title":"acero básica","offer_id":56408326144166,"sku":null,"price":1990.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_2588_JPG_4a3dadf5-63da-4554-a11d-85a35a4ae1c8.jpg?v=1776928564"},{"product_id":"sacred-ornate","title":"SACRED ORNATE","description":"\u003cul data-end=\"424\" data-start=\"180\"\u003e\n\u003cli data-end=\"210\" data-start=\"180\"\u003e\n\u003cp data-end=\"210\" data-start=\"182\"\u003eDije en Aleación de 60% Cobre y 30% Zinc con un 10% de Acabado Metálico de alta resistencia.\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli data-end=\"210\" data-start=\"180\"\u003e\n\u003cp data-end=\"210\" data-start=\"182\"\u003eCadena acero inoxidable\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli data-end=\"288\" data-start=\"248\"\u003e\n\u003cp data-end=\"288\" data-start=\"250\"\u003eAcabado envejecido y textura marcada\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli data-end=\"296\" data-start=\"257\"\u003e\n\u003cp data-end=\"296\" data-start=\"259\"\u003eEvita mojarlo o exponerlo a humedad\u003c\/p\u003e\n\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"Gruesa","offer_id":56430482718886,"sku":null,"price":1990.0,"currency_code":"UYU","in_stock":true},{"title":"Fina","offer_id":56430482751654,"sku":null,"price":1990.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_3101_JPG.jpg?v=1777533825"},{"product_id":"sacred-seal","title":"SACRED SEAL","description":"\u003cul data-end=\"424\" data-start=\"180\"\u003e\n\u003cli data-end=\"210\" data-start=\"180\"\u003e\n\u003cp data-end=\"210\" data-start=\"182\"\u003eDije en Aleación de 60% Cobre y 30% Zinc con un 10% de Acabado Metálico de alta resistencia.\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli data-end=\"210\" data-start=\"180\"\u003e\n\u003cp data-end=\"210\" data-start=\"182\"\u003eCadena acero inoxidable\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli data-end=\"288\" data-start=\"248\"\u003e\n\u003cp data-end=\"288\" data-start=\"250\"\u003eAcabado envejecido y textura marcada\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli data-end=\"296\" data-start=\"257\"\u003e\n\u003cp data-end=\"296\" data-start=\"259\"\u003eEvita mojarlo o exponerlo a humedad\u003c\/p\u003e\n\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":56430486290598,"sku":null,"price":1990.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_3113_JPG.jpg?v=1777533952"},{"product_id":"sacred-petal","title":"SACRED PETAL","description":"\u003cbody\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eAleación de 60% Cobre y 30% Zinc con un 10% de Acabado Metálico de alta resistencia.\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eAcabado envejecido y textura marcada\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eEvitá mojarlo o exponerlo a humedad\u003cbr\u003e\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003cmeta charset=\"UTF-8\"\u003e\n\u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003e\n\u003ctitle\u003eJUST VERO — medí tu talle de anillo\u003c\/title\u003e\n\u003cstyle\u003e\n  #jv-ring-sizer{\n    --jv-black:#111111;\n    --jv-white:#ffffff;\n    --jv-brown:#3F352B;\n    --jv-tan:#BCA08A;\n    --jv-line:#dcd6cd;\n    font-family:Helvetica, Arial, sans-serif;\n    color:var(--jv-black);\n    background:var(--jv-white);\n    max-width:520px;\n    margin:0 auto;\n    padding:24px 18px 40px;\n    line-height:1.45;\n    -webkit-text-size-adjust:100%;\n  }\n  #jv-ring-sizer *{box-sizing:border-box;}\n  #jv-ring-sizer h2{\n    font-size:15px;\n    font-weight:700;\n    letter-spacing:0.08em;\n    text-transform:uppercase;\n    margin:0 0 6px;\n  }\n  #jv-ring-sizer p{\n    font-size:13px;\n    color:var(--jv-brown);\n    margin:0 0 14px;\n  }\n  #jv-ring-sizer .step{\n    display:none;\n    border-top:1px solid var(--jv-line);\n    padding-top:20px;\n    margin-top:18px;\n  }\n  #jv-ring-sizer .step.active{display:block;}\n  #jv-ring-sizer .tag{\n    display:inline-block;\n    font-size:10px;\n    letter-spacing:0.12em;\n    text-transform:uppercase;\n    color:var(--jv-white);\n    background:var(--jv-black);\n    padding:3px 8px;\n    margin-bottom:10px;\n  }\n\n  \/* ---- calibration ---- *\/\n  #jv-ring-sizer .calarea{\n    position:relative;\n    margin:16px 0 10px;\n    min-height:120px;\n  }\n  #jv-ring-sizer .calcard{\n    position:relative;\n    border:2px solid var(--jv-black);\n    border-bottom:2px dashed var(--jv-line);\n    border-radius:6px 6px 0 0;\n    background:\n      linear-gradient(to right, rgba(188,160,138,0.10), rgba(188,160,138,0.02));\n  }\n  #jv-ring-sizer .calcard .corner{\n    position:absolute;\n    top:-2px;\n    left:-2px;\n    width:16px;\n    height:16px;\n    border-top:4px solid var(--jv-black);\n    border-left:4px solid var(--jv-black);\n  }\n  #jv-ring-sizer .calcard .cardlbl{\n    position:absolute;\n    bottom:6px;\n    left:0;\n    right:0;\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.06em;\n    text-transform:uppercase;\n    color:var(--jv-tan);\n  }\n  #jv-ring-sizer .calrow{\n    display:flex;\n    align-items:center;\n    gap:10px;\n    margin:14px 0 4px;\n  }\n  #jv-ring-sizer .calrow input[type=range]{\n    flex:1;\n    accent-color:var(--jv-black);\n    min-width:0;\n  }\n  #jv-ring-sizer .nudge{\n    width:34px;\n    min-width:34px;\n    padding:6px 0;\n    font-size:14px;\n    line-height:1;\n  }\n\n  \/* ---- buttons ---- *\/\n  #jv-ring-sizer button{\n    font-family:Helvetica, Arial, sans-serif;\n    background:var(--jv-black);\n    color:var(--jv-white);\n    border:none;\n    padding:12px 18px;\n    font-size:12px;\n    letter-spacing:0.08em;\n    text-transform:uppercase;\n    cursor:pointer;\n    width:100%;\n    margin-top:8px;\n  }\n  #jv-ring-sizer button:focus-visible{\n    outline:2px solid var(--jv-tan);\n    outline-offset:2px;\n  }\n\n  \/* ---- tabs ---- *\/\n  #jv-ring-sizer .tabs{\n    display:flex;\n    margin-bottom:16px;\n    border:1px solid var(--jv-black);\n  }\n  #jv-ring-sizer .tabs button{\n    flex:1;\n    background:var(--jv-white);\n    color:var(--jv-black);\n    margin:0;\n    padding:11px 6px;\n    font-size:11px;\n  }\n  #jv-ring-sizer .tabs button[aria-selected=\"true\"]{\n    background:var(--jv-black);\n    color:var(--jv-white);\n  }\n  #jv-ring-sizer .panel{display:none;}\n  #jv-ring-sizer .panel.on{display:block;}\n\n  \/* ---- rings ---- *\/\n  #jv-ring-sizer .rings{\n    display:grid;\n    gap:16px 10px;\n    justify-items:center;\n    margin:16px 0 4px;\n  }\n  #jv-ring-sizer .ringwrap{\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.04em;\n    text-transform:uppercase;\n    color:var(--jv-brown);\n  }\n  #jv-ring-sizer .ring{\n    border:1.5px solid var(--jv-black);\n    border-radius:50%;\n    margin:0 auto 5px;\n  }\n\n  \/* ---- vertical ruler ---- *\/\n  #jv-ring-sizer .rulerwrap{\n    position:relative;\n    margin:18px 0 8px;\n  }\n  #jv-ring-sizer .ruler{\n    position:relative;\n    border-left:2px solid var(--jv-black);\n    margin-left:2px;\n  }\n  #jv-ring-sizer .tick{\n    position:absolute;\n    left:0;\n    height:0;\n    border-top:1px solid var(--jv-brown);\n    width:5px;\n  }\n  #jv-ring-sizer .tick.mid{width:10px;}\n  #jv-ring-sizer .tick.major{\n    width:17px;\n    border-top:1.5px solid var(--jv-black);\n  }\n  #jv-ring-sizer .tick .lbl{\n    position:absolute;\n    left:21px;\n    top:-6px;\n    font-size:9px;\n    color:var(--jv-black);\n    white-space:nowrap;\n  }\n  #jv-ring-sizer .mark{\n    position:absolute;\n    left:0;\n    height:0;\n    border-top:1px dashed var(--jv-tan);\n  }\n  #jv-ring-sizer .mark .lbl{\n    position:absolute;\n    top:-6px;\n    font-size:10px;\n    color:var(--jv-brown);\n    white-space:nowrap;\n    background:var(--jv-white);\n    padding:0 3px;\n  }\n\n  \/* ---- table + notes ---- *\/\n  #jv-ring-sizer table{\n    width:100%;\n    border-collapse:collapse;\n    font-size:12px;\n    margin-top:14px;\n  }\n  #jv-ring-sizer th, #jv-ring-sizer td{\n    border-bottom:1px solid var(--jv-line);\n    padding:7px 4px;\n    text-align:center;\n  }\n  #jv-ring-sizer th{\n    text-transform:uppercase;\n    font-size:10px;\n    letter-spacing:0.06em;\n    color:var(--jv-brown);\n    font-weight:700;\n  }\n  #jv-ring-sizer .note{\n    font-size:11px;\n    color:var(--jv-tan);\n    margin:10px 0 0;\n  }\n  #jv-ring-sizer .rule-note{\n    font-size:12px;\n    color:var(--jv-black);\n    border-left:2px solid var(--jv-black);\n    padding:2px 0 2px 10px;\n    margin:16px 0 0;\n  }\n  #jv-ring-sizer .check{\n    margin:18px 0 0;\n    font-size:11px;\n    color:var(--jv-brown);\n  }\n  #jv-ring-sizer .checkbar{\n    height:8px;\n    border:1px solid var(--jv-black);\n    border-top:none;\n    margin-top:3px;\n  }\n  #jv-ring-sizer .warn{\n    font-size:12px;\n    background:#f6f2ec;\n    border-left:2px solid var(--jv-tan);\n    padding:9px 10px;\n    margin:0 0 14px;\n    color:var(--jv-brown);\n    display:none;\n  }\n  #jv-ring-sizer .warn.on{display:block;}\n  #jv-ring-sizer .recal{\n    display:block;\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.06em;\n    text-transform:uppercase;\n    text-decoration:underline;\n    color:var(--jv-brown);\n    background:none;\n    border:none;\n    width:auto;\n    margin:22px auto 0;\n    padding:6px;\n  }\n  #jv-ring-sizer .sr{\n    position:absolute;\n    width:1px;height:1px;\n    padding:0;margin:-1px;\n    overflow:hidden;\n    clip:rect(0,0,0,0);\n    white-space:nowrap;border:0;\n  }\n\u003c\/style\u003e\n\n\n\u003cdiv id=\"jv-ring-sizer\"\u003e\n\n  \u003ch2\u003emedí tu talle de anillo\u003c\/h2\u003e\n  \u003cp\u003ecalibrá la pantalla una vez. después medís desde el celular o la computadora.\u003c\/p\u003e\n\n  \u003c!-- ============ PASO 1 · CALIBRACIÓN ============ --\u003e\n  \u003cdiv class=\"step\" id=\"step-cal\"\u003e\n    \u003cspan class=\"tag\"\u003epaso 1 · calibración\u003c\/span\u003e\n    \u003cp\u003eapoyá una tarjeta sobre la pantalla — crédito, débito o la cédula. en vertical, alineada\n       con la esquina de arriba a la izquierda. movés el control hasta que el ancho del rectángulo\n       coincida con el ancho de la tarjeta.\u003c\/p\u003e\n\n    \u003cdiv class=\"calarea\" id=\"calArea\"\u003e\n      \u003cdiv class=\"calcard\" id=\"calCard\"\u003e\n        \u003cspan class=\"corner\"\u003e\u003c\/span\u003e\n        \u003cspan class=\"cardlbl\"\u003eancho de la tarjeta\u003c\/span\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"calrow\"\u003e\n      \u003cbutton class=\"nudge\" id=\"calDown\" aria-label=\"reducir el ancho\"\u003e−\u003c\/button\u003e\n      \u003cinput type=\"range\" id=\"calSlider\" aria-label=\"ajustar el ancho del rectángulo hasta que coincida con la tarjeta\"\u003e\n      \u003cbutton class=\"nudge\" id=\"calUp\" aria-label=\"aumentar el ancho\"\u003e+\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003cbutton id=\"calConfirm\"\u003econfirmar\u003c\/button\u003e\n    \u003cp class=\"note\"\u003eel zoom del navegador tiene que estar al 100%. si tenés activado el zoom de\n       accesibilidad o el modo lupa, la medida no va a dar.\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003c!-- ============ PASO 2 · HERRAMIENTA ============ --\u003e\n  \u003cdiv class=\"step\" id=\"step-tool\"\u003e\n\n    \u003cdiv class=\"warn\" id=\"dprWarn\"\u003e\n      cambió el zoom o la pantalla desde la última vez que calibraste. conviene recalibrar antes de medir.\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"tabs\" role=\"tablist\" aria-label=\"método de medición\"\u003e\n      \u003cbutton role=\"tab\" id=\"tabA\" aria-selected=\"true\" aria-controls=\"panelA\"\u003ecomparar un anillo\u003c\/button\u003e\n      \u003cbutton role=\"tab\" id=\"tabB\" aria-selected=\"false\" aria-controls=\"panelB\"\u003emedir el dedo\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- opción A --\u003e\n    \u003cdiv class=\"panel on\" id=\"panelA\" role=\"tabpanel\" aria-labelledby=\"tabA\"\u003e\n      \u003cspan class=\"tag\"\u003eopción a\u003c\/span\u003e\n      \u003cp\u003eapoyá un anillo que ya te calce bien sobre los círculos. el talle es el círculo cuyo\n         borde exterior queda justo por dentro del anillo.\u003c\/p\u003e\n      \u003cdiv class=\"rings\" id=\"ringsGrid\"\u003e\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- opción B --\u003e\n    \u003cdiv class=\"panel\" id=\"panelB\" role=\"tabpanel\" aria-labelledby=\"tabB\"\u003e\n      \u003cspan class=\"tag\"\u003eopción b\u003c\/span\u003e\n      \u003cp\u003eenvolvé una tira de papel o un hilo en la base del dedo, donde va a quedar el anillo.\n         marcá el punto donde se superpone. después estirá la tira sobre la regla, arrancando\n         desde el cero.\u003c\/p\u003e\n      \u003cdiv class=\"rulerwrap\"\u003e\n        \u003cdiv class=\"ruler\" id=\"ruler\"\u003e\u003c\/div\u003e\n      \u003c\/div\u003e\n      \u003cp class=\"note\"\u003elas líneas punteadas son la circunferencia de cada talle.\u003c\/p\u003e\n    \u003c\/div\u003e\n\n    \u003ctable\u003e\n      \u003ccaption class=\"sr\"\u003etalles disponibles con su diámetro y circunferencia\u003c\/caption\u003e\n      \u003cthead\u003e\u003ctr\u003e\n\u003cth scope=\"col\"\u003etalle\u003c\/th\u003e\n\u003cth scope=\"col\"\u003ediámetro\u003c\/th\u003e\n\u003cth scope=\"col\"\u003ecircunferencia\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n      \u003ctbody id=\"refBody\"\u003e\u003c\/tbody\u003e\n    \u003c\/table\u003e\n\n    \u003cp class=\"rule-note\"\u003esi te queda entre dos talles, elegí el mayor.\u003c\/p\u003e\n\n    \u003cdiv class=\"check\"\u003e\n      control: esta línea mide 50 mm. si tenés una regla a mano, verificá.\n      \u003cdiv class=\"checkbar\" id=\"checkBar\"\u003e\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cp class=\"note\"\u003ees una medida aproximada — sirve para orientarte, no es exacta al milímetro.\n       el dedo cambia de grosor con el calor y la hora del día.\u003c\/p\u003e\n\n    \u003cbutton class=\"recal\" id=\"recalBtn\"\u003erecalibrar pantalla\u003c\/button\u003e\n  \u003c\/div\u003e\n\n\u003c\/div\u003e\n\n\u003cscript\u003e\n(function(){\n  'use strict';\n\n  var STORAGE_KEY = 'jv_ring_sizer_cal_v2';\n\n  \/\/ ISO\/IEC 7810 ID-1 — short side. The long side (85.6mm) is wider than most\n  \/\/ phone screens, so calibration has to happen on the short side.\n  var CARD_SHORT_MM = 53.98;\n  var CARD_LONG_MM  = 85.60;\n  var CARD_MAX_H_PX = 190;\n\n  var MIN_PPM = 1.6;   \/\/ absolute plausibility floor\n  var MAX_PPM = 22;    \/\/ absolute plausibility ceiling\n  var BASE_PPM = 96 \/ 25.4;\n\n  var SIZES = [\n    {size:6,  d:16.5},\n    {size:7,  d:17.3},\n    {size:8,  d:18.1},\n    {size:9,  d:19.0},\n    {size:10, d:19.8},\n    {size:11, d:20.6}\n  ];\n  SIZES.forEach(function(s){ s.c = s.d * Math.PI; });\n\n  var RULER_MAX_MM = 72;   \/\/ clears size 11 (~64.7mm) with room to read\n\n  var root      = document.getElementById('jv-ring-sizer');\n  var stepCal   = root.querySelector('#step-cal');\n  var stepTool  = root.querySelector('#step-tool');\n  var calArea   = root.querySelector('#calArea');\n  var calCard   = root.querySelector('#calCard');\n  var calSlider = root.querySelector('#calSlider');\n  var calUp     = root.querySelector('#calUp');\n  var calDown   = root.querySelector('#calDown');\n  var calConfirm= root.querySelector('#calConfirm');\n  var recalBtn  = root.querySelector('#recalBtn');\n  var dprWarn   = root.querySelector('#dprWarn');\n  var tabA      = root.querySelector('#tabA');\n  var tabB      = root.querySelector('#tabB');\n  var panelA    = root.querySelector('#panelA');\n  var panelB    = root.querySelector('#panelB');\n  var ringsGrid = root.querySelector('#ringsGrid');\n  var ruler     = root.querySelector('#ruler');\n  var refBody   = root.querySelector('#refBody');\n  var checkBar  = root.querySelector('#checkBar');\n\n  var pxPerMm = null;\n\n  \/* ---------- storage (may throw in partitioned\/blocked contexts) ---------- *\/\n  function readCal(){\n    try{\n      var raw = window.localStorage.getItem(STORAGE_KEY);\n      if(!raw) return null;\n      var o = JSON.parse(raw);\n      var p = parseFloat(o \u0026\u0026 o.ppm);\n      if(!isFinite(p) || p \u003c MIN_PPM || p \u003e MAX_PPM) return null;\n      return {ppm:p, dpr:parseFloat(o.dpr) || null};\n    }catch(e){ return null; }\n  }\n  function writeCal(ppm){\n    try{\n      window.localStorage.setItem(STORAGE_KEY, JSON.stringify({\n        ppm:ppm, dpr:window.devicePixelRatio || 1, ts:Date.now()\n      }));\n    }catch(e){ \/* sin persistencia: la calibración vale para esta sesión *\/ }\n  }\n  function clearCal(){\n    try{ window.localStorage.removeItem(STORAGE_KEY); }catch(e){}\n  }\n\n  \/* ---------- available width ---------- *\/\n  function availWidth(){\n    var w = calArea.clientWidth || root.clientWidth || 320;\n    return Math.max(120, w);\n  }\n\n  \/* ---------- calibration step ---------- *\/\n  function sliderBounds(){\n    \/\/ Cap so the calibration rectangle can never overflow its container.\n    var maxPpm = availWidth() \/ CARD_SHORT_MM;\n    var minPpm = MIN_PPM;\n    if(maxPpm \u003c minPpm + 0.5) maxPpm = minPpm + 0.5;\n    return {min:minPpm, max:maxPpm};\n  }\n\n  function drawCalCard(ppm){\n    var w = CARD_SHORT_MM * ppm;\n    var h = Math.min(CARD_LONG_MM * ppm, CARD_MAX_H_PX);\n    calCard.style.width  = w + 'px';\n    calCard.style.height = h + 'px';\n  }\n\n  function setupCalStep(){\n    var b = sliderBounds();\n    var current = parseFloat(calSlider.value);\n    var start = (isFinite(current) \u0026\u0026 current \u003e= b.min \u0026\u0026 current \u003c= b.max)\n      ? current\n      : Math.min(Math.max(pxPerMm || BASE_PPM, b.min), b.max);\n\n    calSlider.min = b.min.toFixed(3);\n    calSlider.max = b.max.toFixed(3);\n    calSlider.step = '0.005';\n    calSlider.value = start;\n    drawCalCard(start);\n  }\n\n  function nudge(delta){\n    var b = sliderBounds();\n    var v = Math.min(Math.max(parseFloat(calSlider.value) + delta, b.min), b.max);\n    calSlider.value = v;\n    drawCalCard(v);\n  }\n\n  calSlider.addEventListener('input', function(){\n    drawCalCard(parseFloat(calSlider.value));\n  });\n  calUp.addEventListener('click',   function(){ nudge(0.02); });\n  calDown.addEventListener('click', function(){ nudge(-0.02); });\n\n  calConfirm.addEventListener('click', function(){\n    var v = parseFloat(calSlider.value);\n    if(!isFinite(v) || v \u003c MIN_PPM || v \u003e MAX_PPM) return;\n    pxPerMm = v;\n    writeCal(pxPerMm);\n    dprWarn.classList.remove('on');\n    renderTool();\n    stepTool.scrollIntoView({block:'start'});\n  });\n\n  recalBtn.addEventListener('click', function(){\n    clearCal();\n    showStep('cal');\n    setupCalStep();\n    stepCal.scrollIntoView({block:'start'});\n  });\n\n  \/* ---------- tabs ---------- *\/\n  function switchTab(which){\n    var isA = (which === 'A');\n    tabA.setAttribute('aria-selected', isA ? 'true' : 'false');\n    tabB.setAttribute('aria-selected', isA ? 'false' : 'true');\n    panelA.classList.toggle('on', isA);\n    panelB.classList.toggle('on', !isA);\n  }\n  tabA.addEventListener('click', function(){ switchTab('A'); });\n  tabB.addEventListener('click', function(){ switchTab('B'); });\n  [tabA, tabB].forEach(function(t){\n    t.addEventListener('keydown', function(e){\n      if(e.key === 'ArrowRight'){ switchTab('B'); tabB.focus(); }\n      if(e.key === 'ArrowLeft'){ switchTab('A'); tabA.focus(); }\n    });\n  });\n\n  function showStep(which){\n    stepCal.classList.toggle('active', which === 'cal');\n    stepTool.classList.toggle('active', which === 'tool');\n  }\n\n  \/* ---------- render: rings ---------- *\/\n  function renderRings(){\n    ringsGrid.innerHTML = '';\n    var maxPx = 0;\n    SIZES.forEach(function(s){ maxPx = Math.max(maxPx, s.d * pxPerMm); });\n\n    \/\/ Columns must fit the largest circle, otherwise rings overflow their cell.\n    var avail = availWidth();\n    var cols = Math.max(1, Math.floor((avail + 10) \/ (maxPx + 10)));\n    cols = Math.min(cols, SIZES.length);\n    ringsGrid.style.gridTemplateColumns = 'repeat(' + cols + ', 1fr)';\n\n    SIZES.forEach(function(s){\n      var px = s.d * pxPerMm;\n      var wrap = document.createElement('div');\n      wrap.className = 'ringwrap';\n      var ring = document.createElement('div');\n      ring.className = 'ring';\n      ring.style.width  = px + 'px';\n      ring.style.height = px + 'px';\n      wrap.appendChild(ring);\n      wrap.appendChild(document.createTextNode('talle ' + s.size));\n      ringsGrid.appendChild(wrap);\n    });\n  }\n\n  \/* ---------- render: vertical ruler ---------- *\/\n  function renderRuler(){\n    ruler.innerHTML = '';\n    ruler.style.height = (RULER_MAX_MM * pxPerMm) + 'px';\n\n    for(var mm = 0; mm \u003c= RULER_MAX_MM; mm++){\n      var tick = document.createElement('div');\n      var cls = 'tick';\n      if(mm % 10 === 0) cls += ' major';\n      else if(mm % 5 === 0) cls += ' mid';\n      tick.className = cls;\n      tick.style.top = (mm * pxPerMm) + 'px';\n      if(mm % 10 === 0){\n        var lbl = document.createElement('span');\n        lbl.className = 'lbl';\n        lbl.textContent = mm + ' mm';\n        tick.appendChild(lbl);\n      }\n      ruler.appendChild(tick);\n    }\n\n    \/\/ Size marks stagger across two columns: consecutive sizes are ~2.5mm apart,\n    \/\/ which is under 10px on a low-density screen — too tight for one column.\n    var cols = [86, 210];\n    SIZES.forEach(function(s, i){\n      var mark = document.createElement('div');\n      mark.className = 'mark';\n      mark.style.top = (s.c * pxPerMm) + 'px';\n      mark.style.width = (cols[i % 2] + 60) + 'px';\n      var lbl = document.createElement('span');\n      lbl.className = 'lbl';\n      lbl.style.left = cols[i % 2] + 'px';\n      lbl.textContent = 'talle ' + s.size + ' · ' + fmt(s.c) + ' mm';\n      mark.appendChild(lbl);\n      ruler.appendChild(mark);\n    });\n  }\n\n  \/* ---------- render: table + check bar ---------- *\/\n  function fmt(n){ return n.toFixed(1).replace('.', ','); }\n\n  function renderTable(){\n    refBody.innerHTML = '';\n    SIZES.forEach(function(s){\n      var tr = document.createElement('tr');\n      var cells = [String(s.size), fmt(s.d) + ' mm', fmt(s.c) + ' mm'];\n      cells.forEach(function(txt){\n        var td = document.createElement('td');\n        td.textContent = txt;\n        tr.appendChild(td);\n      });\n      refBody.appendChild(tr);\n    });\n  }\n\n  function renderCheck(){\n    checkBar.style.width = (50 * pxPerMm) + 'px';\n  }\n\n  function renderTool(){\n    renderRings();\n    renderRuler();\n    renderTable();\n    renderCheck();\n    showStep('tool');\n  }\n\n  \/* ---------- resize \/ orientation ---------- *\/\n  var rt;\n  window.addEventListener('resize', function(){\n    clearTimeout(rt);\n    rt = setTimeout(function(){\n      if(stepCal.classList.contains('active')) setupCalStep();\n      else if(pxPerMm) renderRings();\n    }, 150);\n  });\n\n  \/* ---------- init ---------- *\/\n  var saved = readCal();\n  if(saved){\n    pxPerMm = saved.ppm;\n    \/\/ A changed devicePixelRatio usually means the browser zoom changed,\n    \/\/ which invalidates the stored calibration.\n    var dprNow = window.devicePixelRatio || 1;\n    if(saved.dpr \u0026\u0026 Math.abs(saved.dpr - dprNow) \u003e 0.01){\n      dprWarn.classList.add('on');\n    }\n    renderTool();\n  }else{\n    showStep('cal');\n    setupCalStep();\n  }\n})();\n\u003c\/script\u003e\n\u003c\/body\u003e","brand":"Just Vero","offers":[{"title":"Sin brillo \/ 7","offer_id":56617446244518,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":false},{"title":"Sin brillo \/ 8","offer_id":56430504706214,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":true},{"title":"Sin brillo \/ 9","offer_id":56430504738982,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":true},{"title":"Sin brillo \/ 10","offer_id":56430504771750,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":false},{"title":"Con brillo \/ 7","offer_id":56617446277286,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":false},{"title":"Con brillo \/ 8","offer_id":56430504804518,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":false},{"title":"Con brillo \/ 9","offer_id":56430504837286,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":false},{"title":"Con brillo \/ 10","offer_id":56430504870054,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":false}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_3158_JPG.jpg?v=1777535099"},{"product_id":"gothic-sigil","title":"GOTHIC SIGIL","description":"\u003cbody\u003e\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eAleación con baño plateado\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eMetal resistente\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eAcabado envejecido y textura marcada\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eEvitá mojarlo o exponerlo a humedad\u003cbr\u003e\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\n  \u003cmeta charset=\"UTF-8\"\u003e\n\u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003e\n\u003ctitle\u003eJUST VERO — medí tu talle de anillo\u003c\/title\u003e\n\u003cstyle\u003e\n  #jv-ring-sizer{\n    --jv-black:#111111;\n    --jv-white:#ffffff;\n    --jv-brown:#3F352B;\n    --jv-tan:#BCA08A;\n    --jv-line:#dcd6cd;\n    font-family:Helvetica, Arial, sans-serif;\n    color:var(--jv-black);\n    background:var(--jv-white);\n    max-width:520px;\n    margin:0 auto;\n    padding:24px 18px 40px;\n    line-height:1.45;\n    -webkit-text-size-adjust:100%;\n  }\n  #jv-ring-sizer *{box-sizing:border-box;}\n  #jv-ring-sizer h2{\n    font-size:15px;\n    font-weight:700;\n    letter-spacing:0.08em;\n    text-transform:uppercase;\n    margin:0 0 6px;\n  }\n  #jv-ring-sizer p{\n    font-size:13px;\n    color:var(--jv-brown);\n    margin:0 0 14px;\n  }\n  #jv-ring-sizer .step{\n    display:none;\n    border-top:1px solid var(--jv-line);\n    padding-top:20px;\n    margin-top:18px;\n  }\n  #jv-ring-sizer .step.active{display:block;}\n  #jv-ring-sizer .tag{\n    display:inline-block;\n    font-size:10px;\n    letter-spacing:0.12em;\n    text-transform:uppercase;\n    color:var(--jv-white);\n    background:var(--jv-black);\n    padding:3px 8px;\n    margin-bottom:10px;\n  }\n\n  \/* ---- calibration ---- *\/\n  #jv-ring-sizer .calarea{\n    position:relative;\n    margin:16px 0 10px;\n    min-height:120px;\n  }\n  #jv-ring-sizer .calcard{\n    position:relative;\n    border:2px solid var(--jv-black);\n    border-bottom:2px dashed var(--jv-line);\n    border-radius:6px 6px 0 0;\n    background:\n      linear-gradient(to right, rgba(188,160,138,0.10), rgba(188,160,138,0.02));\n  }\n  #jv-ring-sizer .calcard .corner{\n    position:absolute;\n    top:-2px;\n    left:-2px;\n    width:16px;\n    height:16px;\n    border-top:4px solid var(--jv-black);\n    border-left:4px solid var(--jv-black);\n  }\n  #jv-ring-sizer .calcard .cardlbl{\n    position:absolute;\n    bottom:6px;\n    left:0;\n    right:0;\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.06em;\n    text-transform:uppercase;\n    color:var(--jv-tan);\n  }\n  #jv-ring-sizer .calrow{\n    display:flex;\n    align-items:center;\n    gap:10px;\n    margin:14px 0 4px;\n  }\n  #jv-ring-sizer .calrow input[type=range]{\n    flex:1;\n    accent-color:var(--jv-black);\n    min-width:0;\n  }\n  #jv-ring-sizer .nudge{\n    width:34px;\n    min-width:34px;\n    padding:6px 0;\n    font-size:14px;\n    line-height:1;\n  }\n\n  \/* ---- buttons ---- *\/\n  #jv-ring-sizer button{\n    font-family:Helvetica, Arial, sans-serif;\n    background:var(--jv-black);\n    color:var(--jv-white);\n    border:none;\n    padding:12px 18px;\n    font-size:12px;\n    letter-spacing:0.08em;\n    text-transform:uppercase;\n    cursor:pointer;\n    width:100%;\n    margin-top:8px;\n  }\n  #jv-ring-sizer button:focus-visible{\n    outline:2px solid var(--jv-tan);\n    outline-offset:2px;\n  }\n\n  \/* ---- tabs ---- *\/\n  #jv-ring-sizer .tabs{\n    display:flex;\n    margin-bottom:16px;\n    border:1px solid var(--jv-black);\n  }\n  #jv-ring-sizer .tabs button{\n    flex:1;\n    background:var(--jv-white);\n    color:var(--jv-black);\n    margin:0;\n    padding:11px 6px;\n    font-size:11px;\n  }\n  #jv-ring-sizer .tabs button[aria-selected=\"true\"]{\n    background:var(--jv-black);\n    color:var(--jv-white);\n  }\n  #jv-ring-sizer .panel{display:none;}\n  #jv-ring-sizer .panel.on{display:block;}\n\n  \/* ---- rings ---- *\/\n  #jv-ring-sizer .rings{\n    display:grid;\n    gap:16px 10px;\n    justify-items:center;\n    margin:16px 0 4px;\n  }\n  #jv-ring-sizer .ringwrap{\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.04em;\n    text-transform:uppercase;\n    color:var(--jv-brown);\n  }\n  #jv-ring-sizer .ring{\n    border:1.5px solid var(--jv-black);\n    border-radius:50%;\n    margin:0 auto 5px;\n  }\n\n  \/* ---- vertical ruler ---- *\/\n  #jv-ring-sizer .rulerwrap{\n    position:relative;\n    margin:18px 0 8px;\n  }\n  #jv-ring-sizer .ruler{\n    position:relative;\n    border-left:2px solid var(--jv-black);\n    margin-left:2px;\n  }\n  #jv-ring-sizer .tick{\n    position:absolute;\n    left:0;\n    height:0;\n    border-top:1px solid var(--jv-brown);\n    width:5px;\n  }\n  #jv-ring-sizer .tick.mid{width:10px;}\n  #jv-ring-sizer .tick.major{\n    width:17px;\n    border-top:1.5px solid var(--jv-black);\n  }\n  #jv-ring-sizer .tick .lbl{\n    position:absolute;\n    left:21px;\n    top:-6px;\n    font-size:9px;\n    color:var(--jv-black);\n    white-space:nowrap;\n  }\n  #jv-ring-sizer .mark{\n    position:absolute;\n    left:0;\n    height:0;\n    border-top:1px dashed var(--jv-tan);\n  }\n  #jv-ring-sizer .mark .lbl{\n    position:absolute;\n    top:-6px;\n    font-size:10px;\n    color:var(--jv-brown);\n    white-space:nowrap;\n    background:var(--jv-white);\n    padding:0 3px;\n  }\n\n  \/* ---- table + notes ---- *\/\n  #jv-ring-sizer table{\n    width:100%;\n    border-collapse:collapse;\n    font-size:12px;\n    margin-top:14px;\n  }\n  #jv-ring-sizer th, #jv-ring-sizer td{\n    border-bottom:1px solid var(--jv-line);\n    padding:7px 4px;\n    text-align:center;\n  }\n  #jv-ring-sizer th{\n    text-transform:uppercase;\n    font-size:10px;\n    letter-spacing:0.06em;\n    color:var(--jv-brown);\n    font-weight:700;\n  }\n  #jv-ring-sizer .note{\n    font-size:11px;\n    color:var(--jv-tan);\n    margin:10px 0 0;\n  }\n  #jv-ring-sizer .rule-note{\n    font-size:12px;\n    color:var(--jv-black);\n    border-left:2px solid var(--jv-black);\n    padding:2px 0 2px 10px;\n    margin:16px 0 0;\n  }\n  #jv-ring-sizer .check{\n    margin:18px 0 0;\n    font-size:11px;\n    color:var(--jv-brown);\n  }\n  #jv-ring-sizer .checkbar{\n    height:8px;\n    border:1px solid var(--jv-black);\n    border-top:none;\n    margin-top:3px;\n  }\n  #jv-ring-sizer .warn{\n    font-size:12px;\n    background:#f6f2ec;\n    border-left:2px solid var(--jv-tan);\n    padding:9px 10px;\n    margin:0 0 14px;\n    color:var(--jv-brown);\n    display:none;\n  }\n  #jv-ring-sizer .warn.on{display:block;}\n  #jv-ring-sizer .recal{\n    display:block;\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.06em;\n    text-transform:uppercase;\n    text-decoration:underline;\n    color:var(--jv-brown);\n    background:none;\n    border:none;\n    width:auto;\n    margin:22px auto 0;\n    padding:6px;\n  }\n  #jv-ring-sizer .sr{\n    position:absolute;\n    width:1px;height:1px;\n    padding:0;margin:-1px;\n    overflow:hidden;\n    clip:rect(0,0,0,0);\n    white-space:nowrap;border:0;\n  }\n\u003c\/style\u003e\n\n\n\u003cdiv id=\"jv-ring-sizer\"\u003e\n\n  \u003ch2\u003emedí tu talle de anillo\u003c\/h2\u003e\n  \u003cp\u003ecalibrá la pantalla una vez. después medís desde el celular o la computadora.\u003c\/p\u003e\n\n  \u003c!-- ============ PASO 1 · CALIBRACIÓN ============ --\u003e\n  \u003cdiv class=\"step\" id=\"step-cal\"\u003e\n    \u003cspan class=\"tag\"\u003epaso 1 · calibración\u003c\/span\u003e\n    \u003cp\u003eapoyá una tarjeta sobre la pantalla — crédito, débito o la cédula. en vertical, alineada\n       con la esquina de arriba a la izquierda. movés el control hasta que el ancho del rectángulo\n       coincida con el ancho de la tarjeta.\u003c\/p\u003e\n\n    \u003cdiv class=\"calarea\" id=\"calArea\"\u003e\n      \u003cdiv class=\"calcard\" id=\"calCard\"\u003e\n        \u003cspan class=\"corner\"\u003e\u003c\/span\u003e\n        \u003cspan class=\"cardlbl\"\u003eancho de la tarjeta\u003c\/span\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"calrow\"\u003e\n      \u003cbutton class=\"nudge\" id=\"calDown\" aria-label=\"reducir el ancho\"\u003e−\u003c\/button\u003e\n      \u003cinput type=\"range\" id=\"calSlider\" aria-label=\"ajustar el ancho del rectángulo hasta que coincida con la tarjeta\"\u003e\n      \u003cbutton class=\"nudge\" id=\"calUp\" aria-label=\"aumentar el ancho\"\u003e+\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003cbutton id=\"calConfirm\"\u003econfirmar\u003c\/button\u003e\n    \u003cp class=\"note\"\u003eel zoom del navegador tiene que estar al 100%. si tenés activado el zoom de\n       accesibilidad o el modo lupa, la medida no va a dar.\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003c!-- ============ PASO 2 · HERRAMIENTA ============ --\u003e\n  \u003cdiv class=\"step\" id=\"step-tool\"\u003e\n\n    \u003cdiv class=\"warn\" id=\"dprWarn\"\u003e\n      cambió el zoom o la pantalla desde la última vez que calibraste. conviene recalibrar antes de medir.\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"tabs\" role=\"tablist\" aria-label=\"método de medición\"\u003e\n      \u003cbutton role=\"tab\" id=\"tabA\" aria-selected=\"true\" aria-controls=\"panelA\"\u003ecomparar un anillo\u003c\/button\u003e\n      \u003cbutton role=\"tab\" id=\"tabB\" aria-selected=\"false\" aria-controls=\"panelB\"\u003emedir el dedo\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- opción A --\u003e\n    \u003cdiv class=\"panel on\" id=\"panelA\" role=\"tabpanel\" aria-labelledby=\"tabA\"\u003e\n      \u003cspan class=\"tag\"\u003eopción a\u003c\/span\u003e\n      \u003cp\u003eapoyá un anillo que ya te calce bien sobre los círculos. el talle es el círculo cuyo\n         borde exterior queda justo por dentro del anillo.\u003c\/p\u003e\n      \u003cdiv class=\"rings\" id=\"ringsGrid\"\u003e\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- opción B --\u003e\n    \u003cdiv class=\"panel\" id=\"panelB\" role=\"tabpanel\" aria-labelledby=\"tabB\"\u003e\n      \u003cspan class=\"tag\"\u003eopción b\u003c\/span\u003e\n      \u003cp\u003eenvolvé una tira de papel o un hilo en la base del dedo, donde va a quedar el anillo.\n         marcá el punto donde se superpone. después estirá la tira sobre la regla, arrancando\n         desde el cero.\u003c\/p\u003e\n      \u003cdiv class=\"rulerwrap\"\u003e\n        \u003cdiv class=\"ruler\" id=\"ruler\"\u003e\u003c\/div\u003e\n      \u003c\/div\u003e\n      \u003cp class=\"note\"\u003elas líneas punteadas son la circunferencia de cada talle.\u003c\/p\u003e\n    \u003c\/div\u003e\n\n    \u003ctable\u003e\n      \u003ccaption class=\"sr\"\u003etalles disponibles con su diámetro y circunferencia\u003c\/caption\u003e\n      \u003cthead\u003e\u003ctr\u003e\n\u003cth scope=\"col\"\u003etalle\u003c\/th\u003e\n\u003cth scope=\"col\"\u003ediámetro\u003c\/th\u003e\n\u003cth scope=\"col\"\u003ecircunferencia\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n      \u003ctbody id=\"refBody\"\u003e\u003c\/tbody\u003e\n    \u003c\/table\u003e\n\n    \u003cp class=\"rule-note\"\u003esi te queda entre dos talles, elegí el mayor.\u003c\/p\u003e\n\n    \u003cdiv class=\"check\"\u003e\n      control: esta línea mide 50 mm. si tenés una regla a mano, verificá.\n      \u003cdiv class=\"checkbar\" id=\"checkBar\"\u003e\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cp class=\"note\"\u003ees una medida aproximada — sirve para orientarte, no es exacta al milímetro.\n       el dedo cambia de grosor con el calor y la hora del día.\u003c\/p\u003e\n\n    \u003cbutton class=\"recal\" id=\"recalBtn\"\u003erecalibrar pantalla\u003c\/button\u003e\n  \u003c\/div\u003e\n\n\u003c\/div\u003e\n\n\u003cscript\u003e\n(function(){\n  'use strict';\n\n  var STORAGE_KEY = 'jv_ring_sizer_cal_v2';\n\n  \/\/ ISO\/IEC 7810 ID-1 — short side. The long side (85.6mm) is wider than most\n  \/\/ phone screens, so calibration has to happen on the short side.\n  var CARD_SHORT_MM = 53.98;\n  var CARD_LONG_MM  = 85.60;\n  var CARD_MAX_H_PX = 190;\n\n  var MIN_PPM = 1.6;   \/\/ absolute plausibility floor\n  var MAX_PPM = 22;    \/\/ absolute plausibility ceiling\n  var BASE_PPM = 96 \/ 25.4;\n\n  var SIZES = [\n    {size:6,  d:16.5},\n    {size:7,  d:17.3},\n    {size:8,  d:18.1},\n    {size:9,  d:19.0},\n    {size:10, d:19.8},\n    {size:11, d:20.6}\n  ];\n  SIZES.forEach(function(s){ s.c = s.d * Math.PI; });\n\n  var RULER_MAX_MM = 72;   \/\/ clears size 11 (~64.7mm) with room to read\n\n  var root      = document.getElementById('jv-ring-sizer');\n  var stepCal   = root.querySelector('#step-cal');\n  var stepTool  = root.querySelector('#step-tool');\n  var calArea   = root.querySelector('#calArea');\n  var calCard   = root.querySelector('#calCard');\n  var calSlider = root.querySelector('#calSlider');\n  var calUp     = root.querySelector('#calUp');\n  var calDown   = root.querySelector('#calDown');\n  var calConfirm= root.querySelector('#calConfirm');\n  var recalBtn  = root.querySelector('#recalBtn');\n  var dprWarn   = root.querySelector('#dprWarn');\n  var tabA      = root.querySelector('#tabA');\n  var tabB      = root.querySelector('#tabB');\n  var panelA    = root.querySelector('#panelA');\n  var panelB    = root.querySelector('#panelB');\n  var ringsGrid = root.querySelector('#ringsGrid');\n  var ruler     = root.querySelector('#ruler');\n  var refBody   = root.querySelector('#refBody');\n  var checkBar  = root.querySelector('#checkBar');\n\n  var pxPerMm = null;\n\n  \/* ---------- storage (may throw in partitioned\/blocked contexts) ---------- *\/\n  function readCal(){\n    try{\n      var raw = window.localStorage.getItem(STORAGE_KEY);\n      if(!raw) return null;\n      var o = JSON.parse(raw);\n      var p = parseFloat(o \u0026\u0026 o.ppm);\n      if(!isFinite(p) || p \u003c MIN_PPM || p \u003e MAX_PPM) return null;\n      return {ppm:p, dpr:parseFloat(o.dpr) || null};\n    }catch(e){ return null; }\n  }\n  function writeCal(ppm){\n    try{\n      window.localStorage.setItem(STORAGE_KEY, JSON.stringify({\n        ppm:ppm, dpr:window.devicePixelRatio || 1, ts:Date.now()\n      }));\n    }catch(e){ \/* sin persistencia: la calibración vale para esta sesión *\/ }\n  }\n  function clearCal(){\n    try{ window.localStorage.removeItem(STORAGE_KEY); }catch(e){}\n  }\n\n  \/* ---------- available width ---------- *\/\n  function availWidth(){\n    var w = calArea.clientWidth || root.clientWidth || 320;\n    return Math.max(120, w);\n  }\n\n  \/* ---------- calibration step ---------- *\/\n  function sliderBounds(){\n    \/\/ Cap so the calibration rectangle can never overflow its container.\n    var maxPpm = availWidth() \/ CARD_SHORT_MM;\n    var minPpm = MIN_PPM;\n    if(maxPpm \u003c minPpm + 0.5) maxPpm = minPpm + 0.5;\n    return {min:minPpm, max:maxPpm};\n  }\n\n  function drawCalCard(ppm){\n    var w = CARD_SHORT_MM * ppm;\n    var h = Math.min(CARD_LONG_MM * ppm, CARD_MAX_H_PX);\n    calCard.style.width  = w + 'px';\n    calCard.style.height = h + 'px';\n  }\n\n  function setupCalStep(){\n    var b = sliderBounds();\n    var current = parseFloat(calSlider.value);\n    var start = (isFinite(current) \u0026\u0026 current \u003e= b.min \u0026\u0026 current \u003c= b.max)\n      ? current\n      : Math.min(Math.max(pxPerMm || BASE_PPM, b.min), b.max);\n\n    calSlider.min = b.min.toFixed(3);\n    calSlider.max = b.max.toFixed(3);\n    calSlider.step = '0.005';\n    calSlider.value = start;\n    drawCalCard(start);\n  }\n\n  function nudge(delta){\n    var b = sliderBounds();\n    var v = Math.min(Math.max(parseFloat(calSlider.value) + delta, b.min), b.max);\n    calSlider.value = v;\n    drawCalCard(v);\n  }\n\n  calSlider.addEventListener('input', function(){\n    drawCalCard(parseFloat(calSlider.value));\n  });\n  calUp.addEventListener('click',   function(){ nudge(0.02); });\n  calDown.addEventListener('click', function(){ nudge(-0.02); });\n\n  calConfirm.addEventListener('click', function(){\n    var v = parseFloat(calSlider.value);\n    if(!isFinite(v) || v \u003c MIN_PPM || v \u003e MAX_PPM) return;\n    pxPerMm = v;\n    writeCal(pxPerMm);\n    dprWarn.classList.remove('on');\n    renderTool();\n    stepTool.scrollIntoView({block:'start'});\n  });\n\n  recalBtn.addEventListener('click', function(){\n    clearCal();\n    showStep('cal');\n    setupCalStep();\n    stepCal.scrollIntoView({block:'start'});\n  });\n\n  \/* ---------- tabs ---------- *\/\n  function switchTab(which){\n    var isA = (which === 'A');\n    tabA.setAttribute('aria-selected', isA ? 'true' : 'false');\n    tabB.setAttribute('aria-selected', isA ? 'false' : 'true');\n    panelA.classList.toggle('on', isA);\n    panelB.classList.toggle('on', !isA);\n  }\n  tabA.addEventListener('click', function(){ switchTab('A'); });\n  tabB.addEventListener('click', function(){ switchTab('B'); });\n  [tabA, tabB].forEach(function(t){\n    t.addEventListener('keydown', function(e){\n      if(e.key === 'ArrowRight'){ switchTab('B'); tabB.focus(); }\n      if(e.key === 'ArrowLeft'){ switchTab('A'); tabA.focus(); }\n    });\n  });\n\n  function showStep(which){\n    stepCal.classList.toggle('active', which === 'cal');\n    stepTool.classList.toggle('active', which === 'tool');\n  }\n\n  \/* ---------- render: rings ---------- *\/\n  function renderRings(){\n    ringsGrid.innerHTML = '';\n    var maxPx = 0;\n    SIZES.forEach(function(s){ maxPx = Math.max(maxPx, s.d * pxPerMm); });\n\n    \/\/ Columns must fit the largest circle, otherwise rings overflow their cell.\n    var avail = availWidth();\n    var cols = Math.max(1, Math.floor((avail + 10) \/ (maxPx + 10)));\n    cols = Math.min(cols, SIZES.length);\n    ringsGrid.style.gridTemplateColumns = 'repeat(' + cols + ', 1fr)';\n\n    SIZES.forEach(function(s){\n      var px = s.d * pxPerMm;\n      var wrap = document.createElement('div');\n      wrap.className = 'ringwrap';\n      var ring = document.createElement('div');\n      ring.className = 'ring';\n      ring.style.width  = px + 'px';\n      ring.style.height = px + 'px';\n      wrap.appendChild(ring);\n      wrap.appendChild(document.createTextNode('talle ' + s.size));\n      ringsGrid.appendChild(wrap);\n    });\n  }\n\n  \/* ---------- render: vertical ruler ---------- *\/\n  function renderRuler(){\n    ruler.innerHTML = '';\n    ruler.style.height = (RULER_MAX_MM * pxPerMm) + 'px';\n\n    for(var mm = 0; mm \u003c= RULER_MAX_MM; mm++){\n      var tick = document.createElement('div');\n      var cls = 'tick';\n      if(mm % 10 === 0) cls += ' major';\n      else if(mm % 5 === 0) cls += ' mid';\n      tick.className = cls;\n      tick.style.top = (mm * pxPerMm) + 'px';\n      if(mm % 10 === 0){\n        var lbl = document.createElement('span');\n        lbl.className = 'lbl';\n        lbl.textContent = mm + ' mm';\n        tick.appendChild(lbl);\n      }\n      ruler.appendChild(tick);\n    }\n\n    \/\/ Size marks stagger across two columns: consecutive sizes are ~2.5mm apart,\n    \/\/ which is under 10px on a low-density screen — too tight for one column.\n    var cols = [86, 210];\n    SIZES.forEach(function(s, i){\n      var mark = document.createElement('div');\n      mark.className = 'mark';\n      mark.style.top = (s.c * pxPerMm) + 'px';\n      mark.style.width = (cols[i % 2] + 60) + 'px';\n      var lbl = document.createElement('span');\n      lbl.className = 'lbl';\n      lbl.style.left = cols[i % 2] + 'px';\n      lbl.textContent = 'talle ' + s.size + ' · ' + fmt(s.c) + ' mm';\n      mark.appendChild(lbl);\n      ruler.appendChild(mark);\n    });\n  }\n\n  \/* ---------- render: table + check bar ---------- *\/\n  function fmt(n){ return n.toFixed(1).replace('.', ','); }\n\n  function renderTable(){\n    refBody.innerHTML = '';\n    SIZES.forEach(function(s){\n      var tr = document.createElement('tr');\n      var cells = [String(s.size), fmt(s.d) + ' mm', fmt(s.c) + ' mm'];\n      cells.forEach(function(txt){\n        var td = document.createElement('td');\n        td.textContent = txt;\n        tr.appendChild(td);\n      });\n      refBody.appendChild(tr);\n    });\n  }\n\n  function renderCheck(){\n    checkBar.style.width = (50 * pxPerMm) + 'px';\n  }\n\n  function renderTool(){\n    renderRings();\n    renderRuler();\n    renderTable();\n    renderCheck();\n    showStep('tool');\n  }\n\n  \/* ---------- resize \/ orientation ---------- *\/\n  var rt;\n  window.addEventListener('resize', function(){\n    clearTimeout(rt);\n    rt = setTimeout(function(){\n      if(stepCal.classList.contains('active')) setupCalStep();\n      else if(pxPerMm) renderRings();\n    }, 150);\n  });\n\n  \/* ---------- init ---------- *\/\n  var saved = readCal();\n  if(saved){\n    pxPerMm = saved.ppm;\n    \/\/ A changed devicePixelRatio usually means the browser zoom changed,\n    \/\/ which invalidates the stored calibration.\n    var dprNow = window.devicePixelRatio || 1;\n    if(saved.dpr \u0026\u0026 Math.abs(saved.dpr - dprNow) \u003e 0.01){\n      dprWarn.classList.add('on');\n    }\n    renderTool();\n  }else{\n    showStep('cal');\n    setupCalStep();\n  }\n})();\n\u003c\/script\u003e\n\u003c\/ul\u003e\u003c\/body\u003e","brand":"Just Vero","offers":[{"title":"9","offer_id":56863288590502,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":true},{"title":"8","offer_id":56863288623270,"sku":null,"price":1590.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_3123_JPG.jpg?v=1777535013"},{"product_id":"linked-chaos","title":"LINKED CHAOS","description":"\u003cp\u003eMaterial:\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eCadena acero quirúrgico inoxidable\u003c\/li\u003e\n\u003cli\u003eDetalles acero\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"1","offer_id":56863249531046,"sku":null,"price":1490.0,"currency_code":"UYU","in_stock":false},{"title":"2","offer_id":56863249563814,"sku":null,"price":1490.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/E436461B-FC03-4427-B663-04F3EF089962.jpg?v=1784994091"},{"product_id":"armored-heart","title":"ARMORED HEART","description":"\u003cp\u003eMaterial:\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eCadena acero quirúrgico inoxidable\u003c\/li\u003e\n\u003cli\u003eDije corazón aleación pesada\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":56863267127462,"sku":null,"price":1490.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/51FADF71-18F7-4F6A-B12F-14B874D4A594.jpg?v=1784994091"},{"product_id":"gothic-band","title":"GOTHIC BAND","description":"\u003cbody\u003e\n\u003cp\u003eMaterial:\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eAcero quirúrgico inoxidable \u003c\/li\u003e\n\u003c\/ul\u003e\n\u003cmeta charset=\"UTF-8\"\u003e\n\u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003e\n\u003ctitle\u003eJUST VERO — medí tu talle de anillo\u003c\/title\u003e\n\u003cstyle\u003e\n  #jv-ring-sizer{\n    --jv-black:#111111;\n    --jv-white:#ffffff;\n    --jv-brown:#3F352B;\n    --jv-tan:#BCA08A;\n    --jv-line:#dcd6cd;\n    font-family:Helvetica, Arial, sans-serif;\n    color:var(--jv-black);\n    background:var(--jv-white);\n    max-width:520px;\n    margin:0 auto;\n    padding:24px 18px 40px;\n    line-height:1.45;\n    -webkit-text-size-adjust:100%;\n  }\n  #jv-ring-sizer *{box-sizing:border-box;}\n  #jv-ring-sizer h2{\n    font-size:15px;\n    font-weight:700;\n    letter-spacing:0.08em;\n    text-transform:uppercase;\n    margin:0 0 6px;\n  }\n  #jv-ring-sizer p{\n    font-size:13px;\n    color:var(--jv-brown);\n    margin:0 0 14px;\n  }\n  #jv-ring-sizer .step{\n    display:none;\n    border-top:1px solid var(--jv-line);\n    padding-top:20px;\n    margin-top:18px;\n  }\n  #jv-ring-sizer .step.active{display:block;}\n  #jv-ring-sizer .tag{\n    display:inline-block;\n    font-size:10px;\n    letter-spacing:0.12em;\n    text-transform:uppercase;\n    color:var(--jv-white);\n    background:var(--jv-black);\n    padding:3px 8px;\n    margin-bottom:10px;\n  }\n\n  \/* ---- calibration ---- *\/\n  #jv-ring-sizer .calarea{\n    position:relative;\n    margin:16px 0 10px;\n    min-height:120px;\n  }\n  #jv-ring-sizer .calcard{\n    position:relative;\n    border:2px solid var(--jv-black);\n    border-bottom:2px dashed var(--jv-line);\n    border-radius:6px 6px 0 0;\n    background:\n      linear-gradient(to right, rgba(188,160,138,0.10), rgba(188,160,138,0.02));\n  }\n  #jv-ring-sizer .calcard .corner{\n    position:absolute;\n    top:-2px;\n    left:-2px;\n    width:16px;\n    height:16px;\n    border-top:4px solid var(--jv-black);\n    border-left:4px solid var(--jv-black);\n  }\n  #jv-ring-sizer .calcard .cardlbl{\n    position:absolute;\n    bottom:6px;\n    left:0;\n    right:0;\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.06em;\n    text-transform:uppercase;\n    color:var(--jv-tan);\n  }\n  #jv-ring-sizer .calrow{\n    display:flex;\n    align-items:center;\n    gap:10px;\n    margin:14px 0 4px;\n  }\n  #jv-ring-sizer .calrow input[type=range]{\n    flex:1;\n    accent-color:var(--jv-black);\n    min-width:0;\n  }\n  #jv-ring-sizer .nudge{\n    width:34px;\n    min-width:34px;\n    padding:6px 0;\n    font-size:14px;\n    line-height:1;\n  }\n\n  \/* ---- buttons ---- *\/\n  #jv-ring-sizer button{\n    font-family:Helvetica, Arial, sans-serif;\n    background:var(--jv-black);\n    color:var(--jv-white);\n    border:none;\n    padding:12px 18px;\n    font-size:12px;\n    letter-spacing:0.08em;\n    text-transform:uppercase;\n    cursor:pointer;\n    width:100%;\n    margin-top:8px;\n  }\n  #jv-ring-sizer button:focus-visible{\n    outline:2px solid var(--jv-tan);\n    outline-offset:2px;\n  }\n\n  \/* ---- tabs ---- *\/\n  #jv-ring-sizer .tabs{\n    display:flex;\n    margin-bottom:16px;\n    border:1px solid var(--jv-black);\n  }\n  #jv-ring-sizer .tabs button{\n    flex:1;\n    background:var(--jv-white);\n    color:var(--jv-black);\n    margin:0;\n    padding:11px 6px;\n    font-size:11px;\n  }\n  #jv-ring-sizer .tabs button[aria-selected=\"true\"]{\n    background:var(--jv-black);\n    color:var(--jv-white);\n  }\n  #jv-ring-sizer .panel{display:none;}\n  #jv-ring-sizer .panel.on{display:block;}\n\n  \/* ---- rings ---- *\/\n  #jv-ring-sizer .rings{\n    display:grid;\n    gap:16px 10px;\n    justify-items:center;\n    margin:16px 0 4px;\n  }\n  #jv-ring-sizer .ringwrap{\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.04em;\n    text-transform:uppercase;\n    color:var(--jv-brown);\n  }\n  #jv-ring-sizer .ring{\n    border:1.5px solid var(--jv-black);\n    border-radius:50%;\n    margin:0 auto 5px;\n  }\n\n  \/* ---- vertical ruler ---- *\/\n  #jv-ring-sizer .rulerwrap{\n    position:relative;\n    margin:18px 0 8px;\n  }\n  #jv-ring-sizer .ruler{\n    position:relative;\n    border-left:2px solid var(--jv-black);\n    margin-left:2px;\n  }\n  #jv-ring-sizer .tick{\n    position:absolute;\n    left:0;\n    height:0;\n    border-top:1px solid var(--jv-brown);\n    width:5px;\n  }\n  #jv-ring-sizer .tick.mid{width:10px;}\n  #jv-ring-sizer .tick.major{\n    width:17px;\n    border-top:1.5px solid var(--jv-black);\n  }\n  #jv-ring-sizer .tick .lbl{\n    position:absolute;\n    left:21px;\n    top:-6px;\n    font-size:9px;\n    color:var(--jv-black);\n    white-space:nowrap;\n  }\n  #jv-ring-sizer .mark{\n    position:absolute;\n    left:0;\n    height:0;\n    border-top:1px dashed var(--jv-tan);\n  }\n  #jv-ring-sizer .mark .lbl{\n    position:absolute;\n    top:-6px;\n    font-size:10px;\n    color:var(--jv-brown);\n    white-space:nowrap;\n    background:var(--jv-white);\n    padding:0 3px;\n  }\n\n  \/* ---- table + notes ---- *\/\n  #jv-ring-sizer table{\n    width:100%;\n    border-collapse:collapse;\n    font-size:12px;\n    margin-top:14px;\n  }\n  #jv-ring-sizer th, #jv-ring-sizer td{\n    border-bottom:1px solid var(--jv-line);\n    padding:7px 4px;\n    text-align:center;\n  }\n  #jv-ring-sizer th{\n    text-transform:uppercase;\n    font-size:10px;\n    letter-spacing:0.06em;\n    color:var(--jv-brown);\n    font-weight:700;\n  }\n  #jv-ring-sizer .note{\n    font-size:11px;\n    color:var(--jv-tan);\n    margin:10px 0 0;\n  }\n  #jv-ring-sizer .rule-note{\n    font-size:12px;\n    color:var(--jv-black);\n    border-left:2px solid var(--jv-black);\n    padding:2px 0 2px 10px;\n    margin:16px 0 0;\n  }\n  #jv-ring-sizer .check{\n    margin:18px 0 0;\n    font-size:11px;\n    color:var(--jv-brown);\n  }\n  #jv-ring-sizer .checkbar{\n    height:8px;\n    border:1px solid var(--jv-black);\n    border-top:none;\n    margin-top:3px;\n  }\n  #jv-ring-sizer .warn{\n    font-size:12px;\n    background:#f6f2ec;\n    border-left:2px solid var(--jv-tan);\n    padding:9px 10px;\n    margin:0 0 14px;\n    color:var(--jv-brown);\n    display:none;\n  }\n  #jv-ring-sizer .warn.on{display:block;}\n  #jv-ring-sizer .recal{\n    display:block;\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.06em;\n    text-transform:uppercase;\n    text-decoration:underline;\n    color:var(--jv-brown);\n    background:none;\n    border:none;\n    width:auto;\n    margin:22px auto 0;\n    padding:6px;\n  }\n  #jv-ring-sizer .sr{\n    position:absolute;\n    width:1px;height:1px;\n    padding:0;margin:-1px;\n    overflow:hidden;\n    clip:rect(0,0,0,0);\n    white-space:nowrap;border:0;\n  }\n\u003c\/style\u003e\n\n\n\u003cdiv id=\"jv-ring-sizer\"\u003e\n\n  \u003ch2\u003emedí tu talle de anillo\u003c\/h2\u003e\n  \u003cp\u003ecalibrá la pantalla una vez. después medís desde el celular o la computadora.\u003c\/p\u003e\n\n  \u003c!-- ============ PASO 1 · CALIBRACIÓN ============ --\u003e\n  \u003cdiv class=\"step\" id=\"step-cal\"\u003e\n    \u003cspan class=\"tag\"\u003epaso 1 · calibración\u003c\/span\u003e\n    \u003cp\u003eapoyá una tarjeta sobre la pantalla — crédito, débito o la cédula. en vertical, alineada\n       con la esquina de arriba a la izquierda. movés el control hasta que el ancho del rectángulo\n       coincida con el ancho de la tarjeta.\u003c\/p\u003e\n\n    \u003cdiv class=\"calarea\" id=\"calArea\"\u003e\n      \u003cdiv class=\"calcard\" id=\"calCard\"\u003e\n        \u003cspan class=\"corner\"\u003e\u003c\/span\u003e\n        \u003cspan class=\"cardlbl\"\u003eancho de la tarjeta\u003c\/span\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"calrow\"\u003e\n      \u003cbutton class=\"nudge\" id=\"calDown\" aria-label=\"reducir el ancho\"\u003e−\u003c\/button\u003e\n      \u003cinput type=\"range\" id=\"calSlider\" aria-label=\"ajustar el ancho del rectángulo hasta que coincida con la tarjeta\"\u003e\n      \u003cbutton class=\"nudge\" id=\"calUp\" aria-label=\"aumentar el ancho\"\u003e+\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003cbutton id=\"calConfirm\"\u003econfirmar\u003c\/button\u003e\n    \u003cp class=\"note\"\u003eel zoom del navegador tiene que estar al 100%. si tenés activado el zoom de\n       accesibilidad o el modo lupa, la medida no va a dar.\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003c!-- ============ PASO 2 · HERRAMIENTA ============ --\u003e\n  \u003cdiv class=\"step\" id=\"step-tool\"\u003e\n\n    \u003cdiv class=\"warn\" id=\"dprWarn\"\u003e\n      cambió el zoom o la pantalla desde la última vez que calibraste. conviene recalibrar antes de medir.\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"tabs\" role=\"tablist\" aria-label=\"método de medición\"\u003e\n      \u003cbutton role=\"tab\" id=\"tabA\" aria-selected=\"true\" aria-controls=\"panelA\"\u003ecomparar un anillo\u003c\/button\u003e\n      \u003cbutton role=\"tab\" id=\"tabB\" aria-selected=\"false\" aria-controls=\"panelB\"\u003emedir el dedo\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- opción A --\u003e\n    \u003cdiv class=\"panel on\" id=\"panelA\" role=\"tabpanel\" aria-labelledby=\"tabA\"\u003e\n      \u003cspan class=\"tag\"\u003eopción a\u003c\/span\u003e\n      \u003cp\u003eapoyá un anillo que ya te calce bien sobre los círculos. el talle es el círculo cuyo\n         borde exterior queda justo por dentro del anillo.\u003c\/p\u003e\n      \u003cdiv class=\"rings\" id=\"ringsGrid\"\u003e\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- opción B --\u003e\n    \u003cdiv class=\"panel\" id=\"panelB\" role=\"tabpanel\" aria-labelledby=\"tabB\"\u003e\n      \u003cspan class=\"tag\"\u003eopción b\u003c\/span\u003e\n      \u003cp\u003eenvolvé una tira de papel o un hilo en la base del dedo, donde va a quedar el anillo.\n         marcá el punto donde se superpone. después estirá la tira sobre la regla, arrancando\n         desde el cero.\u003c\/p\u003e\n      \u003cdiv class=\"rulerwrap\"\u003e\n        \u003cdiv class=\"ruler\" id=\"ruler\"\u003e\u003c\/div\u003e\n      \u003c\/div\u003e\n      \u003cp class=\"note\"\u003elas líneas punteadas son la circunferencia de cada talle.\u003c\/p\u003e\n    \u003c\/div\u003e\n\n    \u003ctable\u003e\n      \u003ccaption class=\"sr\"\u003etalles disponibles con su diámetro y circunferencia\u003c\/caption\u003e\n      \u003cthead\u003e\u003ctr\u003e\n\u003cth scope=\"col\"\u003etalle\u003c\/th\u003e\n\u003cth scope=\"col\"\u003ediámetro\u003c\/th\u003e\n\u003cth scope=\"col\"\u003ecircunferencia\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n      \u003ctbody id=\"refBody\"\u003e\u003c\/tbody\u003e\n    \u003c\/table\u003e\n\n    \u003cp class=\"rule-note\"\u003esi te queda entre dos talles, elegí el mayor.\u003c\/p\u003e\n\n    \u003cdiv class=\"check\"\u003e\n      control: esta línea mide 50 mm. si tenés una regla a mano, verificá.\n      \u003cdiv class=\"checkbar\" id=\"checkBar\"\u003e\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cp class=\"note\"\u003ees una medida aproximada — sirve para orientarte, no es exacta al milímetro.\n       el dedo cambia de grosor con el calor y la hora del día.\u003c\/p\u003e\n\n    \u003cbutton class=\"recal\" id=\"recalBtn\"\u003erecalibrar pantalla\u003c\/button\u003e\n  \u003c\/div\u003e\n\n\u003c\/div\u003e\n\n\u003cscript\u003e\n(function(){\n  'use strict';\n\n  var STORAGE_KEY = 'jv_ring_sizer_cal_v2';\n\n  \/\/ ISO\/IEC 7810 ID-1 — short side. The long side (85.6mm) is wider than most\n  \/\/ phone screens, so calibration has to happen on the short side.\n  var CARD_SHORT_MM = 53.98;\n  var CARD_LONG_MM  = 85.60;\n  var CARD_MAX_H_PX = 190;\n\n  var MIN_PPM = 1.6;   \/\/ absolute plausibility floor\n  var MAX_PPM = 22;    \/\/ absolute plausibility ceiling\n  var BASE_PPM = 96 \/ 25.4;\n\n  var SIZES = [\n    {size:6,  d:16.5},\n    {size:7,  d:17.3},\n    {size:8,  d:18.1},\n    {size:9,  d:19.0},\n    {size:10, d:19.8},\n    {size:11, d:20.6}\n  ];\n  SIZES.forEach(function(s){ s.c = s.d * Math.PI; });\n\n  var RULER_MAX_MM = 72;   \/\/ clears size 11 (~64.7mm) with room to read\n\n  var root      = document.getElementById('jv-ring-sizer');\n  var stepCal   = root.querySelector('#step-cal');\n  var stepTool  = root.querySelector('#step-tool');\n  var calArea   = root.querySelector('#calArea');\n  var calCard   = root.querySelector('#calCard');\n  var calSlider = root.querySelector('#calSlider');\n  var calUp     = root.querySelector('#calUp');\n  var calDown   = root.querySelector('#calDown');\n  var calConfirm= root.querySelector('#calConfirm');\n  var recalBtn  = root.querySelector('#recalBtn');\n  var dprWarn   = root.querySelector('#dprWarn');\n  var tabA      = root.querySelector('#tabA');\n  var tabB      = root.querySelector('#tabB');\n  var panelA    = root.querySelector('#panelA');\n  var panelB    = root.querySelector('#panelB');\n  var ringsGrid = root.querySelector('#ringsGrid');\n  var ruler     = root.querySelector('#ruler');\n  var refBody   = root.querySelector('#refBody');\n  var checkBar  = root.querySelector('#checkBar');\n\n  var pxPerMm = null;\n\n  \/* ---------- storage (may throw in partitioned\/blocked contexts) ---------- *\/\n  function readCal(){\n    try{\n      var raw = window.localStorage.getItem(STORAGE_KEY);\n      if(!raw) return null;\n      var o = JSON.parse(raw);\n      var p = parseFloat(o \u0026\u0026 o.ppm);\n      if(!isFinite(p) || p \u003c MIN_PPM || p \u003e MAX_PPM) return null;\n      return {ppm:p, dpr:parseFloat(o.dpr) || null};\n    }catch(e){ return null; }\n  }\n  function writeCal(ppm){\n    try{\n      window.localStorage.setItem(STORAGE_KEY, JSON.stringify({\n        ppm:ppm, dpr:window.devicePixelRatio || 1, ts:Date.now()\n      }));\n    }catch(e){ \/* sin persistencia: la calibración vale para esta sesión *\/ }\n  }\n  function clearCal(){\n    try{ window.localStorage.removeItem(STORAGE_KEY); }catch(e){}\n  }\n\n  \/* ---------- available width ---------- *\/\n  function availWidth(){\n    var w = calArea.clientWidth || root.clientWidth || 320;\n    return Math.max(120, w);\n  }\n\n  \/* ---------- calibration step ---------- *\/\n  function sliderBounds(){\n    \/\/ Cap so the calibration rectangle can never overflow its container.\n    var maxPpm = availWidth() \/ CARD_SHORT_MM;\n    var minPpm = MIN_PPM;\n    if(maxPpm \u003c minPpm + 0.5) maxPpm = minPpm + 0.5;\n    return {min:minPpm, max:maxPpm};\n  }\n\n  function drawCalCard(ppm){\n    var w = CARD_SHORT_MM * ppm;\n    var h = Math.min(CARD_LONG_MM * ppm, CARD_MAX_H_PX);\n    calCard.style.width  = w + 'px';\n    calCard.style.height = h + 'px';\n  }\n\n  function setupCalStep(){\n    var b = sliderBounds();\n    var current = parseFloat(calSlider.value);\n    var start = (isFinite(current) \u0026\u0026 current \u003e= b.min \u0026\u0026 current \u003c= b.max)\n      ? current\n      : Math.min(Math.max(pxPerMm || BASE_PPM, b.min), b.max);\n\n    calSlider.min = b.min.toFixed(3);\n    calSlider.max = b.max.toFixed(3);\n    calSlider.step = '0.005';\n    calSlider.value = start;\n    drawCalCard(start);\n  }\n\n  function nudge(delta){\n    var b = sliderBounds();\n    var v = Math.min(Math.max(parseFloat(calSlider.value) + delta, b.min), b.max);\n    calSlider.value = v;\n    drawCalCard(v);\n  }\n\n  calSlider.addEventListener('input', function(){\n    drawCalCard(parseFloat(calSlider.value));\n  });\n  calUp.addEventListener('click',   function(){ nudge(0.02); });\n  calDown.addEventListener('click', function(){ nudge(-0.02); });\n\n  calConfirm.addEventListener('click', function(){\n    var v = parseFloat(calSlider.value);\n    if(!isFinite(v) || v \u003c MIN_PPM || v \u003e MAX_PPM) return;\n    pxPerMm = v;\n    writeCal(pxPerMm);\n    dprWarn.classList.remove('on');\n    renderTool();\n    stepTool.scrollIntoView({block:'start'});\n  });\n\n  recalBtn.addEventListener('click', function(){\n    clearCal();\n    showStep('cal');\n    setupCalStep();\n    stepCal.scrollIntoView({block:'start'});\n  });\n\n  \/* ---------- tabs ---------- *\/\n  function switchTab(which){\n    var isA = (which === 'A');\n    tabA.setAttribute('aria-selected', isA ? 'true' : 'false');\n    tabB.setAttribute('aria-selected', isA ? 'false' : 'true');\n    panelA.classList.toggle('on', isA);\n    panelB.classList.toggle('on', !isA);\n  }\n  tabA.addEventListener('click', function(){ switchTab('A'); });\n  tabB.addEventListener('click', function(){ switchTab('B'); });\n  [tabA, tabB].forEach(function(t){\n    t.addEventListener('keydown', function(e){\n      if(e.key === 'ArrowRight'){ switchTab('B'); tabB.focus(); }\n      if(e.key === 'ArrowLeft'){ switchTab('A'); tabA.focus(); }\n    });\n  });\n\n  function showStep(which){\n    stepCal.classList.toggle('active', which === 'cal');\n    stepTool.classList.toggle('active', which === 'tool');\n  }\n\n  \/* ---------- render: rings ---------- *\/\n  function renderRings(){\n    ringsGrid.innerHTML = '';\n    var maxPx = 0;\n    SIZES.forEach(function(s){ maxPx = Math.max(maxPx, s.d * pxPerMm); });\n\n    \/\/ Columns must fit the largest circle, otherwise rings overflow their cell.\n    var avail = availWidth();\n    var cols = Math.max(1, Math.floor((avail + 10) \/ (maxPx + 10)));\n    cols = Math.min(cols, SIZES.length);\n    ringsGrid.style.gridTemplateColumns = 'repeat(' + cols + ', 1fr)';\n\n    SIZES.forEach(function(s){\n      var px = s.d * pxPerMm;\n      var wrap = document.createElement('div');\n      wrap.className = 'ringwrap';\n      var ring = document.createElement('div');\n      ring.className = 'ring';\n      ring.style.width  = px + 'px';\n      ring.style.height = px + 'px';\n      wrap.appendChild(ring);\n      wrap.appendChild(document.createTextNode('talle ' + s.size));\n      ringsGrid.appendChild(wrap);\n    });\n  }\n\n  \/* ---------- render: vertical ruler ---------- *\/\n  function renderRuler(){\n    ruler.innerHTML = '';\n    ruler.style.height = (RULER_MAX_MM * pxPerMm) + 'px';\n\n    for(var mm = 0; mm \u003c= RULER_MAX_MM; mm++){\n      var tick = document.createElement('div');\n      var cls = 'tick';\n      if(mm % 10 === 0) cls += ' major';\n      else if(mm % 5 === 0) cls += ' mid';\n      tick.className = cls;\n      tick.style.top = (mm * pxPerMm) + 'px';\n      if(mm % 10 === 0){\n        var lbl = document.createElement('span');\n        lbl.className = 'lbl';\n        lbl.textContent = mm + ' mm';\n        tick.appendChild(lbl);\n      }\n      ruler.appendChild(tick);\n    }\n\n    \/\/ Size marks stagger across two columns: consecutive sizes are ~2.5mm apart,\n    \/\/ which is under 10px on a low-density screen — too tight for one column.\n    var cols = [86, 210];\n    SIZES.forEach(function(s, i){\n      var mark = document.createElement('div');\n      mark.className = 'mark';\n      mark.style.top = (s.c * pxPerMm) + 'px';\n      mark.style.width = (cols[i % 2] + 60) + 'px';\n      var lbl = document.createElement('span');\n      lbl.className = 'lbl';\n      lbl.style.left = cols[i % 2] + 'px';\n      lbl.textContent = 'talle ' + s.size + ' · ' + fmt(s.c) + ' mm';\n      mark.appendChild(lbl);\n      ruler.appendChild(mark);\n    });\n  }\n\n  \/* ---------- render: table + check bar ---------- *\/\n  function fmt(n){ return n.toFixed(1).replace('.', ','); }\n\n  function renderTable(){\n    refBody.innerHTML = '';\n    SIZES.forEach(function(s){\n      var tr = document.createElement('tr');\n      var cells = [String(s.size), fmt(s.d) + ' mm', fmt(s.c) + ' mm'];\n      cells.forEach(function(txt){\n        var td = document.createElement('td');\n        td.textContent = txt;\n        tr.appendChild(td);\n      });\n      refBody.appendChild(tr);\n    });\n  }\n\n  function renderCheck(){\n    checkBar.style.width = (50 * pxPerMm) + 'px';\n  }\n\n  function renderTool(){\n    renderRings();\n    renderRuler();\n    renderTable();\n    renderCheck();\n    showStep('tool');\n  }\n\n  \/* ---------- resize \/ orientation ---------- *\/\n  var rt;\n  window.addEventListener('resize', function(){\n    clearTimeout(rt);\n    rt = setTimeout(function(){\n      if(stepCal.classList.contains('active')) setupCalStep();\n      else if(pxPerMm) renderRings();\n    }, 150);\n  });\n\n  \/* ---------- init ---------- *\/\n  var saved = readCal();\n  if(saved){\n    pxPerMm = saved.ppm;\n    \/\/ A changed devicePixelRatio usually means the browser zoom changed,\n    \/\/ which invalidates the stored calibration.\n    var dprNow = window.devicePixelRatio || 1;\n    if(saved.dpr \u0026\u0026 Math.abs(saved.dpr - dprNow) \u003e 0.01){\n      dprWarn.classList.add('on');\n    }\n    renderTool();\n  }else{\n    showStep('cal');\n    setupCalStep();\n  }\n})();\n\u003c\/script\u003e\n\u003c\/body\u003e","brand":"Just Vero","offers":[{"title":"8","offer_id":56863529828518,"sku":null,"price":1990.0,"currency_code":"UYU","in_stock":false},{"title":"9","offer_id":56863529861286,"sku":null,"price":1990.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/3E4A3168-B7AF-4271-819D-EC745B8E9247.jpg?v=1784998652"},{"product_id":"dark-signet","title":"DARK SIGNET","description":"\u003cbody\u003e\n\u003cp\u003eMaterial:\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003eAcero quirúrgico inoxidable \u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003cmeta charset=\"UTF-8\"\u003e\n\u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003e\n\u003ctitle\u003eJUST VERO — medí tu talle de anillo\u003c\/title\u003e\n\u003cstyle\u003e\n  #jv-ring-sizer{\n    --jv-black:#111111;\n    --jv-white:#ffffff;\n    --jv-brown:#3F352B;\n    --jv-tan:#BCA08A;\n    --jv-line:#dcd6cd;\n    font-family:Helvetica, Arial, sans-serif;\n    color:var(--jv-black);\n    background:var(--jv-white);\n    max-width:520px;\n    margin:0 auto;\n    padding:24px 18px 40px;\n    line-height:1.45;\n    -webkit-text-size-adjust:100%;\n  }\n  #jv-ring-sizer *{box-sizing:border-box;}\n  #jv-ring-sizer h2{\n    font-size:15px;\n    font-weight:700;\n    letter-spacing:0.08em;\n    text-transform:uppercase;\n    margin:0 0 6px;\n  }\n  #jv-ring-sizer p{\n    font-size:13px;\n    color:var(--jv-brown);\n    margin:0 0 14px;\n  }\n  #jv-ring-sizer .step{\n    display:none;\n    border-top:1px solid var(--jv-line);\n    padding-top:20px;\n    margin-top:18px;\n  }\n  #jv-ring-sizer .step.active{display:block;}\n  #jv-ring-sizer .tag{\n    display:inline-block;\n    font-size:10px;\n    letter-spacing:0.12em;\n    text-transform:uppercase;\n    color:var(--jv-white);\n    background:var(--jv-black);\n    padding:3px 8px;\n    margin-bottom:10px;\n  }\n\n  \/* ---- calibration ---- *\/\n  #jv-ring-sizer .calarea{\n    position:relative;\n    margin:16px 0 10px;\n    min-height:120px;\n  }\n  #jv-ring-sizer .calcard{\n    position:relative;\n    border:2px solid var(--jv-black);\n    border-bottom:2px dashed var(--jv-line);\n    border-radius:6px 6px 0 0;\n    background:\n      linear-gradient(to right, rgba(188,160,138,0.10), rgba(188,160,138,0.02));\n  }\n  #jv-ring-sizer .calcard .corner{\n    position:absolute;\n    top:-2px;\n    left:-2px;\n    width:16px;\n    height:16px;\n    border-top:4px solid var(--jv-black);\n    border-left:4px solid var(--jv-black);\n  }\n  #jv-ring-sizer .calcard .cardlbl{\n    position:absolute;\n    bottom:6px;\n    left:0;\n    right:0;\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.06em;\n    text-transform:uppercase;\n    color:var(--jv-tan);\n  }\n  #jv-ring-sizer .calrow{\n    display:flex;\n    align-items:center;\n    gap:10px;\n    margin:14px 0 4px;\n  }\n  #jv-ring-sizer .calrow input[type=range]{\n    flex:1;\n    accent-color:var(--jv-black);\n    min-width:0;\n  }\n  #jv-ring-sizer .nudge{\n    width:34px;\n    min-width:34px;\n    padding:6px 0;\n    font-size:14px;\n    line-height:1;\n  }\n\n  \/* ---- buttons ---- *\/\n  #jv-ring-sizer button{\n    font-family:Helvetica, Arial, sans-serif;\n    background:var(--jv-black);\n    color:var(--jv-white);\n    border:none;\n    padding:12px 18px;\n    font-size:12px;\n    letter-spacing:0.08em;\n    text-transform:uppercase;\n    cursor:pointer;\n    width:100%;\n    margin-top:8px;\n  }\n  #jv-ring-sizer button:focus-visible{\n    outline:2px solid var(--jv-tan);\n    outline-offset:2px;\n  }\n\n  \/* ---- tabs ---- *\/\n  #jv-ring-sizer .tabs{\n    display:flex;\n    margin-bottom:16px;\n    border:1px solid var(--jv-black);\n  }\n  #jv-ring-sizer .tabs button{\n    flex:1;\n    background:var(--jv-white);\n    color:var(--jv-black);\n    margin:0;\n    padding:11px 6px;\n    font-size:11px;\n  }\n  #jv-ring-sizer .tabs button[aria-selected=\"true\"]{\n    background:var(--jv-black);\n    color:var(--jv-white);\n  }\n  #jv-ring-sizer .panel{display:none;}\n  #jv-ring-sizer .panel.on{display:block;}\n\n  \/* ---- rings ---- *\/\n  #jv-ring-sizer .rings{\n    display:grid;\n    gap:16px 10px;\n    justify-items:center;\n    margin:16px 0 4px;\n  }\n  #jv-ring-sizer .ringwrap{\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.04em;\n    text-transform:uppercase;\n    color:var(--jv-brown);\n  }\n  #jv-ring-sizer .ring{\n    border:1.5px solid var(--jv-black);\n    border-radius:50%;\n    margin:0 auto 5px;\n  }\n\n  \/* ---- vertical ruler ---- *\/\n  #jv-ring-sizer .rulerwrap{\n    position:relative;\n    margin:18px 0 8px;\n  }\n  #jv-ring-sizer .ruler{\n    position:relative;\n    border-left:2px solid var(--jv-black);\n    margin-left:2px;\n  }\n  #jv-ring-sizer .tick{\n    position:absolute;\n    left:0;\n    height:0;\n    border-top:1px solid var(--jv-brown);\n    width:5px;\n  }\n  #jv-ring-sizer .tick.mid{width:10px;}\n  #jv-ring-sizer .tick.major{\n    width:17px;\n    border-top:1.5px solid var(--jv-black);\n  }\n  #jv-ring-sizer .tick .lbl{\n    position:absolute;\n    left:21px;\n    top:-6px;\n    font-size:9px;\n    color:var(--jv-black);\n    white-space:nowrap;\n  }\n  #jv-ring-sizer .mark{\n    position:absolute;\n    left:0;\n    height:0;\n    border-top:1px dashed var(--jv-tan);\n  }\n  #jv-ring-sizer .mark .lbl{\n    position:absolute;\n    top:-6px;\n    font-size:10px;\n    color:var(--jv-brown);\n    white-space:nowrap;\n    background:var(--jv-white);\n    padding:0 3px;\n  }\n\n  \/* ---- table + notes ---- *\/\n  #jv-ring-sizer table{\n    width:100%;\n    border-collapse:collapse;\n    font-size:12px;\n    margin-top:14px;\n  }\n  #jv-ring-sizer th, #jv-ring-sizer td{\n    border-bottom:1px solid var(--jv-line);\n    padding:7px 4px;\n    text-align:center;\n  }\n  #jv-ring-sizer th{\n    text-transform:uppercase;\n    font-size:10px;\n    letter-spacing:0.06em;\n    color:var(--jv-brown);\n    font-weight:700;\n  }\n  #jv-ring-sizer .note{\n    font-size:11px;\n    color:var(--jv-tan);\n    margin:10px 0 0;\n  }\n  #jv-ring-sizer .rule-note{\n    font-size:12px;\n    color:var(--jv-black);\n    border-left:2px solid var(--jv-black);\n    padding:2px 0 2px 10px;\n    margin:16px 0 0;\n  }\n  #jv-ring-sizer .check{\n    margin:18px 0 0;\n    font-size:11px;\n    color:var(--jv-brown);\n  }\n  #jv-ring-sizer .checkbar{\n    height:8px;\n    border:1px solid var(--jv-black);\n    border-top:none;\n    margin-top:3px;\n  }\n  #jv-ring-sizer .warn{\n    font-size:12px;\n    background:#f6f2ec;\n    border-left:2px solid var(--jv-tan);\n    padding:9px 10px;\n    margin:0 0 14px;\n    color:var(--jv-brown);\n    display:none;\n  }\n  #jv-ring-sizer .warn.on{display:block;}\n  #jv-ring-sizer .recal{\n    display:block;\n    text-align:center;\n    font-size:10px;\n    letter-spacing:0.06em;\n    text-transform:uppercase;\n    text-decoration:underline;\n    color:var(--jv-brown);\n    background:none;\n    border:none;\n    width:auto;\n    margin:22px auto 0;\n    padding:6px;\n  }\n  #jv-ring-sizer .sr{\n    position:absolute;\n    width:1px;height:1px;\n    padding:0;margin:-1px;\n    overflow:hidden;\n    clip:rect(0,0,0,0);\n    white-space:nowrap;border:0;\n  }\n\u003c\/style\u003e\n\n\n\u003cdiv id=\"jv-ring-sizer\"\u003e\n\n  \u003ch2\u003emedí tu talle de anillo\u003c\/h2\u003e\n  \u003cp\u003ecalibrá la pantalla una vez. después medís desde el celular o la computadora.\u003c\/p\u003e\n\n  \u003c!-- ============ PASO 1 · CALIBRACIÓN ============ --\u003e\n  \u003cdiv class=\"step\" id=\"step-cal\"\u003e\n    \u003cspan class=\"tag\"\u003epaso 1 · calibración\u003c\/span\u003e\n    \u003cp\u003eapoyá una tarjeta sobre la pantalla — crédito, débito o la cédula. en vertical, alineada\n       con la esquina de arriba a la izquierda. movés el control hasta que el ancho del rectángulo\n       coincida con el ancho de la tarjeta.\u003c\/p\u003e\n\n    \u003cdiv class=\"calarea\" id=\"calArea\"\u003e\n      \u003cdiv class=\"calcard\" id=\"calCard\"\u003e\n        \u003cspan class=\"corner\"\u003e\u003c\/span\u003e\n        \u003cspan class=\"cardlbl\"\u003eancho de la tarjeta\u003c\/span\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"calrow\"\u003e\n      \u003cbutton class=\"nudge\" id=\"calDown\" aria-label=\"reducir el ancho\"\u003e−\u003c\/button\u003e\n      \u003cinput type=\"range\" id=\"calSlider\" aria-label=\"ajustar el ancho del rectángulo hasta que coincida con la tarjeta\"\u003e\n      \u003cbutton class=\"nudge\" id=\"calUp\" aria-label=\"aumentar el ancho\"\u003e+\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003cbutton id=\"calConfirm\"\u003econfirmar\u003c\/button\u003e\n    \u003cp class=\"note\"\u003eel zoom del navegador tiene que estar al 100%. si tenés activado el zoom de\n       accesibilidad o el modo lupa, la medida no va a dar.\u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003c!-- ============ PASO 2 · HERRAMIENTA ============ --\u003e\n  \u003cdiv class=\"step\" id=\"step-tool\"\u003e\n\n    \u003cdiv class=\"warn\" id=\"dprWarn\"\u003e\n      cambió el zoom o la pantalla desde la última vez que calibraste. conviene recalibrar antes de medir.\n    \u003c\/div\u003e\n\n    \u003cdiv class=\"tabs\" role=\"tablist\" aria-label=\"método de medición\"\u003e\n      \u003cbutton role=\"tab\" id=\"tabA\" aria-selected=\"true\" aria-controls=\"panelA\"\u003ecomparar un anillo\u003c\/button\u003e\n      \u003cbutton role=\"tab\" id=\"tabB\" aria-selected=\"false\" aria-controls=\"panelB\"\u003emedir el dedo\u003c\/button\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- opción A --\u003e\n    \u003cdiv class=\"panel on\" id=\"panelA\" role=\"tabpanel\" aria-labelledby=\"tabA\"\u003e\n      \u003cspan class=\"tag\"\u003eopción a\u003c\/span\u003e\n      \u003cp\u003eapoyá un anillo que ya te calce bien sobre los círculos. el talle es el círculo cuyo\n         borde exterior queda justo por dentro del anillo.\u003c\/p\u003e\n      \u003cdiv class=\"rings\" id=\"ringsGrid\"\u003e\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003c!-- opción B --\u003e\n    \u003cdiv class=\"panel\" id=\"panelB\" role=\"tabpanel\" aria-labelledby=\"tabB\"\u003e\n      \u003cspan class=\"tag\"\u003eopción b\u003c\/span\u003e\n      \u003cp\u003eenvolvé una tira de papel o un hilo en la base del dedo, donde va a quedar el anillo.\n         marcá el punto donde se superpone. después estirá la tira sobre la regla, arrancando\n         desde el cero.\u003c\/p\u003e\n      \u003cdiv class=\"rulerwrap\"\u003e\n        \u003cdiv class=\"ruler\" id=\"ruler\"\u003e\u003c\/div\u003e\n      \u003c\/div\u003e\n      \u003cp class=\"note\"\u003elas líneas punteadas son la circunferencia de cada talle.\u003c\/p\u003e\n    \u003c\/div\u003e\n\n    \u003ctable\u003e\n      \u003ccaption class=\"sr\"\u003etalles disponibles con su diámetro y circunferencia\u003c\/caption\u003e\n      \u003cthead\u003e\u003ctr\u003e\n\u003cth scope=\"col\"\u003etalle\u003c\/th\u003e\n\u003cth scope=\"col\"\u003ediámetro\u003c\/th\u003e\n\u003cth scope=\"col\"\u003ecircunferencia\u003c\/th\u003e\n\u003c\/tr\u003e\u003c\/thead\u003e\n      \u003ctbody id=\"refBody\"\u003e\u003c\/tbody\u003e\n    \u003c\/table\u003e\n\n    \u003cp class=\"rule-note\"\u003esi te queda entre dos talles, elegí el mayor.\u003c\/p\u003e\n\n    \u003cdiv class=\"check\"\u003e\n      control: esta línea mide 50 mm. si tenés una regla a mano, verificá.\n      \u003cdiv class=\"checkbar\" id=\"checkBar\"\u003e\u003c\/div\u003e\n    \u003c\/div\u003e\n\n    \u003cp class=\"note\"\u003ees una medida aproximada — sirve para orientarte, no es exacta al milímetro.\n       el dedo cambia de grosor con el calor y la hora del día.\u003c\/p\u003e\n\n    \u003cbutton class=\"recal\" id=\"recalBtn\"\u003erecalibrar pantalla\u003c\/button\u003e\n  \u003c\/div\u003e\n\n\u003c\/div\u003e\n\n\u003cscript\u003e\n(function(){\n  'use strict';\n\n  var STORAGE_KEY = 'jv_ring_sizer_cal_v2';\n\n  \/\/ ISO\/IEC 7810 ID-1 — short side. The long side (85.6mm) is wider than most\n  \/\/ phone screens, so calibration has to happen on the short side.\n  var CARD_SHORT_MM = 53.98;\n  var CARD_LONG_MM  = 85.60;\n  var CARD_MAX_H_PX = 190;\n\n  var MIN_PPM = 1.6;   \/\/ absolute plausibility floor\n  var MAX_PPM = 22;    \/\/ absolute plausibility ceiling\n  var BASE_PPM = 96 \/ 25.4;\n\n  var SIZES = [\n    {size:6,  d:16.5},\n    {size:7,  d:17.3},\n    {size:8,  d:18.1},\n    {size:9,  d:19.0},\n    {size:10, d:19.8},\n    {size:11, d:20.6}\n  ];\n  SIZES.forEach(function(s){ s.c = s.d * Math.PI; });\n\n  var RULER_MAX_MM = 72;   \/\/ clears size 11 (~64.7mm) with room to read\n\n  var root      = document.getElementById('jv-ring-sizer');\n  var stepCal   = root.querySelector('#step-cal');\n  var stepTool  = root.querySelector('#step-tool');\n  var calArea   = root.querySelector('#calArea');\n  var calCard   = root.querySelector('#calCard');\n  var calSlider = root.querySelector('#calSlider');\n  var calUp     = root.querySelector('#calUp');\n  var calDown   = root.querySelector('#calDown');\n  var calConfirm= root.querySelector('#calConfirm');\n  var recalBtn  = root.querySelector('#recalBtn');\n  var dprWarn   = root.querySelector('#dprWarn');\n  var tabA      = root.querySelector('#tabA');\n  var tabB      = root.querySelector('#tabB');\n  var panelA    = root.querySelector('#panelA');\n  var panelB    = root.querySelector('#panelB');\n  var ringsGrid = root.querySelector('#ringsGrid');\n  var ruler     = root.querySelector('#ruler');\n  var refBody   = root.querySelector('#refBody');\n  var checkBar  = root.querySelector('#checkBar');\n\n  var pxPerMm = null;\n\n  \/* ---------- storage (may throw in partitioned\/blocked contexts) ---------- *\/\n  function readCal(){\n    try{\n      var raw = window.localStorage.getItem(STORAGE_KEY);\n      if(!raw) return null;\n      var o = JSON.parse(raw);\n      var p = parseFloat(o \u0026\u0026 o.ppm);\n      if(!isFinite(p) || p \u003c MIN_PPM || p \u003e MAX_PPM) return null;\n      return {ppm:p, dpr:parseFloat(o.dpr) || null};\n    }catch(e){ return null; }\n  }\n  function writeCal(ppm){\n    try{\n      window.localStorage.setItem(STORAGE_KEY, JSON.stringify({\n        ppm:ppm, dpr:window.devicePixelRatio || 1, ts:Date.now()\n      }));\n    }catch(e){ \/* sin persistencia: la calibración vale para esta sesión *\/ }\n  }\n  function clearCal(){\n    try{ window.localStorage.removeItem(STORAGE_KEY); }catch(e){}\n  }\n\n  \/* ---------- available width ---------- *\/\n  function availWidth(){\n    var w = calArea.clientWidth || root.clientWidth || 320;\n    return Math.max(120, w);\n  }\n\n  \/* ---------- calibration step ---------- *\/\n  function sliderBounds(){\n    \/\/ Cap so the calibration rectangle can never overflow its container.\n    var maxPpm = availWidth() \/ CARD_SHORT_MM;\n    var minPpm = MIN_PPM;\n    if(maxPpm \u003c minPpm + 0.5) maxPpm = minPpm + 0.5;\n    return {min:minPpm, max:maxPpm};\n  }\n\n  function drawCalCard(ppm){\n    var w = CARD_SHORT_MM * ppm;\n    var h = Math.min(CARD_LONG_MM * ppm, CARD_MAX_H_PX);\n    calCard.style.width  = w + 'px';\n    calCard.style.height = h + 'px';\n  }\n\n  function setupCalStep(){\n    var b = sliderBounds();\n    var current = parseFloat(calSlider.value);\n    var start = (isFinite(current) \u0026\u0026 current \u003e= b.min \u0026\u0026 current \u003c= b.max)\n      ? current\n      : Math.min(Math.max(pxPerMm || BASE_PPM, b.min), b.max);\n\n    calSlider.min = b.min.toFixed(3);\n    calSlider.max = b.max.toFixed(3);\n    calSlider.step = '0.005';\n    calSlider.value = start;\n    drawCalCard(start);\n  }\n\n  function nudge(delta){\n    var b = sliderBounds();\n    var v = Math.min(Math.max(parseFloat(calSlider.value) + delta, b.min), b.max);\n    calSlider.value = v;\n    drawCalCard(v);\n  }\n\n  calSlider.addEventListener('input', function(){\n    drawCalCard(parseFloat(calSlider.value));\n  });\n  calUp.addEventListener('click',   function(){ nudge(0.02); });\n  calDown.addEventListener('click', function(){ nudge(-0.02); });\n\n  calConfirm.addEventListener('click', function(){\n    var v = parseFloat(calSlider.value);\n    if(!isFinite(v) || v \u003c MIN_PPM || v \u003e MAX_PPM) return;\n    pxPerMm = v;\n    writeCal(pxPerMm);\n    dprWarn.classList.remove('on');\n    renderTool();\n    stepTool.scrollIntoView({block:'start'});\n  });\n\n  recalBtn.addEventListener('click', function(){\n    clearCal();\n    showStep('cal');\n    setupCalStep();\n    stepCal.scrollIntoView({block:'start'});\n  });\n\n  \/* ---------- tabs ---------- *\/\n  function switchTab(which){\n    var isA = (which === 'A');\n    tabA.setAttribute('aria-selected', isA ? 'true' : 'false');\n    tabB.setAttribute('aria-selected', isA ? 'false' : 'true');\n    panelA.classList.toggle('on', isA);\n    panelB.classList.toggle('on', !isA);\n  }\n  tabA.addEventListener('click', function(){ switchTab('A'); });\n  tabB.addEventListener('click', function(){ switchTab('B'); });\n  [tabA, tabB].forEach(function(t){\n    t.addEventListener('keydown', function(e){\n      if(e.key === 'ArrowRight'){ switchTab('B'); tabB.focus(); }\n      if(e.key === 'ArrowLeft'){ switchTab('A'); tabA.focus(); }\n    });\n  });\n\n  function showStep(which){\n    stepCal.classList.toggle('active', which === 'cal');\n    stepTool.classList.toggle('active', which === 'tool');\n  }\n\n  \/* ---------- render: rings ---------- *\/\n  function renderRings(){\n    ringsGrid.innerHTML = '';\n    var maxPx = 0;\n    SIZES.forEach(function(s){ maxPx = Math.max(maxPx, s.d * pxPerMm); });\n\n    \/\/ Columns must fit the largest circle, otherwise rings overflow their cell.\n    var avail = availWidth();\n    var cols = Math.max(1, Math.floor((avail + 10) \/ (maxPx + 10)));\n    cols = Math.min(cols, SIZES.length);\n    ringsGrid.style.gridTemplateColumns = 'repeat(' + cols + ', 1fr)';\n\n    SIZES.forEach(function(s){\n      var px = s.d * pxPerMm;\n      var wrap = document.createElement('div');\n      wrap.className = 'ringwrap';\n      var ring = document.createElement('div');\n      ring.className = 'ring';\n      ring.style.width  = px + 'px';\n      ring.style.height = px + 'px';\n      wrap.appendChild(ring);\n      wrap.appendChild(document.createTextNode('talle ' + s.size));\n      ringsGrid.appendChild(wrap);\n    });\n  }\n\n  \/* ---------- render: vertical ruler ---------- *\/\n  function renderRuler(){\n    ruler.innerHTML = '';\n    ruler.style.height = (RULER_MAX_MM * pxPerMm) + 'px';\n\n    for(var mm = 0; mm \u003c= RULER_MAX_MM; mm++){\n      var tick = document.createElement('div');\n      var cls = 'tick';\n      if(mm % 10 === 0) cls += ' major';\n      else if(mm % 5 === 0) cls += ' mid';\n      tick.className = cls;\n      tick.style.top = (mm * pxPerMm) + 'px';\n      if(mm % 10 === 0){\n        var lbl = document.createElement('span');\n        lbl.className = 'lbl';\n        lbl.textContent = mm + ' mm';\n        tick.appendChild(lbl);\n      }\n      ruler.appendChild(tick);\n    }\n\n    \/\/ Size marks stagger across two columns: consecutive sizes are ~2.5mm apart,\n    \/\/ which is under 10px on a low-density screen — too tight for one column.\n    var cols = [86, 210];\n    SIZES.forEach(function(s, i){\n      var mark = document.createElement('div');\n      mark.className = 'mark';\n      mark.style.top = (s.c * pxPerMm) + 'px';\n      mark.style.width = (cols[i % 2] + 60) + 'px';\n      var lbl = document.createElement('span');\n      lbl.className = 'lbl';\n      lbl.style.left = cols[i % 2] + 'px';\n      lbl.textContent = 'talle ' + s.size + ' · ' + fmt(s.c) + ' mm';\n      mark.appendChild(lbl);\n      ruler.appendChild(mark);\n    });\n  }\n\n  \/* ---------- render: table + check bar ---------- *\/\n  function fmt(n){ return n.toFixed(1).replace('.', ','); }\n\n  function renderTable(){\n    refBody.innerHTML = '';\n    SIZES.forEach(function(s){\n      var tr = document.createElement('tr');\n      var cells = [String(s.size), fmt(s.d) + ' mm', fmt(s.c) + ' mm'];\n      cells.forEach(function(txt){\n        var td = document.createElement('td');\n        td.textContent = txt;\n        tr.appendChild(td);\n      });\n      refBody.appendChild(tr);\n    });\n  }\n\n  function renderCheck(){\n    checkBar.style.width = (50 * pxPerMm) + 'px';\n  }\n\n  function renderTool(){\n    renderRings();\n    renderRuler();\n    renderTable();\n    renderCheck();\n    showStep('tool');\n  }\n\n  \/* ---------- resize \/ orientation ---------- *\/\n  var rt;\n  window.addEventListener('resize', function(){\n    clearTimeout(rt);\n    rt = setTimeout(function(){\n      if(stepCal.classList.contains('active')) setupCalStep();\n      else if(pxPerMm) renderRings();\n    }, 150);\n  });\n\n  \/* ---------- init ---------- *\/\n  var saved = readCal();\n  if(saved){\n    pxPerMm = saved.ppm;\n    \/\/ A changed devicePixelRatio usually means the browser zoom changed,\n    \/\/ which invalidates the stored calibration.\n    var dprNow = window.devicePixelRatio || 1;\n    if(saved.dpr \u0026\u0026 Math.abs(saved.dpr - dprNow) \u003e 0.01){\n      dprWarn.classList.add('on');\n    }\n    renderTool();\n  }else{\n    showStep('cal');\n    setupCalStep();\n  }\n})();\n\u003c\/script\u003e\n\u003c\/body\u003e","brand":"Just Vero","offers":[{"title":"9","offer_id":56863530778790,"sku":null,"price":1990.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/D06CFA5C-271D-4739-985C-E2722AB4268A.jpg?v=1784998787"},{"product_id":"cross-medallion","title":"CROSS MEDALLION","description":"\u003cp\u003e-Largo 115cm\u003c\/p\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":56880917053606,"sku":null,"price":1990.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_3691.jpg?v=1785370423"},{"product_id":"sacred-oval","title":"SACRED OVAL","description":"\u003cp\u003e-Largo 115cm\u003c\/p\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":56880930750630,"sku":null,"price":1990.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_3688.jpg?v=1785370863"},{"product_id":"fleur-relic","title":"FILIGREE RELIC","description":"\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eDije en Aleación de 60% Cobre y 30% Zinc con un 10% de Acabado Metálico de alta resistencia.\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eCadena acero inoxidable\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eAcabado envejecido y textura marcada\u003cbr\u003e\u003c\/p\u003e\n\u003c\/li\u003e\n\u003cli\u003e\n\u003cp\u003eEvita mojarlo o exponerlo a humedad\u003c\/p\u003e\n\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Just Vero","offers":[{"title":"Default Title","offer_id":56880995500198,"sku":null,"price":1990.0,"currency_code":"UYU","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0572\/8439\/5174\/files\/IMG_3680.jpg?v=1785373633"}],"url":"https:\/\/justveroaccs.com\/collections\/menos-de-2000.oembed?page=2","provider":"Just Vero","version":"1.0","type":"link"}