{"product_id":"the-elan-bracelet","title":"The Élan Bracelet","description":"\u003cdiv style=\"max-width: 760px; margin: 0 auto; color: #2a2520; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif; line-height: 1.75;\"\u003e\n\n  \u003cdiv style=\"text-align: center; margin-bottom: 34px;\"\u003e\n    \u003ch2 style=\"font-family: Georgia, 'Times New Roman', serif; font-size: 30px; font-weight: 400; letter-spacing: 0.04em; margin: 0 0 10px;\"\u003e\n      The Élan Bracelet\n    \u003c\/h2\u003e\n\n    \u003cp style=\"font-family: Georgia, 'Times New Roman', serif; font-size: 17px; font-style: italic; margin: 0; color: #6d6258;\"\u003e\n      Elevated. Every day.\n    \u003c\/p\u003e\n  \u003c\/div\u003e\n\n  \u003cdiv style=\"height: 1px; background: #ddd6cf; margin: 0 auto 30px; max-width: 70px;\"\u003e\u003c\/div\u003e\n\n  \u003cp style=\"font-size: 16px; margin-bottom: 22px;\"\u003e\n    An everyday signature with a confident presence.\n  \u003c\/p\u003e\n\n  \u003cp style=\"font-size: 16px; margin-bottom: 22px;\"\u003e\n    The Élan Bracelet pairs a slim, flat stainless-steel bangle with a warm gold-tone finish and evenly spaced round stone accents. Its clean silhouette brings a considered finishing touch to a crisp shirt, a favourite knit or evening tailoring.\n  \u003c\/p\u003e\n\n  \u003cp style=\"font-size: 16px; margin-bottom: 30px;\"\u003e\n    Wear it alone to appreciate its detail, or alongside another Maison Beaumont bracelet to make the combination your own.\n  \u003c\/p\u003e\n\n  \u003cdiv style=\"border-top: 1px solid #ddd6cf; border-bottom: 1px solid #ddd6cf; padding: 22px 0; margin-bottom: 32px;\"\u003e\n\n    \u003cp style=\"margin: 0 0 10px; font-size: 15px;\"\u003e\n      \u003cstrong\u003eMaterial:\u003c\/strong\u003e Stainless steel\n    \u003c\/p\u003e\n\n    \u003cp style=\"margin: 0 0 10px; font-size: 15px;\"\u003e\n      \u003cstrong\u003eColour:\u003c\/strong\u003e Gold-tone\n    \u003c\/p\u003e\n\n    \u003cp style=\"margin: 0; font-size: 15px;\"\u003e\n      \u003cstrong\u003eDetail:\u003c\/strong\u003e Spaced round stone accents\n    \u003c\/p\u003e\n\n  \u003c\/div\u003e\n\n  \u003cdiv style=\"margin-bottom: 34px;\"\u003e\n\n    \u003ch3 style=\"font-family: Georgia, 'Times New Roman', serif; font-size: 21px; font-weight: 400; letter-spacing: 0.04em; margin: 0 0 15px;\"\u003e\n      Care\n    \u003c\/h3\u003e\n\n    \u003cp style=\"font-size: 15px; margin: 0;\"\u003e\n      Avoid prolonged contact with perfumes, lotions, chlorine and harsh chemicals.\n      Wipe gently with a soft, dry cloth after wear and store in a dry place.\n    \u003c\/p\u003e\n\n  \u003c\/div\u003e\n\n  \u003cdiv style=\"text-align: center; background: #faf8f5; padding: 28px 20px; margin: 34px 0;\"\u003e\n\n    \u003ch3 style=\"font-family: Georgia, 'Times New Roman', serif; font-size: 21px; font-weight: 400; letter-spacing: 0.05em; margin: 0 0 10px;\"\u003e\n      SEE IT ON YOU\n    \u003c\/h3\u003e\n\n    \u003cp style=\"font-size: 15px; margin: 0; color: #6d6258;\"\u003e\n      Bring The Élan Bracelet to your wrist.\n    \u003c\/p\u003e\n\n    \u003cp style=\"font-size: 15px; margin: 5px 0 0; color: #6d6258;\"\u003e\n      Try it on virtually and discover how it looks on you.\n    \u003c\/p\u003e\n\n  \u003c\/div\u003e\n\n  \u003cdiv style=\"height: 1px; background: #ddd6cf; margin: 0 auto 25px; max-width: 70px;\"\u003e\u003c\/div\u003e\n\n  \u003cp style=\"text-align: center; font-family: Georgia, 'Times New Roman', serif; font-size: 14px; letter-spacing: 0.12em; margin: 0;\"\u003e\n    MAISON BEAUMONT — YOU ARE THE OCCASION.\n  \u003c\/p\u003e\n\n\u003c\/div\u003e\n\n\n\n\u003cstyle\u003e\n  #mb-nacre-vto {\n    width: 100%;\n    margin: 20px 0;\n    font-family: Arial, Helvetica, sans-serif;\n  }\n\n  #mb-nacre-open {\n    display: block;\n    width: 100%;\n    max-width: 420px;\n    margin: 0 auto;\n    padding: 16px 24px;\n    border: 0;\n    border-radius: 999px;\n    background: #111;\n    color: #fff;\n    font-size: 13px;\n    font-weight: 600;\n    letter-spacing: 2px;\n    text-align: center;\n    cursor: pointer;\n    appearance: none;\n    -webkit-appearance: none;\n  }\n\n  #mb-nacre-modal {\n    display: none;\n    position: fixed;\n    inset: 0;\n    z-index: 2147483647;\n    width: 100vw;\n    height: 100vh;\n    background: #000;\n    overflow: hidden;\n  }\n\n  #mb-nacre-modal.mb-open {\n    display: block;\n  }\n\n  #mb-nacre-stage {\n    position: fixed;\n    inset: 0;\n    width: 100vw;\n    height: 100vh;\n    overflow: hidden;\n    background: #000;\n  }\n\n  \/*\n   * WebAR.rocks uses TWO canvases:\n   * 1. handTrackerCanvas = camera\/video + tracking\n   * 2. VTOCanvas = bracelet\n   *\/\n  #mb-nacre-handTrackerCanvas,\n  #mb-nacre-VTOCanvas {\n    position: fixed;\n    top: 0;\n    left: 0;\n    width: 100vw;\n    height: 100vh;\n  }\n\n  #mb-nacre-handTrackerCanvas {\n    z-index: 1;\n  }\n\n  #mb-nacre-VTOCanvas {\n    z-index: 2;\n    pointer-events: none;\n  }\n\n  #mb-nacre-close {\n    position: fixed;\n    top: max(18px, env(safe-area-inset-top));\n    right: 18px;\n    z-index: 20;\n\n    width: 46px;\n    height: 46px;\n\n    border: 0;\n    border-radius: 50%;\n\n    background: rgba(0,0,0,.58);\n    color: #fff;\n\n    font-size: 30px;\n    line-height: 46px;\n    text-align: center;\n\n    padding: 0;\n    margin: 0;\n\n    cursor: pointer;\n    -webkit-appearance: none;\n    appearance: none;\n  }\n\n  #mb-nacre-loading {\n    position: fixed;\n    inset: 0;\n    z-index: 15;\n\n    display: flex;\n    align-items: center;\n    justify-content: center;\n\n    background: #000;\n    color: #fff;\n\n    text-align: center;\n\n    transition: opacity .35s ease;\n  }\n\n  #mb-nacre-loading-inner {\n    width: min(85vw, 320px);\n  }\n\n  #mb-nacre-loading-title {\n    font-size: 15px;\n    letter-spacing: 3px;\n    margin-bottom: 14px;\n  }\n\n  #mb-nacre-loading-text {\n    font-size: 13px;\n    line-height: 1.6;\n    opacity: .75;\n  }\n\n  #mb-nacre-error {\n    position: fixed;\n    left: 20px;\n    right: 20px;\n    bottom: 30px;\n    z-index: 30;\n\n    display: none;\n\n    padding: 16px 18px;\n    border-radius: 12px;\n\n    background: rgba(0,0,0,.82);\n    color: #fff;\n\n    font-size: 13px;\n    line-height: 1.5;\n    text-align: center;\n  }\n\n  #mb-nacre-hint {\n    position: fixed;\n    left: 20px;\n    right: 20px;\n    bottom: max(24px, env(safe-area-inset-bottom));\n    z-index: 10;\n\n    color: #fff;\n    text-align: center;\n\n    font-size: 13px;\n    letter-spacing: .5px;\n\n    text-shadow:\n      0 1px 4px #000,\n      0 2px 8px #000;\n\n    pointer-events: none;\n  }\n\u003c\/style\u003e\n\n\n\u003cdiv id=\"mb-nacre-vto\"\u003e\n\n  \u003cbutton id=\"mb-nacre-open\" type=\"button\"\u003e\n    TRY IT ON\n  \u003c\/button\u003e\n\n\n  \u003cdiv id=\"mb-nacre-modal\"\u003e\n\n    \u003cdiv id=\"mb-nacre-stage\"\u003e\n\n      \u003c!-- WebAR.rocks camera \/ tracking canvas --\u003e\n      \u003ccanvas id=\"mb-nacre-handTrackerCanvas\"\u003e\u003c\/canvas\u003e\n\n      \u003c!-- Three.js bracelet canvas --\u003e\n      \u003ccanvas id=\"mb-nacre-VTOCanvas\"\u003e\u003c\/canvas\u003e\n\n      \u003cbutton id=\"mb-nacre-close\" type=\"button\" aria-label=\"Close try on\"\u003e\n        ×\n      \u003c\/button\u003e\n\n      \u003cdiv id=\"mb-nacre-loading\"\u003e\n        \u003cdiv id=\"mb-nacre-loading-inner\"\u003e\n\n          \u003cdiv id=\"mb-nacre-loading-title\"\u003e\n            MAISON BEAUMONT\n          \u003c\/div\u003e\n\n          \u003cdiv id=\"mb-nacre-loading-text\"\u003e\n            Starting your virtual try-on…\n          \u003c\/div\u003e\n\n        \u003c\/div\u003e\n      \u003c\/div\u003e\n\n      \u003cdiv id=\"mb-nacre-hint\"\u003e\n        Place your wrist in view.\n      \u003c\/div\u003e\n\n      \u003cdiv id=\"mb-nacre-error\"\u003e\u003c\/div\u003e\n\n    \u003c\/div\u003e\n\n  \u003c\/div\u003e\n\n\u003c\/div\u003e\n\n\n\u003cscript\u003e\n(function () {\n\n  \"use strict\";\n\n\n  \/*\n   * ============================================================\n   * MAISON BEAUMONT — NACRE WRIST VTO\n   *\n   * Uses the official WebAR.rocks wrist VTO architecture.\n   * ============================================================\n   *\/\n\n\n  const MODEL_URL =\n    \"https:\/\/cdn.shopify.com\/3d\/models\/7917e5bf8b1aebb2\/maison_beaumont_elan_vto_corrected.glb\";\n\n\n  const CDN =\n    \"https:\/\/cdn.jsdelivr.net\/gh\/WebAR-rocks\/WebAR.rocks.hand@master\/\";\n\n\n  const SCRIPT_URLS = [\n\n    CDN + \"dist\/WebARRocksHand.js\",\n\n    CDN + \"libs\/three\/v136\/build\/three.min.js\",\n\n    CDN + \"libs\/three\/v136\/examples\/js\/loaders\/GLTFLoader.js\",\n\n    CDN + \"helpers\/HandTrackerThreeHelper.js\",\n\n    CDN + \"helpers\/landmarksStabilizers\/OneEuroLMStabilizer.js\",\n\n    CDN + \"helpers\/PoseFlipFilter.js\"\n\n  ];\n\n\n  const NN_URL =\n    CDN + \"neuralNets\/NN_WRISTBACK_45.json\";\n\n\n  const openButton =\n    document.getElementById(\n      \"mb-nacre-open\"\n    );\n\n\n  const closeButton =\n    document.getElementById(\n      \"mb-nacre-close\"\n    );\n\n\n  const modal =\n    document.getElementById(\n      \"mb-nacre-modal\"\n    );\n\n\n  const loading =\n    document.getElementById(\n      \"mb-nacre-loading\"\n    );\n\n\n  const loadingText =\n    document.getElementById(\n      \"mb-nacre-loading-text\"\n    );\n\n\n  const errorBox =\n    document.getElementById(\n      \"mb-nacre-error\"\n    );\n\n\n  const handTrackerCanvas =\n    document.getElementById(\n      \"mb-nacre-handTrackerCanvas\"\n    );\n\n\n  const VTOCanvas =\n    document.getElementById(\n      \"mb-nacre-VTOCanvas\"\n    );\n\n\n  let isOpen = false;\n  let isStarting = false;\n  let scriptsLoaded = false;\n  let trackerReady = false;\n\n\n  \/*\n   * ------------------------------------------------------------\n   * LOAD EXTERNAL SCRIPT\n   * ------------------------------------------------------------\n   *\/\n\n  function loadScript(src) {\n\n    return new Promise(function (\n      resolve,\n      reject\n    ) {\n\n      \/*\n       * Don't load the same script twice.\n       *\/\n      const existing =\n        document.querySelector(\n          'script[src=\"' + src + '\"]'\n        );\n\n      if (existing) {\n\n        \/*\n         * If the global is already available,\n         * continue immediately.\n         *\/\n        resolve();\n        return;\n      }\n\n\n      const script =\n        document.createElement(\n          \"script\"\n        );\n\n\n      script.src = src;\n\n      script.async = false;\n\n      script.onload =\n        function () {\n          resolve();\n        };\n\n      script.onerror =\n        function () {\n\n          reject(\n            new Error(\n              \"Could not load WebAR component.\"\n            )\n          );\n\n        };\n\n\n      document.head.appendChild(\n        script\n      );\n\n    });\n\n  }\n\n\n  \/*\n   * ------------------------------------------------------------\n   * LOAD WEBAR.ROCKS\n   * ------------------------------------------------------------\n   *\/\n\n  async function loadWebARRocks() {\n\n    if (scriptsLoaded) {\n      return;\n    }\n\n\n    loadingText.textContent =\n      \"Preparing virtual try-on…\";\n\n\n    for (\n      let i = 0;\n      i \u003c SCRIPT_URLS.length;\n      i++\n    ) {\n\n      await loadScript(\n        SCRIPT_URLS[i]\n      );\n\n    }\n\n\n    scriptsLoaded = true;\n\n  }\n\n\n  \/*\n   * ------------------------------------------------------------\n   * SIZE CANVASES\n   *\n   * This follows the official WebAR.rocks\n   * wrist VTO canvas sizing approach.\n   * ------------------------------------------------------------\n   *\/\n\n  function sizeCanvases() {\n\n    const pixelRatio =\n      window.devicePixelRatio || 1;\n\n\n    const width =\n      window.innerWidth;\n\n\n    const height =\n      window.innerHeight;\n\n\n    const canvasWidth =\n      pixelRatio *\n      Math.min(\n        width,\n        height * 0.75\n      );\n\n\n    const canvasHeight =\n      pixelRatio *\n      height;\n\n\n    handTrackerCanvas.width =\n      canvasWidth;\n\n\n    handTrackerCanvas.height =\n      canvasHeight;\n\n\n    VTOCanvas.width =\n      canvasWidth;\n\n\n    VTOCanvas.height =\n      canvasHeight;\n\n  }\n\n\n  \/*\n   * ------------------------------------------------------------\n   * ADD LIGHTING\n   * ------------------------------------------------------------\n   *\/\n\n  function addLighting(three) {\n\n    const scene =\n      three.scene;\n\n\n    const ambient =\n      new THREE.AmbientLight(\n        0xffffff,\n        2.0\n      );\n\n\n    scene.add(\n      ambient\n    );\n\n\n    const key =\n      new THREE.DirectionalLight(\n        0xffffff,\n        2.8\n      );\n\n\n    key.position.set(\n      2,\n      4,\n      6\n    );\n\n\n    scene.add(\n      key\n    );\n\n\n    const fill =\n      new THREE.DirectionalLight(\n        0xffffff,\n        1.8\n      );\n\n\n    fill.position.set(\n      -3,\n      1,\n      4\n    );\n\n\n    scene.add(\n      fill\n    );\n\n  }\n\n\n  \/*\n   * ------------------------------------------------------------\n   * ADD WRIST OCCLUDER\n   *\n   * This is the important part that allows the\n   * wrist to visually sit in front of the bracelet.\n   * ------------------------------------------------------------\n   *\/\n\n  function addWristOccluder() {\n\n    const radiusRange = [\n      4,\n      4.7\n    ];\n\n\n    const occluderRadius =\n      radiusRange[1];\n\n\n    const occluderHeight =\n      48;\n\n\n    const occluder =\n      new THREE.Mesh(\n\n        new THREE.CylinderGeometry(\n          occluderRadius,\n          occluderRadius,\n          occluderHeight,\n          32,\n          1,\n          true\n        ),\n\n        new THREE.MeshNormalMaterial()\n\n      );\n\n\n    occluder.position.set(\n      0,\n      0,\n      0\n    );\n\n\n    \/*\n     * Official wrist VTO orientation.\n     *\/\n    occluder.quaternion.set(\n      0.707,\n      0,\n      0,\n      0.707\n    );\n\n\n    \/*\n     * Flatten the cylinder so it follows\n     * the shape of a wrist.\n     *\/\n    occluder.scale.set(\n      1,\n      1,\n      0.6\n    );\n\n\n    HandTrackerThreeHelper\n      .add_threeSoftOccluder(\n        occluder,\n        radiusRange[1],\n        radiusRange[1] - radiusRange[0],\n        false\n      );\n\n  }\n\n\n  \/*\n   * ------------------------------------------------------------\n   * LOAD NACRE MODEL\n   *\n   * IMPORTANT:\n   * We intentionally keep model.scene.\n   *\n   * Your GLB contains multiple meshes:\n   * gold band + pearlescent panels + stones.\n   * ------------------------------------------------------------\n   *\/\n\n  function loadNacreModel(\n    loadingManager\n  ) {\n\n    return new Promise(\n      function (\n        resolve,\n        reject\n      ) {\n\n\n        const loader =\n          new THREE.GLTFLoader(\n            loadingManager\n          );\n\n\n        loader.load(\n\n          MODEL_URL,\n\n          function (gltf) {\n\n            \/*\n             * KEEP THE WHOLE GLB.\n             *\/\n            const nacre =\n              gltf.scene;\n\n\n            \/*\n             * Make every mesh visible.\n             *\/\n            nacre.traverse(\n              function (\n                object\n              ) {\n\n                if (\n                  object.isMesh\n                ) {\n\n                  object.frustumCulled =\n                    false;\n\n\n                  if (\n                    object.material\n                  ) {\n\n                    object.material.side =\n                      THREE.DoubleSide;\n\n\n                    object.material.needsUpdate =\n                      true;\n\n                  }\n\n                }\n\n              }\n            );\n\n\n            \/*\n             * ------------------------------------------------\n             * NACRE MODEL ORIENTATION\n             *\n             * The Nacre details in the supplied GLB\n             * are on the opposite local side.\n             *\n             * Rotate the complete model 180° around\n             * its local Z axis so the pearlescent\n             * panels and stones face outward.\n             * ------------------------------------------------\n             *\/\n\n            nacre.rotation.z =\n              Math.PI;\n\n\n            \/*\n             * Official wrist demo scale baseline.\n             * The GLB itself is then attached to the\n             * WebAR.rocks wrist tracker.\n             *\/\n            nacre.scale.set(\n              1.2 * 1.462,\n              1.2 * 1.462,\n              1.2 * 1.462\n            );\n\n\n            \/*\n             * Attach the complete bracelet to\n             * the WebAR.rocks wrist tracker.\n             *\/\n            HandTrackerThreeHelper\n              .add_threeObject(\n                nacre\n              );\n\n\n            resolve();\n\n          },\n\n          undefined,\n\n          function (\n            error\n          ) {\n\n            reject(\n              error\n            );\n\n          }\n\n        );\n\n      }\n    );\n\n  }\n\n\n  \/*\n   * ------------------------------------------------------------\n   * INITIALIZE TRACKER\n   * ------------------------------------------------------------\n   *\/\n\n  async function initializeTracker() {\n\n    sizeCanvases();\n\n\n    loadingText.textContent =\n      \"Starting camera…\";\n\n\n    \/*\n     * Official wrist VTO settings.\n     *\n     * These are based on the current\n     * WebAR.rocks wrist demo.\n     *\/\n    const settings = {\n\n      threshold:\n        0.97,\n\n\n      poseLandmarksLabels: [\n\n        \"wristPinkySideBot\",\n\n        \"wristThumbSideBot\",\n\n        \"wristPinkySideTop\",\n\n        \"wristThumbSideTop\",\n\n        \"wristUpTop\",\n\n        \"wristUpBot\",\n\n        \"wristDownTop\",\n\n        \"wristDownBot\"\n\n      ],\n\n\n      modelOffset: [\n        0,\n        0,\n        0\n      ],\n\n\n      modelScale:\n        1.2 * 1.462,\n\n\n      NNsPaths: [\n        NN_URL\n      ],\n\n\n      objectPointsPositionFactors: [\n        1.0,\n        1.0,\n        1.0\n      ],\n\n\n      isPoseFilter:\n        true,\n\n\n      \/*\n       * Official soft wrist occlusion.\n       *\/\n      occluderRadiusRange: [\n        4,\n        4.7\n      ],\n\n\n      occluderHeight:\n        48,\n\n\n      occluderOffset: [\n        0,\n        0,\n        0\n      ],\n\n\n      occluderQuaternion: [\n        0.707,\n        0,\n        0,\n        0.707\n      ],\n\n\n      occluderFlattenCoeff:\n        0.6,\n\n\n      stabilizerOptions: {\n\n        minCutOff:\n          0.001,\n\n        beta:\n          4,\n\n        freqRange: [\n          2,\n          144\n        ],\n\n        forceFilterNNInputPxRange: [\n          2.5,\n          6\n        ]\n\n      }\n\n    };\n\n\n    \/*\n     * ------------------------------------------------\n     * INITIALIZE OFFICIAL THREE HELPER\n     * ------------------------------------------------\n     *\/\n\n    const three =\n      await HandTrackerThreeHelper.init({\n\n        landmarksStabilizerSpec:\n          settings.stabilizerOptions,\n\n\n        scanSettings: {\n\n          translationScalingFactors: [\n            0.3,\n            0.3,\n            1\n          ]\n\n        },\n\n\n        stabilizationSettings: {\n\n          switchNNErrorThreshold:\n            0.7,\n\n          NNSwitchMask: {\n\n            isRightHand:\n              true,\n\n            isFlipped:\n              false\n\n          }\n\n        },\n\n\n        objectPointsPositionFactors:\n          settings.objectPointsPositionFactors,\n\n\n        poseRotationDirectionSrc: [\n          0,\n          1,\n          0\n        ],\n\n\n        poseRotationDirectionDst: [\n          0,\n          0,\n          1\n        ],\n\n\n        poseLandmarksLabels:\n          settings.poseLandmarksLabels,\n\n\n        poseFilter:\n          PoseFlipFilter.instance({}),\n\n\n        NNsPaths:\n          settings.NNsPaths,\n\n\n        threshold:\n          settings.threshold,\n\n\n        callbackTrack:\n          function (\n            detectState\n          ) {\n\n            \/*\n             * The official helper automatically\n             * handles tracking visibility.\n             *\n             * We intentionally do not add our\n             * own MediaPipe loop here.\n             *\/\n\n          },\n\n\n        VTOCanvas:\n          VTOCanvas,\n\n\n        \/*\n         * IMPORTANT:\n         * Rear camera.\n         *\/\n        videoSettings: {\n          facingMode:\n            \"environment\"\n        },\n\n\n        handTrackerCanvas:\n          handTrackerCanvas,\n\n\n        debugDisplayLandmarks:\n          false\n\n      });\n\n\n    trackerReady = true;\n\n\n    \/*\n     * iOS Safari workaround used by\n     * the official demo.\n     *\/\n    VTOCanvas.style.zIndex =\n      \"3\";\n\n\n    \/*\n     * Lighting.\n     *\/\n    addLighting(\n      three\n    );\n\n\n    \/*\n     * Add wrist occluder FIRST.\n     *\/\n    addWristOccluder();\n\n\n    loadingText.textContent =\n      \"Loading The Nacre Bracelet…\";\n\n\n    \/*\n     * Load the ENTIRE Nacre GLB.\n     *\/\n    await loadNacreModel(\n      three.loadingManager\n    );\n\n\n    loading.style.opacity =\n      \"0\";\n\n\n    setTimeout(\n      function () {\n\n        if (\n          loading \u0026\u0026\n          loading.parentNode\n        ) {\n\n          loading.style.display =\n            \"none\";\n\n        }\n\n      },\n      350\n    );\n\n  }\n\n\n  \/*\n   * ------------------------------------------------------------\n   * OPEN\n   * ------------------------------------------------------------\n   *\/\n\n  async function openTryOn() {\n\n    if (isStarting) {\n      return;\n    }\n\n\n    isOpen = true;\n\n    isStarting = true;\n\n\n    modal.classList.add(\n      \"mb-open\"\n    );\n\n\n    document.body.style.overflow =\n      \"hidden\";\n\n\n    loading.style.display =\n      \"flex\";\n\n\n    loading.style.opacity =\n      \"1\";\n\n\n    errorBox.style.display =\n      \"none\";\n\n\n    try {\n\n      await loadWebARRocks();\n\n\n      if (!isOpen) {\n        return;\n      }\n\n\n      await initializeTracker();\n\n\n      isStarting = false;\n\n\n    } catch (\n      error\n    ) {\n\n      console.error(\n        \"Maison Beaumont VTO error:\",\n        error\n      );\n\n\n      isStarting = false;\n\n\n      loading.style.display =\n        \"none\";\n\n\n      errorBox.textContent =\n        \"We couldn't start the try-on. Please close this window and try again.\";\n\n\n      errorBox.style.display =\n        \"block\";\n\n    }\n\n  }\n\n\n  \/*\n   * ------------------------------------------------------------\n   * CLOSE\n   *\n   * This is a REAL tracker shutdown.\n   * ------------------------------------------------------------\n   *\/\n\n  async function closeTryOn() {\n\n    \/*\n     * Make the interface disappear immediately.\n     *\/\n    isOpen = false;\n\n    isStarting = false;\n\n\n    modal.classList.remove(\n      \"mb-open\"\n    );\n\n\n    document.body.style.overflow =\n      \"\";\n\n\n    \/*\n     * Shut down WebAR.rocks camera\/tracker.\n     *\/\n    if (\n      trackerReady \u0026\u0026\n      typeof HandTrackerThreeHelper !==\n        \"undefined\"\n    ) {\n\n      try {\n\n        await HandTrackerThreeHelper\n          .destroy();\n\n      } catch (\n        error\n      ) {\n\n        console.warn(\n          \"VTO shutdown warning:\",\n          error\n        );\n\n      }\n\n    }\n\n\n    trackerReady = false;\n\n\n    \/*\n     * Reset UI.\n     *\/\n    loading.style.display =\n      \"flex\";\n\n\n    loading.style.opacity =\n      \"1\";\n\n\n    errorBox.style.display =\n      \"none\";\n\n  }\n\n\n  \/*\n   * ------------------------------------------------------------\n   * BUTTON EVENTS\n   * ------------------------------------------------------------\n   *\/\n\n  openButton.addEventListener(\n    \"click\",\n    function () {\n\n      openTryOn();\n\n    }\n  );\n\n\n  closeButton.addEventListener(\n    \"click\",\n    function () {\n\n      closeTryOn();\n\n    }\n  );\n\n\n  \/*\n   * ------------------------------------------------------------\n   * SAFETY:\n   * Close with ESC too.\n   * ------------------------------------------------------------\n   *\/\n\n  document.addEventListener(\n    \"keydown\",\n    function (\n      event\n    ) {\n\n      if (\n        event.key === \"Escape\" \u0026\u0026\n        isOpen\n      ) {\n\n        closeTryOn();\n\n      }\n\n    }\n  );\n\n\n  \/*\n   * ------------------------------------------------------------\n   * RESIZE\n   * ------------------------------------------------------------\n   *\/\n\n  window.addEventListener(\n    \"resize\",\n    function () {\n\n      if (\n        isOpen \u0026\u0026\n        trackerReady \u0026\u0026\n        typeof HandTrackerThreeHelper !==\n          \"undefined\"\n      ) {\n\n        sizeCanvases();\n\n\n        HandTrackerThreeHelper\n          .resize(\n            handTrackerCanvas.width,\n            handTrackerCanvas.height\n          );\n\n      }\n\n    }\n  );\n\n\n})();\n\u003c\/script\u003e","brand":"Maison Beaumont","offers":[{"title":"Default Title","offer_id":59500852445509,"sku":null,"price":65.0,"currency_code":"EUR","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1074\/3713\/0053\/files\/image_529e5a59-9925-4b96-9d86-f3a92f08677c.png?v=1790423060","url":"https:\/\/www.lamaisonbeaumont.com\/products\/the-elan-bracelet","provider":"Maison Beaumont","version":"1.0","type":"link"}