{"id":5553,"date":"2026-04-01T12:49:12","date_gmt":"2026-04-01T16:49:12","guid":{"rendered":"https:\/\/www.tulmar.com\/?post_type=3d-viewer&#038;p=5553"},"modified":"2026-04-14T06:42:50","modified_gmt":"2026-04-14T10:42:50","slug":"couffin-pour-bebe","status":"publish","type":"3d-viewer","link":"https:\/\/www.tulmar.com\/fr\/3d-viewer\/baby-bassinet\/","title":{"rendered":"Couffin pour b\u00e9b\u00e9"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"5553\" class=\"elementor elementor-5553\" data-elementor-post-type=\"3d-viewer\">\n\t\t\t\t<div class=\"elementor-element elementor-element-a31f034 e-flex e-con-boxed e-con e-parent\" data-id=\"a31f034\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;jet_parallax_layout_list&quot;:[]}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-ad50284 elementor-widget elementor-widget-html\" data-id=\"ad50284\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<style>\n    \n\n    #sd-picker-ui {\n      --sd-glass-bg: rgba(255, 255, 255, 0.5);\n      --sd-glass-border: rgba(255, 255, 255, 0.6);\n      --sd-glass-blur: blur(24px);\n      --sd-header-color: rgba(60, 60, 67, 0.6);\n      --sd-text-primary: #1d1d1f;\n      --sd-active-bg: rgba(88, 86, 214, 0.1);\n      --sd-active-text: #5856d6;\n      --sd-shadow: 0 12px 32px rgba(0, 0, 0, 0.15);\n      min-width: 300px;\n      width: 100%;\n      height: 100vh;\n      min-height: 450px;\n      position: relative;\n      overflow: hidden;\n    }\n\n    .sd-panel {\n      position: absolute;\n      bottom: 80px;\n      left: 20px;\n      width: 260px;\n      max-height: calc(100% - 90px);\n      background: var(--sd-glass-bg);\n      backdrop-filter: var(--sd-glass-blur);\n      -webkit-backdrop-filter: var(--sd-glass-blur);\n      border: 1px solid rgba(255, 255, 255, 0.4);\n      border-radius: 18px;\n      box-shadow: var(--sd-shadow);\n      opacity: 0;\n      pointer-events: none;\n      transform: translateY(8px) scale(0.98);\n      transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);\n      display: flex;\n      flex-direction: column;\n      overflow: hidden;\n      z-index: 100;\n      padding: 10px;\n    }\n\n    .sd-panel.open {\n      opacity: 1;\n      pointer-events: all;\n      transform: translateY(0) scale(1);\n    }\n\n    .sd-scroll {\n      overflow-y: auto;\n      padding-right: 2px;\n      scrollbar-width: none;\n    }\n\n    .sd-scroll::-webkit-scrollbar {\n      display: none;\n    }\n\n    .sd-group-head {\n      padding: 12px 8px 8px;\n      font-size: 14px;\n      font-weight: 700;\n      color: var(--sd-header-color);\n      letter-spacing: -0.01em;\n      cursor: pointer;\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      user-select: none;\n      transition: color 0.2s;\n    }\n\n    .sd-group-head:hover {\n      color: #000;\n    }\n\n    .sd-arrow {\n      font-size: 10px;\n      opacity: 0.5;\n      transition: transform 0.3s ease;\n    }\n\n    .sd-group.active .sd-arrow {\n      transform: rotate(180deg);\n    }\n\n    .sd-group-body {\n      max-height: 0;\n      overflow: hidden;\n      transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s ease;\n      opacity: 0.5;\n    }\n\n    .sd-group.active .sd-group-body {\n      max-height: 500px;\n      opacity: 1;\n    }\n\n    .sd-divider {\n      height: 1px;\n      background: rgba(0, 0, 0, 0.06);\n      margin: 4px 8px;\n      display: block;\n    }\n\n    .sd-opt {\n      width: 100%;\n      padding: 8px 10px;\n      margin-bottom: 2px;\n      border: none;\n      background: transparent;\n      border-radius: 6px;\n      text-align: left;\n      font-size: 13px;\n      font-weight: 400;\n      color: var(--sd-text-primary);\n      cursor: pointer;\n      transition: all 0.1s ease-out;\n      display: flex;\n      align-items: center;\n      gap: 8px;\n    }\n\n    .sd-opt::before {\n      content: \"\u2022\";\n      font-size: 16px;\n      line-height: 1;\n      color: currentColor;\n      opacity: 0.8;\n      flex: 0 0 auto;\n    }\n\n    .sd-opt:hover {\n      background: rgba(0, 0, 0, 0.05);\n    }\n\n    .sd-opt.selected {\n      background: var(--sd-active-bg);\n      color: var(--sd-active-text);\n      font-weight: 600;\n    }\n\n    .sd-toggle {\n      position: absolute;\n      bottom: 20px;\n      left: 20px;\n      width: 44px;\n      height: 44px;\n      border-radius: 50%;\n      background: rgba(255, 255, 255, 0.9);\n      backdrop-filter: blur(10px);\n      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n      cursor: pointer;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);\n      z-index: 101;\n      border: none;\n    }\n\n    .sd-toggle:hover {\n      transform: scale(1.1);\n    }\n\n    .sd-toggle.rot svg {\n      transform: rotate(90deg);\n      color: var(--sd-active-text);\n    }\n\n    .sd-toggle svg {\n      width: 22px;\n      height: 22px;\n      fill: #333;\n      transition: all 0.4s ease;\n    }\n\n    .sd-color-panel {\n      position: absolute;\n      top: 20px;\n      right: 150px;\n      width: 230px;\n      background: rgba(255, 255, 255, 0.72);\n      backdrop-filter: blur(18px);\n      -webkit-backdrop-filter: blur(18px);\n      border: 1px solid rgba(255, 255, 255, 0.7);\n      border-radius: 18px;\n      box-shadow: 0 16px 30px rgba(0, 0, 0, 0.16);\n      color: #111;\n      z-index: 102;\n      overflow: hidden;\n    }\n\n    .sd-color-panel.collapsed .sd-color-body {\n      display: none;\n    }\n\n    .sd-color-head {\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      gap: 10px;\n      padding: 12px 14px;\n      background: rgba(255, 255, 255, 0.35);\n      cursor: grab;\n      user-select: none;\n      touch-action: none;\n    }\n\n    .sd-color-head:active {\n      cursor: grabbing;\n    }\n\n    .sd-color-title {\n      display: flex;\n      flex-direction: column;\n      gap: 2px;\n    }\n\n    .sd-color-title strong {\n      font-size: 13px;\n      font-weight: 700;\n      letter-spacing: 0.01em;\n    }\n\n    .sd-color-title span {\n      font-size: 11px;\n      color: rgba(29, 29, 31, 0.64);\n    }\n\n    .sd-color-collapse {\n      width: 30px;\n      height: 30px;\n      border: none;\n      border-radius: 10px;\n      background: rgba(17, 17, 17, 0.06);\n      color: #111;\n      cursor: pointer;\n      font-size: 16px;\n      line-height: 1;\n    }\n\n    .sd-color-body {\n      padding: 14px;\n      display: grid;\n      gap: 12px;\n    }\n\n    .sd-color-row {\n      display: flex;\n      align-items: center;\n      gap: 12px;\n    }\n\n    .sd-color-input {\n      width: 54px;\n      height: 54px;\n      padding: 0;\n      border: none;\n      border-radius: 14px;\n      background: transparent;\n      cursor: pointer;\n      overflow: hidden;\n      flex: 0 0 auto;\n    }\n\n    .sd-color-input::-webkit-color-swatch-wrapper {\n      padding: 0;\n    }\n\n    .sd-color-input::-webkit-color-swatch {\n      border: none;\n      border-radius: 14px;\n    }\n\n    .sd-color-input::-moz-color-swatch {\n      border: none;\n      border-radius: 14px;\n    }\n\n    .sd-color-meta {\n      display: grid;\n      gap: 4px;\n      min-width: 0;\n    }\n\n    .sd-color-label {\n      font-size: 12px;\n      color: rgba(29, 29, 31, 0.64);\n    }\n\n    .sd-color-value {\n      font-size: 16px;\n      font-weight: 700;\n      letter-spacing: 0.02em;\n    }\n\n    .sd-color-actions {\n      display: flex;\n      gap: 8px;\n    }\n\n    .sd-color-btn {\n      flex: 1;\n      border: none;\n      border-radius: 12px;\n      padding: 10px 12px;\n      cursor: pointer;\n      font: inherit;\n      font-size: 12px;\n      font-weight: 600;\n      transition: transform 0.15s ease, background 0.15s ease;\n    }\n\n    .sd-color-btn:hover {\n      transform: translateY(-1px);\n    }\n\n    .sd-color-btn.primary {\n      background: #111827;\n      color: #fff;\n    }\n\n    .sd-color-btn.secondary {\n      background: rgba(17, 24, 39, 0.08);\n      color: #111827;\n    }\n\n    .sd-status {\n      min-height: 16px;\n      font-size: 11px;\n      color: rgba(29, 29, 31, 0.68);\n    }\n\n    .sd-selected-wrap {\n      display: grid;\n      gap: 8px;\n      padding-top: 2px;\n    }\n\n    .sd-selected-title {\n      font-size: 12px;\n      font-weight: 700;\n      color: #111827;\n    }\n\n    .sd-selected-list {\n      margin: 0;\n      padding: 10px 12px;\n      list-style: none;\n      display: grid;\n      gap: 6px;\n      border-radius: 12px;\n      background: rgba(17, 24, 39, 0.05);\n      max-height: 140px;\n      overflow-y: auto;\n    }\n\n    .sd-selected-item {\n      font-size: 12px;\n      line-height: 1.35;\n      color: rgba(17, 24, 39, 0.88);\n    }\n\n    .sd-selected-empty {\n      font-size: 12px;\n      color: rgba(17, 24, 39, 0.56);\n    }\n\n    @media (max-width: 720px) {\n      .sd-panel {\n        left: 12px;\n        right: 12px;\n        width: auto;\n      }\n\n      .sd-toggle {\n        left: 12px;\n        bottom: 12px;\n      }\n\n      .sd-color-panel {\n        width: 210px;\n        top: 12px;\n        right: 150px;\n      }\n    }\n  <\/style>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-72a08d9 elementor-widget elementor-widget-html\" data-id=\"72a08d9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div id=\"sd-picker-ui\">\n    <sayduck-viewer product=\"3c515420-16dd-013f-3e04-5e424f58d366\" mode=\"configurator\" background=\"white\" hide-picker hide-embed hide-product-info hide-toggle-lights><\/sayduck-viewer>\n\n    <div class=\"sd-panel\" id=\"sd-panel\">\n      <div class=\"sd-scroll\" id=\"sd-content\"><\/div>\n    <\/div>\n\n    <button class=\"sd-toggle\" id=\"sd-btn\" type=\"button\" aria-label=\"Toggle configurator picker\">\n      <svg viewBox=\"0 0 24 24\"><path d=\"M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.06-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.73,8.87C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.85,11.36,4.8,11.69,4.8,12s0.02,0.64,0.06,0.94l-2.03,1.58c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z\"\/><\/svg>\n    <\/button>\n\n    <div class=\"sd-color-panel\" id=\"sd-color-panel\">\n        <div class=\"sd-color-head\" id=\"sd-color-head\">\n          <div class=\"sd-color-title\">\n            <strong>See Hestia in your airline\u2019s colour<\/strong>\n          <\/div>\n          <button class=\"sd-color-collapse\" id=\"sd-color-collapse\" type=\"button\" aria-label=\"Collapse material color picker\">-<\/button>\n        <\/div>\n      <div class=\"sd-color-body\" id=\"sd-color-body\">\n        <div class=\"sd-color-row\">\n          <input class=\"sd-color-input\" id=\"sd-bassinet-color-input\" type=\"color\" value=\"#d60003\" aria-label=\"Pick a color for bassinet\">\n          <div class=\"sd-color-meta\">\n            <div class=\"sd-color-label\">Bassinet Color<\/div>\n            <div class=\"sd-color-value\" id=\"sd-bassinet-color-value\">#FFFFFF<\/div>\n          <\/div>\n        <\/div>\n        <div class=\"sd-color-row\">\n          <input class=\"sd-color-input\" id=\"sd-mattress-color-input\" type=\"color\" value=\"#d60003\" aria-label=\"Pick a color for mattress\">\n          <div class=\"sd-color-meta\">\n            <div class=\"sd-color-label\">Mattress Color<\/div>\n            <div class=\"sd-color-value\" id=\"sd-mattress-color-value\">#FFFFFF<\/div>\n          <\/div>\n        <\/div>\n        <div class=\"sd-color-actions\">\n          <button class=\"sd-color-btn secondary\" id=\"sd-reset-color\" type=\"button\">Reset<\/button>\n        <\/div>\n        <div class=\"sd-status\" id=\"sd-status\">Ready when viewer API loads.<\/div>\n        <div class=\"sd-selected-wrap\">\n          <div class=\"sd-selected-title\">Selected Configuration<\/div>\n          <ul class=\"sd-selected-list\" id=\"sd-selected-list\"><\/ul>\n        <\/div>\n        <div class=\"sd-color-actions\">\n          <button class=\"sd-color-btn secondary\" id=\"sd-export-variants\" type=\"button\">Export .txt<\/button>\n          <button class=\"sd-color-btn primary\" id=\"sd-email-variants\" type=\"button\">Send Email<\/button>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <script>\n    const PRODUCT_UUID = '3c515420-16dd-013f-3e04-5e424f58d366';\n    const BASSINET_MATERIAL_UUIDS = [\n      '3c825120-16dd-013f-e7ca-5e424f58d366',\n      '3c8a7e80-16dd-013f-efb6-5e424f58d366',\n      '3c7e5ec0-16dd-013f-ecb1-5e424f58d366',\n    ];\n    const MATTRESS_MATERIAL_UUID = '3c9b2470-16dd-013f-cb0f-5e424f58d366';\n    const HIDDEN_SELECTED_CONFIGURATION_NAMES = ['Basket & Canopy', 'Mattress'];\n    const DEFAULT_COLOR = '#d60003';\n\n    function hexToRgb(hex) {\n      const normalized = hex.replace('#', '');\n      return {\n        red: parseInt(normalized.slice(0, 2), 16),\n        green: parseInt(normalized.slice(2, 4), 16),\n        blue: parseInt(normalized.slice(4, 6), 16),\n        alpha: 255,\n      };\n    }\n\n    function clamp(value, min, max) {\n      return Math.min(Math.max(value, min), max);\n    }\n\n    function setupDraggablePanel(panel, handle, container) {\n      let activePointerId = null;\n      let startX = 0;\n      let startY = 0;\n      let originX = 0;\n      let originY = 0;\n\n      handle.addEventListener('pointerdown', (event) => {\n        if (event.target.closest('button')) {\n          return;\n        }\n\n        activePointerId = event.pointerId;\n        startX = event.clientX;\n        startY = event.clientY;\n\n        const panelRect = panel.getBoundingClientRect();\n        const containerRect = container.getBoundingClientRect();\n\n        originX = panelRect.left - containerRect.left;\n        originY = panelRect.top - containerRect.top;\n\n        panel.style.left = originX + 'px';\n        panel.style.top = originY + 'px';\n        panel.style.right = 'auto';\n        panel.style.bottom = 'auto';\n\n        handle.setPointerCapture(activePointerId);\n      });\n\n      handle.addEventListener('pointermove', (event) => {\n        if (event.pointerId !== activePointerId) {\n          return;\n        }\n\n        const maxX = container.clientWidth - panel.offsetWidth;\n        const maxY = container.clientHeight - panel.offsetHeight;\n        const nextX = clamp(originX + (event.clientX - startX), 0, Math.max(maxX, 0));\n        const nextY = clamp(originY + (event.clientY - startY), 0, Math.max(maxY, 0));\n\n        panel.style.left = nextX + 'px';\n        panel.style.top = nextY + 'px';\n      });\n\n      function releasePointer(event) {\n        if (event.pointerId !== activePointerId) {\n          return;\n        }\n\n        handle.releasePointerCapture(activePointerId);\n        activePointerId = null;\n      }\n\n      handle.addEventListener('pointerup', releasePointer);\n      handle.addEventListener('pointercancel', releasePointer);\n    }\n\n    window.addEventListener('sayduck.api-ready', (event) => {\n      const api = event.detail.instance;\n      const root = document.getElementById('sd-picker-ui');\n      const container = document.getElementById('sd-content');\n      const panel = document.getElementById('sd-panel');\n      const btn = document.getElementById('sd-btn');\n      const colorPanel = document.getElementById('sd-color-panel');\n      const colorHead = document.getElementById('sd-color-head');\n      const colorCollapse = document.getElementById('sd-color-collapse');\n      const bassinetColorInput = document.getElementById('sd-bassinet-color-input');\n      const bassinetColorValue = document.getElementById('sd-bassinet-color-value');\n      const mattressColorInput = document.getElementById('sd-mattress-color-input');\n      const mattressColorValue = document.getElementById('sd-mattress-color-value');\n      const resetColor = document.getElementById('sd-reset-color');\n      const selectedList = document.getElementById('sd-selected-list');\n      const exportVariants = document.getElementById('sd-export-variants');\n      const emailVariants = document.getElementById('sd-email-variants');\n      const status = document.getElementById('sd-status');\n\n      console.log('Sayduck product UUID:', PRODUCT_UUID);\n      console.log('Sayduck bassinet material UUID targets:', BASSINET_MATERIAL_UUIDS);\n      console.log('Sayduck mattress material UUID target:', MATTRESS_MATERIAL_UUID);\n      console.log('Available material UUIDs:', api.scene.getAllMaterialUuids());\n\n      btn.onclick = () => {\n        btn.classList.toggle('rot');\n        panel.classList.toggle('open');\n      };\n\n      colorCollapse.onclick = () => {\n        colorPanel.classList.toggle('collapsed');\n        colorCollapse.textContent = colorPanel.classList.contains('collapsed') ? '+' : '-';\n      };\n\n      function getSelectedConfigurationLines() {\n        if (typeof api.configurator.getSelectedVariants === 'function') {\n          const selectedVariants = api.configurator.getSelectedVariants() || [];\n\n          if (selectedVariants.length) {\n            return selectedVariants\n              .map((variant) => {\n                const parentConfig = (api.configurator.getConfigurations() || []).find((config) =>\n                  (config.children || []).some((child) => child.id === variant.id)\n                );\n\n                if (\n                  !parentConfig ||\n                  parentConfig.name === 'Default' ||\n                  HIDDEN_SELECTED_CONFIGURATION_NAMES.includes(parentConfig.name)\n                ) {\n                  return null;\n                }\n\n                return `${parentConfig.name} - ${variant.name}`;\n              })\n              .filter(Boolean);\n          }\n        }\n\n        return api.configurator\n          .getConfigurations()\n          .filter(\n            (config) =>\n              config.name !== 'Default' &&\n              !HIDDEN_SELECTED_CONFIGURATION_NAMES.includes(config.name)\n          )\n          .map((config) => {\n            const selectedVariant = config.value || (config.children || []).find((child) => child.id === config.selectedVariantId);\n\n            if (!selectedVariant || !selectedVariant.name) {\n              return null;\n            }\n\n            return `${config.name} - ${selectedVariant.name}`;\n          })\n          .filter(Boolean);\n      }\n\n      function renderSelectedConfigurations() {\n        const selectedLines = getSelectedConfigurationLines();\n        selectedList.innerHTML = '';\n\n        const bassinetCustomColorItem = document.createElement('li');\n        bassinetCustomColorItem.className = 'sd-selected-item';\n        bassinetCustomColorItem.textContent = `Bassinet Custom Color: ${bassinetColorInput.value.toUpperCase()}`;\n        selectedList.appendChild(bassinetCustomColorItem);\n\n        const mattressCustomColorItem = document.createElement('li');\n        mattressCustomColorItem.className = 'sd-selected-item';\n        mattressCustomColorItem.textContent = `Mattress Custom Color: ${mattressColorInput.value.toUpperCase()}`;\n        selectedList.appendChild(mattressCustomColorItem);\n\n        if (!selectedLines.length) {\n          const emptyItem = document.createElement('li');\n          emptyItem.className = 'sd-selected-empty';\n          emptyItem.textContent = 'No variants selected.';\n          selectedList.appendChild(emptyItem);\n          return [\n            `Bassinet Custom Color: ${bassinetColorInput.value.toUpperCase()}`,\n            `Mattress Custom Color: ${mattressColorInput.value.toUpperCase()}`,\n          ];\n        }\n\n        selectedLines.forEach((line) => {\n          const item = document.createElement('li');\n          item.className = 'sd-selected-item';\n          item.textContent = line;\n          selectedList.appendChild(item);\n        });\n\n        return [\n          `Bassinet Custom Color: ${bassinetColorInput.value.toUpperCase()}`,\n          `Mattress Custom Color: ${mattressColorInput.value.toUpperCase()}`,\n          ...selectedLines,\n        ];\n      }\n\n      function getSelectedConfigurationsText() {\n        return renderSelectedConfigurations().join('\\r\\n');\n      }\n\n      function scheduleSelectedConfigurationsRefresh(delays) {\n        delays.forEach((delay) => {\n          window.setTimeout(() => {\n            renderSelectedConfigurations();\n          }, delay);\n        });\n      }\n\n      async function applyMaterialColor(hex, colorValueElement, materialUuids) {\n        colorValueElement.textContent = hex.toUpperCase();\n        renderSelectedConfigurations();\n        status.textContent = 'Updating material...';\n\n        try {\n          await Promise.all(\n            materialUuids.map((materialUuid) =>\n              api.scene.updateMaterial(materialUuid, {\n                albedoColour: hexToRgb(hex),\n              })\n            )\n          );\n        } catch (error) {\n          console.error('Failed to update materials', error);\n          status.textContent = 'Material update failed. Check console.';\n        }\n      }\n\n      bassinetColorInput.addEventListener('input', () => {\n        applyMaterialColor(bassinetColorInput.value, bassinetColorValue, BASSINET_MATERIAL_UUIDS);\n      });\n\n      mattressColorInput.addEventListener('input', () => {\n        applyMaterialColor(mattressColorInput.value, mattressColorValue, [MATTRESS_MATERIAL_UUID]);\n      });\n\n      resetColor.addEventListener('click', () => {\n        bassinetColorInput.value = DEFAULT_COLOR;\n        mattressColorInput.value = DEFAULT_COLOR;\n        bassinetColorValue.textContent = DEFAULT_COLOR.toUpperCase();\n        mattressColorValue.textContent = DEFAULT_COLOR.toUpperCase();\n        renderSelectedConfigurations();\n        Promise.all([\n          applyMaterialColor(DEFAULT_COLOR, bassinetColorValue, BASSINET_MATERIAL_UUIDS),\n          applyMaterialColor(DEFAULT_COLOR, mattressColorValue, [MATTRESS_MATERIAL_UUID]),\n        ]);\n      });\n\n      exportVariants.addEventListener('click', () => {\n        const selectedText = getSelectedConfigurationsText();\n        const fileContent = selectedText || 'No variants selected.';\n        const blob = new Blob([fileContent], { type: 'text\/plain;charset=utf-8' });\n        const fileUrl = URL.createObjectURL(blob);\n        const link = document.createElement('a');\n\n        link.href = fileUrl;\n        link.download = 'selected-configurations.txt';\n        document.body.appendChild(link);\n        link.click();\n        link.remove();\n        URL.revokeObjectURL(fileUrl);\n      });\n\n      emailVariants.addEventListener('click', () => {\n        const selectedText = getSelectedConfigurationsText() || 'No variants selected.';\n        const subject = encodeURIComponent('Selected Configurations and Variants');\n        const body = encodeURIComponent(selectedText);\n        window.location.href = `mailto:?subject=${subject}&body=${body}`;\n      });\n\n      window.addEventListener('sayduck.viewer.material.updated', () => {\n        status.textContent = 'Material updated in viewer.';\n      });\n\n      setupDraggablePanel(colorPanel, colorHead, root);\n\n      const configs = api.configurator.getConfigurations();\n      container.innerHTML = '';\n\n      configs.forEach((config, index) => {\n        if (config.name === 'Default') {\n          return;\n        }\n\n        if (index > 0) {\n          const divider = document.createElement('div');\n          divider.className = 'sd-divider';\n          container.appendChild(divider);\n        }\n\n        const group = document.createElement('div');\n        group.className = 'sd-group active';\n\n        const header = document.createElement('div');\n        header.className = 'sd-group-head';\n        header.innerHTML = `<span>${config.name}<\/span><span class=\"sd-arrow\">\u25bc<\/span>`;\n        header.onclick = () => {\n          group.classList.toggle('active');\n        };\n\n        const body = document.createElement('div');\n        body.className = 'sd-group-body';\n\n        (config.children || []).forEach((opt) => {\n          const btnOpt = document.createElement('button');\n          btnOpt.className = 'sd-opt';\n          btnOpt.type = 'button';\n          btnOpt.textContent = opt.name;\n\n          const fallbackSelectedChild = !config.value && config.children && config.children[0];\n\n          if ((config.value && config.value.id === opt.id) || (fallbackSelectedChild && fallbackSelectedChild.id === opt.id)) {\n            btnOpt.classList.add('selected');\n          }\n\n          btnOpt.onclick = () => {\n            api.configurator.setConfigurationValue(config, opt);\n            Array.from(body.children).forEach((child) => child.classList.remove('selected'));\n            btnOpt.classList.add('selected');\n            scheduleSelectedConfigurationsRefresh([0, 250, 800, 1500]);\n          };\n\n          body.appendChild(btnOpt);\n        });\n\n        group.appendChild(header);\n        group.appendChild(body);\n        container.appendChild(group);\n      });\n\n      bassinetColorInput.value = DEFAULT_COLOR;\n      bassinetColorValue.textContent = DEFAULT_COLOR.toUpperCase();\n      mattressColorInput.value = DEFAULT_COLOR;\n      mattressColorValue.textContent = DEFAULT_COLOR.toUpperCase();\n      selectedList.innerHTML = '<li class=\"sd-selected-empty\">Loading selected variants...<\/li>';\n      scheduleSelectedConfigurationsRefresh([0, 300, 900, 1800, 3000]);\n      status.textContent = 'Viewer API loaded. Pick a color.';\n    });\n  <\/script>\n\n  <script src=\"https:\/\/viewer.sayduck.com\" type=\"module\" async><\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"template":"","class_list":["post-5553","3d-viewer","type-3d-viewer","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Baby Bassinet - Tulmar<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.tulmar.com\/fr\/visionneuse-3d\/couffin-pour-bebe\/\" \/>\n<meta property=\"og:locale\" content=\"fr_CA\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Baby Bassinet\" \/>\n<meta property=\"og:description\" content=\"See Hestia in your airline\u2019s colour &#8211; Bassinet Color #FFFFFF Mattress Color #FFFFFF Reset Ready when viewer API loads. Selected Configuration Export .txt Send Email\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.tulmar.com\/fr\/visionneuse-3d\/couffin-pour-bebe\/\" \/>\n<meta property=\"og:site_name\" content=\"Tulmar\" \/>\n<meta property=\"article:modified_time\" content=\"2026-04-14T10:42:50+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Estimation du temps de lecture\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.tulmar.com\/3d-viewer\/baby-bassinet\/\",\"url\":\"https:\/\/www.tulmar.com\/3d-viewer\/baby-bassinet\/\",\"name\":\"Baby Bassinet - Tulmar\",\"isPartOf\":{\"@id\":\"https:\/\/www.tulmar.com\/#website\"},\"datePublished\":\"2026-04-01T16:49:12+00:00\",\"dateModified\":\"2026-04-14T10:42:50+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.tulmar.com\/3d-viewer\/baby-bassinet\/#breadcrumb\"},\"inLanguage\":\"fr-CA\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.tulmar.com\/3d-viewer\/baby-bassinet\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.tulmar.com\/3d-viewer\/baby-bassinet\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.tulmar.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Baby Bassinet\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.tulmar.com\/#website\",\"url\":\"https:\/\/www.tulmar.com\/\",\"name\":\"Tulmar\",\"description\":\"Discover Tailored Solutions for Your Industry\",\"publisher\":{\"@id\":\"https:\/\/www.tulmar.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.tulmar.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fr-CA\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.tulmar.com\/#organization\",\"name\":\"Tulmar\",\"url\":\"https:\/\/www.tulmar.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-CA\",\"@id\":\"https:\/\/www.tulmar.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.tulmar.com\/wp-content\/uploads\/2024\/08\/LogoLanding.svg\",\"contentUrl\":\"https:\/\/www.tulmar.com\/wp-content\/uploads\/2024\/08\/LogoLanding.svg\",\"width\":407,\"height\":143,\"caption\":\"Tulmar\"},\"image\":{\"@id\":\"https:\/\/www.tulmar.com\/#\/schema\/logo\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Couffin pour b\u00e9b\u00e9 - Tulmar","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.tulmar.com\/fr\/visionneuse-3d\/couffin-pour-bebe\/","og_locale":"fr_CA","og_type":"article","og_title":"Baby Bassinet","og_description":"See Hestia in your airline\u2019s colour &#8211; Bassinet Color #FFFFFF Mattress Color #FFFFFF Reset Ready when viewer API loads. Selected Configuration Export .txt Send Email","og_url":"https:\/\/www.tulmar.com\/fr\/visionneuse-3d\/couffin-pour-bebe\/","og_site_name":"Tulmar","article_modified_time":"2026-04-14T10:42:50+00:00","twitter_card":"summary_large_image","twitter_misc":{"Estimation du temps de lecture":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.tulmar.com\/3d-viewer\/baby-bassinet\/","url":"https:\/\/www.tulmar.com\/3d-viewer\/baby-bassinet\/","name":"Couffin pour b\u00e9b\u00e9 - Tulmar","isPartOf":{"@id":"https:\/\/www.tulmar.com\/#website"},"datePublished":"2026-04-01T16:49:12+00:00","dateModified":"2026-04-14T10:42:50+00:00","breadcrumb":{"@id":"https:\/\/www.tulmar.com\/3d-viewer\/baby-bassinet\/#breadcrumb"},"inLanguage":"fr-CA","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.tulmar.com\/3d-viewer\/baby-bassinet\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.tulmar.com\/3d-viewer\/baby-bassinet\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.tulmar.com\/"},{"@type":"ListItem","position":2,"name":"Baby Bassinet"}]},{"@type":"WebSite","@id":"https:\/\/www.tulmar.com\/#website","url":"https:\/\/www.tulmar.com\/","name":"Tulmar","description":"D\u00e9couvrez des solutions sur mesure pour votre secteur d'activit\u00e9","publisher":{"@id":"https:\/\/www.tulmar.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.tulmar.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fr-CA"},{"@type":"Organization","@id":"https:\/\/www.tulmar.com\/#organization","name":"Tulmar","url":"https:\/\/www.tulmar.com\/","logo":{"@type":"ImageObject","inLanguage":"fr-CA","@id":"https:\/\/www.tulmar.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.tulmar.com\/wp-content\/uploads\/2024\/08\/LogoLanding.svg","contentUrl":"https:\/\/www.tulmar.com\/wp-content\/uploads\/2024\/08\/LogoLanding.svg","width":407,"height":143,"caption":"Tulmar"},"image":{"@id":"https:\/\/www.tulmar.com\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/www.tulmar.com\/fr\/wp-json\/wp\/v2\/3d-viewer\/5553","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tulmar.com\/fr\/wp-json\/wp\/v2\/3d-viewer"}],"about":[{"href":"https:\/\/www.tulmar.com\/fr\/wp-json\/wp\/v2\/types\/3d-viewer"}],"version-history":[{"count":0,"href":"https:\/\/www.tulmar.com\/fr\/wp-json\/wp\/v2\/3d-viewer\/5553\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tulmar.com\/fr\/wp-json\/wp\/v2\/media?parent=5553"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}