{"id":73603,"date":"2026-07-20T09:34:35","date_gmt":"2026-07-20T07:34:35","guid":{"rendered":"https:\/\/varibox.best4u.dev\/varibox-checker\/"},"modified":"2026-09-17T09:49:49","modified_gmt":"2026-09-17T07:49:49","slug":"varibox-checker","status":"publish","type":"page","link":"https:\/\/varibox.best4u.dev\/es\/varibox-checker\/","title":{"rendered":"VARIBOX Checker"},"content":{"rendered":"\n<div class=\"wp-block-ugb-columns ugb-columns ugb-0d5d96e ugb-columns--design-plain ugb-columns--columns-2 ugb-main-block\"><style>.ugb-0d5d96e > .ugb-inner-block > .ugb-block-content > .ugb-columns__item{grid-template-columns:1.40fr 0.60fr !important}@media screen and (min-width:768px){.ugb-0d5d96e.ugb-columns{margin-bottom:83px !important}}@media screen and (max-width:768px){.ugb-0d5d96e-content-wrapper{grid-row-gap:0 !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-columns__item ugb-0d5d96e-content-wrapper\">\n<div class=\"wp-block-ugb-column ugb-column ugb-b383129 ugb-column--design-plain ugb-main-block\"><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-column__item ugb-b383129-column-wrapper\"><div class=\"ugb-column__content-wrapper\">\n<div class=\"wp-block-ugb-heading ugb-heading wow animate__animated animate__fadeIn ugb-bcdb7f0 ugb-main-block\"><style>.ugb-bcdb7f0 .ugb-heading__subtitle{margin-bottom:-5px !important}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><h1 class=\"ugb-heading__title\">VARIBOX Checker<\/h1><p class=\"ugb-heading__subtitle\">El n\u00famero de art\u00edculo completo consta de 12 caracteres (por ejemplo, VB1001AED709) y se encuentra en la confirmaci\u00f3n de pedido, en la factura o en la placa de identificaci\u00f3n del propio VARIBOX. Introd\u00fazcalo a continuaci\u00f3n para ver el material de la junta, la configuraci\u00f3n del tubo de aspiraci\u00f3n\/respiradero, el sensor de nivel y el color de su unidad. Esta herramienta cubre VARIBOX FC 1000, FC 800, CC 250 y Drumtainer \u2014 para otros productos VARIBOX (como Single Containment), p\u00f3ngase en contacto con el Servicio de Atenci\u00f3n al Cliente.<\/p><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-button ugb-button-wrapper green-button animate__animated animate__fadeIn ugb-ee16d32 ugb-button--mobile-aligned ugb-main-block\"><style>.ugb-ee16d32 .ugb-block-content{justify-content:flex-start !important}.ugb-ee16d32 .ugb-button1 .ugb-button--inner{font-weight:bold !important}.ugb-ee16d32 .ugb-button1:hover{opacity:1}.ugb-ee16d32 .ugb-inner-block{text-align:left}@media screen and (min-width:768px){.ugb-ee16d32.ugb-button-wrapper{margin-bottom:0px !important}}@media screen and (max-width:768px){.ugb-ee16d32 .ugb-block-content{justify-content:center !important}.ugb-ee16d32 .ugb-inner-block{text-align:center}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-button-container\"><a class=\"ugb-button1 ugb-button ugb-button--size-normal\" href=\"https:\/\/varibox.best4u.dev\/es\/contacto\/\" rel=\"\" title=\"\"><span class=\"ugb-button--inner\">P\u00f3ngase en contacto<\/span><\/a><\/div><\/div><\/div><\/div>\n<\/div><\/div><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-column ugb-column ugb-e882f9a ugb-column--design-plain ugb-main-block\"><style>@media screen and (max-width:768px){.ugb-e882f9a .ugb-inner-block{text-align:center}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-column__item ugb-e882f9a-column-wrapper\"><div class=\"ugb-column__content-wrapper\">\n<figure class=\"wp-block-image size-full wow animate__animated animate__fadeIn\"><img decoding=\"async\" width=\"325\" height=\"370\" src=\"https:\/\/varibox.best4u.dev\/wp-content\/uploads\/2024\/11\/VARIBOX-Full-Containment-186.png\" alt=\"\" class=\"wp-image-60399\" srcset=\"https:\/\/varibox.best4u.dev\/wp-content\/uploads\/2024\/11\/VARIBOX-Full-Containment-186.png 325w, https:\/\/varibox.best4u.dev\/wp-content\/uploads\/2024\/11\/VARIBOX-Full-Containment-186-270x307.png 270w\" sizes=\"(max-width: 325px) 100vw, 325px\" \/><\/figure>\n<\/div><\/div><\/div><\/div><\/div>\n<\/div><\/div><\/div><\/div>\n\n\n\n<div class=\"alignfull wp-block-ugb-container ugb-container ugb-25beaa0 ugb-container--v2 ugb-container--design-plain ugb-main-block ugb-main-block--inner-center ugb--has-block-background\"><style>.ugb-25beaa0.ugb-container{background-color:var(--theme-palette-color-7,#F9FAFB)}.ugb-25beaa0.ugb-container:before{background-color:var(--theme-palette-color-7,#F9FAFB)}@media screen and (min-width:768px){.ugb-25beaa0-content-wrapper.ugb-container__content-wrapper{width:85% !important}.ugb-25beaa0.ugb-container{margin-bottom:0px !important;padding-top:0px !important;padding-right:35px !important;padding-bottom:0px !important;padding-left:35px !important}}@media screen and (min-width:768px) and (max-width:1025px){.ugb-25beaa0-content-wrapper.ugb-container__content-wrapper{width:100% !important}}@media screen and (max-width:768px){.ugb-25beaa0.ugb-container{margin-bottom:0px !important;padding-top:0px !important;padding-right:18px !important;padding-bottom:0px !important;padding-left:18px !important}}@media screen and (min-width:768px){.ugb-25beaa0 > .ugb-inner-block > .ugb-block-content > *{padding-top:40px !important;padding-bottom:40px !important}}@media screen and (max-width:768px){.ugb-25beaa0 > .ugb-inner-block > .ugb-block-content > *{padding-top:35px !important;padding-bottom:0px !important}}<\/style><div class=\"ugb-inner-block ugb-inner-block--center\"><div class=\"ugb-block-content\"><div class=\"ugb-container__wrapper ugb-25beaa0-wrapper\"><div class=\"ugb-container__side\"><div class=\"ugb-container__content-wrapper ugb-25beaa0-content-wrapper\">\n<div class=\"aligncenter wp-block-ugb-columns ugb-columns top-icons-columns ugb-609d063 ugb-columns--design-plain ugb-columns--columns-3 ugb-main-block\"><style>.ugb-609d063-content-wrapper{grid-column-gap:15px !important}@media screen and (min-width:768px) and (max-width:1025px){.ugb-609d063-content-wrapper{grid-column-gap:0px !important}}@media screen and (max-width:768px){.ugb-609d063-content-wrapper{grid-row-gap:0 !important;grid-column-gap:0px !important}.ugb-609d063 .ugb-inner-block{text-align:center}.ugb-609d063.ugb-columns{margin-top:0px !important;margin-bottom:0px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-columns__item ugb-609d063-content-wrapper\">\n<div class=\"wp-block-ugb-column ugb-column ugb-aa84cea ugb-column--design-plain ugb-main-block\"><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-column__item ugb-aa84cea-column-wrapper\"><div class=\"ugb-column__content-wrapper\">\n<div class=\"wp-block-group is-layout-flow wp-block-group-is-layout-flow\">\n<div class=\"wp-block-media-text alignwide is-stacked-on-mobile is-vertically-aligned-center content-pages-top-icons\" style=\"grid-template-columns:30% auto\"><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/varibox.best4u.dev\/wp-content\/uploads\/2021\/12\/test.svg\" alt=\"\" class=\"wp-image-3005 size-full\"\/><\/figure><div class=\"wp-block-media-text__content\">\n<h4 class=\"wp-block-heading has-text-align-left has-medium-font-size\">M\u00e1s seguro<\/h4>\n<\/div><\/div>\n<\/div>\n<\/div><\/div><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-column ugb-column ugb-a25ba9c ugb-column--design-plain ugb-main-block\"><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-column__item ugb-a25ba9c-column-wrapper\"><div class=\"ugb-column__content-wrapper\">\n<div class=\"wp-block-group is-layout-flow wp-block-group-is-layout-flow\">\n<div class=\"wp-block-media-text alignwide is-stacked-on-mobile is-vertically-aligned-center content-pages-top-icons\" style=\"grid-template-columns:30% auto\"><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/varibox.best4u.dev\/wp-content\/uploads\/2021\/11\/reuseablility-green-1.svg\" alt=\"\" class=\"wp-image-1838 size-full\"\/><\/figure><div class=\"wp-block-media-text__content\">\n<h4 class=\"wp-block-heading has-text-align-left has-medium-font-size\">Reutilizable<\/h4>\n<\/div><\/div>\n<\/div>\n<\/div><\/div><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-column ugb-column ugb-ed3faa1 ugb-column--design-plain ugb-main-block\"><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-column__item ugb-ed3faa1-column-wrapper\"><div class=\"ugb-column__content-wrapper\">\n<div class=\"wp-block-group is-layout-flow wp-block-group-is-layout-flow\">\n<div class=\"wp-block-media-text alignwide is-stacked-on-mobile is-vertically-aligned-center content-pages-top-icons\" style=\"grid-template-columns:29% auto\"><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/varibox.best4u.dev\/wp-content\/uploads\/2021\/11\/sustainability-green-1.svg\" alt=\"\" class=\"wp-image-1851 size-full\"\/><\/figure><div class=\"wp-block-media-text__content\">\n<h4 class=\"wp-block-heading has-text-align-left has-medium-font-size\">Sostenible<\/h4>\n<\/div><\/div>\n<\/div>\n<\/div><\/div><\/div><\/div><\/div>\n<\/div><\/div><\/div><\/div>\n<\/div><\/div><\/div><\/div><\/div><\/div>\n\n\n<div id=\"varibox-check-tool\" class=\"alignfull wp-block-ugb-container ugb-container ugb-6217927 ugb-container--v2 ugb-container--design-plain ugb-main-block ugb-main-block--inner-center ugb--has-block-background\"><style>.ugb-6217927.ugb-container{background-color:#f7f9fb;background-image:url('https:\/\/varibox.best4u.dev\/wp-content\/uploads\/2026\/08\/VARIBOX-background-hexagon-white-A4.jpg');background-size:cover;background-position:center;background-repeat:no-repeat}.ugb-6217927.ugb-container:before{background-color:#f7f9fb;background-image:url('https:\/\/varibox.best4u.dev\/wp-content\/uploads\/2026\/08\/VARIBOX-background-hexagon-white-A4.jpg');background-size:cover;background-position:center;background-repeat:no-repeat}@media screen and (min-width:768px){.ugb-6217927 > .ugb-inner-block > .ugb-block-content > *{padding-top:48px !important;padding-bottom:48px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-container__wrapper ugb-6217927-wrapper\"><div class=\"ugb-container__side\"><div class=\"ugb-container__content-wrapper ugb-6217927-content-wrapper\">\n\n\n<style>\n\n  .vb-check{\n    --vb-blue:#0078BF;\n    --vb-blue-dark:#005a91;\n    --vb-blue-soft:rgba(0,120,191,.12);\n    --vb-ink:#1c2733;\n    --vb-grey:#6b7684;\n    --vb-line:#e2e6ea;\n    --vb-bg:#f7f9fb;\n    --vb-warn-bg:#fff6e5;\n    --vb-warn-border:#e8b73b;\n    --vb-ease:cubic-bezier(.4,0,.2,1);\n    --vb-ease-spring:cubic-bezier(.34,1.4,.64,1);\n  }\n  .vb-check, .vb-check *, .vb-check *::before, .vb-check *::after{box-sizing:border-box;}\n  @keyframes vb-spin{ to{ transform:rotate(360deg); } }\n  @keyframes vb-result-in{\n    from{ opacity:0; transform:translateY(10px); }\n    to{ opacity:1; transform:translateY(0); }\n  }\n  @keyframes vb-badge-pop{\n    0%{ transform:scale(0.6); opacity:0; }\n    70%{ transform:scale(1.08); opacity:1; }\n    100%{ transform:scale(1); }\n  }\n  @keyframes vb-shake{\n    10%,90%{ transform:translateX(-1px); }\n    20%,80%{ transform:translateX(2px); }\n    30%,50%,70%{ transform:translateX(-4px); }\n    40%,60%{ transform:translateX(4px); }\n  }\n  @media (prefers-reduced-motion: reduce){\n    .vb-check, .vb-check *, .vb-check *::before, .vb-check *::after{\n      animation-duration:0.001ms !important;\n      animation-iteration-count:1 !important;\n      transition-duration:0.001ms !important;\n      scroll-behavior:auto !important;\n    }\n  }\n  .vb-check{ font-family:'Poppins',Arial,Helvetica,sans-serif; color:var(--vb-ink); }\n  .vb-check{ position:relative; max-width:640px; margin:0 auto; padding:34px 28px 36px; background:#fff; border:1px solid var(--vb-line); border-radius:12px; box-shadow:0 1px 2px rgba(16,24,40,.04), 0 10px 28px -8px rgba(16,24,40,.09); overflow:hidden; }\n  .vb-check::before{ content:''; position:absolute; top:0; left:0; right:0; height:3px; background:linear-gradient(90deg, var(--vb-blue) 0%, #4db8ea 50%, var(--vb-blue) 100%); }\n  .vb-top-row{ display:flex; justify-content:space-between; align-items:flex-start; gap:14px; margin-bottom:6px; }\n  .vb-check h2{ font-size:22px; font-weight:600; margin:0; color:var(--vb-ink); flex:1 1 auto; min-width:0; letter-spacing:-0.01em; }\n  #vb-lang{ appearance:none; -webkit-appearance:none; -moz-appearance:none; padding:6px 26px 6px 12px; font-size:13px; font-weight:600; font-family:'Poppins',Arial,sans-serif; border:1px solid var(--vb-line); border-radius:20px; background:#fff url('data:image\/svg+xml;utf8,<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"%236b7684\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4.5 7l4.5 4.5L13.5 7\"\/><\/svg>') no-repeat right 8px center; background-size:12px; color:var(--vb-ink); cursor:pointer; flex:0 0 auto !important; width:auto !important; max-width:100px; box-sizing:border-box; transition:border-color .15s var(--vb-ease), box-shadow .15s var(--vb-ease); }\n  #vb-lang:hover{ border-color:var(--vb-blue); }\n  #vb-lang:focus{ border-color:var(--vb-blue); box-shadow:0 0 0 4px var(--vb-blue-soft); }\n  .vb-check p.vb-intro{ margin:0 0 22px; color:var(--vb-grey); font-size:14.5px; line-height:1.55; }\n  .vb-input-row{ display:flex; gap:10px; flex-wrap:wrap; align-items:flex-start; }\n  .vb-code-wrap{ position:relative; flex:1 1 240px; min-width:0; border-radius:7px; overflow:hidden; }\n  .vb-code-wrap::after{\n    content:''; position:absolute; top:0; left:0; width:56%; height:100%;\n    background:linear-gradient(90deg, transparent, rgba(0,120,191,.35), transparent);\n    pointer-events:none; opacity:0; z-index:1;\n  }\n  .vb-code-wrap.vb-scanning::after{ opacity:1; animation:vb-scan 1.1s var(--vb-ease) infinite; }\n  @keyframes vb-scan{\n    0%{ transform:translateX(-10%); opacity:0; }\n    15%{ opacity:1; }\n    85%{ opacity:1; }\n    100%{ transform:translateX(155%); opacity:0; }\n  }\n  #vb-code{ width:100%; padding:13px 34px 13px 14px; font-size:16px; font-family:'Courier New',monospace; letter-spacing:0.8px; border:2px solid var(--vb-line); border-radius:7px; text-transform:uppercase; outline:none; transition:border-color .15s var(--vb-ease), box-shadow .15s var(--vb-ease); resize:vertical; line-height:1.6; min-height:48px; }\n  .vb-code-clear{ position:absolute; top:8px; right:8px; z-index:2; display:none; align-items:center; justify-content:center; width:22px; height:22px; padding:0; border:none; border-radius:50%; background:var(--vb-line); color:var(--vb-grey); font-size:15px; line-height:1; cursor:pointer; transition:background .15s var(--vb-ease), color .15s var(--vb-ease); }\n  .vb-code-clear:hover{ background:var(--vb-grey); color:#fff; }\n  .vb-code-clear.vb-visible{ display:flex; }\n  #vb-code:focus{ border-color:var(--vb-blue); box-shadow:0 0 0 4px var(--vb-blue-soft); }\n  #vb-submit{ padding:13px 22px; font-size:15px; font-weight:600; font-family:'Poppins',Arial,sans-serif; color:#fff; background:var(--vb-blue); border:none; border-radius:7px; cursor:pointer; transition:background .15s var(--vb-ease), transform .12s var(--vb-ease), box-shadow .15s var(--vb-ease); white-space:nowrap; position:relative; }\n  #vb-submit:hover{ background:var(--vb-blue-dark); transform:translateY(-1px); box-shadow:0 4px 12px -2px rgba(0,120,191,.35); }\n  #vb-submit:active{ transform:translateY(0); box-shadow:none; }\n  #vb-submit:disabled{ cursor:default; transform:none; box-shadow:none; opacity:.85; }\n  #vb-submit.vb-loading{ color:transparent; }\n  #vb-submit.vb-loading::after{\n    content:''; position:absolute; top:50%; left:50%; width:16px; height:16px; margin:-8px 0 0 -8px;\n    border:2px solid rgba(255,255,255,.4); border-top-color:#fff; border-radius:50%;\n    animation:vb-spin .7s linear infinite;\n  }\n  #vb-example{ margin-top:12px; font-size:13px; color:var(--vb-grey); display:flex; align-items:center; gap:8px; flex-wrap:wrap; }\n  #vb-bulk-hint{ display:flex; align-items:flex-start; gap:8px; margin-top:10px; padding:8px 12px; background:var(--vb-bg); border:1px solid var(--vb-line); border-radius:7px; font-size:12.5px; color:var(--vb-grey); line-height:1.5; }\n  .vb-recent-chips{ display:none; flex-wrap:wrap; gap:6px; margin-top:10px; }\n  .vb-recent-chips.vb-visible{ display:flex; }\n  .vb-recent-chip{ padding:5px 11px; background:#fff; border:1px solid var(--vb-line); border-radius:999px; font-size:12px; font-family:'Courier New',monospace; letter-spacing:.3px; color:var(--vb-blue); cursor:pointer; transition:border-color .15s var(--vb-ease), background .15s var(--vb-ease), transform .12s var(--vb-ease); }\n  .vb-recent-chip:hover{ border-color:var(--vb-blue); background:var(--vb-blue-soft); }\n  .vb-recent-chip:active{ transform:scale(.95); }\n  #vb-bulk-hint .vb-row-icon{ flex:0 0 auto; width:15px; height:15px; margin-top:1px; }\n  #vb-bulk-hint:empty{ display:none; padding:0; border:none; margin-top:0; }\n  #vb-example button{ display:inline-flex; align-items:center; padding:5px 13px; background:#fff; border:1.5px solid var(--vb-line); border-radius:20px; color:var(--vb-blue); cursor:pointer; font-size:12.5px; font-weight:600; font-family:inherit; transition:border-color .15s var(--vb-ease), background .15s var(--vb-ease), transform .12s var(--vb-ease); }\n  #vb-example button:hover{ border-color:var(--vb-blue); background:var(--vb-blue-soft); transform:translateY(-1px); }\n  #vb-example button:active{ transform:translateY(0); }\n  #vb-result{ margin-top:26px; }\n  .vb-result-anim{ animation:vb-result-in .4s var(--vb-ease) both; }\n  .vb-error{ display:flex; align-items:flex-start; gap:9px; padding:14px 16px; background:#fdeeee; border:1px solid #e3a0a0; border-radius:7px; color:#8a2c2c; font-size:14px; line-height:1.5; animation:vb-shake .4s var(--vb-ease) both; }\n  .vb-error .vb-row-icon{ color:#c0392b; margin-top:1px; }\n  .vb-card{ border:1px solid var(--vb-line); border-radius:10px; overflow:hidden; box-shadow:0 1px 2px rgba(16,24,40,.03), 0 4px 14px -6px rgba(16,24,40,.08); }\n  .vb-card-head{ background:linear-gradient(180deg,#f4f8fb,var(--vb-bg)); padding:16px 18px; border-bottom:1px solid var(--vb-line); display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:8px; }\n  .vb-serial-note{ display:flex; align-items:flex-start; gap:8px; padding:8px 18px; font-size:12.5px; color:var(--vb-grey); background:var(--vb-bg); border-bottom:1px solid var(--vb-line); }\n  .vb-serial-note .vb-row-icon{ flex:0 0 auto; width:15px; height:15px; margin-top:1px; }\n  .vb-card-head .vb-code-display{ font-family:'Courier New',monospace; font-size:18px; font-weight:700; letter-spacing:1.5px; color:var(--vb-ink); background:#fff; border:1px solid var(--vb-line); border-radius:5px; padding:5px 10px; box-shadow:inset 0 1px 2px rgba(16,24,40,.05); }\n  .vb-card-head .vb-type-name{ font-size:13.5px; color:var(--vb-blue); font-weight:600; text-transform:uppercase; letter-spacing:.03em; }\n  .vb-copy-btn{ position:relative; display:inline-flex; align-items:center; justify-content:center; width:24px; height:24px; margin-left:6px; padding:0; border:none; background:transparent; color:var(--vb-grey); cursor:pointer; border-radius:5px; vertical-align:middle; transition:background .15s var(--vb-ease), color .15s var(--vb-ease); }\n  .vb-copy-btn:hover{ background:var(--vb-line); color:var(--vb-blue); }\n  .vb-copy-btn svg{ width:14px; height:14px; }\n  .vb-copy-icon-check{ display:none; color:#1c7a4a; }\n  .vb-copy-btn.vb-copied{ background:transparent; color:#1c7a4a; }\n  .vb-copy-btn.vb-copied .vb-copy-icon-default{ display:none; }\n  .vb-copy-btn.vb-copied .vb-copy-icon-check{ display:inline-flex; }\n  .vb-copy-tooltip{ position:absolute; bottom:calc(100% + 7px); left:50%; transform:translateX(-50%) translateY(4px); padding:4px 8px; background:var(--vb-ink); color:#fff; font-size:11px; font-weight:600; font-family:'Poppins',Arial,sans-serif; border-radius:5px; white-space:nowrap; opacity:0; pointer-events:none; transition:opacity .15s var(--vb-ease), transform .15s var(--vb-ease); }\n  .vb-copy-btn.vb-copied .vb-copy-tooltip{ opacity:1; transform:translateX(-50%) translateY(0); }\n  .vb-qty-badge{ font-size:12.5px; font-weight:700; color:#fff; background:var(--vb-blue); border-radius:12px; padding:2px 9px; display:inline-block; animation:vb-badge-pop .4s var(--vb-ease-spring) both; }\n  .vb-rows{ padding:4px 0; }\n  .vb-row{ display:flex; padding:14px 18px; border-bottom:1px solid var(--vb-line); gap:16px; align-items:flex-start; transition:background-color .15s var(--vb-ease); }\n  .vb-row:last-child{ border-bottom:none; }\n  .vb-row:hover{ background-color:var(--vb-bg); }\n  .vb-row .vb-label{ flex:0 0 160px; display:flex; align-items:flex-start; gap:8px; font-size:12.5px; text-transform:uppercase; letter-spacing:0.4px; color:var(--vb-grey); font-weight:600; padding-top:2px; }\n  .vb-row-icon{ flex:0 0 auto; display:inline-flex; width:18px; height:18px; color:var(--vb-blue); opacity:.75; }\n  .vb-row-icon svg{ width:100%; height:100%; }\n  .vb-row .vb-value{ flex:1; font-size:15px; line-height:1.45; }\n  .vb-row .vb-value .vb-segment{ display:inline-block; min-width:56px; text-align:center; font-family:'Courier New',monospace; font-size:11.5px; font-weight:600; background:#fff; border:1px solid var(--vb-line); border-radius:20px; padding:2px 9px; margin-right:8px; color:var(--vb-blue); vertical-align:1px; }\n  .vb-value-yes{ color:#1c7a4a; font-weight:600; }\n  .vb-value-yes::before{ content:'\u2713 '; }\n  .vb-alt-list{ margin:6px 0 0; padding-left:18px; font-size:13.5px; color:var(--vb-ink); }\n  .vb-alt-list li{ margin-bottom:2px; }\n  .vb-footer-note{ margin-top:16px; font-size:12.5px; color:var(--vb-grey); line-height:1.5; }\n  .vb-cta-btn{ display:inline-block; padding:11px 22px; background:var(--vb-blue); color:#fff !important; border-radius:7px; text-decoration:none; font-weight:600; font-size:14px; font-family:'Poppins',Arial,sans-serif; transition:background .15s var(--vb-ease), transform .12s var(--vb-ease), box-shadow .15s var(--vb-ease); border:2px solid var(--vb-blue); cursor:pointer; }\n  \/* Zichtbare focus-ring voor toetsenbordgebruikers op alle interactieve elementen die\n     nog geen eigen focus-stijl hadden (:focus-visible i.p.v. :focus, zodat muisklikken\n     geen onnodige ring tonen -- alleen echte toetsenbordnavigatie). *\/\n  .vb-cta-btn:focus-visible,\n  .vb-part-checkbox:focus-visible,\n  .vb-part-qty-btn:focus-visible,\n  .vb-next-step-card:focus-visible,\n  .vb-copy-btn:focus-visible,\n  .vb-parts-toggle-btn:focus-visible{ outline:3px solid var(--vb-blue); outline-offset:2px; }\n  .vb-part-checkbox:focus-visible ~ .vb-part-card-clickzone{ outline:2px solid var(--vb-blue); outline-offset:2px; border-radius:6px; }\n  .vb-cta-btn:hover{ background:var(--vb-blue-dark); border-color:var(--vb-blue-dark); transform:translateY(-1px); box-shadow:0 4px 12px -3px rgba(0,120,191,.35); }\n  .vb-cta-btn:active{ transform:translateY(0); box-shadow:none; }\n  .vb-cta-btn-secondary{ background:transparent; color:var(--vb-blue) !important; }\n  .vb-cta-btn-secondary:hover{ background:var(--vb-blue); color:#fff !important; }\n  .vb-spareparts-note{ margin-top:22px; padding:16px 18px; background:var(--vb-bg); border:1px solid var(--vb-line); border-left:3px solid var(--vb-blue); border-radius:8px; font-size:13px; color:var(--vb-grey); line-height:1.55; display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:12px; }\n  .vb-spareparts-text{ flex:1 1 240px; }\n  .vb-spareparts-links{ display:flex; flex-wrap:wrap; gap:8px; }\n  .vb-spareparts-btn{ display:inline-block; padding:9px 16px; background:#fff; color:var(--vb-blue) !important; border:1.5px solid var(--vb-blue); border-radius:6px; text-decoration:none; font-weight:600; font-size:13px; white-space:nowrap; transition:background .15s var(--vb-ease), color .15s var(--vb-ease), transform .12s var(--vb-ease); }\n  .vb-spareparts-btn:hover{ background:var(--vb-blue); color:#fff !important; transform:translateY(-1px); }\n  .vb-doc-link{ display:inline-block; margin-left:4px; font-size:13px; font-weight:600; color:var(--vb-blue); text-decoration:underline; }\n  .vb-doc-link:hover{ color:var(--vb-blue-dark); }\n  .vb-email-toggle-btn{ background:none; border:none; padding:0; font-size:13px; font-weight:600; color:var(--vb-blue); text-decoration:underline; cursor:pointer; font-family:inherit; }\n  .vb-email-toggle-btn:hover{ color:var(--vb-blue-dark); }\n  .vb-email-form{ padding:14px; background:var(--vb-bg); border:1px solid var(--vb-line); border-radius:7px; display:flex; flex-wrap:wrap; gap:8px; }\n  .vb-email-input{ flex:1 1 200px; min-width:0; padding:9px 11px; font-size:14px; font-family:'Poppins',Arial,sans-serif; border:1px solid var(--vb-line); border-radius:6px; outline:none; text-transform:none; transition:border-color .15s var(--vb-ease), box-shadow .15s var(--vb-ease); }\n  .vb-email-input:focus{ border-color:var(--vb-blue); box-shadow:0 0 0 3px var(--vb-blue-soft); }\n  .vb-email-form-actions{ flex:1 1 100%; display:flex; gap:10px; margin-top:4px; }\n  .vb-email-status{ flex:1 1 100%; font-size:12.5px; color:var(--vb-blue); margin-top:2px; }\n  .vb-email-status:empty{ display:none; }\n  .vb-email-status-error{ color:#8a2c2c; }\n  .vb-email-status-success{ display:flex !important; align-items:center; gap:7px; color:#1c7a4a; font-weight:600; }\n  .vb-success-check{ display:inline-flex; width:18px; height:18px; flex:0 0 auto; }\n  .vb-success-check svg{ width:100%; height:100%; overflow:visible; }\n  .vb-success-circle{ fill:none; stroke:#1c7a4a; stroke-width:1.6; stroke-dasharray:66; stroke-dashoffset:66; animation:vb-draw .45s var(--vb-ease) forwards; }\n  .vb-success-tick{ fill:none; stroke:#1c7a4a; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; stroke-dasharray:14; stroke-dashoffset:14; animation:vb-draw .3s var(--vb-ease) .4s forwards; }\n  @keyframes vb-draw{ to{ stroke-dashoffset:0; } }\n  .vb-qty-wrap{ display:flex; align-items:center; gap:8px; }\n  .vb-qty-wrap label{ font-size:13px; font-weight:600; color:var(--vb-ink); }\n  .vb-qty-stepper{ display:flex; align-items:stretch; border:1px solid var(--vb-line); border-radius:6px; overflow:hidden; }\n  .vb-qty-step-btn{ display:flex; align-items:center; justify-content:center; width:28px; border:none; background:var(--vb-bg); color:var(--vb-ink); font-size:16px; font-weight:600; line-height:1; cursor:pointer; transition:background .15s var(--vb-ease); }\n  .vb-qty-step-btn:hover{ background:var(--vb-line); }\n  .vb-qty-step-btn:active{ background:var(--vb-blue); color:#fff; }\n  .vb-qty-input{ width:44px; padding:7px 4px; font-size:14px; font-family:'Poppins',Arial,sans-serif; border:none; border-left:1px solid var(--vb-line); border-right:1px solid var(--vb-line); outline:none; text-align:center; -moz-appearance:textfield; }\n  .vb-qty-input::-webkit-outer-spin-button, .vb-qty-input::-webkit-inner-spin-button{ -webkit-appearance:none; margin:0; }\n  .vb-qty-input:focus{ background:var(--vb-blue-soft); }\n  .vb-combined-quote{ margin-top:28px; padding:22px; background:linear-gradient(180deg, var(--vb-bg), #fff); border:1px solid var(--vb-line); border-radius:10px; border-top:3px solid var(--vb-blue); }\n  .vb-next-steps-grid{ display:grid; grid-template-columns:1fr 1fr; gap:12px; margin:16px 0 4px; }\n  .vb-next-step-card{ display:flex; flex-direction:column; align-items:center; gap:9px; padding:20px 12px; background:#fff; border:1.5px solid var(--vb-line); border-radius:10px; cursor:pointer; transition:border-color .2s var(--vb-ease), transform .2s var(--vb-ease), box-shadow .2s var(--vb-ease); font-weight:600; font-size:13.5px; color:var(--vb-ink); font-family:inherit; }\n  .vb-next-step-card:hover{ border-color:var(--vb-blue); transform:translateY(-3px); box-shadow:0 8px 20px rgba(0,120,191,.14); }\n  .vb-next-step-icon{ width:36px; height:36px; border-radius:50%; background:var(--vb-blue-soft); display:flex; align-items:center; justify-content:center; color:var(--vb-blue); transition:transform .25s var(--vb-ease); }\n  .vb-next-step-card:hover .vb-next-step-icon{ transform:scale(1.1) rotate(-4deg); }\n  .vb-next-step-icon svg{ width:19px; height:19px; }\n  @media (max-width: 480px){ .vb-next-steps-grid{ grid-template-columns:1fr; } }\n  .vb-combined-quote-title{ margin:0 0 4px; font-size:16px; font-weight:600; color:var(--vb-ink); }\n  .vb-combined-quote-intro{ margin:0; font-size:13.5px; color:var(--vb-grey); line-height:1.5; }\n  .vb-combined-actions{ display:flex; gap:10px; flex-wrap:wrap; margin-top:14px; }\n  .vb-combined-quote .vb-collapsible{ margin-top:14px; }\n  .vb-combined-quote .vb-email-form{ background:#fff; }\n  .vb-info-btn{ display:inline-flex; align-items:center; justify-content:center; width:16px; height:16px; margin-left:4px; padding:0; border:none; border-radius:50%; background:var(--vb-line); color:var(--vb-grey); font-size:11px; font-weight:700; line-height:1; cursor:pointer; vertical-align:middle; transition:background .15s var(--vb-ease), color .15s var(--vb-ease), transform .15s var(--vb-ease-spring); }\n  .vb-info-btn:hover{ background:var(--vb-blue); color:#fff; transform:scale(1.15); }\n  .vb-food-info-note{ padding:10px 18px; font-size:12.5px; color:var(--vb-grey); line-height:1.5; background:var(--vb-warn-bg); border-bottom:1px solid var(--vb-line); }\n  .vb-food-info-note a{ color:var(--vb-blue); text-decoration:underline; font-weight:600; }\n  .vb-food-info-note a:hover{ color:var(--vb-blue-dark); }\n  .vb-parts-toggle-btn{ margin-top:10px; }\n  .vb-parts-popup{ margin-top:12px; padding:16px; background:var(--vb-bg); border:1px solid var(--vb-line); border-radius:8px; }\n  .vb-parts-popup-intro{ margin:0 0 12px; font-size:13px; color:var(--vb-grey); line-height:1.5; }\n  .vb-collapsible.vb-parts-data-loading .vb-parts-list{ opacity:.68; transition:opacity .15s var(--vb-ease); }\n  .vb-collapsible.vb-parts-data-loading .vb-parts-actions .vb-cta-btn{ cursor:progress; }\n  .vb-parts-list{ display:grid; grid-template-columns:repeat(auto-fill, minmax(165px, 1fr)); gap:10px; margin-bottom:14px; }\n  .vb-parts-section-title{ margin:16px 0 8px; font-size:11.5px; font-weight:700; text-transform:uppercase; letter-spacing:.04em; color:var(--vb-grey); }\n  .vb-parts-section-title:first-of-type{ margin-top:0; }\n  \/* Familie-kleuraccent: dunne gekleurde rand links op de kaart, zodat gerelateerde\n     onderdelen (zuigbuis + bijpassende koppeling\/kap) visueel bij elkaar horen. *\/\n  .vb-part-card{ position:relative; display:flex; flex-direction:column; background:#fff; border:1px solid var(--vb-line); border-left:4px solid var(--vb-line); border-radius:8px; padding:10px 10px 9px; transition:border-color .15s var(--vb-ease), box-shadow .15s var(--vb-ease); font-size:13px; }\n  .vb-part-card[data-family=\"safeline\"]{ border-left-color:var(--vb-blue); }\n  .vb-part-card[data-family=\"cds_voetklep\"]{ border-left-color:#d98a33; }\n  .vb-part-card:hover{ border-color:var(--vb-blue); box-shadow:0 2px 8px rgba(0,120,191,.1); }\n  .vb-part-card[data-family=\"safeline\"]:hover, .vb-part-card[data-family=\"cds_voetklep\"]:hover{ border-left-width:4px; }\n  .vb-part-card > input[type=checkbox]{ position:absolute; top:8px; right:8px; z-index:2; width:17px; height:17px; accent-color:var(--vb-blue); cursor:pointer; }\n  .vb-part-card > input[type=checkbox]:checked ~ .vb-part-card-clickzone .vb-part-thumb-wrap{ box-shadow:0 0 0 2px var(--vb-blue); }\n  .vb-part-card-clickzone{ display:flex; flex-direction:column; gap:6px; cursor:pointer; }\n  .vb-part-thumb-wrap{ position:relative; width:100%; aspect-ratio:1; border-radius:6px; background:var(--vb-bg); border:1px solid var(--vb-line); overflow:hidden; display:flex; align-items:center; justify-content:center; transition:box-shadow .15s var(--vb-ease); }\n  .vb-part-thumb-wrap::after{ content:''; position:absolute; inset:0; transform:translateX(-100%); background:linear-gradient(90deg, transparent, rgba(0,120,191,.12), transparent); animation:vb-shimmer 1.4s ease-in-out infinite; }\n  .vb-part-thumb-wrap.vb-loaded::after{ display:none; }\n  .vb-part-thumb{ width:100%; height:100%; object-fit:cover; opacity:0; transition:opacity .25s var(--vb-ease); }\n  .vb-part-thumb-wrap.vb-loaded .vb-part-thumb{ opacity:1; }\n  \/* Getekend vinkje-badge: verschijnt over de foto heen zodra dit onderdeel zojuist is\n     toegevoegd aan de winkelwagen (klasse .vb-just-added op de kaart, via JS gezet). *\/\n  .vb-part-check-badge{ position:absolute; bottom:5px; right:5px; width:24px; height:24px; border-radius:50%; background:#2e9e5b; display:flex; align-items:center; justify-content:center; opacity:0; transform:scale(.6); transition:opacity .2s var(--vb-ease), transform .2s var(--vb-ease); }\n  .vb-just-added .vb-part-check-badge{ opacity:1; transform:scale(1); }\n  .vb-check-svg{ width:14px; height:14px; }\n  .vb-check-path{ stroke-dasharray:26; stroke-dashoffset:26; }\n  .vb-just-added .vb-check-path{ animation:vb-draw-check .45s .1s var(--vb-ease) forwards; }\n  @keyframes vb-draw-check{ to{ stroke-dashoffset:0; } }\n  @media (prefers-reduced-motion: reduce){ .vb-check-path{ animation:none !important; stroke-dashoffset:0; } }\n  .vb-card-stagger-in{ animation:vb-card-fade-in .35s var(--vb-ease) backwards; }\n  @keyframes vb-card-fade-in{ from{ opacity:0; transform:translateY(8px); } to{ opacity:1; transform:translateY(0); } }\n  @media (prefers-reduced-motion: reduce){ .vb-card-stagger-in{ animation:none; } }\n  .vb-part-text{ display:flex; flex-direction:column; gap:1px; overflow-wrap:break-word; word-break:break-word; }\n  .vb-part-role{ font-weight:600; color:var(--vb-blue); text-transform:uppercase; font-size:10px; letter-spacing:.03em; }\n  .vb-part-label{ color:var(--vb-ink); line-height:1.25; }\n  .vb-part-stock-warning{ display:block; font-size:10.5px; font-weight:600; color:#c0392b; margin-top:1px; }\n  .vb-part-stock-warning:empty{ display:none; }\n  .vb-part-card-footer{ display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:6px; margin-top:8px; padding-top:8px; border-top:1px solid var(--vb-line); }\n  .vb-part-qty-stepper{ flex:0 0 auto; display:flex; align-items:center; gap:3px; }\n  .vb-part-qty-btn{ width:21px; height:21px; border:1px solid var(--vb-line); background:#fff; border-radius:5px; font-size:13px; line-height:1; cursor:pointer; color:var(--vb-blue); transition:border-color .15s var(--vb-ease), background .15s var(--vb-ease), transform .1s var(--vb-ease); }\n  .vb-part-qty-btn:active{ transform:scale(.85); background:var(--vb-blue-soft); }\n  @media (prefers-reduced-motion: reduce){ .vb-part-qty-btn:active{ transform:none; } }\n  .vb-part-qty-btn:hover{ border-color:var(--vb-blue); background:var(--vb-blue-soft); }\n  .vb-part-qty-val{ min-width:16px; text-align:center; font-weight:600; font-size:12.5px; }\n  .vb-part-price{ flex:0 0 auto; font-weight:700; font-size:12.5px; color:var(--vb-ink); min-height:1em; text-align:right; }\n  .vb-part-card-unavailable{ opacity:.75; }\n  .vb-part-card-unavailable:hover{ border-color:var(--vb-line); box-shadow:none; }\n  .vb-part-card-out-of-stock{ opacity:.6; }\n  .vb-part-card-partial{ opacity:.78; border-color:var(--vb-warn-border); background:var(--vb-warn-bg); }\n  .vb-part-card-out-of-stock .vb-part-card-clickzone{ cursor:default; }\n  .vb-part-unavailable{ display:block; font-size:11.5px; color:var(--vb-grey); margin-top:6px; }\n  .vb-part-unavailable a{ color:var(--vb-blue); text-decoration:underline; font-weight:600; }\n  \/* Dekkingsbalk: \"X van de Y onderdelen beschikbaar\", v\u00f3\u00f3r de klant iets aanvinkt. *\/\n  .vb-parts-coverage{ display:flex; align-items:center; gap:10px; margin-bottom:14px; }\n  .vb-parts-coverage-track{ flex:1; height:6px; border-radius:3px; background:var(--vb-line); overflow:hidden; }\n  .vb-parts-coverage-fill{ height:100%; background:var(--vb-blue); border-radius:3px; transition:width .4s var(--vb-ease); }\n  .vb-parts-coverage-fill.vb-full-coverage{ background:linear-gradient(90deg, #d4a017, #f4d774, #d4a017); background-size:200% 100%; animation:vb-gold-shimmer 1.8s ease-in-out 1; }\n  @keyframes vb-gold-shimmer{ 0%{ background-position:200% 0; } 100%{ background-position:0 0; } }\n  @media (prefers-reduced-motion: reduce){ .vb-parts-coverage-fill.vb-full-coverage{ animation:none; background:#d4a017; } }\n  .vb-parts-coverage-label{ flex:0 0 auto; font-size:11.5px; font-weight:600; color:var(--vb-grey); white-space:nowrap; }\n  .vb-parts-kit-strip{ display:none; flex-wrap:wrap; gap:6px; padding:8px 2px 2px; }\n  .vb-parts-kit-strip.vb-visible{ display:flex; }\n  .vb-kit-thumb{ width:34px; height:34px; border-radius:6px; overflow:hidden; border:1px solid var(--vb-line); background:var(--vb-bg); animation:vb-kit-pop .3s var(--vb-ease); flex:0 0 auto; }\n  .vb-kit-thumb img{ width:100%; height:100%; object-fit:cover; }\n  .vb-kit-thumb-empty{ background:var(--vb-blue-soft); }\n  @keyframes vb-kit-pop{ from{ transform:scale(.35); opacity:0; } 60%{ transform:scale(1.08); opacity:1; } to{ transform:scale(1); opacity:1; } }\n  @media (prefers-reduced-motion: reduce){ .vb-kit-thumb{ animation:none; } }\n  .vb-parts-subtotal-bar{ display:none; text-align:right; font-weight:700; font-size:14px; color:var(--vb-ink); padding:8px 2px; }\n  .vb-parts-subtotal-bar.vb-visible{ display:block; }\n  .vb-parts-actions{ display:flex; }\n  .vb-parts-sticky-footer{ position:sticky; bottom:0; background:#fff; padding-top:6px; margin-top:2px; z-index:3; }\n  .vb-parts-sticky-footer::before{ content:''; position:absolute; left:-4px; right:-4px; top:-14px; height:14px; background:linear-gradient(to bottom, transparent, #fff); pointer-events:none; }\n  .vb-combined-parts{ margin-top:20px; padding:16px; background:var(--vb-bg); border:1px solid var(--vb-line); border-radius:8px; display:flex; flex-wrap:wrap; align-items:center; gap:12px; }\n  .vb-combined-parts-total{ font-weight:700; font-size:14px; color:var(--vb-ink); }\n  .vb-view-cart-link{ display:inline-block; margin-left:8px; padding:6px 14px; background:var(--vb-blue); color:#fff !important; border-radius:6px; text-decoration:none; font-weight:600; font-size:12.5px; transition:background .15s var(--vb-ease); }\n  .vb-toast-container{ position:fixed; right:16px; bottom:16px; z-index:9999; display:flex; flex-direction:column; gap:8px; pointer-events:none; max-width:min(360px, calc(100vw - 32px)); }\n  .vb-toast{ pointer-events:auto; display:flex; flex-wrap:wrap; align-items:center; gap:8px; background:#fff; border:1px solid var(--vb-line); border-left:4px solid #1c7a4a; border-radius:10px; padding:12px 14px; box-shadow:0 10px 30px rgba(0,0,0,.14); font-size:13px; color:var(--vb-ink); cursor:pointer; opacity:0; transform:translateY(12px) scale(.97); transition:opacity .25s var(--vb-ease), transform .25s var(--vb-ease); }\n  .vb-toast.vb-toast-in{ opacity:1; transform:translateY(0) scale(1); }\n  .vb-toast.vb-toast-out{ opacity:0; transform:translateY(6px) scale(.98); }\n  .vb-toast.vb-toast-error{ border-left-color:#c0392b; }\n  .vb-toast-count{ flex:0 0 100%; font-size:11.5px; color:var(--vb-grey); }\n  @media (prefers-reduced-motion: reduce){ .vb-toast{ transition:opacity .15s linear; transform:none !important; } }\n  .vb-view-cart-link:hover{ background:var(--vb-blue-dark); }\n  .vb-hidden{ display:none !important; }\n  .vb-collapsible{ display:grid; grid-template-rows:0fr; opacity:0; transition:grid-template-rows .32s var(--vb-ease), opacity .22s var(--vb-ease); }\n  .vb-collapsible.vb-open{ grid-template-rows:1fr; opacity:1; }\n  .vb-collapsible-inner{ overflow:hidden; min-height:0; }\n  \/* De echte Gravity Forms (13 en 15) staan verderop op de pagina, in een\n     apart wp:shortcode-blok \u2014 nooit zichtbaar voor de klant. De widget vult\n     en verstuurt ze op de achtergrond; de klant ziet alleen de eigen\n     invulformpjes hierboven. *\/\n  #gform_wrapper_15, #gform_wrapper_13, #gform_confirmation_wrapper_15, #gform_confirmation_wrapper_13{ display:none !important; }\n  .vb-bulk-summary{ margin-bottom:16px; font-size:13.5px; font-weight:600; color:var(--vb-ink); }\n  .vb-bulk-summary .vb-bulk-warn{ display:block; margin-top:4px; font-weight:400; color:var(--vb-grey); }\n  .vb-result-item{ margin-bottom:28px; padding-bottom:20px; border-bottom:1px dashed var(--vb-line); }\n  .vb-result-item:last-child{ margin-bottom:0; padding-bottom:0; border-bottom:none; }\n  .vb-skeleton{ border:1px solid var(--vb-line); border-radius:10px; overflow:hidden; animation:vb-result-in .3s var(--vb-ease) both; }\n  .vb-skeleton-head{ height:54px; background:var(--vb-bg); position:relative; overflow:hidden; }\n  .vb-skeleton-row{ height:52px; border-bottom:1px solid var(--vb-line); position:relative; overflow:hidden; background:#fff; }\n  .vb-skeleton-row:last-child{ border-bottom:none; }\n  .vb-skeleton-head::after, .vb-skeleton-row::after{\n    content:''; position:absolute; inset:0; transform:translateX(-100%);\n    background:linear-gradient(90deg, transparent, rgba(0,120,191,.08), transparent);\n    animation:vb-shimmer 1.4s ease-in-out infinite;\n  }\n  @keyframes vb-shimmer{ to{ transform:translateX(100%); } }\n  @media (max-width:480px){\n    .vb-doc-link{ display:block; margin-left:0; margin-top:4px; }\n  }\n  @media (max-width:480px){\n    .vb-check{ padding:24px 18px 28px; }\n    .vb-row{ flex-direction:column; gap:4px; }\n    .vb-row .vb-label{ flex:none; }\n    .vb-top-row{ flex-direction:column; }\n  }\n\n\n  \/* v16 UX layer: snellere visuele herkenning, rustige progressive disclosure en coherente motion. *\/\n  .vb-input-meta{ min-height:20px; margin-top:7px; font-size:12.5px; color:var(--vb-grey); display:flex; align-items:center; gap:7px; transition:color .18s var(--vb-ease), opacity .18s var(--vb-ease); }\n  .vb-input-meta:empty{ min-height:0; margin-top:0; }\n  .vb-input-meta::before{ content:''; width:7px; height:7px; border-radius:50%; background:var(--vb-line); flex:0 0 auto; transition:background .18s var(--vb-ease), box-shadow .18s var(--vb-ease); }\n  .vb-input-meta.vb-input-meta-ready{ color:#17643e; font-weight:600; }\n  .vb-input-meta.vb-input-meta-ready::before{ background:#2e9e5b; box-shadow:0 0 0 4px rgba(46,158,91,.12); }\n  .vb-input-meta.vb-input-meta-bulk{ color:var(--vb-blue); font-weight:600; }\n  .vb-input-meta.vb-input-meta-bulk::before{ background:var(--vb-blue); box-shadow:0 0 0 4px var(--vb-blue-soft); }\n\n  .vb-card.vb-result-card{ border-radius:14px; box-shadow:0 10px 32px -22px rgba(16,24,40,.38), 0 2px 5px rgba(16,24,40,.04); border-color:#dbe5ec; }\n  .vb-result-hero{ position:relative; display:grid; grid-template-columns:74px minmax(0,1fr); gap:16px; padding:20px 20px 18px; background:linear-gradient(135deg,#f6fbfe 0%,#fff 66%); overflow:hidden; }\n  .vb-result-hero::after{ content:''; position:absolute; right:-54px; top:-68px; width:170px; height:170px; border-radius:50%; background:radial-gradient(circle,rgba(0,120,191,.10),rgba(0,120,191,0) 68%); pointer-events:none; }\n  .vb-result-glyph{ width:74px; height:74px; border-radius:18px; display:flex; align-items:center; justify-content:center; color:var(--vb-blue); background:#fff; border:1px solid #dbe8f0; box-shadow:0 8px 22px -15px rgba(0,120,191,.55); animation:vb-hero-mark-in .42s var(--vb-ease-spring) both; }\n  .vb-result-glyph svg{ width:47px; height:47px; }\n  .vb-result-main{ min-width:0; position:relative; z-index:1; }\n  .vb-match-found{ display:inline-flex; align-items:center; gap:5px; margin-bottom:4px; font-size:11px; text-transform:uppercase; letter-spacing:.055em; font-weight:700; color:#23764a; }\n  .vb-match-found svg{ width:14px; height:14px; }\n  .vb-hero-title-row{ display:flex; align-items:flex-start; justify-content:space-between; gap:10px; }\n  .vb-hero-title{ margin:0; font-size:20px; line-height:1.22; color:var(--vb-ink); letter-spacing:-.015em; }\n  .vb-hero-code-row{ display:flex; align-items:center; flex-wrap:wrap; gap:3px; margin-top:6px; }\n  .vb-hero-code{ font-family:'Courier New',monospace; font-size:13px; font-weight:700; letter-spacing:.65px; color:var(--vb-grey); }\n  .vb-result-hero .vb-copy-btn{ margin-left:2px; }\n  .vb-spec-chips{ grid-column:1 \/ -1; display:flex; flex-wrap:wrap; gap:7px; margin-top:2px; }\n  .vb-spec-chip{ display:inline-flex; align-items:center; gap:6px; min-height:30px; max-width:100%; padding:5px 10px; border:1px solid #dfe8ee; background:rgba(255,255,255,.92); border-radius:999px; font-size:12px; font-weight:600; color:#344454; line-height:1.25; animation:vb-chip-in .34s var(--vb-ease) both; }\n  .vb-spec-chip:nth-child(2){ animation-delay:35ms; }.vb-spec-chip:nth-child(3){ animation-delay:70ms; }.vb-spec-chip:nth-child(4){ animation-delay:105ms; }.vb-spec-chip:nth-child(5){ animation-delay:140ms; }\n  .vb-spec-chip .vb-row-icon{ width:15px; height:15px; opacity:.85; }\n  .vb-spec-chip.vb-food-ok{ color:#17643e; border-color:#cde8d9; background:#f1faf5; }\n  .vb-spec-chip.vb-food-neutral{ color:var(--vb-grey); background:#f8fafb; }\n  .vb-color-swatch{ width:14px; height:14px; border-radius:50%; border:1px solid rgba(16,24,40,.18); box-shadow:inset 0 0 0 1px rgba(255,255,255,.35); flex:0 0 auto; }\n  .vb-technical-bar{ display:flex; align-items:center; justify-content:space-between; gap:10px; padding:10px 18px; border-top:1px solid var(--vb-line); background:#fff; }\n  .vb-details-toggle{ display:inline-flex; align-items:center; gap:8px; padding:7px 10px; margin:-2px 0; border:0; background:transparent; color:var(--vb-blue); font:600 12.5px\/1.2 'Poppins',Arial,sans-serif; cursor:pointer; border-radius:7px; transition:background .15s var(--vb-ease); }\n  .vb-details-toggle:hover{ background:var(--vb-blue-soft); }\n  .vb-details-chevron{ width:16px; height:16px; transition:transform .22s var(--vb-ease); }\n  .vb-details-toggle[aria-expanded=\"true\"] .vb-details-chevron{ transform:rotate(180deg); }\n  .vb-tech-collapse .vb-rows{ border-top:1px solid var(--vb-line); }\n  .vb-tech-collapse.vb-open{ margin-bottom:0; }\n  .vb-tech-collapse .vb-row{ padding-top:12px; padding-bottom:12px; }\n\n  .vb-part-card.vb-selected{ border-color:var(--vb-blue); background:#f6fbfe; box-shadow:0 0 0 2px var(--vb-blue-soft),0 5px 15px -12px rgba(0,120,191,.65); }\n  .vb-part-card.vb-selected .vb-part-thumb-wrap{ box-shadow:0 0 0 2px var(--vb-blue); }\n  .vb-part-card > input[type=checkbox]{ width:19px; height:19px; }\n  .vb-parts-sticky-footer{ display:grid; grid-template-columns:minmax(0,1fr) auto; align-items:center; gap:10px; padding:10px 0 2px; }\n  .vb-parts-selection-summary{ min-width:0; font-size:12px; font-weight:600; color:var(--vb-grey); }\n  .vb-parts-selection-summary.vb-visible{ color:var(--vb-ink); }\n  .vb-parts-subtotal-bar{ text-align:left; padding:1px 0 0; font-size:13px; }\n  .vb-parts-actions{ grid-column:2; grid-row:1 \/ span 2; }\n  .vb-parts-actions .vb-cta-btn{ min-width:150px; }\n  .vb-next-step-card:not(.vb-next-step-card-secondary){ color:#fff; background:linear-gradient(180deg,var(--vb-blue),#0069aa); border-color:var(--vb-blue); box-shadow:0 7px 18px -12px rgba(0,120,191,.75); }\n  .vb-next-step-card:not(.vb-next-step-card-secondary) .vb-next-step-icon{ background:rgba(255,255,255,.16); color:#fff; }\n  .vb-next-step-card-secondary{ background:#fff; }\n  .vb-next-step-card:not(.vb-next-step-card-secondary):hover{ color:#fff; border-color:var(--vb-blue-dark); box-shadow:0 10px 24px -14px rgba(0,90,145,.8); }\n\n  @keyframes vb-hero-mark-in{ from{ opacity:0; transform:scale(.8) rotate(-3deg); } to{ opacity:1; transform:scale(1) rotate(0); } }\n  @keyframes vb-chip-in{ from{ opacity:0; transform:translateY(5px); } to{ opacity:1; transform:translateY(0); } }\n  @media (prefers-reduced-motion: reduce){ .vb-result-glyph,.vb-spec-chip{ animation:none !important; } }\n  @media (max-width:480px){\n    .vb-result-hero{ grid-template-columns:54px minmax(0,1fr); gap:12px; padding:17px 15px 15px; }\n    .vb-result-glyph{ width:54px; height:54px; border-radius:14px; }.vb-result-glyph svg{ width:36px; height:36px; }\n    .vb-hero-title{ font-size:17px; }.vb-spec-chips{ gap:6px; }.vb-spec-chip{ font-size:11.5px; padding:5px 8px; }\n    .vb-parts-sticky-footer{ grid-template-columns:1fr; }.vb-parts-actions{ grid-column:1; grid-row:auto; }.vb-parts-actions .vb-cta-btn{ width:100%; }\n  }\n\n  \/* v17 product layer: product-passport hero, recoverable errors and professional bulk workflow. *\/\n  .vb-check{ max-width:720px; }\n  .vb-code-wrap.vb-input-ready #vb-code{ border-color:#84c7a2; box-shadow:0 0 0 4px rgba(46,158,91,.08); }\n  .vb-code-wrap.vb-input-bulk #vb-code{ border-color:#8bc7e7; box-shadow:0 0 0 4px rgba(0,120,191,.07); }\n  .vb-input-meta{ justify-content:space-between; flex-wrap:wrap; }\n  .vb-input-meta-text{ display:inline-flex; align-items:center; gap:7px; }\n  .vb-input-shortcut{ margin-left:auto; font-size:11px; font-weight:500; color:#8a96a3; }\n  .vb-input-meta-ready .vb-input-shortcut,.vb-input-meta-bulk .vb-input-shortcut{ color:inherit; opacity:.72; }\n  .vb-check.vb-search-success::before{ animation:vb-top-success .8s var(--vb-ease) both; }\n  @keyframes vb-top-success{ 0%{box-shadow:none} 35%{box-shadow:0 0 12px rgba(46,158,91,.45)} 100%{box-shadow:none} }\n\n  .vb-result-item{ animation:vb-result-item-in .38s var(--vb-ease) both; animation-delay:calc(var(--vb-item-order,0) * 45ms); }\n  @keyframes vb-result-item-in{ from{opacity:0;transform:translateY(8px)} to{opacity:1;transform:translateY(0)} }\n  .vb-result-item.vb-filter-hidden{ display:none !important; }\n  .vb-result-hero{ --vb-product-color:var(--vb-blue); border-left:4px solid var(--vb-product-color); }\n  .vb-result-hero::before{ content:''; position:absolute; inset:auto auto -70px -35px; width:180px; height:180px; border-radius:50%; background:radial-gradient(circle,color-mix(in srgb,var(--vb-product-color) 18%,transparent),transparent 67%); pointer-events:none; }\n  .vb-result-glyph{ color:var(--vb-product-color); background:linear-gradient(145deg,#fff,color-mix(in srgb,var(--vb-product-color) 8%,#fff)); border-color:color-mix(in srgb,var(--vb-product-color) 26%,#dbe8f0); }\n  .vb-source-pill{ display:inline-flex; align-items:center; gap:5px; margin-top:7px; padding:3px 8px; border-radius:999px; background:#edf7fc; color:#436477; font-size:10.5px; font-weight:600; }\n  .vb-source-pill .vb-row-icon{ width:13px; height:13px; }\n  .vb-code-anatomy{ grid-column:1\/-1; margin-top:3px; padding-top:12px; border-top:1px solid rgba(114,143,160,.16); }\n  .vb-code-anatomy-title{ margin-bottom:7px; font-size:10.5px; font-weight:700; letter-spacing:.045em; text-transform:uppercase; color:#82909c; }\n  .vb-code-anatomy-track{ display:flex; align-items:stretch; gap:4px; min-width:0; }\n  .vb-code-segment{ min-width:0; display:flex; flex-direction:column; justify-content:center; gap:1px; padding:6px 8px; border:1px solid #dfe8ee; background:rgba(255,255,255,.86); border-radius:7px; }\n  .vb-code-segment:first-child{ flex:1 1 120px; }\n  .vb-code-segment:last-child{ flex:0 1 86px; }\n  .vb-code-segment-value{ font:700 12px\/1.1 'Courier New',monospace; color:#293a49; letter-spacing:.35px; white-space:nowrap; }\n  .vb-code-segment-label{ font-size:8.5px; font-weight:600; color:#87939f; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }\n  .vb-code-segment.vb-seg-type{ border-top:2px solid #0078bf; }\n  .vb-code-segment.vb-seg-gasket{ border-top:2px solid #2e9e5b; }\n  .vb-code-segment.vb-seg-tube{ border-top:2px solid #7b61a8; }\n  .vb-code-segment.vb-seg-sensor{ border-top:2px solid #d98a33; }\n  .vb-code-segment.vb-seg-colour{ border-top:2px solid var(--vb-product-color); }\n\n  .vb-error-card{ display:grid; grid-template-columns:54px minmax(0,1fr); gap:14px; padding:18px; border:1px solid #ebc7c7; border-radius:12px; background:linear-gradient(135deg,#fff8f8,#fff); box-shadow:0 7px 24px -22px rgba(138,44,44,.5); }\n  .vb-error-card.vb-service-error{ border-color:#ead7a4; background:linear-gradient(135deg,#fffaf0,#fff); }\n  .vb-error-icon{ width:54px; height:54px; border-radius:15px; display:flex; align-items:center; justify-content:center; background:#fdeeee; color:#a64444; }\n  .vb-service-error .vb-error-icon{ background:#fff1ce; color:#9a6b14; }\n  .vb-error-icon .vb-row-icon{ width:26px; height:26px; opacity:1; }\n  .vb-error-title{ margin:0 0 5px; font-size:16px; line-height:1.3; color:var(--vb-ink); }\n  .vb-error-message{ margin:0; font-size:13px; line-height:1.55; color:var(--vb-grey); }\n  .vb-error-entered{ display:inline-flex; gap:6px; margin-top:9px; font-size:11.5px; color:#6e7d8a; }\n  .vb-error-entered code{ font-family:'Courier New',monospace; font-weight:700; color:var(--vb-ink); }\n  .vb-error-actions{ grid-column:2; display:flex; flex-wrap:wrap; gap:7px; margin-top:2px; }\n  .vb-mini-action{ display:inline-flex; align-items:center; justify-content:center; min-height:34px; padding:7px 11px; border:1px solid var(--vb-line); border-radius:7px; background:#fff; color:var(--vb-blue); font:600 12px\/1.2 'Poppins',Arial,sans-serif; text-decoration:none; cursor:pointer; transition:border-color .15s var(--vb-ease),background .15s var(--vb-ease),transform .12s var(--vb-ease); }\n  .vb-mini-action:hover{ border-color:var(--vb-blue); background:var(--vb-blue-soft); transform:translateY(-1px); }\n\n  .vb-bulk-overview{ margin-bottom:18px; padding:16px; border:1px solid #dbe6ed; border-radius:12px; background:linear-gradient(135deg,#f5fafd,#fff); }\n  .vb-bulk-overview-top{ display:flex; align-items:flex-start; justify-content:space-between; gap:12px; margin-bottom:12px; }\n  .vb-bulk-overview-title{ margin:0; font-size:15px; color:var(--vb-ink); }\n  .vb-bulk-overview-sub{ margin:3px 0 0; font-size:12px; color:var(--vb-grey); }\n  .vb-bulk-overview .vb-bulk-warn{ display:block; margin-top:3px; color:#9a6b14; }\n  .vb-bulk-stats{ display:grid; grid-template-columns:repeat(3,1fr); gap:8px; }\n  .vb-bulk-stat{ padding:10px 11px; border:1px solid #e1e9ee; border-radius:9px; background:#fff; }\n  .vb-bulk-stat-value{ display:block; font-size:18px; line-height:1; font-weight:700; color:var(--vb-ink); }\n  .vb-bulk-stat-label{ display:block; margin-top:4px; font-size:10.5px; font-weight:600; color:var(--vb-grey); }\n  .vb-bulk-stat.vb-stat-ok .vb-bulk-stat-value{ color:#23764a; }\n  .vb-bulk-stat.vb-stat-attention .vb-bulk-stat-value{ color:#a55b2d; }\n  .vb-bulk-filters{ display:flex; flex-wrap:wrap; gap:6px; margin-top:11px; }\n  .vb-filter-btn{ padding:6px 11px; border:1px solid var(--vb-line); border-radius:999px; background:#fff; color:var(--vb-grey); font:600 11px\/1.2 'Poppins',Arial,sans-serif; cursor:pointer; }\n  .vb-filter-btn[aria-pressed=\"true\"]{ border-color:var(--vb-blue); background:var(--vb-blue-soft); color:var(--vb-blue); }\n\n  .vb-parts-toggle-btn{ display:inline-flex; align-items:center; gap:8px; }\n  .vb-parts-count-badge{ display:inline-flex; min-width:24px; justify-content:center; padding:2px 7px; border-radius:999px; background:var(--vb-blue-soft); color:var(--vb-blue); font-size:10.5px; font-weight:700; }\n  .vb-next-step-card{ text-align:center; }\n  .vb-next-step-label{ font-size:14px; }\n  .vb-next-step-desc{ display:block; max-width:205px; font-size:11.5px; line-height:1.4; font-weight:400; opacity:.78; }\n  .vb-next-step-card:not(.vb-next-step-card-secondary) .vb-next-step-desc{ color:rgba(255,255,255,.86); }\n\n  .vb-bulk-filters .vb-view-toggle{ margin-left:auto; }\n  .vb-compact-results .vb-result-item{ margin-bottom:12px; padding-bottom:10px; }\n  .vb-compact-results .vb-result-hero{ grid-template-columns:46px minmax(0,1fr); gap:10px; padding:12px 14px; }\n  .vb-compact-results .vb-result-glyph{ width:46px; height:46px; border-radius:12px; }\n  .vb-compact-results .vb-result-glyph svg{ width:31px; height:31px; }\n  .vb-compact-results .vb-match-found,.vb-compact-results .vb-code-anatomy,.vb-compact-results .vb-technical-bar{ display:none; }\n  .vb-compact-results .vb-hero-title{ font-size:16px; }\n  .vb-compact-results .vb-hero-code-row{ margin-top:3px; }\n  .vb-compact-results .vb-spec-chips{ gap:5px; margin-top:0; }\n  .vb-compact-results .vb-spec-chip{ min-height:24px; padding:3px 7px; font-size:10.5px; }\n  .vb-compact-results .vb-serial-note{ padding-top:6px; padding-bottom:6px; }\n  @media (prefers-reduced-motion: reduce){ .vb-result-item{ animation:none !important; } .vb-check.vb-search-success::before{animation:none!important;} }\n  @media (max-width:600px){\n    .vb-input-shortcut{ flex:1 1 100%; margin-left:14px; }\n    .vb-code-anatomy-track{ overflow-x:auto; padding-bottom:3px; scrollbar-width:thin; }\n    .vb-code-segment{ min-width:68px; }.vb-code-segment:first-child{ min-width:104px; }\n    .vb-code-segment-label{ display:none; }\n    .vb-bulk-stats{ grid-template-columns:repeat(3,minmax(0,1fr)); }\n    .vb-bulk-stat{ padding:9px 7px; text-align:center; }.vb-bulk-stat-value{ font-size:16px; }.vb-bulk-stat-label{ font-size:9.5px; }\n    .vb-error-card{ grid-template-columns:44px minmax(0,1fr); padding:15px; gap:11px; }.vb-error-icon{ width:44px;height:44px;border-radius:12px; }.vb-error-actions{grid-column:1\/-1;}\n    .vb-next-step-card{ flex-direction:row; text-align:left; justify-content:flex-start; padding:15px; }.vb-next-step-icon{ flex:0 0 auto; }.vb-next-step-desc{max-width:none;}\n  }\n\/* v21 standalone mini-app layer ------------------------------------------------ *\/\n.vb-app-toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:14px 0 2px;padding-top:12px;border-top:1px solid var(--vb-line)}\n.vb-app-tool{display:inline-flex;align-items:center;justify-content:center;gap:7px;min-height:36px;padding:7px 11px;border:1px solid var(--vb-line);border-radius:8px;background:#fff;color:var(--vb-ink);font:600 12px\/1.2 inherit;cursor:pointer;transition:border-color .15s var(--vb-ease),background .15s var(--vb-ease),transform .12s var(--vb-ease),box-shadow .15s var(--vb-ease)}\n.vb-app-tool:hover:not(:disabled){border-color:var(--vb-blue);background:var(--vb-blue-soft);transform:translateY(-1px)}\n.vb-app-tool:focus-visible{outline:none;border-color:var(--vb-blue);box-shadow:0 0 0 4px var(--vb-blue-soft)}\n.vb-app-tool:disabled{opacity:.42;cursor:not-allowed}\n.vb-app-tool svg{width:16px;height:16px;flex:0 0 auto}.vb-app-tool-primary{background:var(--vb-blue);border-color:var(--vb-blue);color:#fff}.vb-app-tool-primary:hover:not(:disabled){background:var(--vb-blue-dark);color:#fff}\n.vb-app-toolbar-spacer{flex:1 1 auto}.vb-app-shortcut{font-size:11px;color:var(--vb-grey);white-space:nowrap}.vb-app-shortcut kbd{font:600 10px\/1 inherit;background:var(--vb-bg);border:1px solid var(--vb-line);border-bottom-width:2px;border-radius:4px;padding:2px 5px;color:var(--vb-ink)}\n.vb-result-item{content-visibility:auto;contain-intrinsic-size:420px 640px}\n.vb-card.vb-compare-picked{box-shadow:0 0 0 2px var(--vb-blue),0 10px 28px -12px rgba(0,120,191,.35)}\n.vb-v21-card-tools{display:flex;gap:6px;align-items:center;margin-left:auto}.vb-v21-compare-btn{display:inline-flex;align-items:center;gap:5px;padding:5px 8px;border:1px solid var(--vb-line);border-radius:999px;background:#fff;color:var(--vb-grey);font:600 11px\/1.1 inherit;cursor:pointer}.vb-v21-compare-btn:hover,.vb-v21-compare-btn[aria-pressed=\"true\"]{border-color:var(--vb-blue);background:var(--vb-blue-soft);color:var(--vb-blue)}\n.vb-v21-command{margin:14px 0 18px;border:1px solid var(--vb-line);border-radius:12px;background:#fff;overflow:hidden}.vb-v21-command-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;padding:14px 16px;background:linear-gradient(180deg,#fff,var(--vb-bg));border-bottom:1px solid var(--vb-line)}.vb-v21-command-title{margin:0;font-size:14px;font-weight:700}.vb-v21-command-sub{margin:3px 0 0;font-size:12px;color:var(--vb-grey)}\n.vb-v21-command-controls{display:grid;grid-template-columns:minmax(150px,1fr) auto;gap:8px;padding:10px 12px;border-bottom:1px solid var(--vb-line)}.vb-v21-command-search,.vb-v21-command-sort{min-height:36px;border:1px solid var(--vb-line);border-radius:7px;background:#fff;color:var(--vb-ink);font:500 12px\/1.2 inherit;padding:7px 10px}.vb-v21-command-search:focus,.vb-v21-command-sort:focus{outline:none;border-color:var(--vb-blue);box-shadow:0 0 0 3px var(--vb-blue-soft)}\n.vb-v21-table-wrap{overflow:auto;max-height:390px}.vb-v21-table{width:100%;border-collapse:collapse;font-size:12px}.vb-v21-table th{position:sticky;top:0;z-index:1;text-align:left;padding:9px 10px;background:var(--vb-bg);border-bottom:1px solid var(--vb-line);color:var(--vb-grey);font-size:10.5px;text-transform:uppercase;letter-spacing:.04em}.vb-v21-table td{padding:9px 10px;border-bottom:1px solid var(--vb-line);vertical-align:middle}.vb-v21-table tbody tr:hover{background:#f9fcfe}.vb-v21-table tr.vb-v21-row-hidden{display:none}.vb-v21-table-code{font-family:'Courier New',monospace;font-weight:700;white-space:nowrap}.vb-v21-status{display:inline-flex;align-items:center;gap:5px;font-weight:600}.vb-v21-status::before{content:'';width:7px;height:7px;border-radius:50%;background:#2e9e5b}.vb-v21-status-error::before{background:#c0392b}.vb-v21-row-view{padding:4px 7px;border:0;background:transparent;color:var(--vb-blue);font:600 11px inherit;cursor:pointer;text-decoration:underline;text-underline-offset:2px}.vb-v21-bulk-check{width:16px;height:16px;accent-color:var(--vb-blue)}\n.vb-v21-command-foot{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:10px 12px;background:#fff}.vb-v21-selection-count{font-size:11.5px;color:var(--vb-grey);margin-right:auto}.vb-v21-command-empty{padding:20px;text-align:center;color:var(--vb-grey);font-size:12px}\n.vb-v21-compare-dock{position:sticky;bottom:12px;z-index:18;margin:16px auto 0;max-width:560px;display:flex;align-items:center;gap:10px;padding:10px 12px;background:rgba(28,39,51,.96);color:#fff;border-radius:12px;box-shadow:0 12px 30px rgba(16,24,40,.24);backdrop-filter:blur(8px);transform:translateY(8px);opacity:0;pointer-events:none;transition:opacity .2s var(--vb-ease),transform .2s var(--vb-ease)}.vb-v21-compare-dock.vb-visible{opacity:1;transform:none;pointer-events:auto}.vb-v21-compare-dock strong{font-size:12.5px}.vb-v21-compare-dock span{font-size:11px;color:#d9e0e6}.vb-v21-dock-actions{margin-left:auto;display:flex;gap:6px}.vb-v21-dock-btn{padding:6px 9px;border:1px solid rgba(255,255,255,.24);border-radius:7px;background:transparent;color:#fff;font:600 11px inherit;cursor:pointer}.vb-v21-dock-btn-primary{background:#fff;color:var(--vb-ink)}.vb-v21-dock-btn:disabled{opacity:.4;cursor:not-allowed}\n.vb-v21-layer{position:relative}.vb-v21-modal{position:fixed;inset:0;z-index:99990;display:none;align-items:center;justify-content:center;padding:18px;background:rgba(15,24,32,.58);backdrop-filter:blur(5px)}.vb-v21-modal.vb-open{display:flex}.vb-v21-dialog{width:min(980px,100%);max-height:min(88vh,820px);overflow:auto;background:#fff;border-radius:16px;box-shadow:0 24px 70px rgba(0,0,0,.28);animation:vb-result-in .22s var(--vb-ease) both}.vb-v21-dialog-head{position:sticky;top:0;z-index:4;display:flex;align-items:center;gap:10px;padding:15px 18px;background:rgba(255,255,255,.96);border-bottom:1px solid var(--vb-line);backdrop-filter:blur(8px)}.vb-v21-dialog-head h3{font-size:16px;margin:0}.vb-v21-dialog-head p{font-size:11.5px;color:var(--vb-grey);margin:2px 0 0}.vb-v21-dialog-close{margin-left:auto;width:34px;height:34px;border:1px solid var(--vb-line);border-radius:50%;background:#fff;cursor:pointer;font-size:18px;color:var(--vb-grey)}.vb-v21-dialog-body{padding:16px 18px 20px}\n.vb-v21-compare-grid{overflow:auto}.vb-v21-compare-table{border-collapse:separate;border-spacing:0;width:100%;min-width:620px;font-size:12px}.vb-v21-compare-table th,.vb-v21-compare-table td{padding:10px 12px;border-right:1px solid var(--vb-line);border-bottom:1px solid var(--vb-line);vertical-align:top}.vb-v21-compare-table th:first-child,.vb-v21-compare-table td:first-child{position:sticky;left:0;z-index:2;background:#fff;font-weight:700;min-width:145px}.vb-v21-compare-table thead th{background:var(--vb-bg);font-size:11px}.vb-v21-compare-table .vb-v21-diff-row td{background:#fff9e9}.vb-v21-compare-table .vb-v21-diff-row td:first-child{background:#fff2c9}.vb-v21-compare-code{font-family:'Courier New',monospace;font-size:11px;color:var(--vb-grey);display:block;margin-top:3px}\n.vb-v21-scan-capture-mode{aspect-ratio:auto;min-height:235px;background:linear-gradient(180deg,#101820,#182431);padding:18px}.vb-v21-capture-panel{width:100%;display:flex;flex-direction:column;gap:14px;align-items:stretch}.vb-v21-scan-capture-mode .vb-v21-scan-message{background:rgba(255,255,255,.96);color:var(--vb-ink);text-align:left}.vb-v21-capture-actions{display:grid;grid-template-columns:1fr 1fr;gap:10px}.vb-v21-capture-button{position:relative;justify-content:center;min-height:46px;overflow:hidden}.vb-v21-capture-input{position:absolute!important;width:1px!important;height:1px!important;opacity:0!important;pointer-events:none!important}.vb-v21-scan-decoding::after{content:'';position:absolute;inset:0;background:rgba(16,24,32,.35);pointer-events:none}.vb-v21-scan-decoding::before{content:'';position:absolute;z-index:2;left:50%;top:50%;width:28px;height:28px;margin:-14px;border:3px solid rgba(255,255,255,.35);border-top-color:#fff;border-radius:50%;animation:vb-spin .75s linear infinite}@media(max-width:420px){.vb-v21-capture-actions{grid-template-columns:1fr}}\n.vb-v21-scan-dialog{width:min(520px,100%)}.vb-v21-scan-stage{position:relative;aspect-ratio:4\/3;border-radius:12px;overflow:hidden;background:#101820;display:flex;align-items:center;justify-content:center;color:#fff}.vb-v21-scan-stage video{width:100%;height:100%;object-fit:cover}.vb-v21-scan-frame{position:absolute;inset:18% 12%;border:2px solid rgba(255,255,255,.9);border-radius:12px;box-shadow:0 0 0 999px rgba(0,0,0,.24);pointer-events:none}.vb-v21-scan-frame::after{content:'';position:absolute;left:6%;right:6%;top:50%;height:2px;background:#58c5ff;box-shadow:0 0 12px #58c5ff;animation:vb-v21-scanline 1.6s ease-in-out infinite alternate}@keyframes vb-v21-scanline{from{transform:translateY(-55px)}to{transform:translateY(55px)}}.vb-v21-scan-message{padding:14px;border-radius:9px;background:var(--vb-bg);color:var(--vb-ink);font-size:12.5px;line-height:1.5}.vb-v21-scan-status{margin-top:10px;font-size:12px;color:var(--vb-grey)}.vb-v21-scan-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}.vb-v21-privacy-note{display:flex;gap:7px;align-items:flex-start;margin-top:10px;color:var(--vb-grey);font-size:10.5px;line-height:1.4}\n.vb-v21-restore-toast{display:flex;align-items:center;gap:8px;margin:10px 0 0;padding:9px 11px;border:1px solid #b9dcc8;border-radius:8px;background:#f1fbf5;color:#286342;font-size:11.5px}\n@media(max-width:640px){.vb-app-toolbar{display:grid;grid-template-columns:1fr 1fr}.vb-app-toolbar-spacer,.vb-app-shortcut{display:none}.vb-app-tool{width:100%}.vb-v21-command-controls{grid-template-columns:1fr}.vb-v21-table th:nth-child(4),.vb-v21-table td:nth-child(4){display:none}.vb-v21-command-foot .vb-app-tool{width:auto;flex:1 1 130px}.vb-v21-compare-dock{bottom:8px;margin-left:-4px;margin-right:-4px}.vb-v21-dialog{max-height:92vh;border-radius:14px}.vb-v21-dialog-body{padding:12px}.vb-v21-modal{padding:8px;align-items:flex-end}.vb-v21-modal .vb-v21-dialog{border-radius:16px 16px 8px 8px}.vb-v21-scan-dialog{width:100%}}\n@media print{body.vb-v21-printing *{visibility:hidden!important}.vb-check,.vb-check *{visibility:visible!important}.vb-check{position:absolute!important;left:0!important;top:0!important;width:100%!important;max-width:none!important;border:0!important;box-shadow:none!important;padding:0!important}.vb-app-toolbar,#vb-input-meta,#vb-example,#vb-bulk-hint,#vb-recent-chips,.vb-input-row,.vb-top-row select,.vb-v21-command,.vb-v21-compare-dock,.vb-combined-quote,.vb-combined-parts,.vb-parts-toggle-btn,.vb-parts-popup,.vb-qty-widget,.vb-copy-btn,.vb-v21-card-tools,.vb-toast-container{display:none!important}.vb-result-item{content-visibility:visible!important;break-inside:avoid}.vb-tech-collapse{grid-template-rows:1fr!important;opacity:1!important}.vb-tech-collapse[aria-hidden=\"true\"]{display:grid!important}.vb-technical-bar{display:none!important}.vb-result-anim{animation:none!important}}\n@media(prefers-reduced-motion:reduce){.vb-v21-scan-frame::after{animation:none}.vb-v21-dialog{animation:none}}\n\/* v22 power layer: progressive enhancement on top of the v21 standalone shell. *\/\n.vb-check{--vb-v22-ok:#237a4b;--vb-v22-warn:#a56b00;--vb-v22-danger:#b83232}\n.vb-app-toolbar{position:sticky;top:8px;z-index:40;background:rgba(255,255,255,.94);backdrop-filter:blur(12px);padding:7px;border:1px solid rgba(226,230,234,.9);border-radius:10px;box-shadow:0 8px 24px -18px rgba(16,24,40,.35)}\n.vb-v22-health{display:flex;align-items:center;gap:7px;margin:8px 0 0;padding:7px 10px;border:1px solid var(--vb-line);border-radius:999px;background:#fff;color:var(--vb-grey);font-size:10.5px;width:max-content;max-width:100%}\n.vb-v22-health-dot{width:8px;height:8px;border-radius:50%;background:#9aa4af;box-shadow:0 0 0 3px rgba(154,164,175,.12)}\n.vb-v22-health[data-state=\"ok\"] .vb-v22-health-dot{background:var(--vb-v22-ok);box-shadow:0 0 0 3px rgba(35,122,75,.12)}\n.vb-v22-health[data-state=\"warn\"] .vb-v22-health-dot{background:#d68b00;box-shadow:0 0 0 3px rgba(214,139,0,.13)}\n.vb-v22-health[data-state=\"error\"] .vb-v22-health-dot{background:var(--vb-v22-danger);box-shadow:0 0 0 3px rgba(184,50,50,.12)}\n.vb-v22-health button{border:0;background:transparent;color:var(--vb-blue);font:600 10.5px inherit;cursor:pointer;padding:0;text-decoration:underline;text-underline-offset:2px}\n.vb-v22-coach{position:relative;margin:10px 0 2px;padding:12px 38px 12px 13px;border:1px solid #b9ddef;border-radius:10px;background:linear-gradient(135deg,#f5fbff,#fff);font-size:11.5px;line-height:1.45;color:var(--vb-ink);box-shadow:0 8px 24px -18px rgba(0,120,191,.35)}\n.vb-v22-coach strong{color:var(--vb-blue)}.vb-v22-coach-close{position:absolute;top:7px;right:7px;width:26px;height:26px;border:0;border-radius:50%;background:transparent;color:var(--vb-grey);cursor:pointer;font-size:17px}\n.vb-v22-correction{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:10px 0 0;padding:10px 12px;border:1px solid #ead38a;border-radius:9px;background:#fffaf0;font-size:12px}.vb-v22-correction code{font-weight:700}.vb-v22-correction button{flex:0 0 auto;border:1px solid #d9b64b;border-radius:7px;background:#fff;color:#725500;font:600 11px inherit;padding:6px 9px;cursor:pointer}\n.vb-v22-card-actions{display:flex;gap:7px;flex-wrap:wrap;margin:10px 0 0}.vb-v22-card-action{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--vb-line);border-radius:999px;background:#fff;color:var(--vb-blue);font:600 10.5px inherit;padding:6px 9px;cursor:pointer;transition:.16s ease}.vb-v22-card-action:hover{border-color:var(--vb-blue);background:var(--vb-blue-soft);transform:translateY(-1px)}\n.vb-v22-explain{margin:10px 0 0;padding:11px 13px;border-left:3px solid var(--vb-blue);border-radius:0 8px 8px 0;background:#f7fbfe;color:var(--vb-ink);font-size:12px;line-height:1.55}.vb-v22-explain[hidden]{display:none}\n.vb-v22-compare-tools{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 12px}.vb-v22-compare-tools .vb-app-tool{width:auto}.vb-v22-diff-summary{margin:0 0 12px;padding:10px 12px;border-radius:9px;background:#fff8e7;border:1px solid #ecd394;font-size:12px;line-height:1.5}.vb-v22-diff-summary strong{color:#735300}.vb-v22-hide-equal .vb-v21-compare-table tr:not(.vb-v21-diff-row){display:none}.vb-v22-hide-equal .vb-v21-compare-table thead tr{display:table-row}\n.vb-v22-passport{max-width:760px;margin:0 auto}.vb-v22-passport-hero{display:grid;grid-template-columns:auto 1fr;gap:16px;align-items:center;padding:18px;border-radius:14px;background:linear-gradient(135deg,#f2f8fc,#fff);border:1px solid var(--vb-line)}.vb-v22-passport-mark{width:64px;height:64px;border-radius:16px;background:var(--vb-blue-soft);display:flex;align-items:center;justify-content:center;color:var(--vb-blue);font-weight:800;font-size:18px}.vb-v22-passport h4{margin:0;font-size:20px}.vb-v22-passport-code{font-family:'Courier New',monospace;font-weight:700;margin-top:4px}.vb-v22-passport-summary{margin:14px 0;padding:12px 14px;border-left:3px solid var(--vb-blue);background:#f8fbfd;border-radius:0 9px 9px 0;font-size:13px;line-height:1.6}.vb-v22-passport-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.vb-v22-passport-row{padding:10px 12px;border:1px solid var(--vb-line);border-radius:9px;background:#fff}.vb-v22-passport-row small{display:block;color:var(--vb-grey);font-size:10px;text-transform:uppercase;letter-spacing:.04em;margin-bottom:3px}.vb-v22-passport-row strong{font-size:12px}.vb-v22-passport-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:14px}\n.vb-v22-workspaces{display:grid;gap:8px}.vb-v22-workspace{display:grid;grid-template-columns:1fr auto;gap:10px;align-items:center;padding:11px 12px;border:1px solid var(--vb-line);border-radius:10px;background:#fff}.vb-v22-workspace-title{font-weight:700;font-size:12px;word-break:break-word}.vb-v22-workspace-meta{font-size:10.5px;color:var(--vb-grey);margin-top:3px}.vb-v22-workspace button{border:1px solid var(--vb-line);border-radius:7px;background:#fff;color:var(--vb-blue);font:600 11px inherit;padding:6px 9px;cursor:pointer}\n.vb-v22-diagnostics{font-size:12px}.vb-v22-diagnostic-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.vb-v22-diag{padding:10px 12px;border:1px solid var(--vb-line);border-radius:9px;background:#fff}.vb-v22-diag small{display:block;color:var(--vb-grey);font-size:10px;text-transform:uppercase}.vb-v22-diag strong{display:block;margin-top:3px;word-break:break-word}.vb-v22-diagnostics pre{white-space:pre-wrap;word-break:break-word;padding:10px;border-radius:9px;background:#101820;color:#dfe8ef;font:11px\/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;max-height:220px;overflow:auto}\n.vb-v22-command-summary{display:flex;gap:7px;flex-wrap:wrap;padding:8px 12px;border-bottom:1px solid var(--vb-line);background:#fbfcfd}.vb-v22-family-chip{border:1px solid var(--vb-line);border-radius:999px;background:#fff;color:var(--vb-ink);font:600 10.5px inherit;padding:5px 8px;cursor:pointer}.vb-v22-family-chip:hover{border-color:var(--vb-blue);color:var(--vb-blue)}.vb-v22-command-actions{display:flex;gap:6px;flex-wrap:wrap;padding:8px 12px;border-bottom:1px solid var(--vb-line)}.vb-v22-command-actions button{border:1px solid var(--vb-line);border-radius:7px;background:#fff;color:var(--vb-blue);font:600 10.5px inherit;padding:6px 8px;cursor:pointer}.vb-v21-table tr.vb-v22-key-active{outline:2px solid var(--vb-blue);outline-offset:-2px;background:#f2f9fd}.vb-v22-inline-details{padding:8px 10px!important;background:#fbfdff!important;color:var(--vb-grey);font-size:11px;line-height:1.5}\n.vb-v22-retry{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:8px 0 0;padding:8px 10px;border:1px solid #e5c37d;border-radius:8px;background:#fff9eb;color:#735300;font-size:10.5px}.vb-v22-retry button{border:1px solid #d8b45c;border-radius:6px;background:#fff;color:#735300;font:600 10.5px inherit;padding:5px 7px;cursor:pointer}\n.vb-v22-scan-controls{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:10px}.vb-v22-scan-controls button{border:1px solid var(--vb-line);border-radius:8px;background:#fff;color:var(--vb-ink);font:600 11px inherit;padding:7px 9px;cursor:pointer}.vb-v22-scan-controls input[type=range]{width:130px}.vb-v22-scan-found{animation:vb-v22-found .35s var(--vb-ease-spring) both}@keyframes vb-v22-found{0%{transform:scale(.98);box-shadow:0 0 0 0 rgba(46,158,91,0)}70%{transform:scale(1.01);box-shadow:0 0 0 5px rgba(46,158,91,.18)}100%{transform:scale(1);box-shadow:0 0 0 0 rgba(46,158,91,0)}}\n.vb-v22-empty-note{padding:12px;border:1px dashed var(--vb-line);border-radius:9px;color:var(--vb-grey);font-size:12px;text-align:center}\n@media(max-width:640px){.vb-app-toolbar{bottom:8px;top:auto;position:sticky;grid-template-columns:repeat(2,minmax(0,1fr));box-shadow:0 -10px 30px -20px rgba(16,24,40,.45)}.vb-v22-health{border-radius:9px;width:100%}.vb-v22-passport-grid,.vb-v22-diagnostic-grid{grid-template-columns:1fr}.vb-v22-workspace{grid-template-columns:1fr}.vb-v22-correction{align-items:flex-start;flex-direction:column}.vb-v22-correction button{width:100%}}\n@media print{body.vb-v22-passport-printing *{visibility:hidden!important}body.vb-v22-passport-printing #vb-v21-compare-modal,body.vb-v22-passport-printing #vb-v21-compare-modal *,body.vb-v22-passport-printing #vb-v22-passport-modal,body.vb-v22-passport-printing #vb-v22-passport-modal *{visibility:visible!important}body.vb-v22-passport-printing .vb-v21-modal{position:absolute!important;inset:0!important;display:block!important;background:#fff!important;padding:0!important}body.vb-v22-passport-printing .vb-v21-dialog{width:100%!important;max-height:none!important;box-shadow:none!important;border-radius:0!important;overflow:visible!important}body.vb-v22-passport-printing .vb-v21-dialog-head,body.vb-v22-passport-printing .vb-v22-passport-actions,body.vb-v22-passport-printing .vb-v22-compare-tools{display:none!important}}\n@media(prefers-reduced-motion:reduce){.vb-v22-scan-found{animation:none}.vb-v22-card-action:hover{transform:none}}\n\/* v23 Field Edition: hardening for real phones, warehouses and unreliable connectivity. *\/\n.vb-check{--vb-v23-field:#0b6f9f;--vb-v23-hi:#08131d;--vb-v23-paper:#fff}\n.vb-v23-field-badge{display:inline-flex;align-items:center;gap:6px;padding:5px 8px;border:1px solid #b9ddef;border-radius:999px;background:#f4fbff;color:#075d87;font:700 10.5px\/1.1 inherit;white-space:nowrap}\n.vb-v23-field-badge::before{content:'';width:7px;height:7px;border-radius:50%;background:#2e9e5b;box-shadow:0 0 0 3px rgba(46,158,91,.12)}\n.vb-v23-field-badge[data-state=\"warn\"]::before{background:#d68b00}.vb-v23-field-badge[data-state=\"error\"]::before{background:#c0392b}\n.vb-v23-scan-queue{margin:0 0 10px;padding:10px;border:1px solid var(--vb-line);border-radius:10px;background:#f8fbfd}\n.vb-v23-scan-queue-head{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-bottom:8px}.vb-v23-scan-queue-head strong{font-size:12px}.vb-v23-scan-counter{font-size:11px;color:var(--vb-grey)}\n.vb-v23-scan-list{display:flex;gap:6px;overflow:auto;padding:2px 0 4px;scrollbar-width:thin}.vb-v23-scan-chip{display:inline-flex;align-items:center;gap:5px;flex:0 0 auto;padding:6px 8px;border:1px solid var(--vb-line);border-radius:8px;background:#fff;font:700 10.5px\/1.1 ui-monospace,SFMono-Regular,Menlo,monospace}.vb-v23-scan-chip small{font:600 9px\/1 inherit;color:var(--vb-grey)}.vb-v23-scan-chip button{width:22px;height:22px;min-height:0!important;border:0;border-radius:50%;background:var(--vb-bg);color:var(--vb-grey);cursor:pointer}\n.vb-v23-scan-queue-actions{display:flex;gap:7px;flex-wrap:wrap;margin-top:8px}.vb-v23-scan-queue-actions .vb-app-tool{width:auto}.vb-v23-scan-empty{font-size:11px;color:var(--vb-grey);padding:4px 0}.vb-v23-scan-flash{animation:vb-v23-queue-flash .3s ease both}@keyframes vb-v23-queue-flash{0%{background:#e5f6ec}100%{background:#f8fbfd}}\n.vb-v23-resume{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;width:100%;height:100%;padding:22px;text-align:center;color:#fff}.vb-v23-resume p{margin:0;max-width:300px;font-size:12px;line-height:1.5}.vb-v23-resume .vb-app-tool{width:auto;background:#fff;color:var(--vb-blue)}\n.vb-v23-selftest{display:grid;gap:12px}.vb-v23-selftest-summary{padding:12px 14px;border:1px solid var(--vb-line);border-radius:10px;background:var(--vb-bg);font-size:12px;line-height:1.55}.vb-v23-selftest-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.vb-v23-test{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px 12px;border:1px solid var(--vb-line);border-radius:9px;background:#fff}.vb-v23-test span{font-size:11px}.vb-v23-test strong{font-size:10.5px}.vb-v23-test[data-state=\"ok\"] strong{color:#237a4b}.vb-v23-test[data-state=\"warn\"] strong{color:#9b6500}.vb-v23-test[data-state=\"error\"] strong{color:#b83232}.vb-v23-selftest-actions{display:flex;gap:8px;flex-wrap:wrap}.vb-v23-selftest pre{white-space:pre-wrap;word-break:break-word;padding:10px;border-radius:9px;background:#101820;color:#dfe8ef;font:11px\/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;max-height:220px;overflow:auto}\n.vb-v23-undo-ready{position:relative}.vb-v23-undo-ready::after{content:'';position:absolute;top:7px;right:7px;width:6px;height:6px;border-radius:50%;background:#2e9e5b}\n.vb-v23-contrast{--vb-ink:#08131d;--vb-grey:#3c4752;--vb-line:#aeb9c3;--vb-blue:#005f9e;--vb-blue-dark:#004b7d;--vb-bg:#f2f5f7;filter:contrast(1.04)}.vb-v23-contrast .vb-card,.vb-v23-contrast .vb-part-card,.vb-v23-contrast .vb-app-toolbar{border-width:2px}.vb-v23-contrast .vb-app-tool,.vb-v23-contrast #vb-submit{font-weight:700}\n.vb-v23-retry-banner{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:10px 0;padding:10px 12px;border:1px solid #e7c875;border-radius:9px;background:#fff9e9;color:#745500;font-size:11px}.vb-v23-retry-banner button{border:1px solid #d4ae43;border-radius:7px;background:#fff;color:#745500;font:700 10.5px inherit;padding:6px 9px;cursor:pointer}\n#vb-v23-print-sheet{display:none}\n@media print{\n  @page{size:A4 portrait;margin:14mm 12mm}\n  body.vb-v23-printing *{visibility:hidden!important}\n  body.vb-v23-printing #vb-v23-print-sheet,body.vb-v23-printing #vb-v23-print-sheet *{visibility:visible!important}\n  body.vb-v23-printing #vb-v23-print-sheet{display:block!important;position:absolute!important;left:0;top:0;width:100%;color:#111;background:#fff;font-family:Arial,Helvetica,sans-serif}\n  .vb-v23-print-head{display:flex;justify-content:space-between;gap:14px;align-items:flex-end;padding-bottom:10px;border-bottom:2px solid #0078bf;margin-bottom:14px}.vb-v23-print-head h1{font-size:22px;margin:0}.vb-v23-print-head p{margin:3px 0 0;font-size:10px;color:#555}.vb-v23-print-date{font-size:9px;color:#666;text-align:right}\n  .vb-v23-print-card{break-inside:avoid;page-break-inside:avoid;margin:0 0 14px;padding:12px;border:1px solid #ccd4db;border-radius:8px}.vb-v23-print-card h2{margin:0;font-size:16px}.vb-v23-print-code{margin:3px 0 10px;font:700 11px ui-monospace,SFMono-Regular,Menlo,monospace}.vb-v23-print-grid{display:grid;grid-template-columns:1fr 1fr;gap:0;border-top:1px solid #dce2e7;border-left:1px solid #dce2e7}.vb-v23-print-row{padding:7px 8px;border-right:1px solid #dce2e7;border-bottom:1px solid #dce2e7}.vb-v23-print-row small{display:block;font-size:8px;text-transform:uppercase;color:#666;margin-bottom:2px}.vb-v23-print-row strong{font-size:10px}.vb-v23-print-summary{font-size:10px;line-height:1.45;margin:8px 0 10px}\n  .vb-v23-print-compare{width:100%;border-collapse:collapse;font-size:9px}.vb-v23-print-compare th,.vb-v23-print-compare td{border:1px solid #ccd4db;padding:6px;text-align:left;vertical-align:top}.vb-v23-print-compare th{background:#f2f5f7}.vb-v23-print-diff td{background:#fff7df}.vb-v23-print-foot{margin-top:12px;padding-top:8px;border-top:1px solid #ccd4db;font-size:8px;color:#666}\n}\n@media(pointer:coarse){.vb-check button,.vb-check select,.vb-check input[type=\"checkbox\"],.vb-check input[type=\"range\"]{min-height:44px}.vb-copy-btn,.vb-info-btn,.vb-part-card>input[type=checkbox]{min-width:44px;min-height:44px}.vb-v23-scan-chip button{min-width:34px;min-height:34px!important}}\n@media(max-width:640px){.vb-app-toolbar{bottom:max(8px,env(safe-area-inset-bottom));padding-bottom:calc(7px + env(safe-area-inset-bottom))}.vb-v21-modal{padding-left:max(8px,env(safe-area-inset-left));padding-right:max(8px,env(safe-area-inset-right));padding-bottom:max(8px,env(safe-area-inset-bottom))}.vb-v23-selftest-grid{grid-template-columns:1fr}.vb-v23-scan-queue-actions .vb-app-tool{flex:1 1 120px}}\n@media(max-width:900px) and (orientation:landscape){.vb-v21-scan-dialog{width:min(900px,100%)}.vb-v21-scan-dialog .vb-v21-dialog-body{display:grid;grid-template-columns:minmax(280px,1.4fr) minmax(220px,.8fr);gap:12px}.vb-v21-scan-stage{aspect-ratio:16\/9}.vb-v23-scan-queue{grid-column:2;grid-row:1}.vb-v21-scan-status,.vb-v21-privacy-note,#vb-v22-scan-controls{grid-column:2}}\n@media(prefers-contrast:more){.vb-check{--vb-grey:#2f3943;--vb-line:#aab4be}.vb-app-tool,.vb-card,.vb-part-card{border-width:2px}}\n@media(prefers-reduced-motion:reduce){.vb-v23-scan-flash{animation:none}}\n\/* Progressive disclosure: the checker stays quiet until an action is useful. *\/\n#vb-v23-undo-btn:disabled{display:none!important}\n\n.vb-app-toolbar{\n  position:static!important;\n  inset:auto!important;\n  display:flex!important;\n  align-items:center;\n  gap:8px;\n  margin:10px 0 0;\n  padding:0!important;\n  border:0!important;\n  border-radius:0!important;\n  background:transparent!important;\n  box-shadow:none!important;\n  backdrop-filter:none!important;\n}\n.vb-app-toolbar .vb-app-tool{width:auto!important}\n#vb-v21-scan-btn{background:#fff;border-color:var(--vb-line);color:var(--vb-blue)}\n#vb-v21-scan-btn:hover{background:var(--vb-blue-soft);border-color:var(--vb-blue)}\n\n\/* Multi-container scanning can be entered from the scanner without adding a permanent extra explanation. *\/\n.vb-v231-scan-multiple{display:flex;justify-content:center;margin-top:10px}\n.vb-v231-scan-multiple[hidden]{display:none!important}\n\n\/* Compare exists only when at least two distinct valid configurations are available. *\/\n[data-vb-action=\"toggle-compare\"][hidden],\n[data-vb-action=\"compare-selected\"][hidden]{display:none!important}\n\n@media(max-width:640px){\n  .vb-app-toolbar{display:flex!important;grid-template-columns:none!important;bottom:auto!important;padding-bottom:0!important}\n  .vb-app-toolbar .vb-app-tool{flex:0 0 auto;width:auto!important;min-height:42px}\n}\n\/* Scan list is a core input method and sits directly next to Scan barcode. *\/\n#vb-v23-field-scan-btn{\n  display:inline-flex!important;\n  background:#fff;\n  border-color:var(--vb-line);\n  color:var(--vb-blue);\n}\n#vb-v23-field-scan-btn:hover{background:var(--vb-blue-soft);border-color:var(--vb-blue)}\n\n@media(max-width:640px){\n  #vb-v21-scan-btn,#vb-v23-field-scan-btn{flex:1 1 calc(50% - 4px);justify-content:center}\n}\n\/* Product finder presentation: calm, modern, task-first input area. *\/\n.vb-check{\n  border-radius:16px;\n  box-shadow:0 10px 35px -18px rgba(16,24,40,.18), 0 2px 8px rgba(16,24,40,.04);\n}\n.vb-check::before{height:4px}\n.vb-top-row{\n  align-items:center;\n  gap:16px;\n  margin-bottom:10px;\n}\n.vb-check h2{\n  font-size:31px;\n  line-height:1.1;\n  font-weight:700;\n  letter-spacing:-0.03em;\n}\n#vb-lang{\n  padding:8px 30px 8px 14px;\n  border-radius:999px;\n  background-color:#fff;\n  box-shadow:0 1px 2px rgba(16,24,40,.04);\n}\n.vb-check p.vb-intro{\n  margin:0 0 18px;\n  font-size:14px;\n  line-height:1.65;\n  max-width:58ch;\n}\n.vb-hero-panel{\n  position:relative;\n  padding:18px;\n  border:1px solid rgba(0,120,191,.14);\n  border-radius:18px;\n  background:linear-gradient(180deg, rgba(246,251,255,.95) 0%, rgba(255,255,255,.98) 72%);\n  box-shadow:inset 0 1px 0 rgba(255,255,255,.75), 0 10px 24px -24px rgba(0,120,191,.35);\n}\n.vb-hero-panel::before{\n  content:'';\n  position:absolute;\n  inset:0 auto auto 0;\n  width:180px;\n  height:180px;\n  border-radius:50%;\n  background:radial-gradient(circle at center, rgba(77,184,234,.13), rgba(77,184,234,0));\n  transform:translate(-34%, -34%);\n  pointer-events:none;\n}\n.vb-input-row{\n  position:relative;\n  z-index:1;\n  gap:12px;\n  align-items:stretch;\n}\n.vb-code-wrap{\n  border-radius:14px;\n  overflow:visible;\n}\n#vb-code{\n  min-height:58px;\n  padding:15px 42px 15px 16px;\n  border-radius:14px;\n  border-color:#d7e3ec;\n  background:#fff;\n  box-shadow:0 1px 2px rgba(16,24,40,.04), 0 8px 22px -18px rgba(16,24,40,.18);\n}\n#vb-code::placeholder{\n  color:#8b96a3;\n}\n#vb-submit{\n  min-height:58px;\n  padding:0 22px;\n  border-radius:14px;\n  background:linear-gradient(180deg, #0a87d2 0%, var(--vb-blue) 100%);\n  box-shadow:0 10px 18px -12px rgba(0,120,191,.55);\n}\n#vb-submit:hover{\n  background:linear-gradient(180deg, #0872b1 0%, var(--vb-blue-dark) 100%);\n}\n#vb-input-meta{\n  position:relative;\n  z-index:1;\n  margin-top:10px;\n}\n#vb-example{\n  position:relative;\n  z-index:1;\n  margin-top:14px;\n  padding:12px 14px;\n  background:#fff;\n  border:1px solid #e6edf3;\n  border-radius:12px;\n  font-size:13px;\n}\n#vb-example-intro{font-weight:500;color:var(--vb-ink)}\n#vb-example button{\n  padding:7px 14px;\n  border-radius:999px;\n  background:linear-gradient(180deg, #fff 0%, #f6f9fb 100%);\n  box-shadow:0 1px 2px rgba(16,24,40,.03);\n}\n#vb-bulk-hint{\n  position:relative;\n  z-index:1;\n  margin-top:12px;\n  padding:11px 14px;\n  border-radius:12px;\n  background:linear-gradient(180deg, #f9fbfd 0%, #f5f8fb 100%);\n  border-color:#e6edf3;\n  font-size:12.75px;\n}\n.vb-app-toolbar{\n  position:relative;\n  z-index:1;\n  margin:14px 0 0;\n  padding:12px 0 0;\n  background:transparent;\n  border:0;\n  border-top:1px solid #e6edf3;\n  box-shadow:none;\n  backdrop-filter:none;\n}\n.vb-app-tool{\n  min-height:44px;\n  border-radius:12px;\n  background:linear-gradient(180deg,#fff 0%, #f7fafc 100%);\n  border:1px solid #dfe7ee;\n  box-shadow:0 1px 2px rgba(16,24,40,.03);\n}\n.vb-app-tool:hover{\n  border-color:#bfd8ea;\n  background:#fff;\n}\n#vb-v21-scan-btn,\n#vb-v23-field-scan-btn{\n  border-color:rgba(0,120,191,.22);\n  background:rgba(0,120,191,.06);\n}\n#vb-v21-scan-btn:hover,\n#vb-v23-field-scan-btn:hover{\n  border-color:var(--vb-blue);\n  background:rgba(0,120,191,.1);\n}\n@media (max-width:640px){\n  .vb-check{padding:24px 18px 24px;border-radius:14px}\n  .vb-check h2{font-size:26px}\n  .vb-hero-panel{padding:14px;border-radius:16px}\n  .vb-input-row{display:grid;grid-template-columns:1fr}\n  #vb-submit{width:100%}\n  #vb-example{padding:10px 12px}\n}\n\/* Quantity controls align as one compact horizontal control. *\/\n.vb-qty-wrap{display:flex;align-items:center;gap:10px;min-height:38px;margin:10px 0 4px}\n.vb-qty-wrap label{display:flex;align-items:center;height:38px;margin:0;font-size:13px;font-weight:600;line-height:1;color:var(--vb-ink)}\n.vb-qty-stepper{display:inline-flex;align-items:stretch;height:38px;border:1px solid var(--vb-line);border-radius:8px;overflow:hidden;background:#fff}\n.vb-qty-step-btn{display:flex;align-items:center;justify-content:center;width:34px;min-width:34px;height:36px;padding:0;margin:0;border:none;background:var(--vb-bg);color:var(--vb-ink);font-size:16px;font-weight:600;line-height:1;cursor:pointer;transition:background .15s var(--vb-ease)}\n.vb-qty-input{display:block;width:42px;height:36px;margin:0;padding:0 4px;font-size:14px;line-height:36px;font-family:'Poppins',Arial,sans-serif;border:none;border-left:1px solid var(--vb-line);border-right:1px solid var(--vb-line);border-radius:0;outline:none;text-align:center;-moz-appearance:textfield}\n\/* Bulk spare-parts ordering: one combined view for the current container scope. *\/\n.vb-v2312-parts-btn{border-color:rgba(0,120,191,.28)!important;background:rgba(0,120,191,.07)!important;color:var(--vb-blue)!important;font-weight:650!important}\n.vb-v2312-parts-btn:hover{border-color:var(--vb-blue)!important;background:rgba(0,120,191,.12)!important}\n.vb-v2312-parts-panel{border-top:1px solid var(--vb-line);background:#fbfdff;padding:14px 14px 16px}\n.vb-v2312-parts-panel[hidden]{display:none!important}\n.vb-v2312-parts-head{display:flex;justify-content:space-between;align-items:flex-start;gap:14px;margin-bottom:12px}\n.vb-v2312-parts-head h4{margin:0 0 3px;font-size:15px;line-height:1.3;color:var(--vb-ink)}\n.vb-v2312-parts-head p{margin:0;color:var(--vb-grey);font-size:12px;line-height:1.5}\n.vb-v2312-scope{display:inline-flex;align-items:center;padding:5px 9px;border:1px solid #dbe7ef;border-radius:999px;background:#fff;color:var(--vb-grey);font-size:10.5px;font-weight:600;white-space:nowrap}\n.vb-v2312-loading,.vb-v2312-empty{padding:18px;border:1px dashed #d8e3eb;border-radius:10px;background:#fff;color:var(--vb-grey);font-size:12.5px;text-align:center}\n.vb-v2312-parts-list{display:grid;gap:8px}\n.vb-v2312-part-row{display:grid;grid-template-columns:auto 46px minmax(0,1fr) auto;gap:10px;align-items:center;padding:10px;border:1px solid #e2eaf0;border-radius:11px;background:#fff;transition:border-color .15s var(--vb-ease),box-shadow .15s var(--vb-ease)}\n.vb-v2312-part-row:has(.vb-part-checkbox:checked){border-color:#9ccde8;box-shadow:0 0 0 2px rgba(0,120,191,.06)}\n.vb-v2312-part-row.vb-v2312-unavailable{opacity:.62}\n.vb-v2312-check{display:flex;align-items:center;justify-content:center}\n.vb-v2312-check .vb-part-checkbox{position:static!important;width:18px!important;height:18px!important;min-width:18px!important;min-height:18px!important;margin:0;accent-color:var(--vb-blue)}\n.vb-v2312-thumb{width:46px;height:46px;border-radius:9px;border:1px solid #edf1f4;background:#f7f9fb;display:flex;align-items:center;justify-content:center;overflow:hidden}\n.vb-v2312-thumb img{width:100%;height:100%;object-fit:contain}\n.vb-v2312-thumb-empty::after{content:'+';font-size:20px;color:#b4c1cb;font-weight:300}\n.vb-v2312-part-copy{min-width:0}\n.vb-v2312-part-role{display:block;font-size:10.5px;line-height:1.2;font-weight:700;text-transform:uppercase;letter-spacing:.035em;color:var(--vb-blue);margin-bottom:2px}\n.vb-v2312-part-name{display:block;font-size:12.5px;line-height:1.35;font-weight:600;color:var(--vb-ink)}\n.vb-v2312-part-fit{display:block;margin-top:3px;font-size:11px;color:var(--vb-grey)}\n.vb-v2312-part-warning{display:block;margin-top:3px;font-size:10.5px;color:#9b6114}\n.vb-v2312-part-side{display:flex;align-items:center;justify-content:flex-end;gap:9px;flex-wrap:wrap;min-width:185px}\n.vb-v2312-qty-wrap{display:flex;flex-direction:column;align-items:flex-end;gap:5px}\n.vb-v2312-qty{display:grid;grid-template-columns:32px 38px 32px;align-items:center;border:1px solid #dfe6ec;border-radius:9px;overflow:hidden;background:#fff;height:34px}\n.vb-v2312-qty .vb-part-qty-btn{width:32px;height:32px;min-height:32px!important;border:0;background:#f7f9fb;color:var(--vb-ink);cursor:pointer;font:600 15px\/1 inherit;padding:0}\n.vb-v2312-qty .vb-part-qty-btn:hover{background:#eef5f9;color:var(--vb-blue)}\n.vb-v2312-qty-val{display:flex;align-items:center;justify-content:center;height:32px;border-left:1px solid #edf1f4;border-right:1px solid #edf1f4;font-size:12px;font-weight:700;color:var(--vb-ink)}\n.vb-v2312-one-per{border:0;background:transparent;color:var(--vb-blue);font:600 10px\/1.25 inherit;padding:0;cursor:pointer;text-decoration:none}\n.vb-v2312-one-per[data-active=\"true\"]{color:#54717f}\n.vb-v2312-price{min-width:82px;text-align:right;font-size:12px;font-weight:700;color:var(--vb-ink)}\n.vb-v2312-footer{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:12px;padding-top:12px;border-top:1px solid #e3eaf0}\n.vb-v2312-total{margin-right:auto;font-size:12px;font-weight:700;color:var(--vb-ink)}\n.vb-v2312-status{flex:1 1 100%;font-size:12px}\n.vb-v2312-add{min-height:42px!important}\n@media(max-width:640px){\n  .vb-v2312-parts-head{flex-direction:column;gap:7px}\n  .vb-v2312-part-row{grid-template-columns:auto 42px minmax(0,1fr)}\n  .vb-v2312-thumb{width:42px;height:42px}\n  .vb-v2312-part-side{grid-column:2 \/ -1;width:100%;justify-content:space-between;min-width:0;padding-top:5px}\n  .vb-v2312-footer .vb-v2312-add{width:100%!important}\n}\n\/* Container overview simplification. *\/\n#vb-v24-select-all{margin:0;vertical-align:middle}\n.vb-v21-command-sub{font-weight:500}\n<\/style>\n<div class=\"vb-check\">\n  <div class=\"vb-top-row\">\n    <h2 id=\"vb-title\">Welke VARIBOX-variant heb ik?<\/h2>\n    <select id=\"vb-lang\" aria-label=\"Taal\">\n      <option value=\"nl\">NL<\/option>\n      <option value=\"en\">EN<\/option>\n      <option value=\"de\">DE<\/option>\n      <option value=\"fr\">FR<\/option>\n      <option value=\"it\">IT<\/option>\n      <option value=\"es\">ES<\/option>\n      <option value=\"pl\">PL<\/option>\n    <\/select>\n  <\/div>\n  <p class=\"vb-intro\" id=\"vb-intro-text\"><\/p>\n\n  <div class=\"vb-hero-panel\">\n  <div class=\"vb-input-row\">\n    <div id=\"vb-code-wrap\" class=\"vb-code-wrap\"><textarea id=\"vb-code\" rows=\"1\" autocomplete=\"off\" spellcheck=\"false\" maxlength=\"5000\" aria-describedby=\"vb-intro-text vb-bulk-hint\"><\/textarea><button type=\"button\" id=\"vb-code-clear\" class=\"vb-code-clear\" aria-label=\"Clear\">\u00d7<\/button><\/div>\n    <button type=\"button\" id=\"vb-submit\"><\/button>\n  <\/div>\n  <div id=\"vb-input-meta\" class=\"vb-input-meta\" role=\"status\" aria-live=\"polite\"><\/div>\n  <div id=\"vb-example\"><span id=\"vb-example-intro\"><\/span> <button type=\"button\" id=\"vb-fill-example\"><\/button><\/div>\n  <div id=\"vb-bulk-hint\"><\/div>\n  <div class=\"vb-app-toolbar\" id=\"vb-app-toolbar\" aria-label=\"VARIBOX checker tools\">\n    <button type=\"button\" id=\"vb-v21-scan-btn\" class=\"vb-app-tool\" data-vb-action=\"open-scanner\"><\/button>\n  <\/div>\n  <\/div>\n\n  <div id=\"vb-result\" aria-live=\"polite\"><\/div>\n  <div id=\"vb-v21-layer\" class=\"vb-v21-layer\">\n    <div id=\"vb-v21-compare-dock\" class=\"vb-v21-compare-dock\" aria-live=\"polite\"><\/div>\n    <div id=\"vb-v21-compare-modal\" class=\"vb-v21-modal\" aria-hidden=\"true\"><div class=\"vb-v21-dialog\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"vb-v21-compare-title\"><div class=\"vb-v21-dialog-head\"><div><h3 id=\"vb-v21-compare-title\"><\/h3><p id=\"vb-v21-compare-sub\"><\/p><\/div><button type=\"button\" class=\"vb-v21-dialog-close\" data-vb-action=\"close-modal\" data-modal-id=\"vb-v21-compare-modal\" aria-label=\"Close\">\u00d7<\/button><\/div><div id=\"vb-v21-compare-body\" class=\"vb-v21-dialog-body\"><\/div><\/div><\/div>\n    <div id=\"vb-v21-scan-modal\" class=\"vb-v21-modal\" aria-hidden=\"true\"><div class=\"vb-v21-dialog vb-v21-scan-dialog\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"vb-v21-scan-title\"><div class=\"vb-v21-dialog-head\"><div><h3 id=\"vb-v21-scan-title\"><\/h3><p id=\"vb-v21-scan-hint\"><\/p><\/div><button type=\"button\" class=\"vb-v21-dialog-close\" data-vb-action=\"close-modal\" data-modal-id=\"vb-v21-scan-modal\" aria-label=\"Close\">\u00d7<\/button><\/div><div class=\"vb-v21-dialog-body\"><div id=\"vb-v21-scan-stage\" class=\"vb-v21-scan-stage\"><\/div><div id=\"vb-v21-scan-status\" class=\"vb-v21-scan-status\" role=\"status\" aria-live=\"polite\"><\/div><div class=\"vb-v21-privacy-note\"><span aria-hidden=\"true\">\ud83d\udd12<\/span><span id=\"vb-v21-scan-privacy\"><\/span><\/div><\/div><\/div><\/div>\n  <\/div>\n  <div id=\"vb-toast-container\" class=\"vb-toast-container\" aria-live=\"polite\"><\/div>\n<\/div>\n\n<script>\nwindow.VBChecker = window.VBChecker || {};\n(() => {\n'use strict';\nconst I18N_DATA = {\"nl\": {\"type\": [[\"VARIBOX FC 1000\", \"VB1001\"], [\"VARIBOX FC 1000 + Connect+\", \"VC1001\"], [\"VARIBOX FC 800\", \"VB0801\"], [\"VARIBOX FC 800 + Connect+\", \"VC0801\"], [\"VARIBOX CC 250\", \"VB0250\"], [\"VARIBOX CC 250 + Connect+\", \"VC0250\"], [\"VARIBOX CC 250 ISPM\", \"VB0251\"], [\"VARIBOX CC 250 ISPM + Connect+\", \"VC0251\"], [\"Binnenbox - vervangingsset VARIBOX FC 1000\", \"VI1001\"], [\"Binnenbox - vervangingsset VARIBOX FC 1000 + Connect+\", \"VK1001\"], [\"Binnenbox - vervangingsset VARIBOX FC 800\", \"VI0801\"], [\"Binnenbox - vervangingsset VARIBOX FC 800 + Connect+\", \"VK0801\"], [\"VARIBOX Drumtainer\", \"DT0200\"]], \"pakking\": [[\"EPDM\", \"A\"], [\"Viton\", \"B\"], [\"EPDM met ISPM-pallet (alleen VARIBOX 250)\", \"D\"], [\"EPDM met ISPM-pallet (alleen VARIBOX 250)\", \"F\"], [\"Viton met ISPM-pallet (alleen VARIBOX 250)\", \"E\"]], \"zuigbuis_venting\": [[\"Geen zuigbuis + Combivent (EPDM)\", \"B\"], [\"Geen zuigbuis + Combivent (Viton)\", \"B\"], [\"Geen zuigbuis + beluchter (EPDM)\", \"L\"], [\"Geen zuigbuis + beluchter (Viton)\", \"L\"], [\"Safeline Performance + Combivent (EPDM)\", \"C\"], [\"Safeline Performance Food + Combivent (EPDM)\", \"K\"], [\"Safeline Performance + Combivent (Viton)\", \"V\"], [\"Safeline Performance + beluchter (EPDM)\", \"E\"], [\"Safeline Performance Food + beluchter (EPDM)\", \"P\"], [\"Safeline Performance + beluchter (Viton)\", \"W\"], [\"Quick Connector + Combivent (EPDM)\", \"R\"], [\"Quick Connector + Combivent (Viton)\", \"R\"], [\"Quick Connector + beluchter (EPDM)\", \"S\"], [\"Quick Connector + beluchter (Viton)\", \"S\"], [\"Safeline Precision + Combivent (EPDM)\", \"Y\"], [\"Safeline Precision + Combivent (Viton)\", \"Y\"], [\"Safeline Precision + beluchter (EPDM)\", \"Z\"], [\"Safeline Precision + beluchter (Viton)\", \"Z\"], [\"CDS voetklep D14 + Combivent, rond (Viton)\", \"D\"], [\"CDS voetklep D14 + beluchter, rond (Viton)\", \"M\"], [\"Ecolab CDS speciaal + Combivent (EPDM)\", \"T\"], [\"Ecolab CDS speciaal + Combivent (Viton)\", \"T\"], [\"Ecolab CDS speciaal + beluchter (EPDM)\", \"U\"], [\"Ecolab CDS speciaal + beluchter (Viton)\", \"U\"], [\"Ecolab, geen zuigbuis + Combivent (EPDM)\", \"D\"], [\"Ecolab, geen zuigbuis + Combivent (Viton)\", \"G\"], [\"Ecolab, geen zuigbuis + beluchter (EPDM)\", \"H\"], [\"Ecolab, geen zuigbuis + beluchter (Viton)\", \"J\"], [\"AS QC2 + Combivent (EPDM)\", \"I\"], [\"AS QC2 + beluchter (EPDM)\", \"N\"], [\"AS GT2 + Combivent (EPDM)\", \"X\"], [\"AS GT2 + beluchter (EPDM)\", \"F\"]], \"levelsensor\": [[\"Geen sensoren\", \"A\"], [\"Leegmelder\", \"B\"], [\"Volmelder\", \"D\"], [\"Leegmelder + volmelder\", \"C\"], [\"Voormelder\", \"E\"], [\"Voormelder + volmelder\", \"J\"]], \"levelsensor_vervanging\": [[\"Geen sensoren (vervangingsset)\", \"A\"], [\"Leegmelder (vervangingsset)\", \"B\"], [\"Volmelder (vervangingsset)\", \"D\"], [\"Leegmelder + volmelder (vervangingsset)\", \"C\"], [\"Voormelder (vervangingsset)\", \"E\"], [\"Voormelder + volmelder (vervangingsset)\", \"J\"]], \"kleur\": [[\"Naturel\", \"000\"], [\"Groen\", \"303\"], [\"Geel\", \"698\"], [\"Donkerblauw\", \"709\"], [\"Lichtblauw\", \"753\"], [\"Oranje\", \"887\"], [\"Rood\", \"892\"]], \"special\": [[\"CDS voetklep D14 + retour\", \"I\"], [\"Colder DQ PRO\", \"H\"], [\"Camlock 2D F + Combivent (EPDM)\", \"N\"], [\"Camlock 2D F + beluchter (EPDM)\", \"P\"], [\"Camlock 2D M + Combivent (Viton)\", \"O\"], [\"Camlock 2D M + beluchter (Viton)\", \"Q\"], [\"Leegmelder SealedAir\", \"G\"], [\"Ecolab 411925\", \"C\"], [\"Ecolab 411920\", \"D\"], [\"Ecolab 411922\", \"E\"], [\"Ecolab 411917\", \"F\"], [\"Ecolab 411923\", \"G\"], [\"Ecolab 411928\", \"H\"], [\"Ecolab 411930\", \"I\"], [\"Ecolab 411919\", \"J\"], [\"Ecolab 411931\", \"K\"], [\"Ecolab 411932\", \"L\"], [\"Ecolab 411933\", \"M\"], [\"Ecolab 411927\", \"N\"], [\"Ecolab 411929\", \"O\"], [\"Ecolab 411924\", \"P\"], [\"Ecolab 412436\", \"Q\"], [\"Ecolab 412438\", \"R\"], [\"Ecolab 412584\", \"S\"], [\"Ecolab 412583\", \"T\"], [\"Ecolab 412791\", \"U\"], [\"Ecolab 413261\", \"V\"], [\"AS Quickconnect + Combivent\", \"J\"], [\"AS Quickconnect + beluchter\", \"K\"], [\"AS Quickconnect + retour\", \"G\"]], \"drumtainer_pallet\": [[\"Levering op wielen (geen pallet)\", \"B\"], [\"Levering op ISPM-pallet\", \"C\"], [\"Levering op ISPM-pallet, webshopuitvoering (incl. zak)\", \"W\"]], \"drumtainer_trailer\": [[\"Standaard\", \"A\"], [\"Trailer\", \"B\"]], \"drumtainer_combo\": [[\"E\u00e9n kleur\", \"A\"], [\"Tweekleurig (lichtblauwe buitenkant, dekselkleur hieronder)\", \"B\"], [\"Tweekleurig (donkerblauwe buitenkant, dekselkleur hieronder)\", \"C\"]], \"drumtainer_kleur\": [[\"Grijs\", \"103\"], [\"Groen\", \"303\"], [\"Geel\", \"698\"], [\"Donkerblauw\", \"709\"], [\"Lichtblauw\", \"753\"], [\"Rood\", \"892\"]]}, \"en\": {\"type\": [[\"VARIBOX FC 1000\", \"VB1001\"], [\"VARIBOX FC 1000 + Connect+\", \"VC1001\"], [\"VARIBOX FC 800\", \"VB0801\"], [\"VARIBOX FC 800 + Connect+\", \"VC0801\"], [\"VARIBOX CC 250\", \"VB0250\"], [\"VARIBOX CC 250 + Connect+\", \"VC0250\"], [\"VARIBOX CC 250 ISPM\", \"VB0251\"], [\"VARIBOX CC 250 ISPM + Connect+\", \"VC0251\"], [\"Inner box - replacement set VARIBOX FC 1000\", \"VI1001\"], [\"Inner box - replacement set VARIBOX FC 1000 + Connect+\", \"VK1001\"], [\"Inner box - replacement set VARIBOX FC 800\", \"VI0801\"], [\"Inner box - replacement set VARIBOX FC 800 + Connect+\", \"VK0801\"], [\"VARIBOX Drumtainer\", \"DT0200\"]], \"pakking\": [[\"EPDM\", \"A\"], [\"Viton\", \"B\"], [\"EPDM with ISPM pallet (only VARIBOX 250)\", \"D\"], [\"EPDM with ISPM pallet (only VARIBOX 250)\", \"F\"], [\"Viton with ISPM pallet (only VARIBOX 250)\", \"E\"]], \"zuigbuis_venting\": [[\"No extractor tube + Combivent (EPDM)\", \"B\"], [\"No extractor tube + Combivent (Viton)\", \"B\"], [\"No extractor tube + vent (EPDM)\", \"L\"], [\"No extractor tube + vent (Viton)\", \"L\"], [\"Safeline Performance + Combivent (EPDM)\", \"C\"], [\"Safeline Performance Food + Combivent (EPDM)\", \"K\"], [\"Safeline Performance + Combivent (Viton)\", \"V\"], [\"Safeline Performance + vent (EPDM)\", \"E\"], [\"Safeline Performance Food + vent (EPDM)\", \"P\"], [\"Safeline Performance + vent (Viton)\", \"W\"], [\"Quick Connector + Combivent (EPDM)\", \"R\"], [\"Quick Connector + Combivent (Viton)\", \"R\"], [\"Quick Connector + vent (EPDM)\", \"S\"], [\"Quick Connector + vent (Viton)\", \"S\"], [\"Safeline Precision + Combivent (EPDM)\", \"Y\"], [\"Safeline Precision + Combivent (Viton)\", \"Y\"], [\"Safeline Precision + vent (EPDM)\", \"Z\"], [\"Safeline Precision + vent (Viton)\", \"Z\"], [\"CDS foot valve D14 + Combivent, round (Viton)\", \"D\"], [\"CDS foot valve D14 + vent, round (Viton)\", \"M\"], [\"Ecolab CDS special + Combivent (EPDM)\", \"T\"], [\"Ecolab CDS special + Combivent (Viton)\", \"T\"], [\"Ecolab CDS special + vent (EPDM)\", \"U\"], [\"Ecolab CDS special + vent (Viton)\", \"U\"], [\"Ecolab, no extractor tube + Combivent (EPDM)\", \"D\"], [\"Ecolab, no extractor tube + Combivent (Viton)\", \"G\"], [\"Ecolab, no extractor tube + vent (EPDM)\", \"H\"], [\"Ecolab, no extractor tube + vent (Viton)\", \"J\"], [\"AS QC2 + Combivent (EPDM)\", \"I\"], [\"AS QC2 + vent (EPDM)\", \"N\"], [\"AS GT2 + Combivent (EPDM)\", \"X\"], [\"AS GT2 + vent (EPDM)\", \"F\"]], \"levelsensor\": [[\"No sensors\", \"A\"], [\"Empty sensor\", \"B\"], [\"Full sensor\", \"D\"], [\"Empty sensor + full sensor\", \"C\"], [\"Low-level sensor\", \"E\"], [\"Low-level sensor + full sensor\", \"J\"]], \"levelsensor_vervanging\": [[\"No sensors (replacement set)\", \"A\"], [\"Empty sensor (replacement set)\", \"B\"], [\"Full sensor (replacement set)\", \"D\"], [\"Empty sensor + full sensor (replacement set)\", \"C\"], [\"Low-level sensor (replacement set)\", \"E\"], [\"Low-level sensor + full sensor (replacement set)\", \"J\"]], \"kleur\": [[\"Natural\", \"000\"], [\"Green\", \"303\"], [\"Yellow\", \"698\"], [\"Dark blue\", \"709\"], [\"Light blue\", \"753\"], [\"Orange\", \"887\"], [\"Red\", \"892\"]], \"special\": [[\"CDS foot valve D14 + return\", \"I\"], [\"Colder DQ PRO\", \"H\"], [\"Camlock 2D F + Combivent (EPDM)\", \"N\"], [\"Camlock 2D F + vent (EPDM)\", \"P\"], [\"Camlock 2D M + Combivent (Viton)\", \"O\"], [\"Camlock 2D M + vent (Viton)\", \"Q\"], [\"Empty sensor SealedAir\", \"G\"], [\"Ecolab 411925\", \"C\"], [\"Ecolab 411920\", \"D\"], [\"Ecolab 411922\", \"E\"], [\"Ecolab 411917\", \"F\"], [\"Ecolab 411923\", \"G\"], [\"Ecolab 411928\", \"H\"], [\"Ecolab 411930\", \"I\"], [\"Ecolab 411919\", \"J\"], [\"Ecolab 411931\", \"K\"], [\"Ecolab 411932\", \"L\"], [\"Ecolab 411933\", \"M\"], [\"Ecolab 411927\", \"N\"], [\"Ecolab 411929\", \"O\"], [\"Ecolab 411924\", \"P\"], [\"Ecolab 412436\", \"Q\"], [\"Ecolab 412438\", \"R\"], [\"Ecolab 412584\", \"S\"], [\"Ecolab 412583\", \"T\"], [\"Ecolab 412791\", \"U\"], [\"Ecolab 413261\", \"V\"], [\"AS Quickconnect + Combivent\", \"J\"], [\"AS Quickconnect + vent\", \"K\"], [\"AS Quickconnect + return\", \"G\"]], \"drumtainer_pallet\": [[\"Delivered on wheels (no pallet)\", \"B\"], [\"Delivered on ISPM pallet\", \"C\"], [\"Delivered on ISPM pallet, webshop version (incl. bag)\", \"W\"]], \"drumtainer_trailer\": [[\"Standard\", \"A\"], [\"Trailer\", \"B\"]], \"drumtainer_combo\": [[\"Single colour\", \"A\"], [\"Two-tone (light blue body, lid colour below)\", \"B\"], [\"Two-tone (dark blue body, lid colour below)\", \"C\"]], \"drumtainer_kleur\": [[\"Grey\", \"103\"], [\"Green\", \"303\"], [\"Yellow\", \"698\"], [\"Dark blue\", \"709\"], [\"Light blue\", \"753\"], [\"Red\", \"892\"]]}, \"de\": {\"type\": [[\"VARIBOX FC 1000\", \"VB1001\"], [\"VARIBOX FC 1000 + Connect+\", \"VC1001\"], [\"VARIBOX FC 800\", \"VB0801\"], [\"VARIBOX FC 800 + Connect+\", \"VC0801\"], [\"VARIBOX CC 250\", \"VB0250\"], [\"VARIBOX CC 250 + Connect+\", \"VC0250\"], [\"VARIBOX CC 250 ISPM\", \"VB0251\"], [\"VARIBOX CC 250 ISPM + Connect+\", \"VC0251\"], [\"Innenbeh\u00e4lter - Ersatzset VARIBOX FC 1000\", \"VI1001\"], [\"Innenbeh\u00e4lter - Ersatzset VARIBOX FC 1000 + Connect+\", \"VK1001\"], [\"Innenbeh\u00e4lter - Ersatzset VARIBOX FC 800\", \"VI0801\"], [\"Innenbeh\u00e4lter - Ersatzset VARIBOX FC 800 + Connect+\", \"VK0801\"], [\"VARIBOX Drumtainer\", \"DT0200\"]], \"pakking\": [[\"EPDM\", \"A\"], [\"Viton\", \"B\"], [\"EPDM mit ISPM-Palette (nur VARIBOX 250)\", \"D\"], [\"EPDM mit ISPM-Palette (nur VARIBOX 250)\", \"F\"], [\"Viton mit ISPM-Palette (nur VARIBOX 250)\", \"E\"]], \"zuigbuis_venting\": [[\"Kein Steigrohr + Combivent (EPDM)\", \"B\"], [\"Kein Steigrohr + Combivent (Viton)\", \"B\"], [\"Kein Steigrohr + Entl\u00fcfter (EPDM)\", \"L\"], [\"Kein Steigrohr + Entl\u00fcfter (Viton)\", \"L\"], [\"Safeline Performance + Combivent (EPDM)\", \"C\"], [\"Safeline Performance Food + Combivent (EPDM)\", \"K\"], [\"Safeline Performance + Combivent (Viton)\", \"V\"], [\"Safeline Performance + Entl\u00fcfter (EPDM)\", \"E\"], [\"Safeline Performance Food + Entl\u00fcfter (EPDM)\", \"P\"], [\"Safeline Performance + Entl\u00fcfter (Viton)\", \"W\"], [\"Quick Connector + Combivent (EPDM)\", \"R\"], [\"Quick Connector + Combivent (Viton)\", \"R\"], [\"Quick Connector + Entl\u00fcfter (EPDM)\", \"S\"], [\"Quick Connector + Entl\u00fcfter (Viton)\", \"S\"], [\"Safeline Precision + Combivent (EPDM)\", \"Y\"], [\"Safeline Precision + Combivent (Viton)\", \"Y\"], [\"Safeline Precision + Entl\u00fcfter (EPDM)\", \"Z\"], [\"Safeline Precision + Entl\u00fcfter (Viton)\", \"Z\"], [\"CDS Bodenventil D14 + Combivent, rund (Viton)\", \"D\"], [\"CDS Bodenventil D14 + Entl\u00fcfter, rund (Viton)\", \"M\"], [\"Ecolab CDS speziell + Combivent (EPDM)\", \"T\"], [\"Ecolab CDS speziell + Combivent (Viton)\", \"T\"], [\"Ecolab CDS speziell + Entl\u00fcfter (EPDM)\", \"U\"], [\"Ecolab CDS speziell + Entl\u00fcfter (Viton)\", \"U\"], [\"Ecolab, Kein Steigrohr + Combivent (EPDM)\", \"D\"], [\"Ecolab, Kein Steigrohr + Combivent (Viton)\", \"G\"], [\"Ecolab, Kein Steigrohr + Entl\u00fcfter (EPDM)\", \"H\"], [\"Ecolab, Kein Steigrohr + Entl\u00fcfter (Viton)\", \"J\"], [\"AS QC2 + Combivent (EPDM)\", \"I\"], [\"AS QC2 + Entl\u00fcfter (EPDM)\", \"N\"], [\"AS GT2 + Combivent (EPDM)\", \"X\"], [\"AS GT2 + Entl\u00fcfter (EPDM)\", \"F\"]], \"levelsensor\": [[\"Keine Sensoren\", \"A\"], [\"Leermelder\", \"B\"], [\"Vollmelder\", \"D\"], [\"Leermelder + Vollmelder\", \"C\"], [\"Vorwarnmelder\", \"E\"], [\"Vorwarnmelder + Vollmelder\", \"J\"]], \"levelsensor_vervanging\": [[\"Keine Sensoren (Ersatzset)\", \"A\"], [\"Leermelder (Ersatzset)\", \"B\"], [\"Vollmelder (Ersatzset)\", \"D\"], [\"Leermelder + Vollmelder (Ersatzset)\", \"C\"], [\"Vorwarnmelder (Ersatzset)\", \"E\"], [\"Vorwarnmelder + Vollmelder (Ersatzset)\", \"J\"]], \"kleur\": [[\"Natur\", \"000\"], [\"Gr\u00fcn\", \"303\"], [\"Gelb\", \"698\"], [\"Dunkelblau\", \"709\"], [\"Hellblau\", \"753\"], [\"Orange\", \"887\"], [\"Rot\", \"892\"]], \"special\": [[\"CDS Bodenventil D14 + R\u00fcckf\u00fchrung\", \"I\"], [\"Colder DQ PRO\", \"H\"], [\"Camlock 2D F + Combivent (EPDM)\", \"N\"], [\"Camlock 2D F + Entl\u00fcfter (EPDM)\", \"P\"], [\"Camlock 2D M + Combivent (Viton)\", \"O\"], [\"Camlock 2D M + Entl\u00fcfter (Viton)\", \"Q\"], [\"Leermelder SealedAir\", \"G\"], [\"Ecolab 411925\", \"C\"], [\"Ecolab 411920\", \"D\"], [\"Ecolab 411922\", \"E\"], [\"Ecolab 411917\", \"F\"], [\"Ecolab 411923\", \"G\"], [\"Ecolab 411928\", \"H\"], [\"Ecolab 411930\", \"I\"], [\"Ecolab 411919\", \"J\"], [\"Ecolab 411931\", \"K\"], [\"Ecolab 411932\", \"L\"], [\"Ecolab 411933\", \"M\"], [\"Ecolab 411927\", \"N\"], [\"Ecolab 411929\", \"O\"], [\"Ecolab 411924\", \"P\"], [\"Ecolab 412436\", \"Q\"], [\"Ecolab 412438\", \"R\"], [\"Ecolab 412584\", \"S\"], [\"Ecolab 412583\", \"T\"], [\"Ecolab 412791\", \"U\"], [\"Ecolab 413261\", \"V\"], [\"AS Quickconnect + Combivent\", \"J\"], [\"AS Quickconnect + Entl\u00fcfter\", \"K\"], [\"AS Quickconnect + R\u00fcckf\u00fchrung\", \"G\"]], \"drumtainer_pallet\": [[\"Lieferung auf R\u00e4dern (ohne Palette)\", \"B\"], [\"Lieferung auf ISPM-Palette\", \"C\"], [\"Lieferung auf ISPM-Palette, Webshop-Version (inkl. Beutel)\", \"W\"]], \"drumtainer_trailer\": [[\"Standard\", \"A\"], [\"Trailer\", \"B\"]], \"drumtainer_combo\": [[\"Eine Farbe\", \"A\"], [\"Zweifarbig (hellblaue Au\u00dfenseite, Deckelfarbe unten)\", \"B\"], [\"Zweifarbig (dunkelblaue Au\u00dfenseite, Deckelfarbe unten)\", \"C\"]], \"drumtainer_kleur\": [[\"Grau\", \"103\"], [\"Gr\u00fcn\", \"303\"], [\"Gelb\", \"698\"], [\"Dunkelblau\", \"709\"], [\"Hellblau\", \"753\"], [\"Rot\", \"892\"]]}, \"fr\": {\"type\": [[\"VARIBOX FC 1000\", \"VB1001\"], [\"VARIBOX FC 1000 + Connect+\", \"VC1001\"], [\"VARIBOX FC 800\", \"VB0801\"], [\"VARIBOX FC 800 + Connect+\", \"VC0801\"], [\"VARIBOX CC 250\", \"VB0250\"], [\"VARIBOX CC 250 + Connect+\", \"VC0250\"], [\"VARIBOX CC 250 ISPM\", \"VB0251\"], [\"VARIBOX CC 250 ISPM + Connect+\", \"VC0251\"], [\"Cuve int\u00e9rieure - kit de remplacement VARIBOX FC 1000\", \"VI1001\"], [\"Cuve int\u00e9rieure - kit de remplacement VARIBOX FC 1000 + Connect+\", \"VK1001\"], [\"Cuve int\u00e9rieure - kit de remplacement VARIBOX FC 800\", \"VI0801\"], [\"Cuve int\u00e9rieure - kit de remplacement VARIBOX FC 800 + Connect+\", \"VK0801\"], [\"VARIBOX Drumtainer\", \"DT0200\"]], \"pakking\": [[\"EPDM\", \"A\"], [\"Viton\", \"B\"], [\"EPDM avec palette ISPM (uniquement VARIBOX 250)\", \"D\"], [\"EPDM avec palette ISPM (uniquement VARIBOX 250)\", \"F\"], [\"Viton avec palette ISPM (uniquement VARIBOX 250)\", \"E\"]], \"zuigbuis_venting\": [[\"Sans tube d'aspiration + Combivent (EPDM)\", \"B\"], [\"Sans tube d'aspiration + Combivent (Viton)\", \"B\"], [\"Sans tube d'aspiration + \u00e9vent (EPDM)\", \"L\"], [\"Sans tube d'aspiration + \u00e9vent (Viton)\", \"L\"], [\"Safeline Performance + Combivent (EPDM)\", \"C\"], [\"Safeline Performance Food + Combivent (EPDM)\", \"K\"], [\"Safeline Performance + Combivent (Viton)\", \"V\"], [\"Safeline Performance + \u00e9vent (EPDM)\", \"E\"], [\"Safeline Performance Food + \u00e9vent (EPDM)\", \"P\"], [\"Safeline Performance + \u00e9vent (Viton)\", \"W\"], [\"Quick Connector + Combivent (EPDM)\", \"R\"], [\"Quick Connector + Combivent (Viton)\", \"R\"], [\"Quick Connector + \u00e9vent (EPDM)\", \"S\"], [\"Quick Connector + \u00e9vent (Viton)\", \"S\"], [\"Safeline Precision + Combivent (EPDM)\", \"Y\"], [\"Safeline Precision + Combivent (Viton)\", \"Y\"], [\"Safeline Precision + \u00e9vent (EPDM)\", \"Z\"], [\"Safeline Precision + \u00e9vent (Viton)\", \"Z\"], [\"CDS clapet de pied D14 + Combivent, rond (Viton)\", \"D\"], [\"CDS clapet de pied D14 + \u00e9vent, rond (Viton)\", \"M\"], [\"Ecolab CDS sp\u00e9cial + Combivent (EPDM)\", \"T\"], [\"Ecolab CDS sp\u00e9cial + Combivent (Viton)\", \"T\"], [\"Ecolab CDS sp\u00e9cial + \u00e9vent (EPDM)\", \"U\"], [\"Ecolab CDS sp\u00e9cial + \u00e9vent (Viton)\", \"U\"], [\"Ecolab, sans tube d'aspiration + Combivent (EPDM)\", \"D\"], [\"Ecolab, sans tube d'aspiration + Combivent (Viton)\", \"G\"], [\"Ecolab, sans tube d'aspiration + \u00e9vent (EPDM)\", \"H\"], [\"Ecolab, sans tube d'aspiration + \u00e9vent (Viton)\", \"J\"], [\"AS QC2 + Combivent (EPDM)\", \"I\"], [\"AS QC2 + \u00e9vent (EPDM)\", \"N\"], [\"AS GT2 + Combivent (EPDM)\", \"X\"], [\"AS GT2 + \u00e9vent (EPDM)\", \"F\"]], \"levelsensor\": [[\"Aucun capteur\", \"A\"], [\"D\u00e9tecteur de vide\", \"B\"], [\"D\u00e9tecteur de plein\", \"D\"], [\"D\u00e9tecteur de vide + d\u00e9tecteur de plein\", \"C\"], [\"D\u00e9tecteur de niveau bas\", \"E\"], [\"D\u00e9tecteur de niveau bas + d\u00e9tecteur de plein\", \"J\"]], \"levelsensor_vervanging\": [[\"Aucun capteur (kit de remplacement)\", \"A\"], [\"D\u00e9tecteur de vide (kit de remplacement)\", \"B\"], [\"D\u00e9tecteur de plein (kit de remplacement)\", \"D\"], [\"D\u00e9tecteur de vide + d\u00e9tecteur de plein (kit de remplacement)\", \"C\"], [\"D\u00e9tecteur de niveau bas (kit de remplacement)\", \"E\"], [\"D\u00e9tecteur de niveau bas + d\u00e9tecteur de plein (kit de remplacement)\", \"J\"]], \"kleur\": [[\"Naturel\", \"000\"], [\"Vert\", \"303\"], [\"Jaune\", \"698\"], [\"Bleu fonc\u00e9\", \"709\"], [\"Bleu clair\", \"753\"], [\"Orange\", \"887\"], [\"Rouge\", \"892\"]], \"special\": [[\"CDS clapet de pied D14 + retour\", \"I\"], [\"Colder DQ PRO\", \"H\"], [\"Camlock 2D F + Combivent (EPDM)\", \"N\"], [\"Camlock 2D F + \u00e9vent (EPDM)\", \"P\"], [\"Camlock 2D M + Combivent (Viton)\", \"O\"], [\"Camlock 2D M + \u00e9vent (Viton)\", \"Q\"], [\"D\u00e9tecteur de vide SealedAir\", \"G\"], [\"Ecolab 411925\", \"C\"], [\"Ecolab 411920\", \"D\"], [\"Ecolab 411922\", \"E\"], [\"Ecolab 411917\", \"F\"], [\"Ecolab 411923\", \"G\"], [\"Ecolab 411928\", \"H\"], [\"Ecolab 411930\", \"I\"], [\"Ecolab 411919\", \"J\"], [\"Ecolab 411931\", \"K\"], [\"Ecolab 411932\", \"L\"], [\"Ecolab 411933\", \"M\"], [\"Ecolab 411927\", \"N\"], [\"Ecolab 411929\", \"O\"], [\"Ecolab 411924\", \"P\"], [\"Ecolab 412436\", \"Q\"], [\"Ecolab 412438\", \"R\"], [\"Ecolab 412584\", \"S\"], [\"Ecolab 412583\", \"T\"], [\"Ecolab 412791\", \"U\"], [\"Ecolab 413261\", \"V\"], [\"AS Quickconnect + Combivent\", \"J\"], [\"AS Quickconnect + \u00e9vent\", \"K\"], [\"AS Quickconnect + retour\", \"G\"]], \"drumtainer_pallet\": [[\"Livr\u00e9 sur roues (sans palette)\", \"B\"], [\"Livr\u00e9 sur palette ISPM\", \"C\"], [\"Livr\u00e9 sur palette ISPM, version webshop (avec sac)\", \"W\"]], \"drumtainer_trailer\": [[\"Standard\", \"A\"], [\"Trailer\", \"B\"]], \"drumtainer_combo\": [[\"Une couleur\", \"A\"], [\"Bicolore (ext\u00e9rieur bleu clair, couleur du couvercle ci-dessous)\", \"B\"], [\"Bicolore (ext\u00e9rieur bleu fonc\u00e9, couleur du couvercle ci-dessous)\", \"C\"]], \"drumtainer_kleur\": [[\"Gris\", \"103\"], [\"Vert\", \"303\"], [\"Jaune\", \"698\"], [\"Bleu fonc\u00e9\", \"709\"], [\"Bleu clair\", \"753\"], [\"Rouge\", \"892\"]]}, \"it\": {\"type\": [[\"VARIBOX FC 1000\", \"VB1001\"], [\"VARIBOX FC 1000 + Connect+\", \"VC1001\"], [\"VARIBOX FC 800\", \"VB0801\"], [\"VARIBOX FC 800 + Connect+\", \"VC0801\"], [\"VARIBOX CC 250\", \"VB0250\"], [\"VARIBOX CC 250 + Connect+\", \"VC0250\"], [\"VARIBOX CC 250 ISPM\", \"VB0251\"], [\"VARIBOX CC 250 ISPM + Connect+\", \"VC0251\"], [\"Vasca interna - kit di ricambio VARIBOX FC 1000\", \"VI1001\"], [\"Vasca interna - kit di ricambio VARIBOX FC 1000 + Connect+\", \"VK1001\"], [\"Vasca interna - kit di ricambio VARIBOX FC 800\", \"VI0801\"], [\"Vasca interna - kit di ricambio VARIBOX FC 800 + Connect+\", \"VK0801\"], [\"VARIBOX Drumtainer\", \"DT0200\"]], \"pakking\": [[\"EPDM\", \"A\"], [\"Viton\", \"B\"], [\"EPDM con pallet ISPM (solo VARIBOX 250)\", \"D\"], [\"EPDM con pallet ISPM (solo VARIBOX 250)\", \"F\"], [\"Viton con pallet ISPM (solo VARIBOX 250)\", \"E\"]], \"zuigbuis_venting\": [[\"Senza tubo di aspirazione + Combivent (EPDM)\", \"B\"], [\"Senza tubo di aspirazione + Combivent (Viton)\", \"B\"], [\"Senza tubo di aspirazione + sfiato (EPDM)\", \"L\"], [\"Senza tubo di aspirazione + sfiato (Viton)\", \"L\"], [\"Safeline Performance + Combivent (EPDM)\", \"C\"], [\"Safeline Performance Food + Combivent (EPDM)\", \"K\"], [\"Safeline Performance + Combivent (Viton)\", \"V\"], [\"Safeline Performance + sfiato (EPDM)\", \"E\"], [\"Safeline Performance Food + sfiato (EPDM)\", \"P\"], [\"Safeline Performance + sfiato (Viton)\", \"W\"], [\"Quick Connector + Combivent (EPDM)\", \"R\"], [\"Quick Connector + Combivent (Viton)\", \"R\"], [\"Quick Connector + sfiato (EPDM)\", \"S\"], [\"Quick Connector + sfiato (Viton)\", \"S\"], [\"Safeline Precision + Combivent (EPDM)\", \"Y\"], [\"Safeline Precision + Combivent (Viton)\", \"Y\"], [\"Safeline Precision + sfiato (EPDM)\", \"Z\"], [\"Safeline Precision + sfiato (Viton)\", \"Z\"], [\"CDS valvola di fondo D14 + Combivent, rotondo (Viton)\", \"D\"], [\"CDS valvola di fondo D14 + sfiato, rotondo (Viton)\", \"M\"], [\"Ecolab CDS speciale + Combivent (EPDM)\", \"T\"], [\"Ecolab CDS speciale + Combivent (Viton)\", \"T\"], [\"Ecolab CDS speciale + sfiato (EPDM)\", \"U\"], [\"Ecolab CDS speciale + sfiato (Viton)\", \"U\"], [\"Ecolab, senza tubo di aspirazione + Combivent (EPDM)\", \"D\"], [\"Ecolab, senza tubo di aspirazione + Combivent (Viton)\", \"G\"], [\"Ecolab, senza tubo di aspirazione + sfiato (EPDM)\", \"H\"], [\"Ecolab, senza tubo di aspirazione + sfiato (Viton)\", \"J\"], [\"AS QC2 + Combivent (EPDM)\", \"I\"], [\"AS QC2 + sfiato (EPDM)\", \"N\"], [\"AS GT2 + Combivent (EPDM)\", \"X\"], [\"AS GT2 + sfiato (EPDM)\", \"F\"]], \"levelsensor\": [[\"Nessun sensore\", \"A\"], [\"Sensore di vuoto\", \"B\"], [\"Sensore di pieno\", \"D\"], [\"Sensore di vuoto + sensore di pieno\", \"C\"], [\"Sensore di livello basso\", \"E\"], [\"Sensore di livello basso + sensore di pieno\", \"J\"]], \"levelsensor_vervanging\": [[\"Nessun sensore (kit di ricambio)\", \"A\"], [\"Sensore di vuoto (kit di ricambio)\", \"B\"], [\"Sensore di pieno (kit di ricambio)\", \"D\"], [\"Sensore di vuoto + sensore di pieno (kit di ricambio)\", \"C\"], [\"Sensore di livello basso (kit di ricambio)\", \"E\"], [\"Sensore di livello basso + sensore di pieno (kit di ricambio)\", \"J\"]], \"kleur\": [[\"Naturale\", \"000\"], [\"Verde\", \"303\"], [\"Giallo\", \"698\"], [\"Blu scuro\", \"709\"], [\"Blu chiaro\", \"753\"], [\"Arancione\", \"887\"], [\"Rosso\", \"892\"]], \"special\": [[\"CDS valvola di fondo D14 + ritorno\", \"I\"], [\"Colder DQ PRO\", \"H\"], [\"Camlock 2D F + Combivent (EPDM)\", \"N\"], [\"Camlock 2D F + sfiato (EPDM)\", \"P\"], [\"Camlock 2D M + Combivent (Viton)\", \"O\"], [\"Camlock 2D M + sfiato (Viton)\", \"Q\"], [\"Sensore di vuoto SealedAir\", \"G\"], [\"Ecolab 411925\", \"C\"], [\"Ecolab 411920\", \"D\"], [\"Ecolab 411922\", \"E\"], [\"Ecolab 411917\", \"F\"], [\"Ecolab 411923\", \"G\"], [\"Ecolab 411928\", \"H\"], [\"Ecolab 411930\", \"I\"], [\"Ecolab 411919\", \"J\"], [\"Ecolab 411931\", \"K\"], [\"Ecolab 411932\", \"L\"], [\"Ecolab 411933\", \"M\"], [\"Ecolab 411927\", \"N\"], [\"Ecolab 411929\", \"O\"], [\"Ecolab 411924\", \"P\"], [\"Ecolab 412436\", \"Q\"], [\"Ecolab 412438\", \"R\"], [\"Ecolab 412584\", \"S\"], [\"Ecolab 412583\", \"T\"], [\"Ecolab 412791\", \"U\"], [\"Ecolab 413261\", \"V\"], [\"AS Quickconnect + Combivent\", \"J\"], [\"AS Quickconnect + sfiato\", \"K\"], [\"AS Quickconnect + ritorno\", \"G\"]], \"drumtainer_pallet\": [[\"Consegnato su ruote (senza pallet)\", \"B\"], [\"Consegnato su pallet ISPM\", \"C\"], [\"Consegnato su pallet ISPM, versione webshop (con sacco)\", \"W\"]], \"drumtainer_trailer\": [[\"Standard\", \"A\"], [\"Trailer\", \"B\"]], \"drumtainer_combo\": [[\"Un colore\", \"A\"], [\"Bicolore (esterno blu chiaro, colore del coperchio sotto)\", \"B\"], [\"Bicolore (esterno blu scuro, colore del coperchio sotto)\", \"C\"]], \"drumtainer_kleur\": [[\"Grigio\", \"103\"], [\"Verde\", \"303\"], [\"Giallo\", \"698\"], [\"Blu scuro\", \"709\"], [\"Blu chiaro\", \"753\"], [\"Rosso\", \"892\"]]}, \"es\": {\"type\": [[\"VARIBOX FC 1000\", \"VB1001\"], [\"VARIBOX FC 1000 + Connect+\", \"VC1001\"], [\"VARIBOX FC 800\", \"VB0801\"], [\"VARIBOX FC 800 + Connect+\", \"VC0801\"], [\"VARIBOX CC 250\", \"VB0250\"], [\"VARIBOX CC 250 + Connect+\", \"VC0250\"], [\"VARIBOX CC 250 ISPM\", \"VB0251\"], [\"VARIBOX CC 250 ISPM + Connect+\", \"VC0251\"], [\"Dep\u00f3sito interior - kit de repuesto VARIBOX FC 1000\", \"VI1001\"], [\"Dep\u00f3sito interior - kit de repuesto VARIBOX FC 1000 + Connect+\", \"VK1001\"], [\"Dep\u00f3sito interior - kit de repuesto VARIBOX FC 800\", \"VI0801\"], [\"Dep\u00f3sito interior - kit de repuesto VARIBOX FC 800 + Connect+\", \"VK0801\"], [\"VARIBOX Drumtainer\", \"DT0200\"]], \"pakking\": [[\"EPDM\", \"A\"], [\"Viton\", \"B\"], [\"EPDM con pal\u00e9 ISPM (solo VARIBOX 250)\", \"D\"], [\"EPDM con pal\u00e9 ISPM (solo VARIBOX 250)\", \"F\"], [\"Viton con pal\u00e9 ISPM (solo VARIBOX 250)\", \"E\"]], \"zuigbuis_venting\": [[\"Sin tubo de aspiraci\u00f3n + Combivent (EPDM)\", \"B\"], [\"Sin tubo de aspiraci\u00f3n + Combivent (Viton)\", \"B\"], [\"Sin tubo de aspiraci\u00f3n + respiradero (EPDM)\", \"L\"], [\"Sin tubo de aspiraci\u00f3n + respiradero (Viton)\", \"L\"], [\"Safeline Performance + Combivent (EPDM)\", \"C\"], [\"Safeline Performance Food + Combivent (EPDM)\", \"K\"], [\"Safeline Performance + Combivent (Viton)\", \"V\"], [\"Safeline Performance + respiradero (EPDM)\", \"E\"], [\"Safeline Performance Food + respiradero (EPDM)\", \"P\"], [\"Safeline Performance + respiradero (Viton)\", \"W\"], [\"Quick Connector + Combivent (EPDM)\", \"R\"], [\"Quick Connector + Combivent (Viton)\", \"R\"], [\"Quick Connector + respiradero (EPDM)\", \"S\"], [\"Quick Connector + respiradero (Viton)\", \"S\"], [\"Safeline Precision + Combivent (EPDM)\", \"Y\"], [\"Safeline Precision + Combivent (Viton)\", \"Y\"], [\"Safeline Precision + respiradero (EPDM)\", \"Z\"], [\"Safeline Precision + respiradero (Viton)\", \"Z\"], [\"CDS v\u00e1lvula de pie D14 + Combivent, redondo (Viton)\", \"D\"], [\"CDS v\u00e1lvula de pie D14 + respiradero, redondo (Viton)\", \"M\"], [\"Ecolab CDS especial + Combivent (EPDM)\", \"T\"], [\"Ecolab CDS especial + Combivent (Viton)\", \"T\"], [\"Ecolab CDS especial + respiradero (EPDM)\", \"U\"], [\"Ecolab CDS especial + respiradero (Viton)\", \"U\"], [\"Ecolab, sin tubo de aspiraci\u00f3n + Combivent (EPDM)\", \"D\"], [\"Ecolab, sin tubo de aspiraci\u00f3n + Combivent (Viton)\", \"G\"], [\"Ecolab, sin tubo de aspiraci\u00f3n + respiradero (EPDM)\", \"H\"], [\"Ecolab, sin tubo de aspiraci\u00f3n + respiradero (Viton)\", \"J\"], [\"AS QC2 + Combivent (EPDM)\", \"I\"], [\"AS QC2 + respiradero (EPDM)\", \"N\"], [\"AS GT2 + Combivent (EPDM)\", \"X\"], [\"AS GT2 + respiradero (EPDM)\", \"F\"]], \"levelsensor\": [[\"Sin sensores\", \"A\"], [\"Sensor de vac\u00edo\", \"B\"], [\"Sensor de lleno\", \"D\"], [\"Sensor de vac\u00edo + sensor de lleno\", \"C\"], [\"Sensor de nivel bajo\", \"E\"], [\"Sensor de nivel bajo + sensor de lleno\", \"J\"]], \"levelsensor_vervanging\": [[\"Sin sensores (kit de repuesto)\", \"A\"], [\"Sensor de vac\u00edo (kit de repuesto)\", \"B\"], [\"Sensor de lleno (kit de repuesto)\", \"D\"], [\"Sensor de vac\u00edo + sensor de lleno (kit de repuesto)\", \"C\"], [\"Sensor de nivel bajo (kit de repuesto)\", \"E\"], [\"Sensor de nivel bajo + sensor de lleno (kit de repuesto)\", \"J\"]], \"kleur\": [[\"Natural\", \"000\"], [\"Verde\", \"303\"], [\"Amarillo\", \"698\"], [\"Azul oscuro\", \"709\"], [\"Azul claro\", \"753\"], [\"Naranja\", \"887\"], [\"Rojo\", \"892\"]], \"special\": [[\"CDS v\u00e1lvula de pie D14 + retorno\", \"I\"], [\"Colder DQ PRO\", \"H\"], [\"Camlock 2D F + Combivent (EPDM)\", \"N\"], [\"Camlock 2D F + respiradero (EPDM)\", \"P\"], [\"Camlock 2D M + Combivent (Viton)\", \"O\"], [\"Camlock 2D M + respiradero (Viton)\", \"Q\"], [\"Sensor de vac\u00edo SealedAir\", \"G\"], [\"Ecolab 411925\", \"C\"], [\"Ecolab 411920\", \"D\"], [\"Ecolab 411922\", \"E\"], [\"Ecolab 411917\", \"F\"], [\"Ecolab 411923\", \"G\"], [\"Ecolab 411928\", \"H\"], [\"Ecolab 411930\", \"I\"], [\"Ecolab 411919\", \"J\"], [\"Ecolab 411931\", \"K\"], [\"Ecolab 411932\", \"L\"], [\"Ecolab 411933\", \"M\"], [\"Ecolab 411927\", \"N\"], [\"Ecolab 411929\", \"O\"], [\"Ecolab 411924\", \"P\"], [\"Ecolab 412436\", \"Q\"], [\"Ecolab 412438\", \"R\"], [\"Ecolab 412584\", \"S\"], [\"Ecolab 412583\", \"T\"], [\"Ecolab 412791\", \"U\"], [\"Ecolab 413261\", \"V\"], [\"AS Quickconnect + Combivent\", \"J\"], [\"AS Quickconnect + respiradero\", \"K\"], [\"AS Quickconnect + retorno\", \"G\"]], \"drumtainer_pallet\": [[\"Entregado sobre ruedas (sin pal\u00e9)\", \"B\"], [\"Entregado sobre pal\u00e9 ISPM\", \"C\"], [\"Entregado sobre pal\u00e9 ISPM, versi\u00f3n webshop (con bolsa)\", \"W\"]], \"drumtainer_trailer\": [[\"Est\u00e1ndar\", \"A\"], [\"Trailer\", \"B\"]], \"drumtainer_combo\": [[\"Un color\", \"A\"], [\"Bicolor (exterior azul claro, color de la tapa abajo)\", \"B\"], [\"Bicolor (exterior azul oscuro, color de la tapa abajo)\", \"C\"]], \"drumtainer_kleur\": [[\"Gris\", \"103\"], [\"Verde\", \"303\"], [\"Amarillo\", \"698\"], [\"Azul oscuro\", \"709\"], [\"Azul claro\", \"753\"], [\"Rojo\", \"892\"]]}, \"pl\": {\"type\": [[\"VARIBOX FC 1000\", \"VB1001\"], [\"VARIBOX FC 1000 + Connect+\", \"VC1001\"], [\"VARIBOX FC 800\", \"VB0801\"], [\"VARIBOX FC 800 + Connect+\", \"VC0801\"], [\"VARIBOX CC 250\", \"VB0250\"], [\"VARIBOX CC 250 + Connect+\", \"VC0250\"], [\"VARIBOX CC 250 ISPM\", \"VB0251\"], [\"VARIBOX CC 250 ISPM + Connect+\", \"VC0251\"], [\"Wk\u0142ad wewn\u0119trzny - zestaw zamienny VARIBOX FC 1000\", \"VI1001\"], [\"Wk\u0142ad wewn\u0119trzny - zestaw zamienny VARIBOX FC 1000 + Connect+\", \"VK1001\"], [\"Wk\u0142ad wewn\u0119trzny - zestaw zamienny VARIBOX FC 800\", \"VI0801\"], [\"Wk\u0142ad wewn\u0119trzny - zestaw zamienny VARIBOX FC 800 + Connect+\", \"VK0801\"], [\"VARIBOX Drumtainer\", \"DT0200\"]], \"pakking\": [[\"EPDM\", \"A\"], [\"Viton\", \"B\"], [\"EPDM z palet\u0105 ISPM (tylko VARIBOX 250)\", \"D\"], [\"EPDM z palet\u0105 ISPM (tylko VARIBOX 250)\", \"F\"], [\"Viton z palet\u0105 ISPM (tylko VARIBOX 250)\", \"E\"]], \"zuigbuis_venting\": [[\"Bez rurki zasysaj\u0105cej + Combivent (EPDM)\", \"B\"], [\"Bez rurki zasysaj\u0105cej + Combivent (Viton)\", \"B\"], [\"Bez rurki zasysaj\u0105cej + odpowietrznik (EPDM)\", \"L\"], [\"Bez rurki zasysaj\u0105cej + odpowietrznik (Viton)\", \"L\"], [\"Safeline Performance + Combivent (EPDM)\", \"C\"], [\"Safeline Performance Food + Combivent (EPDM)\", \"K\"], [\"Safeline Performance + Combivent (Viton)\", \"V\"], [\"Safeline Performance + odpowietrznik (EPDM)\", \"E\"], [\"Safeline Performance Food + odpowietrznik (EPDM)\", \"P\"], [\"Safeline Performance + odpowietrznik (Viton)\", \"W\"], [\"Quick Connector + Combivent (EPDM)\", \"R\"], [\"Quick Connector + Combivent (Viton)\", \"R\"], [\"Quick Connector + odpowietrznik (EPDM)\", \"S\"], [\"Quick Connector + odpowietrznik (Viton)\", \"S\"], [\"Safeline Precision + Combivent (EPDM)\", \"Y\"], [\"Safeline Precision + Combivent (Viton)\", \"Y\"], [\"Safeline Precision + odpowietrznik (EPDM)\", \"Z\"], [\"Safeline Precision + odpowietrznik (Viton)\", \"Z\"], [\"CDS zaw\u00f3r stopowy D14 + Combivent, okr\u0105g\u0142y (Viton)\", \"D\"], [\"CDS zaw\u00f3r stopowy D14 + odpowietrznik, okr\u0105g\u0142y (Viton)\", \"M\"], [\"Ecolab CDS specjalny + Combivent (EPDM)\", \"T\"], [\"Ecolab CDS specjalny + Combivent (Viton)\", \"T\"], [\"Ecolab CDS specjalny + odpowietrznik (EPDM)\", \"U\"], [\"Ecolab CDS specjalny + odpowietrznik (Viton)\", \"U\"], [\"Ecolab, bez rurki zasysaj\u0105cej + Combivent (EPDM)\", \"D\"], [\"Ecolab, bez rurki zasysaj\u0105cej + Combivent (Viton)\", \"G\"], [\"Ecolab, bez rurki zasysaj\u0105cej + odpowietrznik (EPDM)\", \"H\"], [\"Ecolab, bez rurki zasysaj\u0105cej + odpowietrznik (Viton)\", \"J\"], [\"AS QC2 + Combivent (EPDM)\", \"I\"], [\"AS QC2 + odpowietrznik (EPDM)\", \"N\"], [\"AS GT2 + Combivent (EPDM)\", \"X\"], [\"AS GT2 + odpowietrznik (EPDM)\", \"F\"]], \"levelsensor\": [[\"Brak czujnik\u00f3w\", \"A\"], [\"Czujnik pustego zbiornika\", \"B\"], [\"Czujnik pe\u0142nego zbiornika\", \"D\"], [\"Czujnik pustego zbiornika + czujnik pe\u0142nego zbiornika\", \"C\"], [\"Czujnik niskiego poziomu\", \"E\"], [\"Czujnik niskiego poziomu + czujnik pe\u0142nego zbiornika\", \"J\"]], \"levelsensor_vervanging\": [[\"Brak czujnik\u00f3w (zestaw zamienny)\", \"A\"], [\"Czujnik pustego zbiornika (zestaw zamienny)\", \"B\"], [\"Czujnik pe\u0142nego zbiornika (zestaw zamienny)\", \"D\"], [\"Czujnik pustego zbiornika + czujnik pe\u0142nego zbiornika (zestaw zamienny)\", \"C\"], [\"Czujnik niskiego poziomu (zestaw zamienny)\", \"E\"], [\"Czujnik niskiego poziomu + czujnik pe\u0142nego zbiornika (zestaw zamienny)\", \"J\"]], \"kleur\": [[\"Naturalny\", \"000\"], [\"Zielony\", \"303\"], [\"\u017b\u00f3\u0142ty\", \"698\"], [\"Ciemnoniebieski\", \"709\"], [\"Jasnoniebieski\", \"753\"], [\"Pomara\u0144czowy\", \"887\"], [\"Czerwony\", \"892\"]], \"special\": [[\"CDS zaw\u00f3r stopowy D14 + powr\u00f3t\", \"I\"], [\"Colder DQ PRO\", \"H\"], [\"Camlock 2D F + Combivent (EPDM)\", \"N\"], [\"Camlock 2D F + odpowietrznik (EPDM)\", \"P\"], [\"Camlock 2D M + Combivent (Viton)\", \"O\"], [\"Camlock 2D M + odpowietrznik (Viton)\", \"Q\"], [\"Czujnik pustego zbiornika SealedAir\", \"G\"], [\"Ecolab 411925\", \"C\"], [\"Ecolab 411920\", \"D\"], [\"Ecolab 411922\", \"E\"], [\"Ecolab 411917\", \"F\"], [\"Ecolab 411923\", \"G\"], [\"Ecolab 411928\", \"H\"], [\"Ecolab 411930\", \"I\"], [\"Ecolab 411919\", \"J\"], [\"Ecolab 411931\", \"K\"], [\"Ecolab 411932\", \"L\"], [\"Ecolab 411933\", \"M\"], [\"Ecolab 411927\", \"N\"], [\"Ecolab 411929\", \"O\"], [\"Ecolab 411924\", \"P\"], [\"Ecolab 412436\", \"Q\"], [\"Ecolab 412438\", \"R\"], [\"Ecolab 412584\", \"S\"], [\"Ecolab 412583\", \"T\"], [\"Ecolab 412791\", \"U\"], [\"Ecolab 413261\", \"V\"], [\"AS Quickconnect + Combivent\", \"J\"], [\"AS Quickconnect + odpowietrznik\", \"K\"], [\"AS Quickconnect + powr\u00f3t\", \"G\"]], \"drumtainer_pallet\": [[\"Dostawa na ko\u0142ach (bez palety)\", \"B\"], [\"Dostawa na palecie ISPM\", \"C\"], [\"Dostawa na palecie ISPM, wersja webshop (z workiem)\", \"W\"]], \"drumtainer_trailer\": [[\"Standardowy\", \"A\"], [\"Trailer\", \"B\"]], \"drumtainer_combo\": [[\"Jeden kolor\", \"A\"], [\"Dwukolorowy (jasnoniebieska zewn\u0119trzna cz\u0119\u015b\u0107, kolor pokrywy poni\u017cej)\", \"B\"], [\"Dwukolorowy (ciemnoniebieska zewn\u0119trzna cz\u0119\u015b\u0107, kolor pokrywy poni\u017cej)\", \"C\"]], \"drumtainer_kleur\": [[\"Szary\", \"103\"], [\"Zielony\", \"303\"], [\"\u017b\u00f3\u0142ty\", \"698\"], [\"Ciemnoniebieski\", \"709\"], [\"Jasnoniebieski\", \"753\"], [\"Czerwony\", \"892\"]]}};\nconst STRINGS = {\"nl\": {\"title\": \"Welke VARIBOX-variant heb ik?\",\"intro\": \"Voer uw serienummer in (8 tekens, te vinden op het typeplaatje van uw VARIBOX) \u2014 of het volledige artikelnummer (12 tekens, te vinden op de orderbevestiging of factuur) \u2014 en bekijk direct welke uitvoering dit is.\",\"placeholder\": \"bv. VB1001AED709\",\"button\": \"Check artikelnummer\",\"exampleIntro\": \"Nog geen artikelnummer bij de hand?\",\"exampleBtn\": \"Bekijk een voorbeeld\",\"labelType\": \"Type \/ volume\",\"labelPakking\": \"Pakkingmateriaal\",\"labelZuigbuis\": \"Zuigbuis \/ ontluchting\",\"labelSensor\": \"Niveausensor\",\"labelKleur\": \"Kleur\",\"labelFoodContact\": \"Food contact\",\"yesWord\": \"Ja\",\"noWord\": \"Nee\",\"labelPallet\": \"Levering\",\"labelTrailer\": \"Trailer\",\"labelCombo\": \"Kleurcombinatie\",\"labelDIBt\": \"DIBt-goedkeuring\",\"labelADR\": \"ADR-regelgeving\",\"labelVibration\": \"Trillingstest\",\"dtNotApplicable\": \"Niet van toepassing (Trailer-uitvoering)\",\"labelUN\": \"UN-certificeringsnummer\",\"errorLength\": \"Vul een artikelnummer (12 tekens) of serienummer (8 tekens) in. Deze invoer heeft {n} teken(s). Voorbeeld artikelnummer: VB1001AED709, voorbeeld serienummer: M1234567.\",\"errorUnknownSerial\": \"Dit serienummer herkennen wij niet. Controleer of u het volledig en correct heeft overgenomen, of neem contact op met VARIBOX Customer Service (+31 (0)570 660711, info@varibox-ibc.com).\",\"serialMatchNote\": \"Herkend via serienummer {serial}\",\"errorUnknownType\": \"Dit artikelnummer herkennen wij niet. Controleer of u het volledig en correct heeft overgenomen, of neem contact op met VARIBOX Customer Service (+31 (0)570 660711, info@varibox-ibc.com).\",\"unknownCode\": \"Onbekende code \u2014 herkennen wij niet.\",\"noteAmbiguousPakking\": \"Let op: deze pakkingsoorten hebben dezelfde code. Controleer het typeplaatje of de Declaration of Compliance om vast te stellen of dit een Food-uitvoering betreft.\",\"noteSpecialAlt\": \"Mogelijk ook een speciale optie:\",\"noteSpecialAltExplain\": \"Dit veld wordt gebruikt voor niet-standaard\/Special-configuraties in plaats van het standaard pakkingmateriaal. Alleen relevant als dit geen standaard EPDM\/Food\/Viton-uitvoering is.\",\"noteZuigbuisAmbiguous\": \"Deze code komt voor bij meerdere pakkingmaterialen ({materials}). Gebruik het pakkingveld hieronder om te bepalen welke van toepassing is.\",\"footerNote\": \"Twijfelt u over de uitkomst, of komt een combinatie u onbekend voor? Neem contact op met VARIBOX Customer Service (+31 (0)570 660711, info@varibox-ibc.com).\",\"orWord\": \"of\",\"langLabel\": \"Taal\",\"sparePartsNote\": \"Op zoek naar losse onderdelen zoals zuigbuizen, contra koppelingen of sensoren?\",\"sparePartsLink\": \"Bekijk onderdelen in de webshop\",\"foodDocLabel\": \"Download Declaration of Compliance (PDF)\",\"foodContactInfo\": \"Food contact-goedkeuring geldt alleen bij de EPDM-uitvoering, zonder gemonteerde sensoren, met een Safeline Performance Food-, AS QC2- of AS GT2-zuigbuis (of geen zuigbuis), in combinatie met de nieuwe blauwe VARIBOX FC en CC ontluchter. Dit geldt voor containers geproduceerd na 1 oktober 2021; voor eerdere producties kan dit niet via deze tool worden gecontroleerd.\",\"foodContactInfoLink\": \"Meer informatie\",\"bulkHint\": \"Tip: u kunt ook meerdere artikel- of serienummers tegelijk plakken, \u00e9\u00e9n per regel (max. 25 regels).\",\"bulkSummary\": \"{ok} van {total} nummers herkend\",\"bulkTruncated\": \" Alleen de eerste {max} regels zijn verwerkt.\",\"groupNote\": \"Deze configuratie is herkend voor {count} nummers: {list}.\",\"groupNoteMore\": \" en {more} andere\",\"emailResultButton\": \"Mail dit resultaat\",\"emailFormNameLabel\": \"Naam\",\"emailFormEmailLabel\": \"E-mailadres\",\"emailFormPhoneLabel\": \"Telefoonnummer\",\"emailFormCompanyLabel\": \"Bedrijfsnaam\",\"emailFormSubmit\": \"Versturen\",\"emailFormCancel\": \"Annuleren\",\"emailFormSuccess\": \"Verzonden! U ontvangt het resultaat per e-mail.\",\"emailFormError\": \"Vul minimaal uw naam en e-mailadres in.\",\"emailFormMissingForm\": \"Er ging iets mis. Neem contact op met Customer Service.\",\"quoteFormSubmit\": \"Offerte aanvragen\",\"quoteFormSuccess\": \"Verzonden! Ons salesteam neemt contact met u op.\",\"quoteFormError\": \"Vul minimaal uw naam en e-mailadres in.\",\"quoteFormMissingForm\": \"Er ging iets mis. Neem contact op met Customer Service.\",\"quantityLabel\": \"Aantal\",\"combinedQuoteTitle\": \"Volgende stappen\",\"combinedQuoteIntro\": \"Vraag een offerte aan voor deze resultaten, of ontvang ze rechtstreeks per e-mail.\",\"requestQuoteButton\": \"Vraag uw offerte aan\",\"quoteFormCancel\": \"Annuleren\",\"copyLabel\": \"Kopieer code\",\"copiedLabel\": \"Gekopieerd!\",\"quantityDecrease\": \"Aantal verlagen\",\"quantityIncrease\": \"Aantal verhogen\",\"clearInputLabel\": \"Veld wissen\",\"partsButtonLabel\": \"Bestel bijbehorende onderdelen\",\"partsPopupTitle\": \"Beschikbare onderdelen voor deze uitvoering\",\"partsPopupIntro\": \"Vink aan wat u wilt bestellen en voeg het direct toe aan uw winkelwagen.\",\"partsRoleZuigbuis\": \"Zuigbuis\",\"partsRoleSensor\": \"Sensor\",\"partsRoleDeksel\": \"Deksel + ontluchting\",\"partsUnavailable\": \"Nog niet apart te bestellen\",\"partsContactLink\": \"Neem contact op\",\"partsAddToCartButton\": \"Voeg toe aan winkelwagen\",\"partsAddToCartSuccess\": \"Toegevoegd aan uw winkelwagen.\",\"partsNoneSelected\": \"Selecteer minimaal \u00e9\u00e9n onderdeel.\",\"partsRoleCoupler\": \"Contra koppeling voor de zuigbuis\",\"partsRoleCap\": \"Afdekkap voor de zuigbuis\",\"partsRoleSensorConnector\": \"Stekkerset\",\"partsRoleSensorCounterConnector\": \"Contra stekker (aansluiting op uw eigen systeem)\",\"partsBuiltInHeader\": \"Ingebouwde onderdelen\",\"partsExtraHeader\": \"Extra accessoires\",\"partsRoleSensorConnectorSet\": \"Complete stekkerset voor volmelder, leegmelder of voormelder (stekker + contra stekker)\",\"partsViewCartButton\": \"Bekijk winkelwagen\",\"partsAddAllButton\": \"Voeg alle geselecteerde onderdelen in \u00e9\u00e9n keer toe\",\"quotePartsSectionTitle\": \"Geselecteerde losse onderdelen\",\"partsOutOfStock\": \"Tijdelijk niet op voorraad\",\"partsSubtotalLabel\": \"Subtotaal\",\"partsGrandTotalLabel\": \"Totaal (alle resultaten)\",\"partsCoverageLabel\": \"{available} van de {total} onderdelen beschikbaar\",\"shareLinkLabel\": \"Kopieer link naar dit resultaat\",\"shareLinkCopiedLabel\": \"Link gekopieerd!\",\"toastSessionCount\": \"{count} stuk(s) deze sessie toegevoegd\"},\"en\": {\"title\": \"Which VARIBOX version do I have?\",\"intro\": \"Enter your serial number (8 characters, found on the type plate of your VARIBOX) \u2014 or the full article number (12 characters, found on the order confirmation or invoice) \u2014 to see which version this is.\",\"placeholder\": \"e.g. VB1001AED709\",\"button\": \"Check article number\",\"exampleIntro\": \"Don't have an article number to hand?\",\"exampleBtn\": \"View an example\",\"labelType\": \"Type \/ volume\",\"labelPakking\": \"Gasket material\",\"labelZuigbuis\": \"Extractor tube \/ venting\",\"labelSensor\": \"Level sensor\",\"labelKleur\": \"Colour\",\"labelFoodContact\": \"Food contact\",\"yesWord\": \"Yes\",\"noWord\": \"No\",\"labelPallet\": \"Delivery\",\"labelTrailer\": \"Trailer\",\"labelCombo\": \"Colour combination\",\"labelDIBt\": \"DIBt approval\",\"labelADR\": \"ADR regulation\",\"labelVibration\": \"Vibration test\",\"dtNotApplicable\": \"Not applicable (Trailer version)\",\"labelUN\": \"UN certification number\",\"errorLength\": \"Enter an article number (12 characters) or serial number (8 characters). This entry has {n} character(s). Example article number: VB1001AED709, example serial number: M1234567.\",\"errorUnknownSerial\": \"We don't recognise this serial number. Please check that you've entered it fully and correctly, or contact VARIBOX Customer Service (+31 (0)570 660711, info@varibox-ibc.com).\",\"serialMatchNote\": \"Matched via serial number {serial}\",\"errorUnknownType\": \"We don't recognise this article number. Please check that you've entered it fully and correctly, or contact VARIBOX Customer Service (+31 (0)570 660711, info@varibox-ibc.com).\",\"unknownCode\": \"Unknown code \u2014 not recognised.\",\"noteAmbiguousPakking\": \"Note: these gasket types share the same code. Check the type plate or the Declaration of Compliance to confirm whether this is a Food version.\",\"noteSpecialAlt\": \"May also be a special option:\",\"noteSpecialAltExplain\": \"This field is used for non-standard\/special configurations instead of the standard gasket material. Only relevant if this is not a standard EPDM\/Food\/Viton version.\",\"noteZuigbuisAmbiguous\": \"This code occurs for multiple gasket materials ({materials}). Use the gasket field below to determine which applies.\",\"footerNote\": \"Not sure about the result, or is a combination unfamiliar to you? Contact VARIBOX Customer Service (+31 (0)570 660711, info@varibox-ibc.com).\",\"orWord\": \"or\",\"langLabel\": \"Language\",\"sparePartsNote\": \"Looking for individual parts such as extractor tubes, counter couplings or sensors?\",\"sparePartsLink\": \"View parts in the webshop\",\"foodDocLabel\": \"Download Declaration of Compliance (PDF)\",\"foodContactInfo\": \"Food-contact approval only applies to the EPDM version, without any sensors fitted, with a Safeline Performance Food, AS QC2 or AS GT2 extractor tube (or none fitted), in combination with the new blue VARIBOX FC and CC overpressure vent. This applies to containers produced after 1 October 2021; for earlier production dates this cannot be checked using this tool.\",\"foodContactInfoLink\": \"More information\",\"bulkHint\": \"Tip: you can also paste several article or serial numbers at once, one per line (max. 25 lines).\",\"bulkSummary\": \"{ok} of {total} numbers recognised\",\"bulkTruncated\": \" Only the first {max} lines were processed.\",\"groupNote\": \"This configuration was recognised for {count} numbers: {list}.\",\"groupNoteMore\": \" and {more} more\",\"emailResultButton\": \"Email this result\",\"emailFormNameLabel\": \"Name\",\"emailFormEmailLabel\": \"Email address\",\"emailFormPhoneLabel\": \"Phone number\",\"emailFormCompanyLabel\": \"Company name\",\"emailFormSubmit\": \"Send\",\"emailFormCancel\": \"Cancel\",\"emailFormSuccess\": \"Sent! You'll receive the result by email.\",\"emailFormError\": \"Please enter at least your name and email address.\",\"emailFormMissingForm\": \"Something went wrong. Please contact Customer Service.\",\"quoteFormSubmit\": \"Request quote\",\"quoteFormSuccess\": \"Sent! Our sales team will get in touch with you.\",\"quoteFormError\": \"Please enter at least your name and email address.\",\"quoteFormMissingForm\": \"Something went wrong. Please contact Customer Service.\",\"quantityLabel\": \"Quantity\",\"combinedQuoteTitle\": \"Next steps\",\"combinedQuoteIntro\": \"Request a quote for these results, or receive them directly by email.\",\"requestQuoteButton\": \"Request your quote\",\"quoteFormCancel\": \"Cancel\",\"copyLabel\": \"Copy code\",\"copiedLabel\": \"Copied!\",\"quantityDecrease\": \"Decrease quantity\",\"quantityIncrease\": \"Increase quantity\",\"clearInputLabel\": \"Clear field\",\"partsButtonLabel\": \"Order matching parts\",\"partsPopupTitle\": \"Available parts for this configuration\",\"partsPopupIntro\": \"Check what you'd like to order and add it straight to your cart.\",\"partsRoleZuigbuis\": \"Extractor tube\",\"partsRoleSensor\": \"Sensor\",\"partsRoleDeksel\": \"Lid + venting\",\"partsUnavailable\": \"Not yet available as a separate item\",\"partsContactLink\": \"Contact us\",\"partsAddToCartButton\": \"Add to cart\",\"partsAddToCartSuccess\": \"Added to your cart.\",\"partsNoneSelected\": \"Select at least one part.\",\"partsRoleCoupler\": \"Counter coupling for the extractor tube\",\"partsRoleCap\": \"Cover cap for the extractor tube\",\"partsRoleSensorConnector\": \"Plug set\",\"partsRoleSensorCounterConnector\": \"Counter plug (connects to your own system)\",\"partsBuiltInHeader\": \"Built-in components\",\"partsExtraHeader\": \"Additional accessories\",\"partsRoleSensorConnectorSet\": \"Complete plug set for full, empty or low-level sensor (plug + counter plug)\",\"partsViewCartButton\": \"View cart\",\"partsAddAllButton\": \"Add all selected parts at once\",\"quotePartsSectionTitle\": \"Selected individual parts\",\"partsOutOfStock\": \"Currently out of stock\",\"partsSubtotalLabel\": \"Subtotal\",\"partsGrandTotalLabel\": \"Total (all results)\",\"partsCoverageLabel\": \"{available} of {total} parts available\",\"shareLinkLabel\": \"Copy link to this result\",\"shareLinkCopiedLabel\": \"Link copied!\",\"toastSessionCount\": \"{count} item(s) added this session\"},\"de\": {\"title\": \"Welche VARIBOX-Version habe ich?\",\"intro\": \"Geben Sie Ihre Seriennummer ein (8 Zeichen, zu finden auf dem Typenschild Ihrer VARIBOX) \u2014 oder die vollst\u00e4ndige Artikelnummer (12 Zeichen, zu finden auf der Auftragsbest\u00e4tigung oder Rechnung) \u2014, um zu sehen, um welche Ausf\u00fchrung es sich handelt.\",\"placeholder\": \"z. B. VB1001AED709\",\"button\": \"Artikelnummer pr\u00fcfen\",\"exampleIntro\": \"Keine Artikelnummer zur Hand?\",\"exampleBtn\": \"Beispiel ansehen\",\"labelType\": \"Typ \/ Volumen\",\"labelPakking\": \"Dichtungsmaterial\",\"labelZuigbuis\": \"Steigrohr \/ Entl\u00fcftung\",\"labelSensor\": \"F\u00fcllstandssensor\",\"labelKleur\": \"Farbe\",\"labelFoodContact\": \"Lebensmittelkontakt\",\"yesWord\": \"Ja\",\"noWord\": \"Nein\",\"labelPallet\": \"Lieferung\",\"labelTrailer\": \"Trailer\",\"labelCombo\": \"Farbkombination\",\"labelDIBt\": \"DIBt-Zulassung\",\"labelADR\": \"ADR-Vorschrift\",\"labelVibration\": \"Vibrationspr\u00fcfung\",\"dtNotApplicable\": \"Nicht zutreffend (Trailer-Version)\",\"labelUN\": \"UN-Zertifizierungsnummer\",\"errorLength\": \"Geben Sie eine Artikelnummer (12 Zeichen) oder Seriennummer (8 Zeichen) ein. Diese Eingabe hat {n} Zeichen. Beispiel Artikelnummer: VB1001AED709, Beispiel Seriennummer: M1234567.\",\"errorUnknownSerial\": \"Diese Seriennummer erkennen wir nicht. Bitte pr\u00fcfen Sie, ob Sie sie vollst\u00e4ndig und korrekt eingegeben haben, oder wenden Sie sich an den VARIBOX-Kundendienst (+31 (0)570 660711, info@varibox-ibc.com).\",\"serialMatchNote\": \"\u00dcber Seriennummer {serial} erkannt\",\"errorUnknownType\": \"Diese Artikelnummer erkennen wir nicht. Bitte pr\u00fcfen Sie, ob Sie sie vollst\u00e4ndig und korrekt eingegeben haben, oder wenden Sie sich an den VARIBOX-Kundendienst (+31 (0)570 660711, info@varibox-ibc.com).\",\"unknownCode\": \"Unbekannter Code \u2014 nicht erkannt.\",\"noteAmbiguousPakking\": \"Hinweis: Diese Dichtungsmaterialien verwenden denselben Code. Pr\u00fcfen Sie das Typenschild oder die Konformit\u00e4tserkl\u00e4rung, um festzustellen, ob es sich um eine Food-Ausf\u00fchrung handelt.\",\"noteSpecialAlt\": \"M\u00f6glicherweise auch eine Sonderoption:\",\"noteSpecialAltExplain\": \"Dieses Feld wird f\u00fcr nicht standardm\u00e4\u00dfige\/Sonderkonfigurationen anstelle des Standard-Dichtungsmaterials verwendet. Nur relevant, wenn es sich nicht um eine Standard-EPDM\/Food\/Viton-Ausf\u00fchrung handelt.\",\"noteZuigbuisAmbiguous\": \"Dieser Code kommt bei mehreren Dichtungsmaterialien vor ({materials}). Nutzen Sie das Feld Dichtungsmaterial unten, um zu bestimmen, welches zutrifft.\",\"footerNote\": \"Sind Sie sich beim Ergebnis nicht sicher, oder ist Ihnen eine Kombination unbekannt? Wenden Sie sich an den VARIBOX-Kundendienst (+31 (0)570 660711, info@varibox-ibc.com).\",\"orWord\": \"oder\",\"langLabel\": \"Sprache\",\"sparePartsNote\": \"Suchen Sie Einzelteile wie Steigrohre, Gegenkupplungen oder Sensoren?\",\"sparePartsLink\": \"Teile im Webshop ansehen\",\"foodDocLabel\": \"Konformit\u00e4tserkl\u00e4rung herunterladen (PDF)\",\"foodContactInfo\": \"Die Lebensmittelkontakt-Zulassung gilt nur f\u00fcr die EPDM-Ausf\u00fchrung, ohne montierte Sensoren, mit einem Safeline Performance Food-, AS QC2- oder AS GT2-Steigrohr (oder ohne Steigrohr), in Kombination mit dem neuen blauen VARIBOX FC- und CC-Entl\u00fcfter. Dies gilt f\u00fcr Beh\u00e4lter, die nach dem 1. Oktober 2021 hergestellt wurden; f\u00fcr fr\u00fchere Produktionen kann dies mit diesem Tool nicht \u00fcberpr\u00fcft werden.\",\"foodContactInfoLink\": \"Weitere Informationen\",\"bulkHint\": \"Tipp: Sie k\u00f6nnen auch mehrere Artikel- oder Seriennummern gleichzeitig einf\u00fcgen, eine pro Zeile (max. 25 Zeilen).\",\"bulkSummary\": \"{ok} von {total} Nummern erkannt\",\"bulkTruncated\": \" Es wurden nur die ersten {max} Zeilen verarbeitet.\",\"groupNote\": \"Diese Konfiguration wurde f\u00fcr {count} Nummern erkannt: {list}.\",\"groupNoteMore\": \" und {more} weitere\",\"emailResultButton\": \"Ergebnis per E-Mail senden\",\"emailFormNameLabel\": \"Name\",\"emailFormEmailLabel\": \"E-Mail-Adresse\",\"emailFormPhoneLabel\": \"Telefonnummer\",\"emailFormCompanyLabel\": \"Firmenname\",\"emailFormSubmit\": \"Senden\",\"emailFormCancel\": \"Abbrechen\",\"emailFormSuccess\": \"Gesendet! Sie erhalten das Ergebnis per E-Mail.\",\"emailFormError\": \"Bitte geben Sie mindestens Ihren Namen und Ihre E-Mail-Adresse ein.\",\"emailFormMissingForm\": \"Etwas ist schiefgelaufen. Bitte wenden Sie sich an den Kundendienst.\",\"quoteFormSubmit\": \"Angebot anfordern\",\"quoteFormSuccess\": \"Gesendet! Unser Vertriebsteam meldet sich bei Ihnen.\",\"quoteFormError\": \"Bitte geben Sie mindestens Ihren Namen und Ihre E-Mail-Adresse ein.\",\"quoteFormMissingForm\": \"Etwas ist schiefgelaufen. Bitte wenden Sie sich an den Kundendienst.\",\"quantityLabel\": \"Menge\",\"combinedQuoteTitle\": \"N\u00e4chste Schritte\",\"combinedQuoteIntro\": \"Fordern Sie ein Angebot f\u00fcr diese Ergebnisse an, oder erhalten Sie sie direkt per E-Mail.\",\"requestQuoteButton\": \"Angebot anfordern\",\"quoteFormCancel\": \"Abbrechen\",\"copyLabel\": \"Code kopieren\",\"copiedLabel\": \"Kopiert!\",\"quantityDecrease\": \"Menge verringern\",\"quantityIncrease\": \"Menge erh\u00f6hen\",\"clearInputLabel\": \"Feld leeren\",\"partsButtonLabel\": \"Passende Teile bestellen\",\"partsPopupTitle\": \"Verf\u00fcgbare Ersatzteile f\u00fcr diese Ausf\u00fchrung\",\"partsPopupIntro\": \"W\u00e4hlen Sie aus, was Sie bestellen m\u00f6chten, und f\u00fcgen Sie es direkt Ihrem Warenkorb hinzu.\",\"partsRoleZuigbuis\": \"Steigrohr\",\"partsRoleSensor\": \"Sensor\",\"partsRoleDeksel\": \"Deckel + Entl\u00fcftung\",\"partsUnavailable\": \"Noch nicht separat bestellbar\",\"partsContactLink\": \"Kontakt aufnehmen\",\"partsAddToCartButton\": \"In den Warenkorb legen\",\"partsAddToCartSuccess\": \"Zum Warenkorb hinzugef\u00fcgt.\",\"partsNoneSelected\": \"W\u00e4hlen Sie mindestens ein Teil aus.\",\"partsRoleCoupler\": \"Gegenkupplung f\u00fcr das Steigrohr\",\"partsRoleCap\": \"Abdeckkappe f\u00fcr das Steigrohr\",\"partsRoleSensorConnector\": \"Steckersatz\",\"partsRoleSensorCounterConnector\": \"Gegenstecker (Anschluss an Ihr eigenes System)\",\"partsBuiltInHeader\": \"Verbaute Komponenten\",\"partsExtraHeader\": \"Zus\u00e4tzliches Zubeh\u00f6r\",\"partsRoleSensorConnectorSet\": \"Kompletter Stecker-Satz f\u00fcr Vollmelder, Leermelder oder Vorwarnmelder (Stecker + Gegenstecker)\",\"partsViewCartButton\": \"Warenkorb ansehen\",\"partsAddAllButton\": \"Alle ausgew\u00e4hlten Teile auf einmal hinzuf\u00fcgen\",\"quotePartsSectionTitle\": \"Ausgew\u00e4hlte Einzelteile\",\"partsOutOfStock\": \"Vor\u00fcbergehend nicht auf Lager\",\"partsSubtotalLabel\": \"Zwischensumme\",\"partsGrandTotalLabel\": \"Gesamtsumme (alle Ergebnisse)\",\"partsCoverageLabel\": \"{available} von {total} Teilen verf\u00fcgbar\",\"shareLinkLabel\": \"Link zu diesem Ergebnis kopieren\",\"shareLinkCopiedLabel\": \"Link kopiert!\",\"toastSessionCount\": \"{count} St\u00fcck in dieser Sitzung hinzugef\u00fcgt\"},\"fr\": {\"title\": \"Quelle version de VARIBOX ai-je ?\",\"intro\": \"Saisissez votre num\u00e9ro de s\u00e9rie (8 caract\u00e8res, indiqu\u00e9 sur la plaque signal\u00e9tique de votre VARIBOX) \u2014 ou le num\u00e9ro d'article complet (12 caract\u00e8res, indiqu\u00e9 sur la confirmation de commande ou la facture) \u2014 pour conna\u00eetre la version exacte.\",\"placeholder\": \"ex. VB1001AED709\",\"button\": \"V\u00e9rifier le num\u00e9ro d'article\",\"exampleIntro\": \"Vous n'avez pas de num\u00e9ro d'article sous la main ?\",\"exampleBtn\": \"Voir un exemple\",\"labelType\": \"Type \/ volume\",\"labelPakking\": \"Mat\u00e9riau du joint\",\"labelZuigbuis\": \"Tube d'aspiration \/ mise \u00e0 l'air\",\"labelSensor\": \"Capteur de niveau\",\"labelKleur\": \"Couleur\",\"labelFoodContact\": \"Contact alimentaire\",\"yesWord\": \"Oui\",\"noWord\": \"Non\",\"labelPallet\": \"Livraison\",\"labelTrailer\": \"Trailer\",\"labelCombo\": \"Combinaison de couleurs\",\"labelDIBt\": \"Agr\u00e9ment DIBt\",\"labelADR\": \"R\u00e9glementation ADR\",\"labelVibration\": \"Essai de vibration\",\"dtNotApplicable\": \"Non applicable (version Trailer)\",\"labelUN\": \"Num\u00e9ro de certification UN\",\"errorLength\": \"Saisissez un num\u00e9ro d'article (12 caract\u00e8res) ou un num\u00e9ro de s\u00e9rie (8 caract\u00e8res). Cette saisie comporte {n} caract\u00e8re(s). Exemple de num\u00e9ro d'article : VB1001AED709, exemple de num\u00e9ro de s\u00e9rie : M1234567.\",\"errorUnknownSerial\": \"Nous ne reconnaissons pas ce num\u00e9ro de s\u00e9rie. V\u00e9rifiez que vous l'avez saisi enti\u00e8rement et correctement, ou contactez le service client VARIBOX (+31 (0)570 660711, info@varibox-ibc.com).\",\"serialMatchNote\": \"Identifi\u00e9 via le num\u00e9ro de s\u00e9rie {serial}\",\"errorUnknownType\": \"Nous ne reconnaissons pas ce num\u00e9ro d'article. V\u00e9rifiez que vous l'avez saisi enti\u00e8rement et correctement, ou contactez le service client VARIBOX (+31 (0)570 660711, info@varibox-ibc.com).\",\"unknownCode\": \"Code inconnu \u2014 non reconnu.\",\"noteAmbiguousPakking\": \"Attention : ces types de joint partagent le m\u00eame code. V\u00e9rifiez la plaque signal\u00e9tique ou la d\u00e9claration de conformit\u00e9 pour d\u00e9terminer s'il s'agit d'une version Food.\",\"noteSpecialAlt\": \"Peut \u00e9galement correspondre \u00e0 une option sp\u00e9ciale :\",\"noteSpecialAltExplain\": \"Ce champ est utilis\u00e9 pour des configurations non standard\/sp\u00e9ciales \u00e0 la place du mat\u00e9riau de joint standard. Pertinent uniquement si ce n'est pas une version standard EPDM\/Food\/Viton.\",\"noteZuigbuisAmbiguous\": \"Ce code existe pour plusieurs mat\u00e9riaux de joint ({materials}). Utilisez le champ mat\u00e9riau de joint ci-dessous pour d\u00e9terminer lequel s'applique.\",\"footerNote\": \"Vous n'\u00eates pas s\u00fbr du r\u00e9sultat, ou une combinaison vous est inconnue ? Contactez le service client VARIBOX (+31 (0)570 660711, info@varibox-ibc.com).\",\"orWord\": \"ou\",\"langLabel\": \"Langue\",\"sparePartsNote\": \"Vous cherchez des pi\u00e8ces d\u00e9tach\u00e9es telles que des tubes d'aspiration, raccords compl\u00e9mentaires ou capteurs ?\",\"sparePartsLink\": \"Voir les pi\u00e8ces dans la boutique en ligne\",\"foodDocLabel\": \"T\u00e9l\u00e9charger la d\u00e9claration de conformit\u00e9 (PDF)\",\"foodContactInfo\": \"L'approbation de contact alimentaire ne s'applique qu'\u00e0 la version EPDM, sans capteur install\u00e9, avec un tube d'aspiration Safeline Performance Food, AS QC2 ou AS GT2 (ou aucun tube), en association avec le nouvel \u00c9vent de surpression bleu VARIBOX FC et CC. Cela s'applique aux conteneurs fabriqu\u00e9s apr\u00e8s le 1er octobre 2021 ; pour les productions ant\u00e9rieures, cela ne peut pas \u00eatre v\u00e9rifi\u00e9 via cet outil.\",\"foodContactInfoLink\": \"Plus d'informations\",\"bulkHint\": \"Astuce : vous pouvez aussi coller plusieurs num\u00e9ros d'article ou de s\u00e9rie en m\u00eame temps, un par ligne (max. 25 lignes).\",\"bulkSummary\": \"{ok} num\u00e9ro(s) reconnu(s) sur {total}\",\"bulkTruncated\": \" Seules les {max} premi\u00e8res lignes ont \u00e9t\u00e9 trait\u00e9es.\",\"groupNote\": \"Cette configuration a \u00e9t\u00e9 reconnue pour {count} num\u00e9ros : {list}.\",\"groupNoteMore\": \" et {more} autres\",\"emailResultButton\": \"Envoyer ce r\u00e9sultat par e-mail\",\"emailFormNameLabel\": \"Nom\",\"emailFormEmailLabel\": \"Adresse e-mail\",\"emailFormPhoneLabel\": \"Num\u00e9ro de t\u00e9l\u00e9phone\",\"emailFormCompanyLabel\": \"Nom de l'entreprise\",\"emailFormSubmit\": \"Envoyer\",\"emailFormCancel\": \"Annuler\",\"emailFormSuccess\": \"Envoy\u00e9 ! Vous recevrez le r\u00e9sultat par e-mail.\",\"emailFormError\": \"Veuillez indiquer au moins votre nom et votre adresse e-mail.\",\"emailFormMissingForm\": \"Une erreur s'est produite. Veuillez contacter le service client.\",\"quoteFormSubmit\": \"Demander un devis\",\"quoteFormSuccess\": \"Envoy\u00e9 ! Notre \u00e9quipe commerciale vous contactera.\",\"quoteFormError\": \"Veuillez indiquer au moins votre nom et votre adresse e-mail.\",\"quoteFormMissingForm\": \"Une erreur s'est produite. Veuillez contacter le service client.\",\"quantityLabel\": \"Quantit\u00e9\",\"combinedQuoteTitle\": \"\u00c9tapes suivantes\",\"combinedQuoteIntro\": \"Demandez un devis pour ces r\u00e9sultats, ou recevez-les directement par e-mail.\",\"requestQuoteButton\": \"Demander votre devis\",\"quoteFormCancel\": \"Annuler\",\"copyLabel\": \"Copier le code\",\"copiedLabel\": \"Copi\u00e9 !\",\"quantityDecrease\": \"Diminuer la quantit\u00e9\",\"quantityIncrease\": \"Augmenter la quantit\u00e9\",\"clearInputLabel\": \"Effacer le champ\",\"partsButtonLabel\": \"Commander les pi\u00e8ces correspondantes\",\"partsPopupTitle\": \"Pi\u00e8ces disponibles pour cette configuration\",\"partsPopupIntro\": \"Cochez ce que vous souhaitez commander et ajoutez-le directement \u00e0 votre panier.\",\"partsRoleZuigbuis\": \"Tube d'aspiration\",\"partsRoleSensor\": \"Capteur\",\"partsRoleDeksel\": \"Couvercle + mise \u00e0 l'air\",\"partsUnavailable\": \"Pas encore disponible s\u00e9par\u00e9ment\",\"partsContactLink\": \"Contactez-nous\",\"partsAddToCartButton\": \"Ajouter au panier\",\"partsAddToCartSuccess\": \"Ajout\u00e9 \u00e0 votre panier.\",\"partsNoneSelected\": \"S\u00e9lectionnez au moins une pi\u00e8ce.\",\"partsRoleCoupler\": \"Raccord compl\u00e9mentaire pour le tube d'aspiration\",\"partsRoleCap\": \"Capuchon de protection pour le tube d'aspiration\",\"partsRoleSensorConnector\": \"Jeu de connecteurs\",\"partsRoleSensorCounterConnector\": \"Connecteur compl\u00e9mentaire (raccordement \u00e0 votre propre syst\u00e8me)\",\"partsBuiltInHeader\": \"Composants int\u00e9gr\u00e9s\",\"partsExtraHeader\": \"Accessoires suppl\u00e9mentaires\",\"partsRoleSensorConnectorSet\": \"Jeu complet de connecteurs pour d\u00e9tecteur de plein, de vide ou de niveau bas (connecteur + connecteur compl\u00e9mentaire)\",\"partsViewCartButton\": \"Voir le panier\",\"partsAddAllButton\": \"Ajouter toutes les pi\u00e8ces s\u00e9lectionn\u00e9es en une fois\",\"quotePartsSectionTitle\": \"Pi\u00e8ces d\u00e9tach\u00e9es s\u00e9lectionn\u00e9es\",\"partsOutOfStock\": \"Temporairement en rupture de stock\",\"partsSubtotalLabel\": \"Sous-total\",\"partsGrandTotalLabel\": \"Total (tous les r\u00e9sultats)\",\"partsCoverageLabel\": \"{available} pi\u00e8ces disponibles sur {total}\",\"shareLinkLabel\": \"Copier le lien vers ce r\u00e9sultat\",\"shareLinkCopiedLabel\": \"Lien copi\u00e9 !\",\"toastSessionCount\": \"{count} article(s) ajout\u00e9(s) durant cette session\"},\"it\": {\"title\": \"Quale versione di VARIBOX ho?\",\"intro\": \"Inserisca il numero di serie (8 caratteri, riportato sulla targhetta della sua VARIBOX) \u2014 oppure il numero di articolo completo (12 caratteri, riportato sulla conferma d'ordine o sulla fattura) \u2014 per scoprire di quale versione si tratta.\",\"placeholder\": \"es. VB1001AED709\",\"button\": \"Verifica numero articolo\",\"exampleIntro\": \"Non ha un numero di articolo a portata di mano?\",\"exampleBtn\": \"Vedi un esempio\",\"labelType\": \"Tipo \/ volume\",\"labelPakking\": \"Materiale della guarnizione\",\"labelZuigbuis\": \"Tubo di aspirazione \/ sfiato\",\"labelSensor\": \"Sensore di livello\",\"labelKleur\": \"Colore\",\"labelFoodContact\": \"Contatto alimentare\",\"yesWord\": \"S\u00ec\",\"noWord\": \"No\",\"labelPallet\": \"Consegna\",\"labelTrailer\": \"Trailer\",\"labelCombo\": \"Combinazione colori\",\"labelDIBt\": \"Omologazione DIBt\",\"labelADR\": \"Normativa ADR\",\"labelVibration\": \"Test di vibrazione\",\"dtNotApplicable\": \"Non applicabile (versione Trailer)\",\"labelUN\": \"Numero di certificazione UN\",\"errorLength\": \"Inserisca un numero di articolo (12 caratteri) o un numero di serie (8 caratteri). Questo inserimento ha {n} carattere\/i. Esempio numero di articolo: VB1001AED709, esempio numero di serie: M1234567.\",\"errorUnknownSerial\": \"Non riconosciamo questo numero di serie. Verifichi di averlo inserito per intero e correttamente, oppure contatti il servizio clienti VARIBOX (+31 (0)570 660711, info@varibox-ibc.com).\",\"serialMatchNote\": \"Riconosciuto tramite il numero di serie {serial}\",\"errorUnknownType\": \"Non riconosciamo questo numero di articolo. Verifichi di averlo inserito per intero e correttamente, oppure contatti il servizio clienti VARIBOX (+31 (0)570 660711, info@varibox-ibc.com).\",\"unknownCode\": \"Codice sconosciuto \u2014 non riconosciuto.\",\"noteAmbiguousPakking\": \"Attenzione: questi tipi di guarnizione condividono lo stesso codice. Verifichi la targhetta o la Declaration of Compliance per stabilire se si tratta di una versione Food.\",\"noteSpecialAlt\": \"Potrebbe anche trattarsi di un'opzione speciale:\",\"noteSpecialAltExplain\": \"Questo campo viene utilizzato per configurazioni non standard\/speciali al posto del materiale di guarnizione standard. Rilevante solo se non si tratta di una versione standard EPDM\/Food\/Viton.\",\"noteZuigbuisAmbiguous\": \"Questo codice \u00e8 presente per pi\u00f9 materiali di guarnizione ({materials}). Utilizzi il campo materiale guarnizione qui sotto per stabilire quale si applica.\",\"footerNote\": \"Non \u00e8 sicuro del risultato, o una combinazione le \u00e8 sconosciuta? Contatti il servizio clienti VARIBOX (+31 (0)570 660711, info@varibox-ibc.com).\",\"orWord\": \"o\",\"langLabel\": \"Lingua\",\"sparePartsNote\": \"\u00c8 in cerca di singoli componenti come tubi di aspirazione, raccordi complementari o sensori?\",\"sparePartsLink\": \"Visualizzi i componenti nel webshop\",\"foodDocLabel\": \"Scarica la Declaration of Compliance (PDF)\",\"foodContactInfo\": \"L'approvazione per il contatto alimentare \u00e8 valida solo per la versione in EPDM, senza sensori montati, con un tubo di aspirazione Safeline Performance Food, AS QC2 o AS GT2 (o nessun tubo), in combinazione con il nuovo Sfiato sovrapressione blu VARIBOX FC e CC. Questo vale per i contenitori prodotti dopo il 1\u00b0 ottobre 2021; per le produzioni precedenti non \u00e8 possibile verificarlo tramite questo strumento.\",\"foodContactInfoLink\": \"Maggiori informazioni\",\"bulkHint\": \"Suggerimento: pu\u00f2 anche incollare pi\u00f9 numeri di articolo o di serie contemporaneamente, uno per riga (massimo 25 righe).\",\"bulkSummary\": \"{ok} numeri riconosciuti su {total}\",\"bulkTruncated\": \" Sono state elaborate solo le prime {max} righe.\",\"groupNote\": \"Questa configurazione \u00e8 stata riconosciuta per {count} numeri: {list}.\",\"groupNoteMore\": \" e altri {more}\",\"emailResultButton\": \"Invia questo risultato via e-mail\",\"emailFormNameLabel\": \"Nome\",\"emailFormEmailLabel\": \"Indirizzo e-mail\",\"emailFormPhoneLabel\": \"Numero di telefono\",\"emailFormCompanyLabel\": \"Nome dell'azienda\",\"emailFormSubmit\": \"Invia\",\"emailFormCancel\": \"Annulla\",\"emailFormSuccess\": \"Inviato! Ricever\u00e0 il risultato via e-mail.\",\"emailFormError\": \"Inserisca almeno il nome e l'indirizzo e-mail.\",\"emailFormMissingForm\": \"Si \u00e8 verificato un errore. La preghiamo di contattare il servizio clienti.\",\"quoteFormSubmit\": \"Richiedi preventivo\",\"quoteFormSuccess\": \"Inviato! Il nostro team commerciale la contatter\u00e0.\",\"quoteFormError\": \"Inserisca almeno il nome e l'indirizzo e-mail.\",\"quoteFormMissingForm\": \"Si \u00e8 verificato un errore. La preghiamo di contattare il servizio clienti.\",\"quantityLabel\": \"Quantit\u00e0\",\"combinedQuoteTitle\": \"Prossimi passi\",\"combinedQuoteIntro\": \"Richieda un preventivo per questi risultati, oppure li riceva direttamente via e-mail.\",\"requestQuoteButton\": \"Richieda il suo preventivo\",\"quoteFormCancel\": \"Annulla\",\"copyLabel\": \"Copia codice\",\"copiedLabel\": \"Copiato!\",\"quantityDecrease\": \"Diminuisci quantit\u00e0\",\"quantityIncrease\": \"Aumenta quantit\u00e0\",\"clearInputLabel\": \"Cancella campo\",\"partsButtonLabel\": \"Ordina i componenti corrispondenti\",\"partsPopupTitle\": \"Componenti disponibili per questa configurazione\",\"partsPopupIntro\": \"Selezioni ci\u00f2 che desidera ordinare e lo aggiunga direttamente al carrello.\",\"partsRoleZuigbuis\": \"Tubo di aspirazione\",\"partsRoleSensor\": \"Sensore\",\"partsRoleDeksel\": \"Coperchio + sfiato\",\"partsUnavailable\": \"Non ancora disponibile separatamente\",\"partsContactLink\": \"Contattaci\",\"partsAddToCartButton\": \"Aggiungi al carrello\",\"partsAddToCartSuccess\": \"Aggiunto al carrello.\",\"partsNoneSelected\": \"Selezioni almeno un componente.\",\"partsRoleCoupler\": \"Raccordo complementare per il tubo di aspirazione\",\"partsRoleCap\": \"Cappuccio di protezione per il tubo di aspirazione\",\"partsRoleSensorConnector\": \"Set di connettori\",\"partsRoleSensorCounterConnector\": \"Connettore complementare (collegamento al proprio sistema)\",\"partsBuiltInHeader\": \"Componenti integrati\",\"partsExtraHeader\": \"Accessori aggiuntivi\",\"partsRoleSensorConnectorSet\": \"Set completo di connettori per sensore di pieno, di vuoto o di livello basso (connettore + connettore complementare)\",\"partsViewCartButton\": \"Visualizza carrello\",\"partsAddAllButton\": \"Aggiungi tutti i componenti selezionati in una volta\",\"quotePartsSectionTitle\": \"Componenti singoli selezionati\",\"partsOutOfStock\": \"Temporaneamente non disponibile\",\"partsSubtotalLabel\": \"Subtotale\",\"partsGrandTotalLabel\": \"Totale (tutti i risultati)\",\"partsCoverageLabel\": \"{available} componenti disponibili su {total}\",\"shareLinkLabel\": \"Copia il link a questo risultato\",\"shareLinkCopiedLabel\": \"Link copiato!\",\"toastSessionCount\": \"{count} pezzo\/i aggiunti in questa sessione\"},\"es\": {\"title\": \"\u00bfQu\u00e9 versi\u00f3n de VARIBOX tengo?\",\"intro\": \"Introduzca su n\u00famero de serie (8 caracteres, indicado en la placa de identificaci\u00f3n de su VARIBOX) \u2014 o el n\u00famero de art\u00edculo completo (12 caracteres, indicado en la confirmaci\u00f3n de pedido o la factura) \u2014 para ver de qu\u00e9 versi\u00f3n se trata.\",\"placeholder\": \"ej. VB1001AED709\",\"button\": \"Comprobar n\u00famero de art\u00edculo\",\"exampleIntro\": \"\u00bfNo tiene un n\u00famero de art\u00edculo a mano?\",\"exampleBtn\": \"Ver un ejemplo\",\"labelType\": \"Tipo \/ volumen\",\"labelPakking\": \"Material de la junta\",\"labelZuigbuis\": \"Tubo de aspiraci\u00f3n \/ respiradero\",\"labelSensor\": \"Sensor de nivel\",\"labelKleur\": \"Color\",\"labelFoodContact\": \"Contacto alimentario\",\"yesWord\": \"S\u00ed\",\"noWord\": \"No\",\"labelPallet\": \"Entrega\",\"labelTrailer\": \"Trailer\",\"labelCombo\": \"Combinaci\u00f3n de colores\",\"labelDIBt\": \"Homologaci\u00f3n DIBt\",\"labelADR\": \"Normativa ADR\",\"labelVibration\": \"Prueba de vibraci\u00f3n\",\"dtNotApplicable\": \"No aplicable (versi\u00f3n Trailer)\",\"labelUN\": \"N\u00famero de certificaci\u00f3n UN\",\"errorLength\": \"Introduzca un n\u00famero de art\u00edculo (12 caracteres) o un n\u00famero de serie (8 caracteres). Esta entrada tiene {n} car\u00e1cter(es). Ejemplo de n\u00famero de art\u00edculo: VB1001AED709, ejemplo de n\u00famero de serie: M1234567.\",\"errorUnknownSerial\": \"No reconocemos este n\u00famero de serie. Compruebe que lo ha introducido de forma completa y correcta, o p\u00f3ngase en contacto con el Servicio de Atenci\u00f3n al Cliente de VARIBOX (+31 (0)570 660711, info@varibox-ibc.com).\",\"serialMatchNote\": \"Identificado mediante el n\u00famero de serie {serial}\",\"errorUnknownType\": \"No reconocemos este n\u00famero de art\u00edculo. Compruebe que lo ha introducido de forma completa y correcta, o p\u00f3ngase en contacto con el servicio de atenci\u00f3n al cliente de VARIBOX (+31 (0)570 660711, info@varibox-ibc.com).\",\"unknownCode\": \"C\u00f3digo desconocido \u2014 no reconocido.\",\"noteAmbiguousPakking\": \"Atenci\u00f3n: estos tipos de junta comparten el mismo c\u00f3digo. Compruebe la placa de identificaci\u00f3n o la Declaration of Compliance para determinar si se trata de una versi\u00f3n Food.\",\"noteSpecialAlt\": \"Tambi\u00e9n podr\u00eda ser una opci\u00f3n especial:\",\"noteSpecialAltExplain\": \"Este campo se utiliza para configuraciones no est\u00e1ndar\/especiales en lugar del material de junta est\u00e1ndar. Solo es relevante si no se trata de una versi\u00f3n est\u00e1ndar EPDM\/Food\/Viton.\",\"noteZuigbuisAmbiguous\": \"Este c\u00f3digo existe para varios materiales de junta ({materials}). Utilice el campo de material de junta a continuaci\u00f3n para determinar cu\u00e1l se aplica.\",\"footerNote\": \"\u00bfNo est\u00e1 seguro del resultado, o una combinaci\u00f3n le resulta desconocida? P\u00f3ngase en contacto con el servicio de atenci\u00f3n al cliente de VARIBOX (+31 (0)570 660711, info@varibox-ibc.com).\",\"orWord\": \"o\",\"langLabel\": \"Idioma\",\"sparePartsNote\": \"\u00bfBusca piezas sueltas como tubos de aspiraci\u00f3n, acoples complementarios o sensores?\",\"sparePartsLink\": \"Ver piezas en la tienda online\",\"foodDocLabel\": \"Descargar la Declaration of Compliance (PDF)\",\"foodContactInfo\": \"La aprobaci\u00f3n de contacto alimentario solo es v\u00e1lida para la versi\u00f3n de EPDM, sin sensores instalados, con un tubo de aspiraci\u00f3n Safeline Performance Food, AS QC2 o AS GT2 (o sin tubo), en combinaci\u00f3n con el nuevo Venteo de sobrepresi\u00f3n azul VARIBOX FC y CC. Esto se aplica a los contenedores fabricados despu\u00e9s del 1 de octubre de 2021; para producciones anteriores, esto no se puede comprobar mediante esta herramienta.\",\"foodContactInfoLink\": \"M\u00e1s informaci\u00f3n\",\"bulkHint\": \"Consejo: tambi\u00e9n puede pegar varios n\u00fameros de art\u00edculo o de serie a la vez, uno por l\u00ednea (m\u00e1x. 25 l\u00edneas).\",\"bulkSummary\": \"{ok} de {total} n\u00fameros reconocidos\",\"bulkTruncated\": \" Solo se han procesado las primeras {max} l\u00edneas.\",\"groupNote\": \"Esta configuraci\u00f3n se ha reconocido para {count} n\u00fameros: {list}.\",\"groupNoteMore\": \" y {more} m\u00e1s\",\"emailResultButton\": \"Enviar este resultado por correo\",\"emailFormNameLabel\": \"Nombre\",\"emailFormEmailLabel\": \"Correo electr\u00f3nico\",\"emailFormPhoneLabel\": \"N\u00famero de tel\u00e9fono\",\"emailFormCompanyLabel\": \"Nombre de la empresa\",\"emailFormSubmit\": \"Enviar\",\"emailFormCancel\": \"Cancelar\",\"emailFormSuccess\": \"\u00a1Enviado! Recibir\u00e1 el resultado por correo electr\u00f3nico.\",\"emailFormError\": \"Introduzca al menos su nombre y correo electr\u00f3nico.\",\"emailFormMissingForm\": \"Algo ha salido mal. P\u00f3ngase en contacto con el Servicio de Atenci\u00f3n al Cliente.\",\"quoteFormSubmit\": \"Solicitar presupuesto\",\"quoteFormSuccess\": \"\u00a1Enviado! Nuestro equipo comercial se pondr\u00e1 en contacto con usted.\",\"quoteFormError\": \"Introduzca al menos su nombre y correo electr\u00f3nico.\",\"quoteFormMissingForm\": \"Algo ha salido mal. P\u00f3ngase en contacto con el Servicio de Atenci\u00f3n al Cliente.\",\"quantityLabel\": \"Cantidad\",\"combinedQuoteTitle\": \"Pr\u00f3ximos pasos\",\"combinedQuoteIntro\": \"Solicite un presupuesto para estos resultados, o rec\u00edbalos directamente por correo electr\u00f3nico.\",\"requestQuoteButton\": \"Solicite su presupuesto\",\"quoteFormCancel\": \"Cancelar\",\"copyLabel\": \"Copiar c\u00f3digo\",\"copiedLabel\": \"\u00a1Copiado!\",\"quantityDecrease\": \"Disminuir cantidad\",\"quantityIncrease\": \"Aumentar cantidad\",\"clearInputLabel\": \"Borrar campo\",\"partsButtonLabel\": \"Pedir piezas correspondientes\",\"partsPopupTitle\": \"Piezas disponibles para esta configuraci\u00f3n\",\"partsPopupIntro\": \"Marque lo que desea pedir y a\u00f1\u00e1dalo directamente a su carrito.\",\"partsRoleZuigbuis\": \"Tubo de aspiraci\u00f3n\",\"partsRoleSensor\": \"Sensor\",\"partsRoleDeksel\": \"Tapa + respiradero\",\"partsUnavailable\": \"A\u00fan no disponible por separado\",\"partsContactLink\": \"Cont\u00e1ctenos\",\"partsAddToCartButton\": \"A\u00f1adir al carrito\",\"partsAddToCartSuccess\": \"A\u00f1adido al carrito.\",\"partsNoneSelected\": \"Seleccione al menos una pieza.\",\"partsRoleCoupler\": \"Acople complementario para el tubo de aspiraci\u00f3n\",\"partsRoleCap\": \"Tapa protectora para el tubo de aspiraci\u00f3n\",\"partsRoleSensorConnector\": \"Juego de conectores\",\"partsRoleSensorCounterConnector\": \"Conector complementario (conexi\u00f3n a su propio sistema)\",\"partsBuiltInHeader\": \"Componentes integrados\",\"partsExtraHeader\": \"Accesorios adicionales\",\"partsRoleSensorConnectorSet\": \"Juego completo de conectores para sensor de lleno, de vac\u00edo o de nivel bajo (conector + conector complementario)\",\"partsViewCartButton\": \"Ver carrito\",\"partsAddAllButton\": \"A\u00f1adir todas las piezas seleccionadas a la vez\",\"quotePartsSectionTitle\": \"Piezas sueltas seleccionadas\",\"partsOutOfStock\": \"Temporalmente sin existencias\",\"partsSubtotalLabel\": \"Subtotal\",\"partsGrandTotalLabel\": \"Total (todos los resultados)\",\"partsCoverageLabel\": \"{available} de {total} piezas disponibles\",\"shareLinkLabel\": \"Copiar enlace a este resultado\",\"shareLinkCopiedLabel\": \"\u00a1Enlace copiado!\",\"toastSessionCount\": \"{count} unidad(es) a\u00f1adidas en esta sesi\u00f3n\"},\"pl\": {\"title\": \"Kt\u00f3r\u0105 wersj\u0119 VARIBOX posiadam?\",\"intro\": \"Wprowad\u017a sw\u00f3j numer seryjny (8 znak\u00f3w, widoczny na tabliczce znamionowej Twojego VARIBOX) \u2014 lub pe\u0142ny numer artyku\u0142u (12 znak\u00f3w, widoczny na potwierdzeniu zam\u00f3wienia lub fakturze) \u2014, aby sprawdzi\u0107, o kt\u00f3r\u0105 wersj\u0119 chodzi.\",\"placeholder\": \"np. VB1001AED709\",\"button\": \"Sprawd\u017a numer artyku\u0142u\",\"exampleIntro\": \"Nie masz pod r\u0119k\u0105 numeru artyku\u0142u?\",\"exampleBtn\": \"Zobacz przyk\u0142ad\",\"labelType\": \"Typ \/ obj\u0119to\u015b\u0107\",\"labelPakking\": \"Materia\u0142 uszczelki\",\"labelZuigbuis\": \"Rurka zasysaj\u0105ca \/ odpowietrznik\",\"labelSensor\": \"Czujnik poziomu\",\"labelKleur\": \"Kolor\",\"labelFoodContact\": \"Kontakt z \u017cywno\u015bci\u0105\",\"yesWord\": \"Tak\",\"noWord\": \"Nie\",\"labelPallet\": \"Dostawa\",\"labelTrailer\": \"Trailer\",\"labelCombo\": \"Kombinacja kolor\u00f3w\",\"labelDIBt\": \"Zatwierdzenie DIBt\",\"labelADR\": \"Przepisy ADR\",\"labelVibration\": \"Test wibracji\",\"dtNotApplicable\": \"Nie dotyczy (wersja Trailer)\",\"labelUN\": \"Numer certyfikacji UN\",\"errorLength\": \"Wprowad\u017a numer artyku\u0142u (12 znak\u00f3w) lub numer seryjny (8 znak\u00f3w). To wprowadzenie ma {n} znak(\u00f3w). Przyk\u0142ad numeru artyku\u0142u: VB1001AED709, przyk\u0142ad numeru seryjnego: M1234567.\",\"errorUnknownSerial\": \"Nie rozpoznajemy tego numeru seryjnego. Sprawd\u017a, czy wprowadzi\u0142e\u015b go w ca\u0142o\u015bci i poprawnie, lub skontaktuj si\u0119 z Obs\u0142ug\u0105 Klienta VARIBOX (+31 (0)570 660711, info@varibox-ibc.com).\",\"serialMatchNote\": \"Rozpoznano na podstawie numeru seryjnego {serial}\",\"errorUnknownType\": \"Nie rozpoznajemy tego numeru artyku\u0142u. Sprawd\u017a, czy wprowadzi\u0142e\u015b go w ca\u0142o\u015bci i poprawnie, lub skontaktuj si\u0119 z Obs\u0142ug\u0105 Klienta VARIBOX (+31 (0)570 660711, info@varibox-ibc.com).\",\"unknownCode\": \"Nieznany kod \u2014 nierozpoznany.\",\"noteAmbiguousPakking\": \"Uwaga: te rodzaje uszczelek maj\u0105 ten sam kod. Sprawd\u017a tabliczk\u0119 znamionow\u0105 lub Declaration of Compliance, aby ustali\u0107, czy jest to wersja Food.\",\"noteSpecialAlt\": \"Mo\u017ce to by\u0107 r\u00f3wnie\u017c opcja specjalna:\",\"noteSpecialAltExplain\": \"To pole jest u\u017cywane dla niestandardowych\/specjalnych konfiguracji zamiast standardowego materia\u0142u uszczelki. Istotne tylko wtedy, gdy nie jest to standardowa wersja EPDM\/Food\/Viton.\",\"noteZuigbuisAmbiguous\": \"Ten kod wyst\u0119puje dla kilku materia\u0142\u00f3w uszczelek ({materials}). U\u017cyj pola materia\u0142u uszczelki poni\u017cej, aby ustali\u0107, kt\u00f3ry dotyczy tego przypadku.\",\"footerNote\": \"Nie jeste\u015b pewien wyniku lub kombinacja jest Ci nieznana? Skontaktuj si\u0119 z Obs\u0142ug\u0105 Klienta VARIBOX (+31 (0)570 660711, info@varibox-ibc.com).\",\"orWord\": \"lub\",\"langLabel\": \"J\u0119zyk\",\"sparePartsNote\": \"Szukaj\u0105 Pa\u0144stwo pojedynczych cz\u0119\u015bci, takich jak rurki zasysaj\u0105ce, z\u0142\u0105cza przeciwne lub czujniki?\",\"sparePartsLink\": \"Zobacz cz\u0119\u015bci w sklepie internetowym\",\"foodDocLabel\": \"Pobierz Declaration of Compliance (PDF)\",\"foodContactInfo\": \"Dopuszczenie do kontaktu z \u017cywno\u015bci\u0105 obowi\u0105zuje wy\u0142\u0105cznie dla wersji EPDM, bez zamontowanych czujnik\u00f3w, z rurk\u0105 zasysaj\u0105c\u0105 Safeline Performance Food, AS QC2 lub AS GT2 (lub bez rurki), w po\u0142\u0105czeniu z nowym niebieskim odpowietrznikiem nadci\u015bnieniowym VARIBOX FC i CC. Dotyczy to kontener\u00f3w wyprodukowanych po 1 pa\u017adziernika 2021 r.; w przypadku wcze\u015bniejszej produkcji nie mo\u017cna tego sprawdzi\u0107 za pomoc\u0105 tego narz\u0119dzia.\",\"foodContactInfoLink\": \"Wi\u0119cej informacji\",\"bulkHint\": \"Wskaz\u00f3wka: mo\u017cna r\u00f3wnie\u017c wklei\u0107 kilka numer\u00f3w artyku\u0142u lub numer\u00f3w seryjnych jednocze\u015bnie, jeden w ka\u017cdym wierszu (maks. 25 wierszy).\",\"bulkSummary\": \"Rozpoznano {ok} z {total} numer\u00f3w\",\"bulkTruncated\": \" Przetworzono tylko pierwsze {max} wierszy.\",\"groupNote\": \"T\u0119 konfiguracj\u0119 rozpoznano dla {count} numer\u00f3w: {list}.\",\"groupNoteMore\": \" i {more} innych\",\"emailResultButton\": \"Wy\u015blij ten wynik e-mailem\",\"emailFormNameLabel\": \"Imi\u0119 i nazwisko\",\"emailFormEmailLabel\": \"Adres e-mail\",\"emailFormPhoneLabel\": \"Numer telefonu\",\"emailFormCompanyLabel\": \"Nazwa firmy\",\"emailFormSubmit\": \"Wy\u015blij\",\"emailFormCancel\": \"Anuluj\",\"emailFormSuccess\": \"Wys\u0142ano! Otrzymaj\u0105 Pa\u0144stwo wynik e-mailem.\",\"emailFormError\": \"Prosz\u0119 poda\u0107 co najmniej imi\u0119 i adres e-mail.\",\"emailFormMissingForm\": \"Co\u015b posz\u0142o nie tak. Prosimy o kontakt z Obs\u0142ug\u0105 Klienta.\",\"quoteFormSubmit\": \"Popro\u015b o wycen\u0119\",\"quoteFormSuccess\": \"Wys\u0142ano! Nasz zesp\u00f3\u0142 sprzeda\u017cy skontaktuje si\u0119 z Pa\u0144stwem.\",\"quoteFormError\": \"Prosz\u0119 poda\u0107 co najmniej imi\u0119 i adres e-mail.\",\"quoteFormMissingForm\": \"Co\u015b posz\u0142o nie tak. Prosimy o kontakt z Obs\u0142ug\u0105 Klienta.\",\"quantityLabel\": \"Ilo\u015b\u0107\",\"combinedQuoteTitle\": \"Kolejne kroki\",\"combinedQuoteIntro\": \"Popro\u015b o wycen\u0119 dla tych wynik\u00f3w lub otrzymaj je bezpo\u015brednio e-mailem.\",\"requestQuoteButton\": \"Popro\u015b o wycen\u0119\",\"quoteFormCancel\": \"Anuluj\",\"copyLabel\": \"Kopiuj kod\",\"copiedLabel\": \"Skopiowano!\",\"quantityDecrease\": \"Zmniejsz ilo\u015b\u0107\",\"quantityIncrease\": \"Zwi\u0119ksz ilo\u015b\u0107\",\"clearInputLabel\": \"Wyczy\u015b\u0107 pole\",\"partsButtonLabel\": \"Zam\u00f3w pasuj\u0105ce cz\u0119\u015bci\",\"partsPopupTitle\": \"Dost\u0119pne cz\u0119\u015bci dla tej konfiguracji\",\"partsPopupIntro\": \"Zaznacz, co chcesz zam\u00f3wi\u0107, i dodaj to bezpo\u015brednio do koszyka.\",\"partsRoleZuigbuis\": \"Rurka zasysaj\u0105ca\",\"partsRoleSensor\": \"Czujnik\",\"partsRoleDeksel\": \"Pokrywa + odpowietrznik\",\"partsUnavailable\": \"Jeszcze niedost\u0119pne osobno\",\"partsContactLink\": \"Skontaktuj si\u0119 z nami\",\"partsAddToCartButton\": \"Dodaj do koszyka\",\"partsAddToCartSuccess\": \"Dodano do koszyka.\",\"partsNoneSelected\": \"Wybierz co najmniej jedn\u0105 cz\u0119\u015b\u0107.\",\"partsRoleCoupler\": \"Z\u0142\u0105cze przeciwne do rurki zasysaj\u0105cej\",\"partsRoleCap\": \"Za\u015blepka ochronna do rurki zasysaj\u0105cej\",\"partsRoleSensorConnector\": \"Zestaw z\u0142\u0105czy\",\"partsRoleSensorCounterConnector\": \"Z\u0142\u0105cze przeciwne (pod\u0142\u0105czenie do w\u0142asnego systemu)\",\"partsBuiltInHeader\": \"Wbudowane komponenty\",\"partsExtraHeader\": \"Dodatkowe akcesoria\",\"partsRoleSensorConnectorSet\": \"Kompletny zestaw z\u0142\u0105czy do czujnika pe\u0142nego, pustego lub niskiego poziomu (z\u0142\u0105cze + z\u0142\u0105cze przeciwne)\",\"partsViewCartButton\": \"Zobacz koszyk\",\"partsAddAllButton\": \"Dodaj wszystkie zaznaczone cz\u0119\u015bci naraz\",\"quotePartsSectionTitle\": \"Wybrane cz\u0119\u015bci zamienne\",\"partsOutOfStock\": \"Chwilowo niedost\u0119pne\",\"partsSubtotalLabel\": \"Suma cz\u0119\u015bciowa\",\"partsGrandTotalLabel\": \"Suma ca\u0142kowita (wszystkie wyniki)\",\"partsCoverageLabel\": \"{available} z {total} cz\u0119\u015bci dost\u0119pnych\",\"shareLinkLabel\": \"Kopiuj link do tego wyniku\",\"shareLinkCopiedLabel\": \"Link skopiowany!\",\"toastSessionCount\": \"{count} szt. dodanych w tej sesji\"}};\nwindow.VBChecker.data = { I18N_DATA, STRINGS };\n})();\n<\/script>\n<script>\n(() => {\n'use strict';\n\/\/ VARIBOX Checker observability layer (v20).\n\/\/ Privacy-first by design: no raw article\/serial numbers, SKUs, product IDs,\n\/\/ names, email addresses, phone numbers or free-form user input are ever\n\/\/ included in metric payloads. By default events stay inside the page as\n\/\/ `varibox:metric` CustomEvents. External forwarding (e.g. GTM\/dataLayer) is\n\/\/ opt-in through window.VARIBOX_CHECKER_ANALYTICS.\nconst VB_METRIC_SCHEMA_VERSION = 1;\nconst VB_METRIC_STARTED_AT = (typeof performance !== 'undefined' ? !!performance.now : false) ? performance.now() : Date.now();\nlet VB_METRIC_SEQUENCE = 0;\nconst VB_METRIC_BUFFER = [];\nconst VB_METRIC_BUFFER_MAX = 100;\n\nconst VB_METRIC_ALLOWED_FIELDS = new Set([\n  'source','language','mode','lookup_kind','entry_count','recognized_count','error_count',\n  'unique_configurations','duration_ms','error_type','product_line','product_line_count',\n  'is_replacement','is_drumtainer','food_contact','parts_count','selected_count','quantity',\n  'cart_item_count','cart_quantity','succeeded_count','failed_count','form_kind','outcome',\n  'filter','compact','copy_kind','truncated','from_serial','had_parts','result_count',\n  'open','provider','reason','interaction','bulk','pending_count','feature','format','compare_count','scanner_supported'\n]);\nconst VB_METRIC_ENUM_FIELDS = {\n  source: new Set(['button','keyboard','example','recent','shared_link','language_change','auto','unknown','scanner','restore','history']),\n  mode: new Set(['single','bulk','empty']),\n  lookup_kind: new Set(['serial','article','mixed','unknown']),\n  error_type: new Set(['length','unknown','service','exception','validation','missing_form','commerce','none']),\n  product_line: new Set(['fc1000','fc800','cc250','drumtainer','mixed','unknown']),\n  form_kind: new Set(['quote','email']),\n  outcome: new Set(['success','failure','partial','started','cancelled']),\n  filter: new Set(['all','ok','error']),\n  copy_kind: new Set(['code','share_link','unknown']),\n  provider: new Set(['local','dataLayer','callback']),\n  reason: new Set(['timeout','validation','missing_form','ajax','network','permission','unknown']),\n  interaction: new Set(['open','close','select','deselect','increase','decrease','submit','clear','change']) ,\n  feature: new Set(['compare','export','print','scanner','history','session']),\n  format: new Set(['csv','pdf'])\n};\nconst VB_METRIC_BOOLEAN_FIELDS = new Set([\n  'is_replacement','is_drumtainer','food_contact','truncated','from_serial','had_parts','compact','open','bulk','scanner_supported'\n]);\nconst VB_METRIC_INTEGER_FIELDS = new Set([\n  'entry_count','recognized_count','error_count','unique_configurations','duration_ms','product_line_count',\n  'parts_count','selected_count','quantity','cart_item_count','cart_quantity','succeeded_count','failed_count',\n  'result_count','pending_count','compare_count'\n]);\n\nfunction getVBMetricConfig(){\n  let rawCfgOk = false;\n  if(typeof window !== 'undefined'){\n    if(window.VARIBOX_CHECKER_ANALYTICS){\n      if(typeof window.VARIBOX_CHECKER_ANALYTICS === 'object') rawCfgOk = true;\n    }\n  }\n  const raw = rawCfgOk ? window.VARIBOX_CHECKER_ANALYTICS : {};\n  return {\n    enabled: raw.enabled !== false,\n    dataLayer: raw.dataLayer === true,\n    debug: raw.debug === true,\n    callback: typeof raw.onEvent === 'function' ? raw.onEvent : null,\n    respectDnt: raw.respectDnt !== false\n  };\n}\nfunction vbMetricDntEnabled(){\n  if(typeof navigator === 'undefined') return false;\n  if(navigator.doNotTrack === '1') return true;\n  if(navigator.msDoNotTrack === '1') return true;\n  if(typeof window !== 'undefined'){\n    if(window.doNotTrack === '1') return true;\n  }\n  return false;\n}\nfunction vbMetricClampInteger(value, max){\n  const n = Number(value);\n  if(!Number.isFinite(n)) return null;\n  return Math.max(0, Math.min(max == null ? 1000000 : max, Math.round(n)));\n}\nfunction sanitizeVBMetricPayload(payload){\n  const clean = {};\n  if(!payload || typeof payload !== 'object') return clean;\n  Object.keys(payload).forEach(key => {\n    if(!VB_METRIC_ALLOWED_FIELDS.has(key)) return;\n    let value = payload[key];\n    if(VB_METRIC_BOOLEAN_FIELDS.has(key)){\n      if(typeof value === 'boolean') clean[key] = value;\n      return;\n    }\n    if(VB_METRIC_INTEGER_FIELDS.has(key)){\n      const n = vbMetricClampInteger(value, key === 'duration_ms' ? 3600000 : 100000);\n      if(n !== null) clean[key] = n;\n      return;\n    }\n    if(key === 'language'){\n      const lang = String(value || '').slice(0,2).toLowerCase();\n      if(STRINGS){\n        if(STRINGS[lang]) clean[key] = lang;\n      }\n      return;\n    }\n    if(VB_METRIC_ENUM_FIELDS[key]){\n      const str = String(value || '');\n      if(VB_METRIC_ENUM_FIELDS[key].has(str)) clean[key] = str;\n      return;\n    }\n  });\n  return clean;\n}\nfunction vbMetricElapsedMs(){\n  const now = (typeof performance !== 'undefined' ? !!performance.now : false) ? performance.now() : Date.now();\n  return vbMetricClampInteger(now - VB_METRIC_STARTED_AT, 3600000) || 0;\n}\nfunction vbMetric(eventName, payload){\n  const cfg = getVBMetricConfig();\n  if(!cfg.enabled) return null;\n  const name = String(eventName || '').toLowerCase().replace(\/[^a-z0-9_]\/g,'').slice(0,64);\n  if(!name) return null;\n  const detail = {\n    schema_version: VB_METRIC_SCHEMA_VERSION,\n    event: 'varibox_' + name,\n    sequence: ++VB_METRIC_SEQUENCE,\n    session_elapsed_ms: vbMetricElapsedMs(),\n    ...sanitizeVBMetricPayload(payload)\n  };\n  VB_METRIC_BUFFER.push(detail);\n  if(VB_METRIC_BUFFER.length > VB_METRIC_BUFFER_MAX) VB_METRIC_BUFFER.shift();\n\n  \/\/ Local event bus: always safe\/no network. Sites can subscribe with\n  \/\/ document.addEventListener('varibox:metric', e => ...).\n  try{\n    let canDispatch = false;\n    if(typeof document !== 'undefined'){\n      if(document.dispatchEvent){\n        if(typeof CustomEvent === 'function') canDispatch = true;\n      }\n    }\n    if(canDispatch){\n      document.dispatchEvent(new CustomEvent('varibox:metric', { detail }));\n    }\n  } catch(e){ \/* observability must never break the checker *\/ }\n\n  \/\/ Explicit callback hook. The hosting site decides what (if anything) happens next.\n  if(cfg.callback){\n    try{ cfg.callback(detail); } catch(e){ \/* user adapter error is isolated *\/ }\n  }\n\n  \/\/ Explicit GTM\/dataLayer opt-in. Respect browser DNT by default.\n  let dntBlocks = false;\n  if(cfg.respectDnt){\n    if(vbMetricDntEnabled()) dntBlocks = true;\n  }\n  if(cfg.dataLayer ? !dntBlocks : false){\n    try{\n      if(typeof window !== 'undefined'){\n        if(!Array.isArray(window.dataLayer)) window.dataLayer = [];\n        window.dataLayer.push({ event: detail.event, varibox: detail });\n      }\n    } catch(e){ \/* external adapter errors never affect UX *\/ }\n  }\n  let canDebugLog = false;\n  if(cfg.debug){\n    if(typeof console !== 'undefined'){\n      if(console.debug) canDebugLog = true;\n    }\n  }\n  if(canDebugLog){\n    console.debug('[VARIBOX metric]', detail);\n  }\n  return detail;\n}\nfunction vbMetricLookupDescriptor(raw){\n  const text = String(raw == null ? '' : raw);\n  const bounded = text.slice(0, 5000);\n  const entries = bounded.split(\/[\\n,;]+\/).map(v => v.trim()).filter(Boolean).slice(0,25);\n  if(entries.length === 0) return { mode:'empty', lookup_kind:'unknown', entry_count:0, bulk:false };\n  const kinds = entries.map(value => {\n    const normalized = value.toUpperCase().replace(\/\\s+\/g,'');\n    if(normalized.length === 8) return 'serial';\n    if(normalized.length === 12) return 'article';\n    return 'unknown';\n  });\n  const uniqueKinds = [...new Set(kinds)];\n  const kind = uniqueKinds.length === 1 ? uniqueKinds[0] : 'mixed';\n  return {\n    mode: entries.length > 1 ? 'bulk' : 'single',\n    lookup_kind: kind,\n    entry_count: entries.length,\n    bulk: entries.length > 1\n  };\n}\nfunction vbMetricResultSummary(results){\n  const list = Array.isArray(results) ? results : [];\n  const successful = list.filter(r => r ? !r.error : false);\n  const errors = list.filter(r => r ? !!r.error : false);\n  const lines = new Set();\n  successful.forEach(result => {\n    const line = getProductLine(result.typeCode);\n    if(line) lines.add(line);\n  });\n  let productLine = 'unknown';\n  if(lines.size === 1) productLine = [...lines][0];\n  else if(lines.size > 1) productLine = 'mixed';\n  const groups = typeof groupResults === 'function' ? groupResults(list) : [];\n  const partsCount = successful.reduce((sum, result) => {\n    try{ return sum + getAvailablePartsForResult(result).filter(item => item ? item.skus : false).length; }\n    catch(e){ return sum; }\n  }, 0);\n  return {\n    recognized_count: successful.length,\n    error_count: errors.length,\n    unique_configurations: groups.filter(g => { if(!g) return false; if(!g.result) return false; return !g.result.error; }).length,\n    result_count: list.length,\n    product_line: productLine,\n    product_line_count: lines.size,\n    had_parts: partsCount > 0,\n    parts_count: partsCount,\n    truncated: !!list.truncated,\n    from_serial: successful.some(r => !!r.matchedSerial),\n    error_type: errors.length === 1 ? (errors[0].errorType || 'unknown') : (errors.length > 1 ? 'unknown' : 'none')\n  };\n}\nfunction vbMetricFormKind(formId){\n  if(typeof GF_QUOTE_FORM_ID !== 'undefined'){\n    if(Number(formId) === Number(GF_QUOTE_FORM_ID)) return 'quote';\n  }\n  if(typeof GF_RESULT_FORM_ID !== 'undefined'){\n    if(Number(formId) === Number(GF_RESULT_FORM_ID)) return 'email';\n  }\n  return null;\n}\nfunction getVBMetricBuffer(){ return VB_METRIC_BUFFER.slice(); }\nconst { I18N_DATA, STRINGS } = window.VBChecker.data;\nlet CURRENT_LANG = 'nl';\nconst UX_STRINGS = {\n  nl:{matchFound:'Match gevonden',technicalDetails:'Technische details',serialNumber:'Serienummer',articleNumber:'Artikelnummer',bulkDetected:'Bulkmodus \u00b7 {count} nummers gedetecteerd',progress:'{kind} \u00b7 {n}\/{max}',ready:'{kind} \u00b7 compleet',selected:'{count} geselecteerd',enterHint:'Enter om te controleren \u00b7 Shift+Enter voor meerdere nummers',bulkOverview:'Bulkoverzicht',recognized:'Herkend',configurations:'Configuraties',attention:'Aandacht',filterAll:'Alles',filterRecognized:'Herkend',filterAttention:'Aandacht nodig',couldNotIdentify:'Dit nummer konden we niet identificeren',serviceUnavailable:'De serienummercontrole is tijdelijk niet beschikbaar',enteredValue:'Ingevoerd',editNumber:'Nummer aanpassen',useExample:'Voorbeeld gebruiken',contactSupport:'Customer Service',codeBreakdown:'Opbouw artikelnummer',codeType:'Type',codeGasket:'Pakking',codeTube:'Zuigbuis',codeSensor:'Sensor',codeColour:'Kleur',codeDelivery:'Levering',codeTrailer:'Trailer',codeCombination:'Combinatie',quoteDesc:'Laat ons team een passende offerte maken',emailDesc:'Ontvang deze configuratie direct in uw inbox',partsAvailable:'{count} onderdelen',identifiedFromSerial:'Herkend via serienummer',compactView:'Compact',cardView:'Kaarten'},\n  en:{matchFound:'Match found',technicalDetails:'Technical details',serialNumber:'Serial number',articleNumber:'Article number',bulkDetected:'Bulk mode \u00b7 {count} numbers detected',progress:'{kind} \u00b7 {n}\/{max}',ready:'{kind} \u00b7 complete',selected:'{count} selected',enterHint:'Enter to check \u00b7 Shift+Enter for multiple numbers',bulkOverview:'Bulk overview',recognized:'Recognised',configurations:'Configurations',attention:'Attention',filterAll:'All',filterRecognized:'Recognised',filterAttention:'Needs attention',couldNotIdentify:\"We couldn't identify this number\",serviceUnavailable:'The serial-number check is temporarily unavailable',enteredValue:'Entered',editNumber:'Edit number',useExample:'Use example',contactSupport:'Customer Service',codeBreakdown:'Article number breakdown',codeType:'Type',codeGasket:'Gasket',codeTube:'Extractor',codeSensor:'Sensor',codeColour:'Colour',codeDelivery:'Delivery',codeTrailer:'Trailer',codeCombination:'Combination',quoteDesc:'Let our team prepare a tailored quote',emailDesc:'Receive this configuration directly in your inbox',partsAvailable:'{count} parts',identifiedFromSerial:'Identified via serial number',compactView:'Compact',cardView:'Cards'},\n  de:{matchFound:'Treffer gefunden',technicalDetails:'Technische Details',serialNumber:'Seriennummer',articleNumber:'Artikelnummer',bulkDetected:'Stapelmodus \u00b7 {count} Nummern erkannt',progress:'{kind} \u00b7 {n}\/{max}',ready:'{kind} \u00b7 vollst\u00e4ndig',selected:'{count} ausgew\u00e4hlt',enterHint:'Enter zum Pr\u00fcfen \u00b7 Shift+Enter f\u00fcr mehrere Nummern',bulkOverview:'Stapel\u00fcbersicht',recognized:'Erkannt',configurations:'Konfigurationen',attention:'Pr\u00fcfen',filterAll:'Alle',filterRecognized:'Erkannt',filterAttention:'Pr\u00fcfung n\u00f6tig',couldNotIdentify:'Diese Nummer konnte nicht identifiziert werden',serviceUnavailable:'Die Seriennummernpr\u00fcfung ist vor\u00fcbergehend nicht verf\u00fcgbar',enteredValue:'Eingegeben',editNumber:'Nummer bearbeiten',useExample:'Beispiel verwenden',contactSupport:'Kundendienst',codeBreakdown:'Aufbau der Artikelnummer',codeType:'Typ',codeGasket:'Dichtung',codeTube:'Steigrohr',codeSensor:'Sensor',codeColour:'Farbe',codeDelivery:'Lieferung',codeTrailer:'Trailer',codeCombination:'Kombination',quoteDesc:'Lassen Sie unser Team ein passendes Angebot erstellen',emailDesc:'Diese Konfiguration direkt per E-Mail erhalten',partsAvailable:'{count} Teile',identifiedFromSerial:'\u00dcber Seriennummer erkannt',compactView:'Kompakt',cardView:'Karten'},\n  fr:{matchFound:'Correspondance trouv\u00e9e',technicalDetails:'D\u00e9tails techniques',serialNumber:'Num\u00e9ro de s\u00e9rie',articleNumber:\"Num\u00e9ro d\u2019article\",bulkDetected:'Mode group\u00e9 \u00b7 {count} num\u00e9ros d\u00e9tect\u00e9s',progress:'{kind} \u00b7 {n}\/{max}',ready:'{kind} \u00b7 complet',selected:'{count} s\u00e9lectionn\u00e9(s)',enterHint:'Entr\u00e9e pour v\u00e9rifier \u00b7 Maj+Entr\u00e9e pour plusieurs num\u00e9ros',bulkOverview:'Aper\u00e7u group\u00e9',recognized:'Reconnus',configurations:'Configurations',attention:'\u00c0 v\u00e9rifier',filterAll:'Tous',filterRecognized:'Reconnus',filterAttention:'\u00c0 v\u00e9rifier',couldNotIdentify:\"Nous n\u2019avons pas pu identifier ce num\u00e9ro\",serviceUnavailable:'La v\u00e9rification du num\u00e9ro de s\u00e9rie est temporairement indisponible',enteredValue:'Saisi',editNumber:'Modifier le num\u00e9ro',useExample:'Utiliser un exemple',contactSupport:'Service client',codeBreakdown:\"Structure du num\u00e9ro d\u2019article\",codeType:'Type',codeGasket:'Joint',codeTube:\"Tube d\u2019aspiration\",codeSensor:'Capteur',codeColour:'Couleur',codeDelivery:'Livraison',codeTrailer:'Trailer',codeCombination:'Combinaison',quoteDesc:'Demandez \u00e0 notre \u00e9quipe de pr\u00e9parer une offre adapt\u00e9e',emailDesc:'Recevez cette configuration directement par e-mail',partsAvailable:'{count} pi\u00e8ces',identifiedFromSerial:'Identifi\u00e9 via le num\u00e9ro de s\u00e9rie',compactView:'Compact',cardView:'Cartes'},\n  it:{matchFound:'Corrispondenza trovata',technicalDetails:'Dettagli tecnici',serialNumber:'Numero di serie',articleNumber:'Numero articolo',bulkDetected:'Modalit\u00e0 multipla \u00b7 {count} numeri rilevati',progress:'{kind} \u00b7 {n}\/{max}',ready:'{kind} \u00b7 completo',selected:'{count} selezionati',enterHint:'Invio per verificare \u00b7 Maiusc+Invio per pi\u00f9 numeri',bulkOverview:'Riepilogo multiplo',recognized:'Riconosciuti',configurations:'Configurazioni',attention:'Da verificare',filterAll:'Tutti',filterRecognized:'Riconosciuti',filterAttention:'Da verificare',couldNotIdentify:'Non siamo riusciti a identificare questo numero',serviceUnavailable:'La verifica del numero di serie \u00e8 temporaneamente non disponibile',enteredValue:'Inserito',editNumber:'Modifica numero',useExample:'Usa esempio',contactSupport:'Servizio clienti',codeBreakdown:'Struttura del numero articolo',codeType:'Tipo',codeGasket:'Guarnizione',codeTube:'Tubo',codeSensor:'Sensore',codeColour:'Colore',codeDelivery:'Consegna',codeTrailer:'Trailer',codeCombination:'Combinazione',quoteDesc:'Il nostro team preparer\u00e0 un preventivo su misura',emailDesc:'Riceva questa configurazione direttamente via e-mail',partsAvailable:'{count} componenti',identifiedFromSerial:'Riconosciuto tramite numero di serie',compactView:'Compatto',cardView:'Schede'},\n  es:{matchFound:'Coincidencia encontrada',technicalDetails:'Detalles t\u00e9cnicos',serialNumber:'N\u00famero de serie',articleNumber:'N\u00famero de art\u00edculo',bulkDetected:'Modo m\u00faltiple \u00b7 {count} n\u00fameros detectados',progress:'{kind} \u00b7 {n}\/{max}',ready:'{kind} \u00b7 completo',selected:'{count} seleccionados',enterHint:'Intro para comprobar \u00b7 May\u00fas+Intro para varios n\u00fameros',bulkOverview:'Resumen m\u00faltiple',recognized:'Reconocidos',configurations:'Configuraciones',attention:'Revisar',filterAll:'Todos',filterRecognized:'Reconocidos',filterAttention:'Requiere atenci\u00f3n',couldNotIdentify:'No hemos podido identificar este n\u00famero',serviceUnavailable:'La comprobaci\u00f3n del n\u00famero de serie no est\u00e1 disponible temporalmente',enteredValue:'Introducido',editNumber:'Editar n\u00famero',useExample:'Usar ejemplo',contactSupport:'Atenci\u00f3n al cliente',codeBreakdown:'Estructura del n\u00famero de art\u00edculo',codeType:'Tipo',codeGasket:'Junta',codeTube:'Tubo',codeSensor:'Sensor',codeColour:'Color',codeDelivery:'Entrega',codeTrailer:'Trailer',codeCombination:'Combinaci\u00f3n',quoteDesc:'Nuestro equipo preparar\u00e1 una oferta a medida',emailDesc:'Reciba esta configuraci\u00f3n directamente por correo',partsAvailable:'{count} piezas',identifiedFromSerial:'Identificado mediante n\u00famero de serie',compactView:'Compacto',cardView:'Tarjetas'},\n  pl:{matchFound:'Znaleziono dopasowanie',technicalDetails:'Szczeg\u00f3\u0142y techniczne',serialNumber:'Numer seryjny',articleNumber:'Numer artyku\u0142u',bulkDetected:'Tryb zbiorczy \u00b7 wykryto {count} numer\u00f3w',progress:'{kind} \u00b7 {n}\/{max}',ready:'{kind} \u00b7 kompletne',selected:'Wybrano: {count}',enterHint:'Enter, aby sprawdzi\u0107 \u00b7 Shift+Enter dla wielu numer\u00f3w',bulkOverview:'Podsumowanie zbiorcze',recognized:'Rozpoznane',configurations:'Konfiguracje',attention:'Do sprawdzenia',filterAll:'Wszystkie',filterRecognized:'Rozpoznane',filterAttention:'Wymaga uwagi',couldNotIdentify:'Nie uda\u0142o si\u0119 zidentyfikowa\u0107 tego numeru',serviceUnavailable:'Sprawdzanie numeru seryjnego jest tymczasowo niedost\u0119pne',enteredValue:'Wprowadzono',editNumber:'Edytuj numer',useExample:'U\u017cyj przyk\u0142adu',contactSupport:'Obs\u0142uga klienta',codeBreakdown:'Budowa numeru artyku\u0142u',codeType:'Typ',codeGasket:'Uszczelka',codeTube:'Rura',codeSensor:'Czujnik',codeColour:'Kolor',codeDelivery:'Dostawa',codeTrailer:'Trailer',codeCombination:'Kombinacja',quoteDesc:'Nasz zesp\u00f3\u0142 przygotuje dopasowan\u0105 ofert\u0119',emailDesc:'Otrzymaj t\u0119 konfiguracj\u0119 bezpo\u015brednio e-mailem',partsAvailable:'{count} cz\u0119\u015bci',identifiedFromSerial:'Rozpoznano po numerze seryjnym',compactView:'Kompaktowo',cardView:'Karty'}\n};\nconst VB_COLOR_SWATCHES = { '000':'#eee9dc','103':'#848a90','303':'#4d9b5b','698':'#ead241','709':'#244d7f','753':'#63b6df','887':'#df7a2b','892':'#bd4044' };\nconst FOOD_CONTACT_INFO_URL = 'https:\/\/varibox.best4u.dev\/product\/varibox-overpressure-vent\/';\n\/\/ Onderdelen-koppeltabel voor de \"Bekijk beschikbare onderdelen\"-pop-up: per zuigbuis-\/sensor-\/\n\/\/ deksel-omschrijving (dezelfde tekst als zuigbuisMatches[0][0]\/sensorMatches[0][0] uit decode())\n\/\/ de bijbehorende webshop-SKU('s) per productlijn+materiaal. ALLEEN onderdelen die daadwerkelijk\n\/\/ bevestigd in de webshop staan (handmatig gecontroleerd door Jeffrey, september 2026) staan hierin\n\/\/ \u2014 nog niet bevestigde onderdelen komen hier expliciet niet in, en tonen in de pop-up dus\n\/\/ \"neem contact op\" in plaats van een aanvinkbaar vakje. Bij een volgende update (na verdere\n\/\/ bevestiging) wordt dit object hier vervangen door de uitgebreide lijst.\nconst PARTS_LOOKUP = {\"zuigbuis\":{\"B_Food\":{\"FC1000_Food\":[\"5880513\"]},\"L_Food\":{\"FC1000_Food\":[\"5880513\"]},\"C_EPDM\":{\"FC1000_EPDM\":[\"5880526\"],\"FC800_EPDM\":[\"5880531\"],\"CC250_EPDM\":[\"5880527\"]},\"K_Food\":{\"FC1000_Food\":[\"5880513\"],\"FC800_Food\":[\"5880509\"],\"CC250_Food\":[\"5880511\"]},\"V_Viton\":{\"FC1000_Viton\":[\"5880481\"],\"FC800_Viton\":[\"5880483\"],\"CC250_Viton\":[\"5880485\"]},\"E_EPDM\":{\"FC1000_EPDM\":[\"5880526\"],\"FC800_EPDM\":[\"5880531\"],\"CC250_EPDM\":[\"5880527\"]},\"P_Food\":{\"FC1000_Food\":[\"5880513\"],\"FC800_Food\":[\"5880509\"],\"CC250_Food\":[\"5880511\"]},\"W_Viton\":{\"FC1000_Viton\":[\"5880481\"],\"FC800_Viton\":[\"5880483\"],\"CC250_Viton\":[\"5880485\"]},\"R_Viton\":{\"FC1000_Viton\":[\"5880435\"],\"FC800_Viton\":[\"5880423\"]},\"S_Viton\":{\"FC1000_Viton\":[\"5880435\"],\"FC800_Viton\":[\"5880423\"]},\"Y_EPDM\":{\"FC1000_EPDM\":[\"5880528\"],\"FC800_EPDM\":[\"5880529\"],\"CC250_EPDM\":[\"5880530\"]},\"Y_Viton\":{\"FC1000_Viton\":[\"5880491\"],\"FC800_Viton\":[\"5880501\"],\"CC250_Viton\":[\"5880487\"]},\"Z_EPDM\":{\"FC1000_EPDM\":[\"5880528\"],\"FC800_EPDM\":[\"5880529\"],\"CC250_EPDM\":[\"5880530\"]},\"Z_Viton\":{\"FC1000_Viton\":[\"5880491\"],\"FC800_Viton\":[\"5880501\"],\"CC250_Viton\":[\"5880487\"]},\"D_Viton\":{\"FC1000_Viton\":[\"5880387\"],\"CC250_Viton\":[\"5880521\"]},\"M_Viton\":{\"FC1000_Viton\":[\"5880387\"],\"CC250_Viton\":[\"5880521\"]},\"R_EPDM\":{\"FC1000_EPDM\":[\"5880434\"],\"FC800_EPDM\":[\"5880431\"]},\"S_EPDM\":{\"FC1000_EPDM\":[\"5880434\"],\"FC800_EPDM\":[\"5880431\"]}},\"sensor\":{\"B\":{\"FC1000_EPDM\":[\"9900641\"],\"FC1000_Viton\":[\"9900642\"],\"FC800_EPDM\":[\"9900660\"],\"FC800_Viton\":[\"9900661\"],\"CC250_EPDM\":[\"9900694\"],\"CC250_Viton\":[\"9900695\"]},\"D\":{\"FC1000_EPDM\":[\"9900612\"],\"FC1000_Viton\":[\"9900643\"],\"FC800_EPDM\":[\"9900612\"],\"FC800_Viton\":[\"9900643\"],\"CC250_EPDM\":[\"9900612\"],\"CC250_Viton\":[\"9900643\"]},\"C\":{\"FC1000_EPDM\":[\"9900641\",\"9900612\"],\"FC1000_Viton\":[\"9900642\",\"9900643\"],\"FC800_EPDM\":[\"9900660\",\"9900612\"],\"FC800_Viton\":[\"9900661\",\"9900643\"],\"CC250_EPDM\":[\"9900694\",\"9900612\"],\"CC250_Viton\":[\"9900695\",\"9900643\"]},\"E\":{\"FC1000_EPDM\":[\"9900669\"],\"FC1000_Viton\":[\"9900670\"],\"FC800_EPDM\":[\"9900663\"],\"FC800_Viton\":[\"9900659\"],\"CC250_EPDM\":[\"9900663\"],\"CC250_Viton\":[\"9900659\"]},\"J\":{\"FC1000_EPDM\":[\"9900669\",\"9900612\"],\"FC1000_Viton\":[\"9900670\",\"9900643\"],\"FC800_EPDM\":[\"9900663\",\"9900612\"],\"FC800_Viton\":[\"9900659\",\"9900643\"],\"CC250_EPDM\":[\"9900663\",\"9900612\"],\"CC250_Viton\":[\"9900659\",\"9900643\"]}},\"deksel\":{\"EPDM\":{\"B\":[\"7300196\"],\"L\":[\"7300192\"],\"C\":[\"7300196\"],\"K\":[\"7300196\"],\"E\":[\"7300192\"],\"P\":[\"7300192\"],\"R\":[\"7300196\"],\"S\":[\"7300192\"],\"Y\":[\"7300196\"],\"Z\":[\"7300192\"]},\"Viton\":{\"B\":[\"7300197\"],\"L\":[\"7300194\"],\"V\":[\"7300197\"],\"W\":[\"7300194\"],\"R\":[\"7300197\"],\"S\":[\"7300194\"],\"Y\":[\"7300197\"],\"Z\":[\"7300194\"],\"D\":[\"7300197\"],\"M\":[\"7300194\"]}},\"accessory\":{\"safeline\":{\"EPDM\":{\"coupler\":[\"5880532\"],\"cap\":[\"5880451\"]},\"Viton\":{\"coupler\":[\"5880455\"],\"cap\":[\"5880454\"]},\"Food\":{\"coupler\":[\"5880514\"],\"cap\":[\"5880451\"]}},\"cds_voetklep\":{\"Viton\":{\"coupler\":[\"5880445\"],\"cap\":[\"5880454\"]}}},\"sensorConnector\":{\"B\":[\"9900631\"],\"D\":[\"9900632\"],\"C\":[\"9900631\",\"9900632\"],\"E\":[\"9900631\"],\"J\":[\"9900631\",\"9900632\"]},\"sensorCounterConnector\":{\"B\":[\"9900603\"],\"D\":[\"9900602\"],\"C\":[\"9900603\",\"9900602\"],\"E\":[\"9900603\"],\"J\":[\"9900603\",\"9900602\"]}};\n\/\/ SKU -> WooCommerce product-ID, voor het daadwerkelijk toevoegen aan de winkelwagen via\n\/\/ WooCommerce's eigen wc-ajax=add_to_cart endpoint. Bron: handmatige export Producten -> Exporteren\n\/\/ (september 2026). Bij nieuwe producten in de webshop moet deze lijst worden bijgewerkt.\nconst SKU_TO_PRODUCT_ID = {\"5880435\":\"2284\",\"5880445\":\"2286\",\"5880532\":\"2288\",\"5880451-old\":\"2290\",\"5880454\":\"2292\",\"5880455\":\"2294\",\"5880527\":\"2296\",\"5880481\":\"2298\",\"5880482\":\"2300\",\"5880483\":\"2302\",\"5880484\":\"2304\",\"5880485\":\"2306\",\"5880530\":\"2308\",\"5880487\":\"2310\",\"5880528\":\"2312\",\"5880491\":\"2314\",\"6000245\":\"2316\",\"6000252\":\"2318\",\"6020217\":\"2319\",\"6080057\":\"2321\",\"7070120\":\"2323\",\"7070121\":\"2325\",\"7250057\":\"2327\",\"7250058\":\"2329\",\"7300192\":\"2331\",\"7300194\":\"2333\",\"7300196\":\"2335\",\"7300197\":\"2337\",\"9900602\":\"2339\",\"9900603\":\"2341\",\"9900612\":\"2342\",\"9900631\":\"2344\",\"9900632\":\"2346\",\"9900641\":\"2347\",\"9900642\":\"2348\",\"9900643\":\"2349\",\"9900659\":\"2350\",\"9900660\":\"2351\",\"9900661\":\"2352\",\"9900663\":\"2353\",\"9900669\":\"2354\",\"9900670\":\"2355\",\"9900689\":\"2357\",\"9900694\":\"2358\",\"9900695\":\"2359\",\"9900697\":\"2361\",\"5880529\":\"2804\",\"5880501\":\"2808\",\"5840483\":\"2852\",\"5600555\":\"2868\",\"5600556\":\"2880\",\"5880511\":\"2941\",\"5880509\":\"2942\",\"5880513\":\"2943\",\"5880514\":\"2944\",\"5880519\":\"3135\",\"5600557\":\"4860\",\"5880521\":\"64132\",\"5880387\":\"64135\",\"5880447\":\"68605\",\"5880437\":\"68606\",\"5880439\":\"68607\",\"7300213\":\"68609\",\"7300214\":\"68610\",\"5820027\":\"68705\",\"5820269\":\"68736\",\"5880451\":\"71332\",\"5880526\":\"2278\",\"5880531\":\"2281\",\"5880434\":\"2283\",\"5880431\":\"2282\",\"5880423\":\"2279\"};\n\n\/\/ Gravity Forms-koppeling \u2014 vult een verborgen Gravity Form op dezelfde\n\/\/ pagina in en dient dat in. Geen iframe\/postMessage nodig, in tegenstelling\n\/\/ tot de configurator, omdat de Checker rechtstreeks op de pagina draait.\n\/\/ Twee formulieren:\n\/\/ - Formulier 15 (\"Checker Result Request\"): \"Mail dit resultaat\" \u2014 stuurt\n\/\/   alleen een klantbevestiging met PDF, geen interne melding.\n\/\/ - Formulier 13 (bestaand offerteformulier): \"Request your quote\" \u2014 stuurt\n\/\/   zowel een klantbevestiging als een interne melding naar het salesteam.\nconst GF_RESULT_FORM_ID = 15;\nconst GF_RESULT_FIELD_NAME = 1;\nconst GF_RESULT_FIELD_EMAIL = 3;\nconst GF_RESULT_FIELD_PHONE = 4;\nconst GF_RESULT_FIELD_COMPANY = 6;\nconst GF_RESULT_FIELD_DETAILS = 7;\nconst GF_RESULT_FIELD_LANGUAGE = 15;\n\nconst GF_QUOTE_FORM_ID = 13;\nconst GF_QUOTE_FIELD_NAME = 12;\nconst GF_QUOTE_FIELD_EMAIL = 5;\nconst GF_QUOTE_FIELD_PHONE = 4;\nconst GF_QUOTE_FIELD_COMPANY = 3;\nconst GF_QUOTE_FIELD_DETAILS = 13;\nconst GF_QUOTE_FIELD_QUANTITY = 14;\nconst GF_QUOTE_FIELD_LANGUAGE = 8;\n\nfunction gfInputId(formId, fieldId){\n  return 'input_' + formId + '_' + fieldId;\n}\n\nconst GF_PENDING_UI = {};\nfunction beginGravityFormSubmission(formId, statusEl, pendingText){\n  if(GF_PENDING_UI[formId]) return false;\n  const formWrap = statusEl ? statusEl.closest('.vb-email-form') : null;\n  const timeoutId = setTimeout(() => finishGravityFormSubmission(formId, false, 'timeout'), 25000);\n  GF_PENDING_UI[formId] = { statusEl, formWrap, timeoutId, lang: CURRENT_LANG };\n  const formKind = vbMetricFormKind(formId);\n  if(formKind) vbMetric('form_submission_started', { form_kind:formKind, language:CURRENT_LANG, outcome:'started', interaction:'submit' });\n  if(statusEl){\n    statusEl.classList.remove('vb-email-status-error', 'vb-email-status-success');\n    statusEl.textContent = pendingText + '\u2026';\n  }\n  if(formWrap){\n    formWrap.querySelectorAll('button.vb-cta-btn').forEach(btn => { btn.disabled = true; });\n  }\n  return true;\n}\nfunction finishGravityFormSubmission(formId, success, reason){\n  const pending = GF_PENDING_UI[formId];\n  if(!pending) return;\n  const S = STRINGS[pending.lang] || STRINGS[CURRENT_LANG];\n  const statusEl = pending.statusEl;\n  const formWrap = pending.formWrap;\n  if(pending.timeoutId) clearTimeout(pending.timeoutId);\n  const feedbackText = success\n    ? (formId === GF_QUOTE_FORM_ID ? S.quoteFormSuccess : S.emailFormSuccess)\n    : (formId === GF_QUOTE_FORM_ID ? S.quoteFormMissingForm : S.emailFormMissingForm);\n  let statusElOk = false;\n  if(statusEl){\n    if(statusEl.isConnected) statusElOk = true;\n  }\n  if(statusElOk){\n    statusEl.classList.remove('vb-email-status-error', 'vb-email-status-success');\n    if(success){\n      statusEl.classList.add('vb-email-status-success');\n      statusEl.innerHTML = buildSuccessHtml(feedbackText);\n    } else {\n      statusEl.classList.add('vb-email-status-error');\n      statusEl.textContent = feedbackText;\n    }\n  } else {\n    \/\/ Resultaat-DOM kan tijdens de AJAX-submit vervangen zijn door een nieuwe zoekactie of\n    \/\/ taalwissel. Laat de bevestiging dan globaal zien in plaats van in een detached element.\n    showFormFeedbackToast(feedbackText, success);\n  }\n  let formWrapOk = false;\n  if(formWrap){\n    if(formWrap.isConnected) formWrapOk = true;\n  }\n  if(formWrapOk){\n    if(success){\n      formWrap.querySelectorAll('input, button.vb-cta-btn').forEach(elm => { elm.style.display = 'none'; });\n    } else {\n      formWrap.querySelectorAll('button.vb-cta-btn').forEach(btn => { btn.disabled = false; });\n    }\n  }\n  const formKind = vbMetricFormKind(formId);\n  if(formKind){\n    const metricPayload = { form_kind:formKind, language:pending.lang || CURRENT_LANG, outcome:success ? 'success' : 'failure', error_type:success ? 'none' : (reason === 'timeout' ? 'service' : 'validation') };\n    if(!success) metricPayload.reason = reason || 'unknown';\n    vbMetric('form_submission_completed', metricPayload);\n  }\n  delete GF_PENDING_UI[formId];\n}\nfunction inspectGravityFormForErrors(formId){\n  if(!GF_PENDING_UI[formId]) return;\n  const wrapper = document.getElementById('gform_wrapper_' + formId);\n  let hasValidationError = false;\n  if(wrapper){\n    if(wrapper.querySelector('.gform_validation_errors, .validation_error, .gfield_error')) hasValidationError = true;\n  }\n  if(hasValidationError){\n    finishGravityFormSubmission(formId, false, 'validation');\n  }\n}\nlet VB_GF_LEGACY_HOOKS_BOUND = false;\nlet VB_GF_MODERN_HOOKS_BOUND = false;\nfunction bindLegacyGravityFormsHooks(){\n  if(VB_GF_LEGACY_HOOKS_BOUND || !window.jQuery) return;\n  VB_GF_LEGACY_HOOKS_BOUND = true;\n  window.jQuery(document).on('gform_confirmation_loaded.variboxChecker', function(event, formId){\n    finishGravityFormSubmission(Number(formId), true);\n  });\n  window.jQuery(document).on('gform_post_render.variboxChecker', function(event, formId){\n    setTimeout(() => inspectGravityFormForErrors(Number(formId)), 0);\n  });\n}\nfunction bindModernGravityFormsHooks(){\n  if(VB_GF_MODERN_HOOKS_BOUND || !window.gform || !window.gform.utils || typeof window.gform.utils.addAsyncFilter !== 'function') return;\n  VB_GF_MODERN_HOOKS_BOUND = true;\n  window.gform.utils.addAsyncFilter('gform\/ajax\/pre_display_confirmation', async function(data){\n    if(data){\n      if(data.formId != null) finishGravityFormSubmission(Number(data.formId), true);\n    }\n    return data;\n  });\n  window.gform.utils.addAsyncFilter('gform\/ajax\/pre_display_error', async function(data){\n    if(data){\n      if(data.formId != null) finishGravityFormSubmission(Number(data.formId), false, 'ajax');\n    }\n    return data;\n  });\n}\nfunction registerGravityFormsFeedbackHooks(){\n  bindLegacyGravityFormsHooks();\n  bindModernGravityFormsHooks();\n  document.addEventListener('gform\/theme\/scripts_loaded', function(){\n    bindLegacyGravityFormsHooks();\n    bindModernGravityFormsHooks();\n  });\n  document.addEventListener('gform\/post_render', function(event){\n    bindLegacyGravityFormsHooks();\n    bindModernGravityFormsHooks();\n    let formId = NaN;\n    if(event){\n      if(event.detail) formId = Number(event.detail.formId);\n    }\n    if(!Number.isNaN(formId)) setTimeout(() => inspectGravityFormForErrors(formId), 0);\n  });\n  const bindWhenReady = function(){ bindLegacyGravityFormsHooks(); bindModernGravityFormsHooks(); };\n  if(document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bindWhenReady, { once:true });\n  window.addEventListener('load', bindWhenReady, { once:true });\n}\nregisterGravityFormsFeedbackHooks();\n\n\/\/ Zet een gedecodeerd resultaat om naar leesbare platte tekst voor het\n\/\/ verborgen \"Resultaatdetails\"-veld (komt terecht in de PDF-bijlage).\nfunction buildResultDetailsText(result, S, group){\n  const lines = [];\n  lines.push(S.labelType + ': ' + result.typeName + ' (' + result.typeCode + ')');\n  lines.push('Code: ' + result.code);\n  let groupHasMultipleInputs = false;\n  if(group){\n    if(group.count > 1){\n      if(Array.isArray(group.inputs)){\n        if(group.inputs.length > 0) groupHasMultipleInputs = true;\n      }\n    }\n  }\n  if(groupHasMultipleInputs){\n    lines.push(S.groupNote.replace('{count}', group.count).replace('{list}', group.inputs.join(', ')));\n  } else if(result.matchedSerial){\n    lines.push(S.serialMatchNote.replace('{serial}', result.matchedSerial));\n  }\n  if(result.isDrumtainer){\n    lines.push(S.labelTrailer + ': ' + (result.trailerMatches[0] ? result.trailerMatches[0][0] : S.unknownCode));\n    lines.push(S.labelCombo + ': ' + (result.comboMatches[0] ? result.comboMatches[0][0] : S.unknownCode));\n    lines.push(S.labelKleur + ': ' + (result.kleurMatches[0] ? result.kleurMatches[0][0] : S.unknownCode));\n  } else {\n    lines.push(S.labelPakking + ': ' + (result.pakkingMatches[0] ? result.pakkingMatches[0][0] : S.unknownCode));\n    lines.push(S.labelZuigbuis + ': ' + (result.zuigbuisMatches[0] ? result.zuigbuisMatches[0][0] : S.unknownCode));\n    lines.push(S.labelSensor + ': ' + (result.sensorMatches[0] ? result.sensorMatches[0][0] : S.unknownCode));\n    lines.push(S.labelKleur + ': ' + (result.kleurMatches[0] ? result.kleurMatches[0][0] : S.unknownCode));\n    lines.push(S.labelFoodContact + ': ' + (result.foodContact ? S.yesWord : S.noWord));\n  }\n  return lines.join('\\n');\n}\n\n\/\/ Bewaart de laatst getoonde resultaten (in kaartvolgorde) zodat de\n\/\/ \"Mail dit resultaat\"-knoppen, die alleen de kaart-index meekrijgen, het\n\/\/ bijbehorende resultaat kunnen terugvinden op het moment van versturen.\nlet LAST_RENDERED_RESULTS = [];\nlet LAST_RENDERED_GROUPS = [];\n\n\/\/ Verzamelt alle getoonde resultaten (met hun per-kaart ingevulde aantal) tot\n\/\/ \u00e9\u00e9n offerteaanvraag: \u00e9\u00e9n klantnaam\/e-mail\/telefoon\/bedrijf, \u00e9\u00e9n inzending\n\/\/ in formulier 13, met een regel per configuratie (inclusief aantal) in het\n\/\/ resultaatdetails-veld en de som van alle aantallen in het aparte\n\/\/ aantal-veld (indien GF_QUOTE_FIELD_QUANTITY is ingevuld).\n\/\/ Verzamelt een leesbare samenvatting van alle AANGEVINKTE losse onderdelen (uit alle\n\/\/ resultaatkaarten tegelijk), zodat zowel de offerte-aanvraag als de e-mail-functie ook de\n\/\/ gewenste losse onderdelen kunnen meesturen -- niet alleen de containers zelf.\nfunction collectSelectedPartsSummary(){\n  const lines = [];\n  const checked = document.querySelectorAll('[id^=\"vb-parts-popup-\"] .vb-part-checkbox:checked');\n  checked.forEach(cb => {\n    const row = cb.closest('.vb-part-card');\n    const popup = cb.closest('[id^=\"vb-parts-popup-\"]');\n    if(!row || !popup) return;\n    const popupIdx = popup.id.replace('vb-parts-popup-', '');\n    const itemIdx = row.dataset.itemIdx;\n    const qty = itemIdx != null ? getPartQty(popupIdx, itemIdx) : 1;\n    const roleEl = row.querySelector('.vb-part-role');\n    const labelEl = row.querySelector('.vb-part-label');\n    const role = roleEl ? roleEl.textContent.trim() : '';\n    const label = labelEl ? labelEl.textContent.trim() : '';\n    const description = label ? (role ? role + ': ' + label : label) : role;\n    if(description) lines.push(qty + 'x ' + description);\n  });\n  return lines;\n}\nfunction submitCombinedQuote(){\n  const lang = CURRENT_LANG;\n  const S = STRINGS[lang];\n  const statusEl = document.getElementById('vb-combined-quote-status');\n  if(!statusEl) return;\n\n  const name = (document.getElementById('vb-combined-quote-name').value || '').trim();\n  const email = (document.getElementById('vb-combined-quote-email').value || '').trim();\n  const phone = (document.getElementById('vb-combined-quote-phone').value || '').trim();\n  const company = (document.getElementById('vb-combined-quote-company').value || '').trim();\n\n  if(!name || !email){\n    statusEl.textContent = S.quoteFormError;\n    statusEl.classList.add('vb-email-status-error');\n    vbMetric('form_validation_error', { form_kind:'quote', language:lang, outcome:'failure', reason:'validation', error_type:'validation' });\n    return;\n  }\n\n  let totalQty = 0;\n  const lines = [];\n  LAST_RENDERED_GROUPS.forEach((group, idx) => {\n    const result = group.result;\n    if(result.error) return;\n    const qtyEl = document.getElementById('vb-qty-input-' + idx);\n    let qty = normalizePartQty(qtyEl ? qtyEl.value : group.count || 1);\n    totalQty += qty;\n    lines.push(qty + 'x ' + result.code + ' \u2014 ' + result.typeName);\n    lines.push(buildResultDetailsText(result, S, group));\n    lines.push('');\n  });\n\n  let detailsText = lines.join('\\n');\n  const partsSummaryQuote = collectSelectedPartsSummary();\n  if(partsSummaryQuote.length > 0){\n    detailsText += '\\n\\n' + S.quotePartsSectionTitle + ':\\n' + partsSummaryQuote.map(l => '- ' + l).join('\\n');\n  }\n\n  const nameField = document.getElementById(gfInputId(GF_QUOTE_FORM_ID, GF_QUOTE_FIELD_NAME));\n  const emailField = document.getElementById(gfInputId(GF_QUOTE_FORM_ID, GF_QUOTE_FIELD_EMAIL));\n  const detailsField = document.getElementById(gfInputId(GF_QUOTE_FORM_ID, GF_QUOTE_FIELD_DETAILS));\n\n  if(!nameField || !emailField || !detailsField){\n    statusEl.textContent = S.quoteFormMissingForm;\n    statusEl.classList.add('vb-email-status-error');\n    vbMetric('form_submission_blocked', { form_kind:'quote', language:lang, outcome:'failure', reason:'missing_form', error_type:'missing_form' });\n    return;\n  }\n\n  const phoneField = document.getElementById(gfInputId(GF_QUOTE_FORM_ID, GF_QUOTE_FIELD_PHONE));\n  const companyField = document.getElementById(gfInputId(GF_QUOTE_FORM_ID, GF_QUOTE_FIELD_COMPANY));\n  const qtyField = GF_QUOTE_FIELD_QUANTITY ? document.getElementById(gfInputId(GF_QUOTE_FORM_ID, GF_QUOTE_FIELD_QUANTITY)) : null;\n  const langField = GF_QUOTE_FIELD_LANGUAGE ? document.getElementById(gfInputId(GF_QUOTE_FORM_ID, GF_QUOTE_FIELD_LANGUAGE)) : null;\n\n  nameField.value = name;\n  emailField.value = email;\n  if(phoneField) phoneField.value = phone;\n  if(companyField) companyField.value = company;\n  if(qtyField) qtyField.value = totalQty;\n  if(langField) langField.value = lang;\n  detailsField.value = detailsText;\n\n  const submitBtn = document.getElementById('gform_submit_button_' + GF_QUOTE_FORM_ID);\n  const gfForm = document.getElementById('gform_' + GF_QUOTE_FORM_ID);\n  let hasNoForm = false;\n  if(!submitBtn){\n    if(!gfForm) hasNoForm = true;\n  }\n  if(hasNoForm){\n    statusEl.textContent = S.quoteFormMissingForm;\n    statusEl.classList.add('vb-email-status-error');\n    vbMetric('form_submission_blocked', { form_kind:'quote', language:lang, outcome:'failure', reason:'missing_form', error_type:'missing_form' });\n    return;\n  }\n  if(!beginGravityFormSubmission(GF_QUOTE_FORM_ID, statusEl, S.quoteFormSubmit)) return;\n  if(submitBtn){\n    submitBtn.click();\n  } else if(gfForm){\n    if(gfForm.requestSubmit) gfForm.requestSubmit(); else gfForm.submit();\n  }\n}\n\n\/\/ Verzamelt alle getoonde resultaten tot \u00e9\u00e9n \"Mail dit resultaat\"-inzending\n\/\/ (formulier 15, alleen klantbevestiging met PDF) \u2014 analoog aan\n\/\/ submitCombinedQuote(), maar zonder aantallen (die zijn alleen relevant\n\/\/ voor een offerteaanvraag).\nfunction submitCombinedEmail(){\n  const lang = CURRENT_LANG;\n  const S = STRINGS[lang];\n  const statusEl = document.getElementById('vb-combined-email-status');\n  if(!statusEl) return;\n\n  const name = (document.getElementById('vb-combined-email-name').value || '').trim();\n  const email = (document.getElementById('vb-combined-email-email').value || '').trim();\n  const phone = (document.getElementById('vb-combined-email-phone').value || '').trim();\n  const company = (document.getElementById('vb-combined-email-company').value || '').trim();\n\n  if(!name || !email){\n    statusEl.textContent = S.emailFormError;\n    statusEl.classList.add('vb-email-status-error');\n    vbMetric('form_validation_error', { form_kind:'email', language:lang, outcome:'failure', reason:'validation', error_type:'validation' });\n    return;\n  }\n\n  const lines = [];\n  LAST_RENDERED_GROUPS.forEach((group) => {\n    const result = group.result;\n    if(result.error) return;\n    lines.push(buildResultDetailsText(result, S, group));\n    lines.push('');\n  });\n  let detailsText = lines.join('\\n');\n  const partsSummaryEmail = collectSelectedPartsSummary();\n  if(partsSummaryEmail.length > 0){\n    detailsText += '\\n\\n' + S.quotePartsSectionTitle + ':\\n' + partsSummaryEmail.map(l => '- ' + l).join('\\n');\n  }\n\n  const nameField = document.getElementById(gfInputId(GF_RESULT_FORM_ID, GF_RESULT_FIELD_NAME));\n  const emailField = document.getElementById(gfInputId(GF_RESULT_FORM_ID, GF_RESULT_FIELD_EMAIL));\n  const detailsField = document.getElementById(gfInputId(GF_RESULT_FORM_ID, GF_RESULT_FIELD_DETAILS));\n\n  if(!nameField || !emailField || !detailsField){\n    statusEl.textContent = S.emailFormMissingForm;\n    statusEl.classList.add('vb-email-status-error');\n    vbMetric('form_submission_blocked', { form_kind:'email', language:lang, outcome:'failure', reason:'missing_form', error_type:'missing_form' });\n    return;\n  }\n\n  const phoneField = document.getElementById(gfInputId(GF_RESULT_FORM_ID, GF_RESULT_FIELD_PHONE));\n  const companyField = document.getElementById(gfInputId(GF_RESULT_FORM_ID, GF_RESULT_FIELD_COMPANY));\n  const langField = GF_RESULT_FIELD_LANGUAGE ? document.getElementById(gfInputId(GF_RESULT_FORM_ID, GF_RESULT_FIELD_LANGUAGE)) : null;\n\n  nameField.value = name;\n  emailField.value = email;\n  if(phoneField) phoneField.value = phone;\n  if(companyField) companyField.value = company;\n  if(langField) langField.value = lang;\n  detailsField.value = detailsText;\n\n  const submitBtn = document.getElementById('gform_submit_button_' + GF_RESULT_FORM_ID);\n  const gfForm = document.getElementById('gform_' + GF_RESULT_FORM_ID);\n  let hasNoForm2 = false;\n  if(!submitBtn){\n    if(!gfForm) hasNoForm2 = true;\n  }\n  if(hasNoForm2){\n    statusEl.textContent = S.emailFormMissingForm;\n    statusEl.classList.add('vb-email-status-error');\n    vbMetric('form_submission_blocked', { form_kind:'email', language:lang, outcome:'failure', reason:'missing_form', error_type:'missing_form' });\n    return;\n  }\n  if(!beginGravityFormSubmission(GF_RESULT_FORM_ID, statusEl, S.emailFormSubmit)) return;\n  if(submitBtn){\n    submitBtn.click();\n  } else if(gfForm){\n    if(gfForm.requestSubmit) gfForm.requestSubmit(); else gfForm.submit();\n  }\n}\n\n\/\/ Serienummer -> artikelnummer koppeling. Dit bestand is te groot (35.000+\n\/\/ entries, ~900KB) om nog in de widget-code zelf op te nemen, dus wordt\n\/\/ opgehaald als los bestand \u2014 maar pas op het moment dat een klant\n\/\/ daadwerkelijk een serienummer (8 tekens) invoert, en daarna gecachet in het\n\/\/ geheugen voor de rest van het bezoek (zodat het niet telkens opnieuw wordt\n\/\/ gedownload).\nconst SERIAL_LOOKUP_URL = 'https:\/\/varibox.best4u.dev\/wp-content\/uploads\/varibox-serial-lookup.json';\nconst SERIAL_LOOKUP_ERROR_TEXT = {\n  nl: 'De serienummerdatabase kan op dit moment niet worden geladen. Probeer het opnieuw, of gebruik het 12-teken artikelnummer.',\n  en: 'The serial-number database cannot be loaded right now. Please try again, or use the 12-character article number.',\n  de: 'Die Seriennummerdatenbank kann derzeit nicht geladen werden. Bitte versuchen Sie es erneut oder verwenden Sie die 12-stellige Artikelnummer.',\n  fr: 'La base des num\u00e9ros de s\u00e9rie ne peut pas \u00eatre charg\u00e9e pour le moment. R\u00e9essayez ou utilisez le num\u00e9ro d\u2019article \u00e0 12 caract\u00e8res.',\n  it: 'Al momento non \u00e8 possibile caricare il database dei numeri di serie. Riprovi oppure utilizzi il numero articolo di 12 caratteri.',\n  es: 'La base de datos de n\u00fameros de serie no se puede cargar en este momento. Int\u00e9ntelo de nuevo o utilice el n\u00famero de art\u00edculo de 12 caracteres.',\n  pl: 'Nie mo\u017cna teraz za\u0142adowa\u0107 bazy numer\u00f3w seryjnych. Prosz\u0119 spr\u00f3bowa\u0107 ponownie lub u\u017cy\u0107 12-znakowego numeru artyku\u0142u.'\n};\nfunction fetchWithTimeout(url, options, timeoutMs){\n  const opts = Object.assign({}, options || {});\n  const controller = typeof AbortController === 'function' ? new AbortController() : null;\n  if(controller){\n    if(!opts.signal) opts.signal = controller.signal;\n  }\n  let timeoutId = null;\n  const timeoutPromise = new Promise((resolve, reject) => {\n    timeoutId = setTimeout(() => {\n      if(controller) controller.abort();\n      reject(new Error('request timed out after ' + timeoutMs + 'ms'));\n    }, timeoutMs);\n  });\n  return Promise.race([fetch(url, opts), timeoutPromise]).finally(() => {\n    if(timeoutId !== null) clearTimeout(timeoutId);\n  });\n}\n\nlet SERIAL_LOOKUP_CACHE = null;\nlet serialLookupPromise = null;\nfunction loadSerialLookup(){\n  if (SERIAL_LOOKUP_CACHE) return Promise.resolve(SERIAL_LOOKUP_CACHE);\n  if (serialLookupPromise) return serialLookupPromise;\n  serialLookupPromise = fetchWithTimeout(SERIAL_LOOKUP_URL, { credentials:'same-origin' }, 10000)\n    .then(r => { if(!r.ok) throw new Error('serial lookup fetch failed: ' + r.status); return r.json(); })\n    .then(data => {\n      if(!data || typeof data !== 'object' || Array.isArray(data)) throw new Error('serial lookup has an invalid format');\n      SERIAL_LOOKUP_CACHE = data;\n      serialLookupPromise = null;\n      return data;\n    })\n    .catch(err => {\n      serialLookupPromise = null; \/\/ allow a retry after a transient network\/CDN failure\n      throw err;\n    });\n  return serialLookupPromise;\n}\n\/\/ Cache voor live opgehaalde productdata (naam, afbeelding, prijs) via WooCommerce's eigen\n\/\/ publieke Store API. Wordt per product-ID maar \u00e9\u00e9n keer per sessie opgehaald, pas op het\n\/\/ moment dat een klant de onderdelen-pop-up daadwerkelijk openklapt (niet vooraf voor elke\n\/\/ kaart, om onnodige verzoeken te voorkomen bij bulk-invoer met veel resultaten).\nconst PRODUCT_DATA_CACHE = {};\nconst PRODUCT_DATA_MISSING = new Map();\nconst PRODUCT_DATA_MISSING_TTL_MS = 60000;\nlet PRODUCT_DATA_INFLIGHT = null;\nfunction isProductDataMissingFresh(sku){\n  const key = String(sku);\n  const seenAt = PRODUCT_DATA_MISSING.get(key);\n  if(!seenAt) return false;\n  if(Date.now() - seenAt < PRODUCT_DATA_MISSING_TTL_MS) return true;\n  PRODUCT_DATA_MISSING.delete(key);\n  return false;\n}\n\/\/ Aantal per onderdeel-vakje, per resultaatkaart. Sleutel: \"idx-itemIdx\". Standaard 1 zodra\n\/\/ een vakje voor het eerst wordt aangepast; ontbrekende sleutels tellen als 1.\nconst PART_QTY_STATE = {};\nfunction normalizePartQty(value){\n  const n = parseInt(value, 10);\n  if(!Number.isFinite(n) || n < 1) return 1;\n  return Math.min(n, 999);\n}\nfunction getPartQty(idx, itemIdx){\n  const key = idx + '-' + itemIdx;\n  return normalizePartQty(PART_QTY_STATE[key]);\n}\n\/\/ Past het aantal voor \u00e9\u00e9n onderdeel-vakje aan (min. 1), werkt de weergave en de prijs\/\n\/\/ subtotaal bij. Vinkt het vakje NIET automatisch aan -- dat blijft een losse keuze.\n\/\/ Onthoudt welke onderdelen (en welk aantal) een klant heeft aangevinkt, per gedecodeerd\n\/\/ artikelnummer, binnen de browsertab-sessie (verdwijnt bij sluiten van het tabblad). Zo gaat\n\/\/ een selectie niet verloren bij per ongeluk verversen of terugnavigeren. sessionStorage kan\n\/\/ in sommige browserinstellingen geblokkeerd zijn -- faalt dan stil, zonder de rest te breken.\nconst PARTS_SELECTION_STORAGE_KEY = 'vb_parts_selection';\nfunction savePartsSelectionState(){\n  try{\n    let state = {};\n    const existing = sessionStorage.getItem(PARTS_SELECTION_STORAGE_KEY);\n    if(existing){\n      const parsed = JSON.parse(existing);\n      if(parsed){\n        if(typeof parsed === 'object'){\n          if(!Array.isArray(parsed)) state = parsed;\n        }\n      }\n    }\n    LAST_RENDERED_RESULTS.forEach((result, idx) => {\n      if(result.error) return;\n      const popup = document.getElementById('vb-parts-popup-' + idx);\n      if(!popup) return;\n      const checked = popup.querySelectorAll('.vb-part-checkbox:checked');\n      if(checked.length === 0){\n        delete state[result.code];\n        return;\n      }\n      const codeState = {};\n      checked.forEach(cb => {\n        const row = cb.closest('.vb-part-card');\n        const itemIdx = row ? row.dataset.itemIdx : null;\n        if(itemIdx === null) return;\n        const stateKey = (row.dataset.skus || '').trim() || cb.dataset.productIds;\n        codeState[stateKey] = getPartQty(idx, itemIdx);\n      });\n      if(Object.keys(codeState).length > 0) state[result.code] = codeState;\n    });\n    sessionStorage.setItem(PARTS_SELECTION_STORAGE_KEY, JSON.stringify(state));\n  } catch(e){ \/* sessionStorage niet beschikbaar -- gewoon negeren *\/ }\n}\nfunction restorePartsSelectionState(){\n  let state = null;\n  try{\n    const raw = sessionStorage.getItem(PARTS_SELECTION_STORAGE_KEY);\n    if(raw) state = JSON.parse(raw);\n  } catch(e){ return; }\n  if(!state) return;\n  LAST_RENDERED_RESULTS.forEach((result, idx) => {\n    if(result.error) return;\n    const codeState = state[result.code];\n    if(!codeState) return;\n    const popup = document.getElementById('vb-parts-popup-' + idx);\n    if(!popup) return;\n    popup.querySelectorAll('.vb-part-checkbox').forEach(cb => {\n      const row = cb.closest('.vb-part-card');\n      const stateKey = row ? ((row.dataset.skus || '').trim() || cb.dataset.productIds) : cb.dataset.productIds;\n      const savedQty = codeState[stateKey] !== undefined ? codeState[stateKey] : codeState[cb.dataset.productIds];\n      if(savedQty !== undefined){\n        cb.checked = true;\n        const itemIdx = row ? row.dataset.itemIdx : null;\n        if(itemIdx !== null){\n          const normalizedQty = normalizePartQty(savedQty);\n          PART_QTY_STATE[idx + '-' + itemIdx] = normalizedQty;\n          const valEl = document.getElementById('vb-part-qty-' + idx + '-' + itemIdx);\n          if(valEl) valEl.textContent = String(normalizedQty);\n        }\n      }\n    });\n    updatePartsSubtotal(idx);\n    updatePartsKitStrip(idx);\n  });\n  updateCombinedPartsTotal();\n}\nfunction adjustPartQty(idx, itemIdx, delta){\n  const key = idx + '-' + itemIdx;\n  let val = normalizePartQty(getPartQty(idx, itemIdx) + delta);\n  PART_QTY_STATE[key] = val;\n  const valEl = document.getElementById('vb-part-qty-' + idx + '-' + itemIdx);\n  if(valEl) valEl.textContent = String(val);\n  updatePartRowPrice(idx, itemIdx);\n  updatePartsSubtotal(idx);\n  updateCombinedPartsTotal();\n  savePartsSelectionState();\n  vbMetric('part_quantity_changed', { quantity:val, language:CURRENT_LANG, interaction:delta >= 0 ? 'increase' : 'decrease' });\n}\n\/\/ Bouwt de live \"pakket\"-strip bovenaan de pop-up op: \u00e9\u00e9n klein fotootje per aangevinkt\n\/\/ onderdeel, gebaseerd op de al opgehaalde live productfoto (eerste SKU van het vakje). Wordt\n\/\/ bij elke aan\/uitvink-actie herbouwd, zodat het geheel meegroeit met de keuze van de klant.\nfunction updatePartsKitStrip(idx){\n  const strip = document.getElementById('vb-parts-kit-strip-' + idx);\n  if(!strip) return;\n  const popup = document.getElementById('vb-parts-popup-' + idx);\n  if(!popup) return;\n  const checked = popup.querySelectorAll('.vb-part-checkbox:checked');\n  if(checked.length === 0){\n    strip.innerHTML = '';\n    strip.classList.remove('vb-visible');\n    return;\n  }\n  let html = '';\n  checked.forEach(cb => {\n    const row = cb.closest('.vb-part-card');\n    if(!row) return;\n    const skus = (row.dataset.skus || '').split(',').filter(Boolean);\n    const firstSku = skus[0];\n    const data = firstSku ? PRODUCT_DATA_CACHE[firstSku] : null;\n    const img = data ? data.image : null;\n    if(img){\n      html += `<div class=\"vb-kit-thumb\"><img decoding=\"async\" src=\"${esc(img)}\" alt=\"\"><\/div>`;\n    } else {\n      html += `<div class=\"vb-kit-thumb vb-kit-thumb-empty\"><\/div>`;\n    }\n  });\n  strip.innerHTML = html;\n  strip.classList.add('vb-visible');\n}\nfunction onPartCheckboxChange(idx, itemIdx){\n  updatePartsSubtotal(idx);\n  updateCombinedPartsTotal();\n  updatePartsKitStrip(idx);\n  savePartsSelectionState();\n  const popup = document.getElementById('vb-parts-popup-' + idx);\n  const checkbox = document.getElementById('vb-part-' + idx + '-' + itemIdx);\n  const selectedCount = popup ? popup.querySelectorAll('.vb-part-checkbox:checked').length : 0;\n  vbMetric('part_selection_changed', { selected_count:selectedCount, language:CURRENT_LANG, interaction:(checkbox ? checkbox.checked : false) ? 'select' : 'deselect' });\n}\n\/\/ Zet WooCommerce's Store API-prijsveld (in centen\/kleinste eenheid) om naar een correct\n\/\/ opgemaakte prijstekst, met respect voor de decimaalscheiding\/valutasymbool zoals de API\n\/\/ die zelf teruggeeft (dus geen aannames over EUR\/komma die overal correct zouden moeten zijn).\nfunction formatStorePriceMinor(priceMinor, prices){\n  const numeric = Number(priceMinor);\n  if(!Number.isFinite(numeric)) return null;\n  let minorUnit = 2;\n  let decSep = ',';\n  let thousandSep = '';\n  let prefix = '';\n  let suffix = '';\n  if(prices){\n    if(prices.currency_minor_unit != null) minorUnit = Math.max(0, parseInt(prices.currency_minor_unit, 10) || 0);\n    if(prices.currency_decimal_separator != null) decSep = String(prices.currency_decimal_separator);\n    if(prices.currency_thousand_separator != null) thousandSep = String(prices.currency_thousand_separator);\n    if(prices.currency_prefix) prefix = prices.currency_prefix;\n    if(prices.currency_suffix) suffix = prices.currency_suffix;\n  }\n  const roundedMinor = Math.round(numeric);\n  const sign = roundedMinor < 0 ? '-' : '';\n  const absMinor = Math.abs(roundedMinor);\n  const factor = Math.pow(10, minorUnit);\n  let integerPart = String(Math.floor(absMinor \/ factor));\n  if(thousandSep) integerPart = integerPart.replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, thousandSep);\n  let valueStr = sign + integerPart;\n  if(minorUnit > 0){\n    const fraction = String(absMinor % factor).padStart(minorUnit, '0');\n    valueStr += decSep + fraction;\n  }\n  return prefix + valueStr + suffix;\n}\n\/\/ Haalt naam\/afbeelding\/prijs op voor de meegegeven SKU's (niet product-ID's!) via de Store\n\/\/ API. Reden: deze site is meertalig (WPML) en elke taal heeft een EIGEN intern product-ID\n\/\/ voor dezelfde fysieke SKU. Onze koppeltabel bevat maar \u00e9\u00e9n taal se ID per SKU, dus zoeken\n\/\/ op product-ID levert op een andere taalpagina niets op. De SKU blijft w\u00e9l overal gelijk,\n\/\/ en de Store API geeft dan vanzelf de bij de paginataal passende versie terug.\nasync function fetchProductData(skus){\n  const requested = [...new Set(skus)].filter(Boolean);\n  let uncached = requested.filter(sku => !PRODUCT_DATA_CACHE[sku] ? !isProductDataMissingFresh(sku) : false);\n  if(uncached.length === 0) return;\n  if(PRODUCT_DATA_INFLIGHT){\n    try{ await PRODUCT_DATA_INFLIGHT; } catch(e){ \/* retry below if still uncached *\/ }\n    uncached = requested.filter(sku => !PRODUCT_DATA_CACHE[sku] ? !isProductDataMissingFresh(sku) : false);\n    if(uncached.length === 0) return;\n  }\n  const requestPromise = (async () => {\n   try{\n    const urlObj = buildWpRestUrl('wc\/store\/v1\/products');\n    urlObj.searchParams.set('per_page', '100');\n    urlObj.searchParams.set('sku', uncached.join(','));\n    const url = urlObj.toString();\n    const resp = await fetchWithTimeout(url, { credentials:'same-origin' }, 10000);\n    if(!resp.ok){\n      console.warn('[VARIBOX Checker] Store API gaf status ' + resp.status + ' terug voor ' + url + ' -- prijzen\/afbeeldingen worden niet getoond.');\n      return;\n    }\n    const data = await resp.json();\n    if(!Array.isArray(data)){\n      console.warn('[VARIBOX Checker] Store API-respons is geen array, kreeg:', data);\n      return;\n    }\n    if(data.length === 0){\n      console.warn('[VARIBOX Checker] Store API vond geen producten voor SKU(\\'s): ' + uncached.join(', ') + ' -- controleer of deze producten zichtbaar\/gepubliceerd zijn.');\n    }\n    const returnedSkus = new Set();\n    data.forEach(product => {\n      if(!product.sku) return;\n      returnedSkus.add(String(product.sku));\n      let image = null;\n      if(product.images){\n        if(product.images[0]) image = product.images[0].thumbnail;\n      }\n      let priceMinor = null;\n      let hasPriceField = false;\n      if(product.prices){\n        if(product.prices.price !== undefined) hasPriceField = true;\n      }\n      if(hasPriceField){\n        const parsedPrice = parseInt(product.prices.price, 10);\n        if(Number.isFinite(parsedPrice)) priceMinor = parsedPrice;\n      }\n      \/\/ Store API geeft is_in_stock (bool) en is_purchasable (bool) terug. We behandelen een\n      \/\/ artikel als \"niet op voorraad\" alleen als het expliciet false is -- ontbreekt het veld\n      \/\/ (bijv. oudere WooCommerce-versie), dan gaan we ervan uit dat het gewoon te bestellen is.\n      let inStock = true;\n      if(product.is_in_stock === false) inStock = false;\n      PRODUCT_DATA_CACHE[product.sku] = {\n        id: product.id != null ? String(product.id) : null,\n        name: product.name || '',\n        image: image,\n        priceMinor: priceMinor,\n        prices: product.prices || null,\n        inStock: inStock,\n        purchasable: product.is_purchasable !== false\n      };\n    });\n    uncached.forEach(sku => {\n      if(!returnedSkus.has(String(sku))) PRODUCT_DATA_MISSING.set(String(sku), Date.now());\n    });\n   } catch(e){\n    console.warn('[VARIBOX Checker] Store API-aanroep mislukt:', e);\n    \/\/ stil falen -- widget blijft werken zonder afbeelding\/prijs; mislukte requests worden niet negatief gecachet\n   }\n  })();\n  PRODUCT_DATA_INFLIGHT = requestPromise;\n  try{ await requestPromise; }\n  finally{ if(PRODUCT_DATA_INFLIGHT === requestPromise) PRODUCT_DATA_INFLIGHT = null; }\n}\n\/\/ Vult, n\u00e1 het ophalen, de afbeelding en prijs in bij elke rij van de opengeklapte pop-up.\n\/\/ Telt bij gebundelde onderdelen (meerdere product-ID's per vakje, bijv. stekker + contra\n\/\/ stekker) de losse prijzen bij elkaar op tot \u00e9\u00e9n totaalbedrag voor dat vakje.\n\/\/ Prijs per stuk (v\u00f3\u00f3r vermenigvuldiging met het gekozen aantal) per onderdeel-vakje.\n\/\/ Sleutel: \"idx-itemIdx\". Wordt gevuld door populatePartsRowData zodra de live Store\n\/\/ API-data binnen is, en gebruikt door updatePartRowPrice\/updatePartsSubtotal bij elke\n\/\/ aanpassing van het aantal.\nconst ROW_UNIT_PRICE_STATE = {};\nfunction populatePartsRowData(idx){\n  const popup = document.getElementById('vb-parts-popup-' + idx);\n  if(!popup) return;\n  const S = STRINGS[CURRENT_LANG];\n  const rows = popup.querySelectorAll('.vb-part-card[data-skus]');\n  let selectionChanged = false;\n  rows.forEach(row => {\n    const skus = (row.dataset.skus || '').split(',').filter(Boolean);\n    const itemIdx = row.dataset.itemIdx;\n    if(skus.length === 0) return;\n    const firstData = PRODUCT_DATA_CACHE[skus[0]];\n    const thumbImg = row.querySelector('.vb-part-thumb');\n    if(thumbImg){\n      if(firstData){\n        if(firstData.image){\n          thumbImg.src = firstData.image;\n          const wrap = thumbImg.closest('.vb-part-thumb-wrap');\n          if(wrap) wrap.classList.add('vb-loaded');\n        }\n      }\n    }\n    let total = 0;\n    let anyKnown = false;\n    let refPrices = null;\n    let anyOutOfStock = false;\n    skus.forEach(sku => {\n      const d = PRODUCT_DATA_CACHE[sku];\n      if(d){\n        if(d.priceMinor !== null){\n          total += d.priceMinor;\n          anyKnown = true;\n          refPrices = d.prices;\n        }\n        if(d.inStock === false || d.purchasable === false) anyOutOfStock = true;\n      }\n    });\n    if(anyKnown){\n      ROW_UNIT_PRICE_STATE[idx + '-' + itemIdx] = { priceMinor: total, refPrices: refPrices };\n      updatePartRowPrice(idx, itemIdx);\n    }\n    const stockEl = document.getElementById('vb-part-stock-' + idx + '-' + itemIdx);\n    const checkboxEl = document.getElementById('vb-part-' + idx + '-' + itemIdx);\n    const liveIdsComplete = skus.every(sku => PRODUCT_DATA_CACHE[sku] ? !!PRODUCT_DATA_CACHE[sku].id : false);\n    const staticIds = (row.dataset.productIds || '').split(',').filter(Boolean);\n    const staticFallbackComplete = staticIds.length === skus.length;\n    if(anyOutOfStock){\n      if(stockEl) stockEl.textContent = S.partsOutOfStock;\n      if(checkboxEl){\n        if(checkboxEl.checked) selectionChanged = true;\n        checkboxEl.checked = false;\n        checkboxEl.disabled = true;\n      }\n      row.classList.add('vb-part-card-out-of-stock');\n    } else if(!liveIdsComplete ? !staticFallbackComplete : false){\n      if(stockEl) stockEl.textContent = S.partsUnavailable;\n      if(checkboxEl){\n        if(checkboxEl.checked) selectionChanged = true;\n        checkboxEl.checked = false;\n        checkboxEl.disabled = true;\n      }\n      row.classList.add('vb-part-card-unavailable');\n    } else {\n      if(stockEl){\n        if(!row.classList.contains('vb-part-card-partial')) stockEl.textContent = '';\n      }\n      if(checkboxEl){\n        if(!row.classList.contains('vb-part-card-partial')) checkboxEl.disabled = false;\n      }\n      row.classList.remove('vb-part-card-out-of-stock', 'vb-part-card-unavailable');\n    }\n  });\n  updatePartsSubtotal(idx);\n  updateCombinedPartsTotal();\n  updatePartsKitStrip(idx);\n  if(selectionChanged) savePartsSelectionState();\n}\n\/\/ Werkt de getoonde prijs van \u00e9\u00e9n rij bij op basis van het huidige aantal (prijs per stuk \u00d7\n\/\/ aantal). Wordt aangeroepen zowel n\u00e1 het ophalen van de live prijs als bij elke klik op +\/-.\nfunction updatePartRowPrice(idx, itemIdx){\n  const key = idx + '-' + itemIdx;\n  const unit = ROW_UNIT_PRICE_STATE[key];\n  const priceEl = document.getElementById('vb-part-price-' + idx + '-' + itemIdx);\n  if(!priceEl) return;\n  if(!unit) return;\n  const qty = getPartQty(idx, itemIdx);\n  const totalMinor = unit.priceMinor * qty;\n  const formatted = formatStorePriceMinor(totalMinor, unit.refPrices);\n  if(formatted) priceEl.textContent = formatted;\n}\n\/\/ Telt de prijzen van alle AANGEVINKTE rijen in deze pop-up bij elkaar op (elk met zijn eigen\n\/\/ gekozen aantal) en toont dat als lopend subtotaal bovenaan de \"Voeg toe\"-knop.\nfunction updatePartsSubtotal(idx){\n  const popup = document.getElementById('vb-parts-popup-' + idx);\n  const subtotalEl = document.getElementById('vb-parts-subtotal-' + idx);\n  if(!popup) return;\n  if(!subtotalEl) return;\n  const S = STRINGS[CURRENT_LANG];\n  const U = UX_STRINGS[CURRENT_LANG] || UX_STRINGS.en;\n  popup.querySelectorAll('.vb-part-checkbox').forEach(cb => {\n    const row = cb.closest('.vb-part-card');\n    if(row) row.classList.toggle('vb-selected', !!cb.checked);\n  });\n  const checked = popup.querySelectorAll('.vb-part-checkbox:checked');\n  const selectionEl = document.getElementById('vb-parts-selection-summary-' + idx);\n  let selectedQty = 0;\n  checked.forEach(cb => {\n    const row = cb.closest('.vb-part-card');\n    const itemIdx = row ? row.dataset.itemIdx : null;\n    selectedQty += itemIdx !== null ? getPartQty(idx, itemIdx) : 1;\n  });\n  if(selectionEl){\n    selectionEl.textContent = selectedQty > 0 ? U.selected.replace('{count}', selectedQty) : '';\n    selectionEl.classList.toggle('vb-visible', selectedQty > 0);\n  }\n  let total = 0;\n  let anyKnown = false;\n  let refPrices = null;\n  checked.forEach(cb => {\n    const row = cb.closest('.vb-part-card');\n    const itemIdx = row ? row.dataset.itemIdx : null;\n    if(itemIdx === null) return;\n    const unit = ROW_UNIT_PRICE_STATE[idx + '-' + itemIdx];\n    if(unit){\n      const qty = getPartQty(idx, itemIdx);\n      total += unit.priceMinor * qty;\n      anyKnown = true;\n      refPrices = unit.refPrices;\n    }\n  });\n  if(anyKnown){\n    if(total > 0){\n      const formatted = formatStorePriceMinor(total, refPrices);\n      subtotalEl.textContent = S.partsSubtotalLabel + ': ' + formatted;\n      subtotalEl.classList.add('vb-visible');\n      return;\n    }\n  }\n  subtotalEl.textContent = '';\n  subtotalEl.classList.remove('vb-visible');\n}\n\/\/ Opent\/sluit de onderdelen-pop-up, en haalt bij het OPENEN (niet vooraf) de live prijzen en\n\/\/ afbeeldingen op voor de onderdelen in die kaart -- op basis van SKU, niet product-ID (zie\n\/\/ toelichting bij fetchProductData hierboven).\nfunction setCollapsibleState(el, open){\n  if(!el) return;\n  el.classList.toggle('vb-open', !!open);\n  el.setAttribute('aria-hidden', open ? 'false' : 'true');\n  if(open){\n    el.removeAttribute('inert');\n  } else {\n    el.setAttribute('inert', '');\n  }\n  if(el.id){\n    document.querySelectorAll('[aria-controls=\"' + el.id + '\"]').forEach(btn => {\n      btn.setAttribute('aria-expanded', open ? 'true' : 'false');\n    });\n  }\n}\nfunction syncCombinedPartsButtonState(){\n  const btn = document.getElementById('vb-combined-parts-btn');\n  if(!btn) return;\n  const hasLoadingPopup = !!document.querySelector('.vb-collapsible.vb-parts-data-loading');\n  const cartPending = btn.dataset.vbCartPending === '1';\n  btn.disabled = hasLoadingPopup || cartPending;\n}\nfunction setPartsPopupLoading(popup, loading){\n  if(!popup) return;\n  popup.setAttribute('aria-busy', loading ? 'true' : 'false');\n  popup.classList.toggle('vb-parts-data-loading', !!loading);\n  popup.querySelectorAll('.vb-part-checkbox, .vb-parts-actions .vb-cta-btn').forEach(control => {\n    if(loading){\n      if(!control.disabled){\n        control.dataset.vbTempDisabled = '1';\n        control.disabled = true;\n      }\n    } else if(control.dataset.vbTempDisabled === '1'){\n      control.disabled = false;\n      delete control.dataset.vbTempDisabled;\n    }\n  });\n  syncCombinedPartsButtonState();\n}\nasync function togglePartsPopup(idx){\n  const popup = document.getElementById('vb-parts-popup-' + idx);\n  if(!popup) return;\n  const wasOpen = popup.classList.contains('vb-open');\n  setCollapsibleState(popup, !wasOpen);\n  const availableCards = popup.querySelectorAll('.vb-part-card[data-skus]').length;\n  vbMetric('parts_panel_toggled', { open:!wasOpen, parts_count:availableCards, language:CURRENT_LANG, interaction:!wasOpen ? 'open' : 'close' });\n  if(!wasOpen){\n    \/\/ Getrapte inglij: elke kaart een fractie later dan de vorige, i.p.v. dat alles\n    \/\/ tegelijk verschijnt. Reflow forceren zodat de animatie ook bij een tweede keer\n    \/\/ openklappen weer opnieuw afspeelt (anders blijft de browser 'm overslaan).\n    const cards = popup.querySelectorAll('.vb-part-card');\n    cards.forEach((card, i) => {\n      card.classList.remove('vb-card-stagger-in');\n      void card.offsetWidth;\n      card.style.animationDelay = (i * 40) + 'ms';\n      card.classList.add('vb-card-stagger-in');\n    });\n    const skus = [];\n    popup.querySelectorAll('.vb-part-card[data-skus]').forEach(row => {\n      const rowSkus = (row.dataset.skus || '').split(',').filter(Boolean);\n      skus.push(...rowSkus);\n    });\n    if(skus.length > 0){\n      setPartsPopupLoading(popup, true);\n      try{\n        await fetchProductData(skus);\n      } finally {\n        \/\/ Restore temporarily disabled controls first; populatePartsRowData may then\n        \/\/ permanently disable products that are actually unavailable\/out of stock.\n        setPartsPopupLoading(popup, false);\n      }\n      \/\/ Een nieuwe zoekactie kan intussen de volledige resultaat-DOM hebben vervangen.\n      \/\/ Vul dan nooit een nieuwe popup met de afronding van een oude async lookup.\n      if(!popup.isConnected || document.getElementById('vb-parts-popup-' + idx) !== popup) return;\n      populatePartsRowData(idx);\n    }\n  }\n}\nconst WEBSHOP_URLS = {\n  \/\/ FC 800 heeft geen eigen productpagina in de webshop en verwijst daarom\n  \/\/ naar dezelfde pagina als FC 1000.\n  fc1000: 'https:\/\/varibox.best4u.dev\/product\/varibox-fc-1000\/',\n  fc800: 'https:\/\/varibox.best4u.dev\/product\/varibox-fc-1000\/',\n  cc250: 'https:\/\/varibox.best4u.dev\/product\/varibox-cc-250\/',\n  drumtainer: 'https:\/\/varibox.best4u.dev\/product\/adr-drum-container\/'\n};\n\/\/ Categoriepagina's met losse onderdelen (afdichtingen, sensoren, aansluitingen,\n\/\/ enz.) per productlijn \u2014 los van of het om een nieuwe unit of vervangingsset gaat.\nconst SPAREPARTS_URLS = {\n  fc1000: 'https:\/\/varibox.best4u.dev\/product-category\/varibox-fc-1000\/',\n  fc800: 'https:\/\/varibox.best4u.dev\/product-category\/varibox-fc-800\/',\n  cc250: 'https:\/\/varibox.best4u.dev\/product-category\/varibox-cc-250\/',\n  drumtainer: 'https:\/\/varibox.best4u.dev\/product-category\/varibox-drumtainer\/'\n};\n\/\/ Food-contact Declaration of Compliance-documenten. FC 1000 en FC 800 delen\n\/\/ hetzelfde document; CC 250 heeft zijn eigen document. Drumtainer heeft geen\n\/\/ food-contact-resultaat en komt hier dus niet in voor.\nconst FOOD_DOC_URLS = {\n  fc1000: 'https:\/\/varibox.best4u.dev\/wp-content\/uploads\/2026\/07\/DOC-Deventer-VARIBOX-FC.pdf',\n  fc800: 'https:\/\/varibox.best4u.dev\/wp-content\/uploads\/2026\/07\/DOC-Deventer-VARIBOX-FC.pdf',\n  cc250: 'https:\/\/varibox.best4u.dev\/wp-content\/uploads\/2026\/07\/DOC-Deventer-VARIBOX-CC-14-06-2021.pdf'\n};\n\/\/ Groepeert een typeCode (nieuwe unit of vervangingsset-binnenbox) naar de\n\/\/ bijbehorende webshop-productcategorie. Drumtainer heeft geen vervangingsset-\n\/\/ variant, dus die komt hier ook niet voor.\nfunction getProductLine(typeCode){\n  if(['VB1001','VC1001','VI1001','VK1001'].includes(typeCode)) return 'fc1000';\n  if(['VB0801','VC0801','VI0801','VK0801'].includes(typeCode)) return 'fc800';\n  if(['VB0250','VC0250','VB0251','VC0251'].includes(typeCode)) return 'cc250';\n  if(typeCode === 'DT0200') return 'drumtainer';\n  return null;\n}\n\/\/ Bepaalt welke losse onderdelen (zuigbuis, sensor, deksel+venting) bij een gedecodeerd\n\/\/ resultaat horen, op basis van PARTS_LOOKUP. Matcht op de lettercode (zuigbuisChar\/sensorChar\/\n\/\/ pakkingChar) i.p.v. op de omschrijving, omdat de omschrijving per taal verschilt maar de\n\/\/ lettercode in elke taal hetzelfde is. Levert alleen onderdelen op die eenduidig zijn\n\/\/ (zuigbuisMatches\/sensorMatches met precies 1 match) \u2014 bij dubbelzinnige uitkomsten wordt niets\n\/\/ getoond, om nooit het verkeerde onderdeel voor te stellen. Drumtainer en foutresultaten leveren\n\/\/ niets op. Voor Food-pakking is er nog geen deksel-koppeling bekend (alleen EPDM\/Viton).\n\/\/ Splitst een zuigbuis+venting-omschrijving (bijv. \"Safeline Performance + Combivent (EPDM)\")\n\/\/ in een zuigbuis-deel (\"Safeline Performance\") en een venting\/deksel-deel (\"Combivent (EPDM)\").\n\/\/ Werkt in alle 7 talen, want \" + \" is overal de vaste scheiding tussen beide (zie I18N_DATA).\n\/\/ De venting (Combivent\/beluchter) hoort bij het deksel, niet bij de zuigbuis zelf \u2014 vandaar de\n\/\/ aparte labels voor de twee rijen in de onderdelen-pop-up.\nfunction splitZuigbuisLabel(fullLabel){\n  const idx = fullLabel.indexOf(' + ');\n  if(idx === -1) return { tubeLabel: fullLabel, ventingLabel: fullLabel };\n  return {\n    tubeLabel: fullLabel.slice(0, idx).trim(),\n    ventingLabel: fullLabel.slice(idx + 3).trim()\n  };\n}\n\/\/ Deze families zijn structureel nooit los te bestellen (bevestigd door Jeffrey, sept. 2026):\n\/\/ Ecolab-varianten (op maat), losse AS-onderdelen, en \"geen zuigbuis\"-configuraties. Voor deze\n\/\/ gevallen tonen we in de pop-up helemaal geen rij (in plaats van een \"neem contact op\"-melding),\n\/\/ omdat dit nooit een bestelbaar los onderdeel wordt.\nfunction isStructurallyUnavailable(fullZuigbuisLabel){\n  const l = fullZuigbuisLabel.toLowerCase();\n  return l.includes('ecolab') || l.includes('as qc2') || l.includes('as gt2') || l.includes('no extractor tube')\n    || l.includes('geen zuigbuis') || l.includes('kein steigrohr') || l.includes(\"sans tube d'aspiration\")\n    || l.includes('senza tubo di aspirazione') || l.includes('sin tubo de aspiraci\u00f3n') || l.includes('bez rurki zasysaj\u0105cej');\n}\n\/\/ Bepaalt de zuigbuis-FAMILIE (voor de koppeling\/afdekkap-koppeling) op basis van de omschrijving.\n\/\/ \"Safeline\" dekt zowel Performance als Precision (bevestigd: zelfde koppeling\/kap voor beide).\n\/\/ Wordt alleen aangeroepen nadat isStructurallyUnavailable() al Ecolab heeft uitgesloten, dus\n\/\/ \"cds\" hier betekent altijd de gewone \"CDS voetklep D14\"-familie, niet \"Ecolab CDS speciaal\".\nfunction getZuigbuisFamily(fullLabel){\n  const l = fullLabel.toLowerCase();\n  if(l.includes('safeline')) return 'safeline';\n  if(l.includes('cds')) return 'cds_voetklep';\n  return null;\n}\nfunction getAvailablePartsForResult(result){\n  if(result.error || result.isDrumtainer) return [];\n  const lineKey = { fc1000:'FC1000', fc800:'FC800', cc250:'CC250' }[getProductLine(result.typeCode)];\n  if(!lineKey) return [];\n  const zuigbuisFullLabel = result.zuigbuisMatches.length === 1 ? result.zuigbuisMatches[0][0] : null;\n  \/\/ Materiaal bij voorkeur uit de zuigbuis-omschrijving zelf halen (die is altijd ondubbelzinnig\n  \/\/ EPDM\/Food\/Viton), niet uit de pakking-lettercode -- want EPDM en Food delen dezelfde\n  \/\/ pakking-code ('A') in de configurator, dus pakkingMatches alleen is daar niet betrouwbaar voor.\n  const materialFromZuigbuis = zuigbuisFullLabel ? detectMaterial(zuigbuisFullLabel) : null;\n  const material = materialFromZuigbuis || (result.pakkingMatches[0] ? detectMaterial(result.pakkingMatches[0][0]) : null);\n  if(!material) return [];\n  const matKey = lineKey + '_' + material;\n  const items = [];\n  const zuigbuisIsStructurallyOut = zuigbuisFullLabel ? isStructurallyUnavailable(zuigbuisFullLabel) : false;\n  \/\/ Familie (Safeline \/ CDS voetklep) wordt \u00e9\u00e9n keer bepaald en meegegeven aan elk item dat\n  \/\/ van de zuigbuis afstamt, zodat de pop-up ze visueel kan groeperen (kleurcodering).\n  let zuigbuisFamily = null;\n  if(zuigbuisFullLabel){\n    if(!zuigbuisIsStructurallyOut){\n      zuigbuisFamily = getZuigbuisFamily(zuigbuisFullLabel);\n    }\n  }\n  if(zuigbuisFullLabel){\n   if(!zuigbuisIsStructurallyOut){\n    const { tubeLabel } = splitZuigbuisLabel(zuigbuisFullLabel);\n    const zKey = result.zuigbuisChar + '_' + material;\n    const entry = PARTS_LOOKUP.zuigbuis[zKey];\n    const skus = entry ? entry[matKey] : null;\n    items.push({ role:'zuigbuis', label: tubeLabel, skus: skus || null, family: zuigbuisFamily });\n   }\n  }\n  if(result.sensorMatches.length === 1){\n    if(result.sensorChar !== 'A'){\n      const label = result.sensorMatches[0][0];\n      const entry = PARTS_LOOKUP.sensor[result.sensorChar];\n      const skus = entry ? entry[matKey] : null;\n      items.push({ role:'sensor', label, skus: skus || null });\n      \/\/ Stekker (9900631\/9900632): zit al ingebouwd onder de kap om de melder naar buiten toe\n      \/\/ aansluitbaar te maken -- hoort dus bij \"Ingebouwde onderdelen\", niet bij de extra's.\n      const connSkus = PARTS_LOOKUP.sensorConnector[result.sensorChar];\n      items.push({ role:'sensorConnector', label:label, skus: connSkus || null });\n      \/\/ Contra stekker (9900602\/9900603): de daadwerkelijke tegenkoppeling om aan te sluiten op\n      \/\/ het systeem van de klant -- dit is w\u00e9l een echte extra accessoire.\n      const counterConnSkus = PARTS_LOOKUP.sensorCounterConnector[result.sensorChar];\n      items.push({ role:'sensorCounterConnector', label:label, skus: counterConnSkus || null });\n    }\n  }\n  if(zuigbuisFullLabel){\n   if(!zuigbuisIsStructurallyOut){\n    if(material === 'EPDM' || material === 'Viton'){\n      const { ventingLabel } = splitZuigbuisLabel(zuigbuisFullLabel);\n      const dekselTable = PARTS_LOOKUP.deksel[material];\n      const skus = dekselTable ? dekselTable[result.zuigbuisChar] : null;\n      items.push({ role:'deksel', label: ventingLabel, skus: skus || null, family: zuigbuisFamily });\n    }\n   }\n  }\n  \/\/ Koppeling + afdekkap: gekoppeld aan de zuigbuis-FAMILIE (Safeline of CDS voetklep) + materiaal,\n  \/\/ niet aan de productlijn -- bevestigd door Jeffrey: dezelfde koppeling\/kap geldt voor zowel\n  \/\/ Safeline Performance als Precision, en voor alle productlijnen (FC1000\/FC800\/CC250).\n  if(zuigbuisFullLabel){\n   if(!zuigbuisIsStructurallyOut){\n    const family = zuigbuisFamily;\n    if(family){\n      const accForFamily = PARTS_LOOKUP.accessory[family];\n      const accForMaterial = accForFamily ? accForFamily[material] : null;\n      if(accForMaterial){\n        const { tubeLabel: accTubeLabel } = splitZuigbuisLabel(zuigbuisFullLabel);\n        if(accForMaterial.coupler){\n          items.push({ role:'coupler', label:`(${accTubeLabel})`, skus: accForMaterial.coupler, family: family });\n        }\n        if(accForMaterial.cap){\n          items.push({ role:'cap', label:`(${accTubeLabel})`, skus: accForMaterial.cap, family: family });\n        }\n      }\n    }\n   }\n  }\n  return items;\n}\n\/\/ Bouwt de \"Bekijk beschikbare onderdelen\"-knop + inklapbare pop-up voor \u00e9\u00e9n resultaatkaart.\n\/\/ Onderdelen met een bevestigde webshop-SKU krijgen een aanvinkbaar vakje; onderdelen zonder\n\/\/ bevestigde SKU tonen in plaats daarvan een \"neem contact op\"-link. Levert lege string op als\n\/\/ er voor dit resultaat helemaal geen onderdelen bekend zijn (dan verschijnt er geen knop).\nfunction buildPartsPopupHtml(result, idx, S){\n  const items = getAvailablePartsForResult(result);\n  if(items.length === 0) return '';\n  const roleLabels = { zuigbuis: S.partsRoleZuigbuis, sensor: S.partsRoleSensor, deksel: S.partsRoleDeksel, coupler: S.partsRoleCoupler, cap: S.partsRoleCap, sensorConnector: S.partsRoleSensorConnector, sensorCounterConnector: S.partsRoleSensorCounterConnector };\n  \/\/ Ingebouwde onderdelen = de kernonderdelen van DEZE configuratie (zuigbuis\/sensor\/deksel).\n  \/\/ Extra accessoires = aanvullende artikelen die geen deel van de configuratie zelf zijn, maar\n  \/\/ er wel bij horen (koppeling, afdekkap, stekkersets).\n  const BUILT_IN_ROLES = ['zuigbuis', 'sensor', 'deksel', 'sensorConnector'];\n  \/\/ Familie (voor de kleuraccent-rand): alleen relevant voor de zuigbuis-gerelateerde rollen,\n  \/\/ want die delen allemaal dezelfde familie (Safeline\/CDS) als DEZE configuratie.\n  const FAMILY_ROLES = ['zuigbuis', 'deksel', 'coupler', 'cap'];\n  let resultFamily = null;\n  if(result.zuigbuisMatches.length === 1){\n    resultFamily = getZuigbuisFamily(result.zuigbuisMatches[0][0]);\n  }\n  function buildRowHtml(item, itemIdx){\n    const family = FAMILY_ROLES.includes(item.role) ? (resultFamily || 'neutral') : 'neutral';\n    if(item.skus){\n      const productIds = item.skus.map(sku => SKU_TO_PRODUCT_ID[sku]).filter(Boolean);\n      const staticFallbackIds = productIds.length === item.skus.length ? productIds.join(',') : '';\n      const checkboxId = `vb-part-${idx}-${itemIdx}`;\n      const qtyId = `vb-part-qty-${idx}-${itemIdx}`;\n      \/\/ SKU is de primaire identiteit. Een complete statische product-ID mapping is alleen nog\n      \/\/ fallback: de live Store API mag een nieuwe\/vertaalde SKU dus ook zonder tabelupdate redden.\n      return `<div class=\"vb-part-card\" data-family=\"${esc(family)}\" data-product-ids=\"${esc(staticFallbackIds)}\" data-skus=\"${esc(item.skus.join(','))}\" data-item-idx=\"${itemIdx}\">\n        <input type=\"checkbox\" id=\"${checkboxId}\" class=\"vb-part-checkbox\" data-product-ids=\"${esc(staticFallbackIds)}\" data-vb-action=\"part-checkbox\" data-idx=\"${idx}\" data-item-idx=\"${itemIdx}\">\n        <label for=\"${checkboxId}\" class=\"vb-part-card-clickzone\">\n          <span class=\"vb-part-thumb-wrap\">\n            <img class=\"vb-part-thumb\" alt=\"\" loading=\"lazy\">\n            <span class=\"vb-part-check-badge\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"vb-check-svg\"><path class=\"vb-check-path\" d=\"M4 12.5l5 5L20 6\" fill=\"none\" stroke=\"#fff\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><\/span>\n          <\/span>\n          <span class=\"vb-part-text\">\n            <span class=\"vb-part-role\">${esc(roleLabels[item.role] || item.role)}<\/span>\n            <span class=\"vb-part-label\">${esc(item.label)}<\/span>\n            <span class=\"vb-part-stock-warning\" id=\"vb-part-stock-${idx}-${itemIdx}\"><\/span>\n          <\/span>\n        <\/label>\n        <div class=\"vb-part-card-footer\">\n          <div class=\"vb-part-qty-stepper\" data-idx=\"${idx}\" data-item-idx=\"${itemIdx}\">\n            <button type=\"button\" class=\"vb-part-qty-btn\" data-vb-action=\"part-qty\" data-idx=\"${idx}\" data-item-idx=\"${itemIdx}\" data-delta=\"-1\" aria-label=\"${esc(S.quantityDecrease)}\">\u2212<\/button>\n            <span class=\"vb-part-qty-val\" id=\"${qtyId}\">1<\/span>\n            <button type=\"button\" class=\"vb-part-qty-btn\" data-vb-action=\"part-qty\" data-idx=\"${idx}\" data-item-idx=\"${itemIdx}\" data-delta=\"1\" aria-label=\"${esc(S.quantityIncrease)}\">+<\/button>\n          <\/div>\n          <span class=\"vb-part-price\" id=\"vb-part-price-${idx}-${itemIdx}\"><\/span>\n        <\/div>\n      <\/div>`;\n    }\n    return `<div class=\"vb-part-card vb-part-card-unavailable\" data-family=\"${esc(family)}\">\n      <span class=\"vb-part-role\">${esc(roleLabels[item.role] || item.role)}<\/span>\n      <span class=\"vb-part-label\">${esc(item.label)}<\/span>\n      <span class=\"vb-part-unavailable\">${esc(S.partsUnavailable)} \u2014 <a href=\"https:\/\/varibox.best4u.dev\/es\/contacto\/\" target=\"_blank\" rel=\"noopener\">${esc(S.partsContactLink)}<\/a><\/span>\n    <\/div>`;\n  }\n  const indexed = items.map((item, itemIdx) => ({ item, itemIdx }));\n  const builtInHtml = indexed.filter(x => BUILT_IN_ROLES.includes(x.item.role)).map(x => buildRowHtml(x.item, x.itemIdx)).join('');\n  const extraHtml = indexed.filter(x => !BUILT_IN_ROLES.includes(x.item.role)).map(x => buildRowHtml(x.item, x.itemIdx)).join('');\n  const sectionsHtml =\n    (builtInHtml ? `<h4 class=\"vb-parts-section-title\">${esc(S.partsBuiltInHeader)}<\/h4><div class=\"vb-parts-list\">${builtInHtml}<\/div>` : '') +\n    (extraHtml ? `<h4 class=\"vb-parts-section-title\">${esc(S.partsExtraHeader)}<\/h4><div class=\"vb-parts-list\">${extraHtml}<\/div>` : '');\n  \/\/ Dekkingsbalk: hoeveel van de getoonde onderdelen zijn daadwerkelijk beschikbaar (bevestigd\n  \/\/ in de webshop), als snel visueel signaal v\u00f3\u00f3r de klant iets aanvinkt.\n  const availableCount = items.filter(i => i.skus).length;\n  const totalCount = items.length;\n  const coveragePct = totalCount > 0 ? Math.round((availableCount \/ totalCount) * 100) : 0;\n  const fullCoverageClass = coveragePct === 100 ? ' vb-full-coverage' : '';\n  const coverageHtml = `<div class=\"vb-parts-coverage\">\n    <div class=\"vb-parts-coverage-track\"><div class=\"vb-parts-coverage-fill${fullCoverageClass}\" style=\"width:${coveragePct}%\"><\/div><\/div>\n    <span class=\"vb-parts-coverage-label\">${esc(S.partsCoverageLabel.replace('{available}', availableCount).replace('{total}', totalCount))}<\/span>\n  <\/div>`;\n  return `\n    <button type=\"button\" class=\"vb-cta-btn vb-cta-btn-secondary vb-parts-toggle-btn\" data-vb-action=\"toggle-parts\" data-idx=\"${idx}\" aria-controls=\"vb-parts-popup-${idx}\" aria-expanded=\"false\"><span>${esc(S.partsButtonLabel)}<\/span><span class=\"vb-parts-count-badge\">${esc((UX_STRINGS[CURRENT_LANG]||UX_STRINGS.en).partsAvailable.replace('{count}',availableCount))}<\/span><\/button>\n    <div id=\"vb-parts-popup-${idx}\" class=\"vb-collapsible\" aria-hidden=\"true\" inert><div class=\"vb-collapsible-inner\">\n      <div class=\"vb-parts-popup\">\n        <p class=\"vb-parts-popup-intro\">${esc(S.partsPopupIntro)}<\/p>\n        ${coverageHtml}\n        ${sectionsHtml}\n        <div class=\"vb-parts-kit-strip\" id=\"vb-parts-kit-strip-${idx}\"><\/div>\n        <div class=\"vb-parts-sticky-footer\">\n          <div class=\"vb-parts-selection-summary\" id=\"vb-parts-selection-summary-${idx}\"><\/div>\n          <div class=\"vb-parts-subtotal-bar\" id=\"vb-parts-subtotal-${idx}\"><\/div>\n          <div class=\"vb-parts-actions\">\n            <button type=\"button\" class=\"vb-cta-btn\" data-vb-action=\"add-parts\" data-idx=\"${idx}\">${esc(S.partsAddToCartButton)}<\/button>\n          <\/div>\n        <\/div>\n        <div id=\"vb-parts-status-${idx}\" class=\"vb-email-status\" role=\"status\" aria-live=\"polite\"><\/div>\n      <\/div>\n    <\/div><\/div>`;\n}\n\/\/ Voegt alle aangevinkte onderdelen van de pop-up bij kaart `idx` toe aan de winkelwagen, via\n\/\/ WooCommerce's eigen wc-ajax=add_to_cart endpoint (hetzelfde mechanisme dat de normale\n\/\/ \"In winkelwagen\"-knoppen op de site al gebruiken \u2014 dus geen aparte backend-ontwikkeling nodig).\n\/\/ Roept dit na elkaar aan per product-ID (niet parallel), zodat WooCommerce's sessie-\/\n\/\/ cart-hash-afhandeling niet in de knoop raakt bij meerdere gelijktijdige aanvragen.\n\/\/ Voegt een lijst product-ID's toe aan de winkelwagen via WooCommerce's eigen\n\/\/ wc-ajax=add_to_cart endpoint, en toont daarna een \"Toegevoegd!\"-melding met een\n\/\/ \"Bekijk winkelwagen\"-link die in een NIEUW tabblad opent. Navigeert NIET meer weg van\n\/\/ de Checker-pagina, zodat de klant nooit zijn ingevoerde artikelnummer en resultaat\n\/\/ kwijtraakt door terug te navigeren.\n\/\/ items: array van {productId, quantity} -- elk item wordt met zijn EIGEN gekozen aantal\n\/\/ toegevoegd (niet meer altijd 1 stuks).\nconst CART_PARTIAL_ERROR_TEXT = {\n  nl: 'Een deel is toegevoegd aan de winkelwagen, maar niet alles. Controleer uw winkelwagen en probeer de ontbrekende onderdelen opnieuw.',\n  en: 'Some items were added to your cart, but not all of them. Check your cart and retry the missing items.',\n  de: 'Einige Artikel wurden zum Warenkorb hinzugef\u00fcgt, aber nicht alle. Pr\u00fcfen Sie den Warenkorb und versuchen Sie die fehlenden Artikel erneut.',\n  fr: 'Certains articles ont \u00e9t\u00e9 ajout\u00e9s au panier, mais pas tous. V\u00e9rifiez votre panier et r\u00e9essayez pour les articles manquants.',\n  it: 'Alcuni articoli sono stati aggiunti al carrello, ma non tutti. Controlli il carrello e riprovi per gli articoli mancanti.',\n  es: 'Algunos art\u00edculos se han a\u00f1adido al carrito, pero no todos. Revise el carrito y vuelva a intentarlo con los art\u00edculos que faltan.',\n  pl: 'Cz\u0119\u015b\u0107 produkt\u00f3w dodano do koszyka, ale nie wszystkie. Sprawd\u017a koszyk i spr\u00f3buj ponownie doda\u0107 brakuj\u0105ce produkty.'\n};\nconst CART_PARTIAL_ROW_TEXT = {\n  nl: 'Gedeeltelijk toegevoegd \u2014 controleer uw winkelwagen voordat u dit onderdeel opnieuw probeert.',\n  en: 'Partly added \u2014 check your cart before trying this component again.',\n  de: 'Teilweise hinzugef\u00fcgt \u2014 pr\u00fcfen Sie Ihren Warenkorb, bevor Sie dieses Teil erneut versuchen.',\n  fr: 'Ajout partiel \u2014 v\u00e9rifiez votre panier avant de r\u00e9essayer ce composant.',\n  it: 'Aggiunto parzialmente \u2014 controlli il carrello prima di riprovare questo componente.',\n  es: 'A\u00f1adido parcialmente \u2014 revise el carrito antes de volver a intentar este componente.',\n  pl: 'Dodano cz\u0119\u015bciowo \u2014 sprawd\u017a koszyk przed ponown\u0105 pr\u00f3b\u0105 dodania tego elementu.'\n};\nfunction getWooAjaxUrl(endpoint){\n  const candidates = [window.wc_add_to_cart_params, window.woocommerce_params, window.wc_cart_fragments_params];\n  for(const params of candidates){\n    if(params){\n     if(params.wc_ajax_url){\n      return String(params.wc_ajax_url).replace('%%endpoint%%', encodeURIComponent(endpoint));\n     }\n    }\n  }\n  return '\/?wc-ajax=' + encodeURIComponent(endpoint);\n}\nfunction getWooCartUrl(){\n  if(window.wc_add_to_cart_params){\n   if(window.wc_add_to_cart_params.cart_url){\n    return String(window.wc_add_to_cart_params.cart_url);\n   }\n  }\n  const cartLink = document.querySelector('a.cart-contents[href], a.wc-forward[href*=\"cart\"], a[href*=\"\/cart\/\"]');\n  return cartLink ? cartLink.href : '\/cart\/';\n}\nfunction getWpRestRoot(){\n  if(window.wpApiSettings){\n    if(window.wpApiSettings.root) return String(window.wpApiSettings.root);\n  }\n  const link = document.querySelector('link[rel=\"https:\/\/api.w.org\/\"]');\n  if(link){\n    if(link.href) return link.href;\n  }\n  return '\/wp-json\/';\n}\nfunction buildWpRestUrl(route){\n  const root = getWpRestRoot();\n  try{\n    const rootUrl = new URL(root, window.location.href);\n    const cleanRoute = String(route || '').replace(\/^\\\/+\/, '');\n    if(rootUrl.searchParams.has('rest_route')){\n      const baseRoute = (rootUrl.searchParams.get('rest_route') || '\/').replace(\/\\\/?$\/, '\/');\n      rootUrl.searchParams.set('rest_route', baseRoute + cleanRoute);\n      return rootUrl;\n    }\n    const baseHref = rootUrl.href.endsWith('\/') ? rootUrl.href : rootUrl.href + '\/';\n    return new URL(cleanRoute, baseHref);\n  } catch(e){\n    return new URL('\/wp-json\/' + String(route || '').replace(\/^\\\/+\/, ''), window.location.origin);\n  }\n}\nfunction applyWooCartResponse(data){\n  if(!data) return;\n  if(data.fragments){\n    Object.keys(data.fragments).forEach(selector => {\n      try{\n        document.querySelectorAll(selector).forEach(el => { el.outerHTML = data.fragments[selector]; });\n      } catch(fragErr){ \/* onbekend\/ongeldig selectortype -- deze fragment overslaan *\/ }\n    });\n  }\n  if(window.jQuery){\n    window.jQuery(document.body).trigger('added_to_cart', [data.fragments, data.cart_hash]);\n  }\n}\nfunction mergeCartItems(items){\n  const merged = new Map();\n  (items || []).forEach(item => {\n    const id = String(item.productId || '').trim();\n    if(!id) return;\n    const qty = normalizePartQty(item.quantity);\n    merged.set(id, (merged.get(id) || 0) + qty);\n  });\n  return Array.from(merged, ([productId, quantity]) => ({ productId, quantity }));\n}\nfunction uniqueCartRows(cardsToMark){\n  return [...new Set((cardsToMark || []).filter(Boolean))];\n}\nfunction setCartRowsPending(rows, pending){\n  uniqueCartRows(rows).forEach(row => {\n    if(pending) row.dataset.vbCartPending = '1'; else delete row.dataset.vbCartPending;\n    row.querySelectorAll('.vb-part-checkbox, .vb-part-qty-btn').forEach(control => {\n      if(pending){\n        if(!control.disabled){\n          control.dataset.vbCartTempDisabled = '1';\n          control.disabled = true;\n        }\n      } else if(control.dataset.vbCartTempDisabled === '1'){\n        control.disabled = false;\n        delete control.dataset.vbCartTempDisabled;\n      }\n    });\n  });\n}\nfunction reconcileCartRowsAfterAttempt(rows, successfulProductIds, S, cartLang){\n  const touchedPopups = new Set();\n  uniqueCartRows(rows).forEach(row => {\n    const cb = row.querySelector('.vb-part-checkbox');\n    if(!cb) return;\n    const ids = getResolvedProductIdsForPart(row, cb);\n    if(ids.length === 0) return;\n    const successCount = ids.filter(id => successfulProductIds.has(String(id))).length;\n    const popup = row.closest('[id^=\"vb-parts-popup-\"]');\n    if(popup) touchedPopups.add(popup.id.replace('vb-parts-popup-', ''));\n    if(successCount === ids.length){\n      cb.checked = false;\n      row.classList.add('vb-just-added');\n      setTimeout(() => { if(row.isConnected) row.classList.remove('vb-just-added'); }, 2500);\n    } else if(successCount > 0){\n      \/\/ E\u00e9n visuele rij kan een bundel van meerdere WooCommerce-producten zijn. Als zo'n\n      \/\/ bundel halverwege faalt, blokkeren we direct opnieuw bestellen om duplicaten van het\n      \/\/ reeds gelukte deel te voorkomen. De klant controleert dan eerst de winkelwagen.\n      cb.checked = false;\n      delete cb.dataset.vbCartTempDisabled;\n      cb.disabled = true;\n      row.querySelectorAll('.vb-part-qty-btn').forEach(btn => { delete btn.dataset.vbCartTempDisabled; btn.disabled = true; });\n      row.classList.add('vb-part-card-partial');\n      const stockEl = row.querySelector('.vb-part-stock-warning');\n      if(stockEl) stockEl.textContent = CART_PARTIAL_ROW_TEXT[cartLang] || CART_PARTIAL_ROW_TEXT.en;\n    }\n  });\n  touchedPopups.forEach(idx => {\n    updatePartsSubtotal(idx);\n    updatePartsKitStrip(idx);\n  });\n  updateCombinedPartsTotal();\n  savePartsSelectionState();\n}\n\/\/ Serialize ALL cart writes from this widget, including clicks on different result cards.\nlet CART_OPERATION_CHAIN = Promise.resolve();\n\/\/ Telt hoeveel stuks er deze sessie in totaal via de widget zijn toegevoegd aan de winkelwagen\n\/\/ (over alle kaarten en klikken heen), voor de zwevende bevestigingsmelding.\nlet SESSION_CART_ADD_COUNT = 0;\n\/\/ Toont een korte, zwevende bevestiging rechtsonder in beeld (blijft zichtbaar ook als de klant\n\/\/ al verder is gescrold), naast de bestaande inline statustekst bij de knop zelf. Verdwijnt na\n\/\/ enkele seconden vanzelf, of eerder als de klant er zelf op klikt.\nfunction showAddedToCartToast(S, totalCount){\n  const container = document.getElementById('vb-toast-container');\n  if(!container) return;\n  const toast = document.createElement('div');\n  toast.className = 'vb-toast';\n  toast.innerHTML = `${buildSuccessHtml(S.partsAddToCartSuccess)}\n    <span class=\"vb-toast-count\">${esc(S.toastSessionCount.replace('{count}', totalCount))}<\/span>\n    <a href=\"${esc(getWooCartUrl())}\" target=\"_blank\" rel=\"noopener\" class=\"vb-view-cart-link\">${esc(S.partsViewCartButton)}<\/a>`;\n  container.appendChild(toast);\n  requestAnimationFrame(() => { toast.classList.add('vb-toast-in'); });\n  const remove = () => {\n    toast.classList.remove('vb-toast-in');\n    toast.classList.add('vb-toast-out');\n    setTimeout(() => { if(toast.parentNode) toast.parentNode.removeChild(toast); }, 300);\n  };\n  toast.addEventListener('click', remove);\n  setTimeout(remove, 4200);\n}\nasync function addProductIdsToCartNow(items, statusEl, addBtn, S, cardsToMark, cartLang){\n  if(addBtn) addBtn.disabled = true;\n  statusEl.classList.remove('vb-email-status-error');\n  statusEl.classList.remove('vb-email-status-success');\n  statusEl.textContent = '';\n  const mergedItems = mergeCartItems(items);\n  const requestedQty = mergedItems.reduce((sum, item) => sum + (Number(item.quantity) || 0), 0);\n  vbMetric('cart_started', { cart_item_count:mergedItems.length, cart_quantity:requestedQty, language:cartLang || CURRENT_LANG, outcome:'started', interaction:'submit' });\n  if(mergedItems.length === 0){\n    statusEl.classList.add('vb-email-status-error');\n    statusEl.textContent = S.quoteFormMissingForm;\n    vbMetric('cart_completed', { cart_item_count:0, cart_quantity:0, succeeded_count:0, failed_count:0, language:cartLang || CURRENT_LANG, outcome:'failure', error_type:'commerce' });\n    if(addBtn) addBtn.disabled = false;\n    return;\n  }\n  let lastData = null;\n  let successfulQty = 0;\n  const successfulProductIds = new Set();\n  try{\n    for(const item of mergedItems){\n      const formData = new FormData();\n      formData.append('product_id', item.productId);\n      formData.append('quantity', String(item.quantity));\n      const resp = await fetchWithTimeout(getWooAjaxUrl('add_to_cart'), { method:'POST', body: formData, credentials:'same-origin' }, 12000);\n      if(!resp.ok){\n        throw new Error('add_to_cart failed for product ' + item.productId);\n      }\n      \/\/ WooCommerce kan HTTP 200 teruggeven maar t\u00f3ch een fout melden in de inhoud zelf\n      \/\/ (bijv. voorraad die tussen laden en klikken op is geraakt) -- dus altijd de body\n      \/\/ controleren, niet alleen de HTTP-status.\n      let data = null;\n      try{ data = await resp.json(); } catch(parseErr){ \/* geen JSON -- negeren, HTTP was wel ok *\/ }\n      if(data){\n        if(data.error){\n          throw new Error('WooCommerce meldde een fout voor product ' + item.productId);\n        }\n        lastData = data;\n      }\n      successfulQty += Number(item.quantity) || 0;\n      successfulProductIds.add(String(item.productId));\n    }\n    \/\/ Werk het winkelwagen-icoontje in de header van de site live bij, met de \"fragments\" die\n    \/\/ WooCommerce specifiek voor dat doel teruggeeft -- zonder dit blijft dat icoontje het oude\n    \/\/ aantal tonen totdat de klant zelf de pagina herlaadt.\n    applyWooCartResponse(lastData);\n    reconcileCartRowsAfterAttempt(cardsToMark, successfulProductIds, S, cartLang);\n    statusEl.classList.add('vb-email-status-success');\n    statusEl.innerHTML = buildSuccessHtml(S.partsAddToCartSuccess) + ` <a href=\"${esc(getWooCartUrl())}\" target=\"_blank\" rel=\"noopener\" class=\"vb-view-cart-link\">${esc(S.partsViewCartButton)}<\/a>`;\n    if(addBtn) addBtn.disabled = false;\n    \/\/ Telt hoeveel stuks er deze sessie via de widget zijn toegevoegd (niet de werkelijke\n    \/\/ winkelwagen-inhoud van de site zelf, die kan al meer bevatten) en toont dat in de\n    \/\/ zwevende melding, als extra, duidelijk zichtbare bevestiging naast de inline statustekst.\n    const addedQty = successfulQty;\n    SESSION_CART_ADD_COUNT += addedQty;\n    vbMetric('cart_completed', { cart_item_count:mergedItems.length, cart_quantity:addedQty, succeeded_count:mergedItems.length, failed_count:0, language:cartLang || CURRENT_LANG, outcome:'success' });\n    showAddedToCartToast(S, SESSION_CART_ADD_COUNT);\n  } catch(e){\n    console.warn('[VARIBOX Checker] Toevoegen aan winkelwagen deels\/geheel mislukt:', e);\n    applyWooCartResponse(lastData);\n    statusEl.classList.add('vb-email-status-error');\n    if(successfulQty > 0){\n      SESSION_CART_ADD_COUNT += successfulQty;\n      vbMetric('cart_completed', { cart_item_count:mergedItems.length, cart_quantity:successfulQty, succeeded_count:successfulProductIds.size, failed_count:Math.max(0, mergedItems.length - successfulProductIds.size), language:cartLang || CURRENT_LANG, outcome:'partial', error_type:'commerce' });\n      reconcileCartRowsAfterAttempt(cardsToMark, successfulProductIds, S, cartLang);\n      statusEl.textContent = CART_PARTIAL_ERROR_TEXT[cartLang] || CART_PARTIAL_ERROR_TEXT.en;\n      showAddedToCartToast(S, SESSION_CART_ADD_COUNT);\n    } else {\n      statusEl.textContent = S.quoteFormMissingForm;\n      vbMetric('cart_completed', { cart_item_count:mergedItems.length, cart_quantity:0, succeeded_count:0, failed_count:mergedItems.length, language:cartLang || CURRENT_LANG, outcome:'failure', error_type:'commerce' });\n    }\n    if(addBtn) addBtn.disabled = false;\n  }\n}\nfunction addProductIdsToCart(items, statusEl, addBtn, S, cardsToMark, cartLang){\n  const rows = uniqueCartRows(cardsToMark);\n  if(addBtn){\n    if(addBtn.dataset.vbCartPending === '1') return Promise.resolve(false);\n  }\n  if(addBtn){\n    addBtn.dataset.vbCartPending = '1';\n    addBtn.disabled = true;\n  }\n  setCartRowsPending(rows, true);\n  const operation = () => addProductIdsToCartNow(items, statusEl, addBtn, S, rows, cartLang);\n  const run = CART_OPERATION_CHAIN.then(operation, operation);\n  CART_OPERATION_CHAIN = run.catch(() => {});\n  return run.finally(() => {\n    setCartRowsPending(rows, false);\n    if(addBtn){\n      delete addBtn.dataset.vbCartPending;\n      addBtn.disabled = false;\n    }\n  });\n}\nfunction getResolvedProductIdsForPart(row, checkbox){\n  const skus = row ? (row.dataset.skus || '').split(',').filter(Boolean) : [];\n  if(skus.length > 0){\n    const liveIds = skus.map(sku => {\n      const data = PRODUCT_DATA_CACHE[sku];\n      if(data){\n        if(data.id) return data.id;\n      }\n      return null;\n    }).filter(Boolean);\n    if(liveIds.length === skus.length) return liveIds;\n  }\n  let fallbackIdsStr = '';\n  if(checkbox){\n    if(checkbox.dataset.productIds) fallbackIdsStr = checkbox.dataset.productIds;\n  }\n  if(!fallbackIdsStr){\n    if(row){\n      if(row.dataset.productIds) fallbackIdsStr = row.dataset.productIds;\n    }\n  }\n  return fallbackIdsStr\n    .split(',')\n    .filter(Boolean);\n}\n\nasync function addSelectedPartsToCart(idx){\n  const S = STRINGS[CURRENT_LANG];\n  const statusEl = document.getElementById('vb-parts-status-' + idx);\n  const popup = document.getElementById('vb-parts-popup-' + idx);\n  if(!popup || !statusEl) return;\n  const checked = [...popup.querySelectorAll('.vb-part-checkbox:checked')].filter(cb => {\n    const row = cb.closest('.vb-part-card');\n    return !row || row.dataset.vbCartPending !== '1';\n  });\n  if(checked.length === 0){\n    statusEl.classList.remove('vb-email-status-success');\n    statusEl.classList.add('vb-email-status-error');\n    statusEl.textContent = S.partsNoneSelected;\n    return;\n  }\n  const items = [];\n  const cardsToMark = [];\n  checked.forEach(cb => {\n    const row = cb.closest('.vb-part-card');\n    const itemIdx = row ? row.dataset.itemIdx : null;\n    const qty = itemIdx !== null ? getPartQty(idx, itemIdx) : 1;\n    const ids = getResolvedProductIdsForPart(row, cb);\n    ids.forEach(id => items.push({ productId: id, quantity: qty }));\n    if(row) cardsToMark.push(row);\n  });\n  const addBtn = popup.querySelector('.vb-parts-actions .vb-cta-btn');\n  await addProductIdsToCart(items, statusEl, addBtn, S, cardsToMark, CURRENT_LANG);\n}\n\/\/ Verzamelt de aangevinkte onderdelen uit \u00c1LLE resultaatkaarten tegelijk (bij invoer van\n\/\/ meerdere artikelnummers) en voegt ze in \u00e9\u00e9n keer toe aan de winkelwagen, elk met zijn eigen\n\/\/ gekozen aantal -- zodat de klant niet per resultaat apart op \"Voeg toe\" hoeft te klikken.\nasync function addAllSelectedPartsToCart(){\n  const S = STRINGS[CURRENT_LANG];\n  const statusEl = document.getElementById('vb-combined-parts-status');\n  if(!statusEl) return;\n  const allPopups = document.querySelectorAll('[id^=\"vb-parts-popup-\"]');\n  const items = [];\n  const cardsToMark = [];\n  allPopups.forEach(popup => {\n    const popupIdx = popup.id.replace('vb-parts-popup-', '');\n    popup.querySelectorAll('.vb-part-checkbox:checked').forEach(cb => {\n      const row = cb.closest('.vb-part-card');\n      if(row){\n        if(row.dataset.vbCartPending === '1') return;\n      }\n      const itemIdx = row ? row.dataset.itemIdx : null;\n      const qty = itemIdx !== null ? getPartQty(popupIdx, itemIdx) : 1;\n      const ids = getResolvedProductIdsForPart(row, cb);\n      ids.forEach(id => items.push({ productId: id, quantity: qty }));\n      if(row) cardsToMark.push(row);\n    });\n  });\n  if(items.length === 0){\n    statusEl.classList.remove('vb-email-status-success');\n    statusEl.classList.add('vb-email-status-error');\n    statusEl.textContent = S.partsNoneSelected;\n    return;\n  }\n  const addBtn = document.getElementById('vb-combined-parts-btn');\n  await addProductIdsToCart(items, statusEl, addBtn, S, cardsToMark, CURRENT_LANG);\n}\n\nfunction detectLang(){\n  const htmlLang = (document.documentElement.lang || '').slice(0,2).toLowerCase();\n  if(STRINGS[htmlLang]) return htmlLang;\n  const nav = (navigator.language || 'en').slice(0,2).toLowerCase();\n  if(STRINGS[nav]) return nav;\n  return 'en';\n}\n\nfunction findAll(table, code){\n  return table.filter(row => row[1].toUpperCase() === code.toUpperCase());\n}\nfunction detectMaterial(desc){\n  const d = desc.toLowerCase();\n  if(d.includes('food')) return 'Food';\n  if(d.includes('epdm')) return 'EPDM';\n  if(d.includes('viton')) return 'Viton';\n  return null;\n}\n\nfunction decode(raw, lang){\n  const D = I18N_DATA[lang];\n  const S = STRINGS[lang];\n  const code = raw.trim().toUpperCase().replace(\/\\s+\/g,'');\n  if(code.length !== 12){\n    return { error: S.errorLength.replace('{n}', code.length), errorType:'length', originalInput:code };\n  }\n  const typeCode = code.slice(0,6);\n  const pakkingChar = code.slice(6,7);\n  const zuigbuisChar = code.slice(7,8);\n  const sensorChar = code.slice(8,9);\n  const kleurCode = code.slice(9,12);\n\n  const typeMatches = findAll(D.type, typeCode);\n  if(typeMatches.length === 0){\n    return { error: S.errorUnknownType, errorType:'unknown', originalInput:code };\n  }\n  const typeName = typeMatches[0][0];\n\n  \/\/ Drumtainer uses a completely different field layout (no gasket\/extractor tube\/\n  \/\/ sensor \u2014 it's a mobile overpack for drums, not an IBC): trailer variant,\n  \/\/ colour-combination indicator, colour. Position 7 (delivery: wheels vs ISPM\n  \/\/ pallet) is intentionally NOT shown \u2014 deemed not relevant for the customer\n  \/\/ (colleague feedback, July 2026) \u2014 but is still skipped over below since the\n  \/\/ field layout is fixed-width.\n  if(typeCode === 'DT0200'){\n    const trailerChar = code.slice(7,8);\n    const comboChar = code.slice(8,9);\n    const kleurCode = code.slice(9,12);\n    return {\n      isDrumtainer: true,\n      code, typeCode, typeName,\n      trailerChar, trailerMatches: findAll(D.drumtainer_trailer, trailerChar),\n      comboChar, comboMatches: findAll(D.drumtainer_combo, comboChar),\n      kleurCode, kleurMatches: findAll(D.drumtainer_kleur, kleurCode),\n      dibtApplicable: (trailerChar === 'A'),\n      shopUrl: WEBSHOP_URLS.drumtainer,\n      showShopButton: true,\n      sparePartsUrl: SPAREPARTS_URLS.drumtainer\n    };\n  }\n\n  const isReplacement = \/^V[IK]\/.test(typeCode);\n\n  \/\/ Pakking is unambiguous: each code maps to exactly one material (EPDM or Viton).\n  const pakkingMatches = findAll(D.pakking, pakkingChar);\n  const specialMatches = findAll(D.special, pakkingChar);\n\n  \/\/ A few extractor-tube codes (currently only \"no extractor tube\": B\/L) cover both EPDM\n  \/\/ and Viton under the same letter. Since pakking already tells us the material with\n  \/\/ certainty, narrow down to the matching one.\n  let zuigbuisMatches = findAll(D.zuigbuis_venting, zuigbuisChar);\n  if(zuigbuisMatches.length > 1){\n   if(pakkingMatches.length === 1){\n    const pakkingMaterial = detectMaterial(pakkingMatches[0][0]);\n    if(pakkingMaterial){\n      const narrowed = zuigbuisMatches.filter(m => detectMaterial(m[0]) === pakkingMaterial);\n      if(narrowed.length === 1){\n        zuigbuisMatches = narrowed;\n      }\n    }\n   }\n  }\n\n  const sensorTable = isReplacement ? D.levelsensor_vervanging : D.levelsensor;\n  const sensorMatches = findAll(sensorTable, sensorChar);\n  const kleurMatches = findAll(D.kleur, kleurCode);\n\n  \/\/ Food contact rule (bijgewerkt door collega, augustus 2026):\n  \/\/ - Harde eis 1: de pakking moet EPDM zijn (codes A\/D\/F). Bij Viton (B\/E) is\n  \/\/   het altijd Nee, ongeacht zuigbuis of sensor.\n  \/\/ - Harde eis 2: er mag GEEN sensor gemonteerd zijn. Zodra er een sensor\n  \/\/   aanwezig is (elke code behalve \"Geen sensoren\"), is food contact altijd\n  \/\/   Nee, ongeacht pakking of zuigbuis.\n  \/\/ - Bij EPDM + geen sensoren: Ja als de zuigbuis Safeline Performance Food\n  \/\/   (K\/P), AS QC2 (I\/N) of AS GT2 (X\/F) is \u2014 of wanneer er helemaal geen\n  \/\/   zuigbuis is gemonteerd (B\/L). Let op: de gewone Safeline Performance\n  \/\/   EPDM (zonder \"Food\", codes C\/E) telt NIET mee \u2014 die is niet toegestaan\n  \/\/   voor food contact.\n  \/\/ - Nee in alle andere gevallen (een specifieke niet-food-zuigbuis, Viton,\n  \/\/   of wanneer er w\u00e9l een sensor gemonteerd is).\n  const NO_SENSOR_CODE = 'A';\n  const FOOD_TUBE_CODES = ['K','P','I','N','X','F'];\n  const NO_TUBE_CODES = ['B','L'];\n  const EPDM_PAKKING_CODES = ['A','D','F'];\n  const foodContact = [\n    sensorChar === NO_SENSOR_CODE,\n    EPDM_PAKKING_CODES.includes(pakkingChar),\n    (FOOD_TUBE_CODES.includes(zuigbuisChar) || NO_TUBE_CODES.includes(zuigbuisChar))\n  ].every(Boolean);\n\n  \/\/ UN certification number + DIBt number rows apply per product family \u2014 confirmed so\n  \/\/ far for FC 1000 and CC 250 (colleague, July 2026). NOT yet confirmed for FC 800 \u2014\n  \/\/ do not add FC 800 to this table until its numbers are confirmed.\n  const DIBT_SHARED_TEXT = 'Allgemeine bauaufsichtliche Zulassung (abZ) Z-40.21-534';\n  const CERT_BY_TYPE = {\n    'VB1001': { un: 'UN 31HH1\/Y\/**--\/NL\/TCPIPROMENS3-140531\/3750\/2028', dibt: DIBT_SHARED_TEXT },\n    'VC1001': { un: 'UN 31HH1\/Y\/**--\/NL\/TCPIPROMENS3-140531\/3750\/2028', dibt: DIBT_SHARED_TEXT },\n    'VB0801': { un: 'UN 31HH1\/Y\/**--\/NL\/TCPIPROMENS3-140531\/3060\/1700', dibt: DIBT_SHARED_TEXT },\n    'VC0801': { un: 'UN 31HH1\/Y\/**--\/NL\/TCPIPROMENS3-140531\/3060\/1700', dibt: DIBT_SHARED_TEXT },\n    'VB0250': { un: 'UN 31HH1\/Y\/**--\/NL\/TCPI-PROMENS3-200518\/950\/522', dibt: DIBT_SHARED_TEXT },\n    'VC0250': { un: 'UN 31HH1\/Y\/**--\/NL\/TCPI-PROMENS3-200518\/950\/522', dibt: DIBT_SHARED_TEXT },\n    'VB0251': { un: 'UN 31HH1\/Y\/**--\/NL\/TCPI-PROMENS3-200518\/950\/522', dibt: DIBT_SHARED_TEXT },\n    'VC0251': { un: 'UN 31HH1\/Y\/**--\/NL\/TCPI-PROMENS3-200518\/950\/522', dibt: DIBT_SHARED_TEXT },\n  };\n  const certInfo = CERT_BY_TYPE[typeCode] || null;\n\n  return {\n    code, typeCode, typeName, isReplacement,\n    pakkingChar, pakkingMatches, specialMatches,\n    zuigbuisChar, zuigbuisMatches,\n    sensorChar, sensorMatches,\n    kleurCode, kleurMatches,\n    foodContact, certInfo,\n    \/\/ Vervangingssets (binnenboxen, codes VI...\/VK...) staan niet in de webshop\n    \/\/ en moeten worden aangevraagd. Nieuwe units gaan naar de webshopcategorie.\n    shopUrl: WEBSHOP_URLS[getProductLine(typeCode)] || null,\n    showShopButton: !isReplacement,\n    sparePartsUrl: SPAREPARTS_URLS[getProductLine(typeCode)] || null,\n    foodDocUrl: foodContact ? (FOOD_DOC_URLS[getProductLine(typeCode)] || null) : null\n  };\n}\n\n\/\/ E\u00e9n ingang voor het verwerken van gebruikersinvoer: herkent zelf of het een\n\/\/ artikelnummer (12 tekens) of een serienummer (8 tekens) is. Bij een\n\/\/ serienummer wordt eerst het bijbehorende artikelnummer opgezocht in de\n\/\/ ingebedde SERIAL_LOOKUP-lijst, en pas daarna gedecodeerd als een normaal\n\/\/ artikelnummer.\nasync function resolveAndDecode(raw, lang){\n  const S = STRINGS[lang];\n  const trimmed = raw.trim().toUpperCase().replace(\/\\s+\/g,'');\n\n  if(trimmed.length === 8){\n    let lookup;\n    try{\n      lookup = await loadSerialLookup();\n    } catch(err){\n      console.warn('[VARIBOX Checker] Serienummerlookup kon niet worden geladen:', err);\n      return { error: SERIAL_LOOKUP_ERROR_TEXT[lang] || SERIAL_LOOKUP_ERROR_TEXT.en, errorType:'service', originalInput:trimmed };\n    }\n    const article = lookup[trimmed];\n    if(!article){\n      return { error: S.errorUnknownSerial, errorType:'unknown', originalInput:trimmed };\n    }\n    if(typeof article !== 'string' || article.trim().length !== 12){\n      console.warn('[VARIBOX Checker] Ongeldige artikelwaarde in serienummerdatabase voor ' + trimmed + ':', article);\n      return { error: SERIAL_LOOKUP_ERROR_TEXT[lang] || SERIAL_LOOKUP_ERROR_TEXT.en, errorType:'service', originalInput:trimmed };\n    }\n    const result = decode(article, lang);\n    result.originalInput = trimmed;\n    if(!result.error){ result.matchedSerial = trimmed; }\n    return result;\n  }\n\n  if(trimmed.length === 12){\n    const result = decode(trimmed, lang);\n    result.originalInput = trimmed;\n    return result;\n  }\n\n  return { error: S.errorLength.replace('{n}', trimmed.length), errorType:'length', originalInput:trimmed };\n}\n\n\/\/ Maximaal aantal codes dat in \u00e9\u00e9n keer verwerkt wordt bij bulk-invoer, als\n\/\/ eenvoudige veiligheidsgrens tegen extreem lange plakacties.\nconst MAX_BULK_CODES = 25;\nconst MAX_BULK_INPUT_CHARS = 5000;\n\n\/\/ Splitst de ruwe tekstvak-invoer op in losse codes (\u00e9\u00e9n per regel, of\n\/\/ gescheiden door komma's\/puntkomma's), en decodeert ze allemaal. Werkt ook\n\/\/ gewoon voor een enkele code (array van lengte 1).\nasync function parseAndResolveAll(raw, lang){\n  const rawText = String(raw == null ? '' : raw);\n  const inputWasCharTruncated = rawText.length > MAX_BULK_INPUT_CHARS;\n  const boundedRaw = inputWasCharTruncated ? rawText.slice(0, MAX_BULK_INPUT_CHARS) : rawText;\n  const entries = boundedRaw\n    .split(\/[\\n,;]+\/)\n    .map(s => s.trim())\n    .filter(s => s.length > 0);\n\n  if(entries.length === 0){\n    const emptyResults = [await resolveAndDecode('', lang)];\n    emptyResults.truncated = false;\n    return emptyResults;\n  }\n\n  const truncated = inputWasCharTruncated || entries.length > MAX_BULK_CODES;\n  const toProcess = truncated ? entries.slice(0, MAX_BULK_CODES) : entries;\n\n  const results = await Promise.all(toProcess.map(entry => resolveAndDecode(entry, lang)));\n  results.truncated = truncated;\n  return results;\n}\n\n\/\/ Bundelt meerdere ingevoerde nummers die op dezelfde configuratie uitkomen\n\/\/ (bijvoorbeeld drie serienummers van dezelfde batch) tot \u00e9\u00e9n kaart met een\n\/\/ aantal-badge, in plaats van dezelfde kaart meerdere keren te tonen.\n\/\/ Foutmeldingen worden nooit gebundeld \u2014 die blijven stuk voor stuk staan.\nfunction groupResults(results){\n  const groups = [];\n  const indexByCode = {};\n\n  results.forEach(result => {\n    if(result.error){\n      groups.push({ result, count: 1, inputs: [] });\n      return;\n    }\n    if(indexByCode[result.code] !== undefined){\n      const group = groups[indexByCode[result.code]];\n      group.count++;\n      if(result.originalInput) group.inputs.push(result.originalInput);\n    } else {\n      indexByCode[result.code] = groups.length;\n      groups.push({ result, count: 1, inputs: result.originalInput ? [result.originalInput] : [] });\n    }\n  });\n\n  return groups;\n}\n\n\/\/ Kleine, consistente lijnicoontjes per specificatie-type \u2014 geen decoratie,\n\/\/ maar structuur: elke rij is een technisch attribuut, het icoon helpt het\n\/\/ snel te herkennen zonder de labeltekst te hoeven lezen.\nconst ROW_ICONS = {\n  type: '<svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M2.5 5.5L9 2l6.5 3.5v7L9 16 2.5 12.5v-7z\"\/><path d=\"M2.5 5.5L9 9l6.5-3.5\"\/><path d=\"M9 9v7\"\/><\/svg>',\n  pakking: '<svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><circle cx=\"9\" cy=\"9\" r=\"6\"\/><circle cx=\"9\" cy=\"9\" r=\"2.2\"\/><\/svg>',\n  zuigbuis: '<svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M2.5 9h4\"\/><rect x=\"6.5\" y=\"6\" width=\"5\" height=\"6\" rx=\"1\"\/><path d=\"M11.5 9h4\"\/><\/svg>',\n  sensor: '<svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 11a6 6 0 0 1 12 0\"\/><path d=\"M9 11l3-3.5\"\/><circle cx=\"9\" cy=\"11\" r=\".9\" fill=\"currentColor\" stroke=\"none\"\/><\/svg>',\n  kleur: '<svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linejoin=\"round\"><path d=\"M9 2.3s5 5.7 5 9.1a5 5 0 0 1-10 0c0-3.4 5-9.1 5-9.1z\"\/><\/svg>',\n  food: '<svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 2l1.9 1.4 2.35-.2.75 2.25L16 6.9l-.9 2.1.9 2.1-1.98 1.45-.75 2.25-2.35-.2L9 16l-1.9-1.4-2.35.2-.75-2.25L2 10.9l.9-2.1L2 6.9l1.98-1.45.75-2.25 2.35.2L9 2z\"\/><path d=\"M6.6 9.1l1.7 1.7 3.1-3.5\"\/><\/svg>',\n  trailer: '<svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2\" y=\"6\" width=\"7\" height=\"6\"\/><path d=\"M9 8h3l2.5 2.5V12h-2\"\/><circle cx=\"5\" cy=\"13.4\" r=\"1.15\"\/><circle cx=\"12.5\" cy=\"13.4\" r=\"1.15\"\/><\/svg>',\n  combo: '<svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><circle cx=\"7\" cy=\"9\" r=\"4.3\"\/><circle cx=\"11\" cy=\"9\" r=\"4.3\"\/><\/svg>',\n  cert: '<svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 2l6 2v4.3c0 4-2.7 6.8-6 7.5-3.3-.7-6-3.5-6-7.5V4l6-2z\"\/><\/svg>',\n  reg: '<svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2.5\" y=\"3\" width=\"13\" height=\"12\" rx=\"1.5\"\/><path d=\"M5.5 7h7M5.5 10h5\"\/><\/svg>',\n  test: '<svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M7 2.5h4\"\/><path d=\"M8 2.5v4.3L3.8 13a1.6 1.6 0 0 0 1.35 2.5h7.7A1.6 1.6 0 0 0 14.2 13L10 6.8V2.5\"\/><\/svg>',\n  warning: '<svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 2.3L16.2 15H1.8L9 2.3z\"\/><path d=\"M9 7.3v3.4\"\/><circle cx=\"9\" cy=\"13.1\" r=\".15\" fill=\"currentColor\" stroke-width=\"2.2\"\/><\/svg>',\n  notfound: '<svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"7.8\" cy=\"7.8\" r=\"4.8\"\/><path d=\"M14.5 14.5l-2.9-2.9\"\/><path d=\"M7.8 5.7v.1\"\/><path d=\"M7.8 6.9a1 1 0 1 1 1 1.6c-.4.3-.6.6-.6 1.1v.1\"\/><\/svg>',\n  layers: '<svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 2.3l6.5 3.5L9 9.3 2.5 5.8 9 2.3z\"\/><path d=\"M2.5 9.3L9 12.8l6.5-3.5\"\/><path d=\"M2.5 12.8L9 16.3l6.5-3.5\"\/><\/svg>',\n  barcode: '<svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"><path d=\"M3 3v3M6 3v3M8.5 3v3M11 3v3M14 3v3\"\/><path d=\"M3 12v3M6 12v3M8.5 12v3M11 12v3M14 12v3\"\/><\/svg>',\n};\nfunction rowIcon(name){\n  return `<span class=\"vb-row-icon\">${ROW_ICONS[name] || ''}<\/span>`;\n}\n\nfunction buildProductGlyph(isDrumtainer){\n  if(isDrumtainer){\n    return `<svg viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M20 11h24l4 7v30l-5 5H21l-5-5V18l4-7z\"\/><path d=\"M18 22h28M18 42h28M24 11V7h16v4\"\/><circle cx=\"24\" cy=\"54\" r=\"3\"\/><circle cx=\"40\" cy=\"54\" r=\"3\"\/><\/svg>`;\n  }\n  return `<svg viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"13\" y=\"13\" width=\"38\" height=\"38\" rx=\"4\"\/><path d=\"M18 18h28v28H18zM18 25h28M18 39h28M25 18v28M39 18v28M27 9h10v4M11 52h42\"\/><\/svg>`;\n}\nfunction firstMatchLabel(matches){ return (matches ? matches.length === 1 : false) ? matches[0][0] : ''; }\nfunction buildColorSwatch(code){\n  const color = VB_COLOR_SWATCHES[code];\n  return color ? `<span class=\"vb-color-swatch\" style=\"background:${color}\" aria-hidden=\"true\"><\/span>` : '';\n}\nfunction buildSpecChip(icon, text, extraClass, ariaLabel){\n  if(!text) return '';\n  return `<span class=\"vb-spec-chip${extraClass ? ' ' + extraClass : ''}\"${ariaLabel ? ` aria-label=\"${esc(ariaLabel)}\"` : ''}>${icon ? rowIcon(icon) : ''}${esc(text)}<\/span>`;\n}\nfunction buildResultHero(result, S, U, shareValue, qtyBadgeHtml){\n  const chips = [];\n  if(result.isDrumtainer){\n    chips.push(buildSpecChip('trailer', firstMatchLabel(result.trailerMatches)));\n    chips.push(buildSpecChip('combo', firstMatchLabel(result.comboMatches)));\n    const colour = firstMatchLabel(result.kleurMatches);\n    if(colour) chips.push(`<span class=\"vb-spec-chip\">${buildColorSwatch(result.kleurCode)}${esc(colour)}<\/span>`);\n  } else {\n    chips.push(buildSpecChip('pakking', firstMatchLabel(result.pakkingMatches)));\n    let tube = firstMatchLabel(result.zuigbuisMatches);\n    if(tube){ try{ tube = splitZuigbuisLabel(tube).tubeLabel || tube; }catch(e){} }\n    chips.push(buildSpecChip('zuigbuis', tube));\n    chips.push(buildSpecChip('sensor', firstMatchLabel(result.sensorMatches)));\n    const colour = firstMatchLabel(result.kleurMatches);\n    if(colour) chips.push(`<span class=\"vb-spec-chip\">${buildColorSwatch(result.kleurCode)}${esc(colour)}<\/span>`);\n    chips.push(buildSpecChip('food', result.foodContact ? `${S.labelFoodContact}: ${S.yesWord}` : `${S.labelFoodContact}: ${S.noWord}`, result.foodContact ? 'vb-food-ok' : 'vb-food-neutral'));\n  }\n  const productColor = VB_COLOR_SWATCHES[result.kleurCode] || '#0078BF';\n  const sourcePill = result.matchedSerial ? `<span class=\"vb-source-pill\">${rowIcon('barcode')}${esc(U.identifiedFromSerial)}<\/span>` : '';\n  return `<div class=\"vb-result-hero\" style=\"--vb-product-color:${productColor}\">\n    <div class=\"vb-result-glyph\">${buildProductGlyph(!!result.isDrumtainer)}<\/div>\n    <div class=\"vb-result-main\">\n      <div class=\"vb-match-found\"><svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\"><circle cx=\"9\" cy=\"9\" r=\"7\"\/><path d=\"M5.5 9.2l2.2 2.2 4.8-5\"\/><\/svg>${esc(U.matchFound)}<\/div>\n      <div class=\"vb-hero-title-row\"><h3 class=\"vb-hero-title\">${esc(result.typeName)}<\/h3>${qtyBadgeHtml}<\/div>\n      <div class=\"vb-hero-code-row\"><span class=\"vb-hero-code\">${esc(result.code)}<\/span>${buildCopyBtn(result.code,S)}${buildShareLinkBtn(shareValue,S)}<\/div>\n      ${sourcePill}\n    <\/div>\n    <div class=\"vb-spec-chips\">${chips.filter(Boolean).join('')}<\/div>\n    ${buildCodeAnatomy(result,U)}\n  <\/div>`;\n}\nfunction buildTechnicalToggle(detailsId, U){\n  return `<div class=\"vb-technical-bar\"><button type=\"button\" class=\"vb-details-toggle\" data-vb-action=\"toggle-info\" data-info-id=\"${detailsId}\" aria-controls=\"${detailsId}\" aria-expanded=\"false\"><span>${esc(U.technicalDetails)}<\/span><svg class=\"vb-details-chevron\" viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.7\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 7l5 5 5-5\"\/><\/svg><\/button><\/div>`;\n}\n\nfunction buildCodeAnatomy(result, U){\n  if(!result || !result.code || result.code.length !== 12) return '';\n  const segments = result.isDrumtainer ? [\n    ['vb-seg-type', result.code.slice(0,6), U.codeType],\n    ['vb-seg-gasket', result.code.slice(6,7), U.codeDelivery],\n    ['vb-seg-tube', result.code.slice(7,8), U.codeTrailer],\n    ['vb-seg-sensor', result.code.slice(8,9), U.codeCombination],\n    ['vb-seg-colour', result.code.slice(9,12), U.codeColour]\n  ] : [\n    ['vb-seg-type', result.typeCode, U.codeType],\n    ['vb-seg-gasket', result.pakkingChar, U.codeGasket],\n    ['vb-seg-tube', result.zuigbuisChar, U.codeTube],\n    ['vb-seg-sensor', result.sensorChar, U.codeSensor],\n    ['vb-seg-colour', result.kleurCode, U.codeColour]\n  ];\n  return `<div class=\"vb-code-anatomy\" aria-label=\"${esc(U.codeBreakdown)}\"><div class=\"vb-code-anatomy-title\">${esc(U.codeBreakdown)}<\/div><div class=\"vb-code-anatomy-track\">${segments.map(([cls,value,label])=>`<span class=\"vb-code-segment ${cls}\" title=\"${esc(label)}\"><span class=\"vb-code-segment-value\">${esc(value)}<\/span><span class=\"vb-code-segment-label\">${esc(label)}<\/span><\/span>`).join('')}<\/div><\/div>`;\n}\nfunction buildErrorState(result, S, U){\n  const service = result.errorType === 'service';\n  const entered = result.originalInput || '';\n  const title = service ? U.serviceUnavailable : U.couldNotIdentify;\n  const icon = service ? rowIcon('warning') : rowIcon('notfound');\n  const enteredHtml = entered ? `<div class=\"vb-error-entered\"><span>${esc(U.enteredValue)}:<\/span><code>${esc(entered)}<\/code><\/div>` : '';\n  return `<div class=\"vb-error-card${service ? ' vb-service-error' : ''}\">\n    <div class=\"vb-error-icon\">${icon}<\/div>\n    <div><h3 class=\"vb-error-title\">${esc(title)}<\/h3><p class=\"vb-error-message\">${esc(result.error)}<\/p>${enteredHtml}<\/div>\n    <div class=\"vb-error-actions\">\n      <button type=\"button\" class=\"vb-mini-action\" data-vb-action=\"focus-search\">${esc(U.editNumber)}<\/button>\n      <button type=\"button\" class=\"vb-mini-action\" data-vb-action=\"fill-search\" data-code=\"VB1001AED709\">${esc(U.useExample)}<\/button>\n      <a class=\"vb-mini-action\" href=\"https:\/\/varibox.best4u.dev\/es\/contacto\/\" target=\"_blank\" rel=\"noopener\">${esc(U.contactSupport)}<\/a>\n    <\/div>\n  <\/div>`;\n}\nfunction buildBulkOverview(results, groups, S, U){\n  if(results.length <= 1) return '';\n  const ok = results.filter(r => !r.error).length;\n  const attention = results.length - ok;\n  const configs = groups.filter(g => !g.result.error).length;\n  const subtitle = S.bulkSummary.replace('{ok}',ok).replace('{total}',results.length);\n  const truncated = results.truncated ? `<span class=\"vb-bulk-warn\">${esc(S.bulkTruncated.replace('{max}',MAX_BULK_CODES))}<\/span>` : '';\n  return `<section class=\"vb-bulk-overview\" aria-label=\"${esc(U.bulkOverview)}\">\n    <div class=\"vb-bulk-overview-top\"><div><h3 class=\"vb-bulk-overview-title\">${esc(U.bulkOverview)}<\/h3><p class=\"vb-bulk-overview-sub\">${esc(subtitle)} ${truncated}<\/p><\/div>${rowIcon('layers')}<\/div>\n    <div class=\"vb-bulk-stats\">\n      <div class=\"vb-bulk-stat vb-stat-ok\"><span class=\"vb-bulk-stat-value\">${ok}<\/span><span class=\"vb-bulk-stat-label\">${esc(U.recognized)}<\/span><\/div>\n      <div class=\"vb-bulk-stat\"><span class=\"vb-bulk-stat-value\">${configs}<\/span><span class=\"vb-bulk-stat-label\">${esc(U.configurations)}<\/span><\/div>\n      <div class=\"vb-bulk-stat vb-stat-attention\"><span class=\"vb-bulk-stat-value\">${attention}<\/span><span class=\"vb-bulk-stat-label\">${esc(U.attention)}<\/span><\/div>\n    <\/div>\n    <div class=\"vb-bulk-filters\" role=\"group\" aria-label=\"${esc(U.bulkOverview)}\">\n      <button type=\"button\" class=\"vb-filter-btn\" data-vb-action=\"filter-results\" data-filter=\"all\" aria-pressed=\"true\">${esc(U.filterAll)}<\/button>\n      ${attention > 0 ? `<button type=\"button\" class=\"vb-filter-btn\" data-vb-action=\"filter-results\" data-filter=\"ok\" aria-pressed=\"false\">${esc(U.filterRecognized)}<\/button><button type=\"button\" class=\"vb-filter-btn\" data-vb-action=\"filter-results\" data-filter=\"error\" aria-pressed=\"false\">${esc(U.filterAttention)}<\/button>` : ''}\n      ${groups.length > 3 ? `<button type=\"button\" class=\"vb-filter-btn vb-view-toggle\" data-vb-action=\"toggle-compact\" data-compact-label=\"${esc(U.compactView)}\" data-card-label=\"${esc(U.cardView)}\" aria-pressed=\"false\">${esc(U.compactView)}<\/button>` : ''}\n    <\/div>\n  <\/section>`;\n}\nfunction filterResultCards(filter, button){\n  const root = document.getElementById('vb-result');\n  if(!root) return;\n  root.querySelectorAll('.vb-result-item[data-vb-status]').forEach(item => {\n    const show = filter === 'all' || item.dataset.vbStatus === filter;\n    item.classList.toggle('vb-filter-hidden', !show);\n  });\n  root.querySelectorAll('.vb-filter-btn[data-filter]').forEach(btn => btn.setAttribute('aria-pressed', String(btn === button)));\n  vbMetric('bulk_filter_changed', { filter, language:CURRENT_LANG, mode:'bulk', interaction:'change' });\n}\nfunction toggleCompactResults(button){\n  const root = document.getElementById('vb-result');\n  if(!root || !button) return;\n  const compact = root.classList.toggle('vb-compact-results');\n  button.setAttribute('aria-pressed', String(compact));\n  button.textContent = compact ? (button.dataset.cardLabel || 'Cards') : (button.dataset.compactLabel || 'Compact');\n  vbMetric('bulk_view_changed', { compact, language:CURRENT_LANG, mode:'bulk', interaction:'change' });\n}\n\n\/\/ Bouwt de kleine kopieer-knop naast een code-uitleesweergave. Klikken\n\/\/ kopieert de code naar het klembord (nuttig, want artikel-\/serienummers\n\/\/ worden vaak overgenomen in bestellingen of e-mails) en toont kort een\n\/\/ bevestigend vinkje + tooltip.\nfunction buildCopyBtn(code, S){\n  return `<button type=\"button\" class=\"vb-copy-btn\" data-vb-action=\"copy\" data-copy-kind=\"code\" data-copy-value=\"${esc(code)}\" aria-label=\"${esc(S.copyLabel)}\">\n    <svg class=\"vb-copy-icon-default\" viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"6\" y=\"6\" width=\"9\" height=\"9\" rx=\"1.3\"\/><path d=\"M12 6V3.8A1.3 1.3 0 0 0 10.7 2.5H3.8A1.3 1.3 0 0 0 2.5 3.8v6.9A1.3 1.3 0 0 0 3.8 12H6\"\/><\/svg>\n    <svg class=\"vb-copy-icon-check\" viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3.5 9.5l3.2 3.2L14.5 5\"\/><\/svg>\n    <span class=\"vb-copy-tooltip\">${esc(S.copiedLabel)}<\/span>\n  <\/button>`;\n}\n\n\/\/ Bouwt een tweede kleine knop naast de code-weergave: kopieert een deelbare link naar dit\n\/\/ specifieke resultaat (artikelnummer als URL-parameter) naar het klembord, zodat een collega\n\/\/ die opent en direct hetzelfde resultaat ziet zonder het nummer opnieuw te hoeven intypen.\n\/\/ Hergebruikt dezelfde .vb-copy-btn-stijl en copyCode()-logica als de code-kopieerknop.\nfunction buildShareLinkBtn(code, S){\n  let url;\n  try{\n    const shareUrl = new URL(window.location.href);\n    shareUrl.searchParams.set('vbcode', code);\n    shareUrl.searchParams.set('vblang', CURRENT_LANG);\n    shareUrl.hash = '';\n    url = shareUrl.toString();\n  } catch(e){\n    url = window.location.origin + window.location.pathname + '?vbcode=' + encodeURIComponent(code) + '&vblang=' + encodeURIComponent(CURRENT_LANG);\n  }\n  return `<button type=\"button\" class=\"vb-copy-btn\" data-vb-action=\"copy\" data-copy-kind=\"share_link\" data-copy-value=\"${esc(url)}\" aria-label=\"${esc(S.shareLinkLabel)}\" title=\"${esc(S.shareLinkLabel)}\">\n    <svg class=\"vb-copy-icon-default\" viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"13.5\" cy=\"4.5\" r=\"2\"\/><circle cx=\"4.5\" cy=\"9\" r=\"2\"\/><circle cx=\"13.5\" cy=\"13.5\" r=\"2\"\/><path d=\"M6.3 7.8L11.7 5.2M6.3 10.2L11.7 12.8\"\/><\/svg>\n    <svg class=\"vb-copy-icon-check\" viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3.5 9.5l3.2 3.2L14.5 5\"\/><\/svg>\n    <span class=\"vb-copy-tooltip\">${esc(S.shareLinkCopiedLabel)}<\/span>\n  <\/button>`;\n}\nfunction esc(s){\n  return String(s)\n    .replace(\/\\u0026\/g,'&amp;')\n    .replace(\/<\/g,'&lt;')\n    .replace(\/>\/g,'&gt;')\n    .replace(\/\"\/g,'&quot;')\n    .replace(\/'\/g,'&#39;');\n}\n\n\/\/ Bouwt een klein, geanimeerd vinkje + tekst voor een geslaagde\n\/\/ formulierverzending \u2014 vervangt platte \"Verzonden!\"-tekst door een subtiel,\n\/\/ premium bevestigingsmoment dat direct reageert op de actie van de klant.\nfunction buildSuccessHtml(text){\n  return `<span class=\"vb-success-check\"><svg viewBox=\"0 0 24 24\" fill=\"none\"><circle class=\"vb-success-circle\" cx=\"12\" cy=\"12\" r=\"10.5\"\/><path class=\"vb-success-tick\" d=\"M7 12.5l3.2 3.2L17 9\"\/><\/svg><\/span><span>${esc(text)}<\/span>`;\n}\nfunction showFormFeedbackToast(text, success){\n  const container = document.getElementById('vb-toast-container');\n  if(!container) return;\n  const toast = document.createElement('div');\n  toast.className = 'vb-toast' + (success ? '' : ' vb-toast-error');\n  toast.setAttribute('role', 'status');\n  toast.innerHTML = success ? buildSuccessHtml(text) : `<span>${esc(text)}<\/span>`;\n  container.appendChild(toast);\n  requestAnimationFrame(() => toast.classList.add('vb-toast-in'));\n  const remove = () => {\n    toast.classList.remove('vb-toast-in');\n    toast.classList.add('vb-toast-out');\n    setTimeout(() => { if(toast.parentNode) toast.parentNode.removeChild(toast); }, 300);\n  };\n  toast.addEventListener('click', remove);\n  setTimeout(remove, 5200);\n}\n\n\/\/ Kopieert een code naar het klembord en toont kort een bevestigend vinkje +\n\/\/ tooltip op de knop zelf. Valt terug op document.execCommand voor oudere\n\/\/ browsers\/contexten zonder navigator.clipboard (bv. geen HTTPS).\nfunction copyCode(code, btn){\n  const showFeedback = () => {\n    btn.classList.add('vb-copied');\n    vbMetric('copy_completed', { copy_kind:(btn ? btn.dataset : false) ? (btn.dataset.copyKind || 'unknown') : 'unknown', language:CURRENT_LANG, outcome:'success' });\n    clearTimeout(btn._copyTimeout);\n    btn._copyTimeout = setTimeout(() => btn.classList.remove('vb-copied'), 1600);\n  };\n  const fallbackCopy = () => {\n    const helper = document.createElement('textarea');\n    helper.value = code;\n    helper.setAttribute('readonly', '');\n    helper.style.position = 'fixed';\n    helper.style.left = '-9999px';\n    helper.style.opacity = '0';\n    document.body.appendChild(helper);\n    helper.select();\n    helper.setSelectionRange(0, helper.value.length);\n    let copied = false;\n    try { copied = document.execCommand('copy'); } catch(e) { copied = false; }\n    document.body.removeChild(helper);\n    if(copied) showFeedback();\n  };\n  let canUseClipboard = false;\n  if(navigator.clipboard){\n    if(navigator.clipboard.writeText) canUseClipboard = true;\n  }\n  if(canUseClipboard){\n    navigator.clipboard.writeText(code).then(showFeedback).catch(fallbackCopy);\n  } else {\n    fallbackCopy();\n  }\n}\n\n\/\/ Verhoogt\/verlaagt het aantal-veldje van een resultaatkaart met 1 (nooit\n\/\/ onder 1), voor de plus\/min-knoppen naast het invoerveld.\nfunction adjustQty(idx, delta){\n  const input = document.getElementById('vb-qty-input-' + idx);\n  if(!input) return;\n  const val = normalizePartQty(normalizePartQty(input.value) + delta);\n  input.value = val;\n}\n\n\/\/ Bouwt de \u00c9\u00c9N-KEER getoonde, afsluitende actiesectie onderaan alle\n\/\/ resultaatkaarten: titel\/toelichting, gevolgd door twee knoppen n\u00e1\u00e1st\n\/\/ elkaar (\"Vraag uw offerte aan\" \/ formulier 13, en \"Mail dit resultaat\" \/\n\/\/ formulier 15), die elk hun eigen compacte formulier openklappen. Beide\n\/\/ verzamelen alle getoonde resultaten in \u00e9\u00e9n inzending \u2014 bij de offerte\n\/\/ inclusief het per kaart ingevulde aantal (vb-qty-input-*).\n\/\/ Klapt \u00e9\u00e9n van de twee \"Volgende stappen\"-formulieren (offerte\/e-mail) open, en sluit daarbij\n\/\/ altijd eerst het ANDERE formulier -- zodat het gedrag als exclusieve tabbladen werkt in plaats\n\/\/ van dat beide tegelijk open kunnen staan.\nfunction toggleNextStepForm(formId, otherFormId){\n  const otherEl = document.getElementById(otherFormId);\n  if(otherEl) setCollapsibleState(otherEl, false);\n  const el = document.getElementById(formId);\n  if(el){\n    const willOpen = !el.classList.contains('vb-open');\n    setCollapsibleState(el, willOpen);\n    const formKind = String(formId || '').includes('quote') ? 'quote' : (String(formId || '').includes('email') ? 'email' : null);\n    if(formKind) vbMetric('next_step_toggled', { form_kind:formKind, open:willOpen, language:CURRENT_LANG, interaction:willOpen ? 'open' : 'close' });\n  }\n}\nfunction closeNextStepForm(formId){\n  setCollapsibleState(document.getElementById(formId), false);\n  const formKind = String(formId || '').includes('quote') ? 'quote' : (String(formId || '').includes('email') ? 'email' : null);\n  if(formKind) vbMetric('next_step_toggled', { form_kind:formKind, open:false, language:CURRENT_LANG, interaction:'close', outcome:'cancelled' });\n}\nfunction toggleInfoPanel(infoId, btn){\n  const el = document.getElementById(infoId);\n  if(!el) return;\n  setCollapsibleState(el, !el.classList.contains('vb-open'));\n  if(btn) btn.setAttribute('aria-expanded', el.classList.contains('vb-open') ? 'true' : 'false');\n}\nfunction buildCombinedQuoteHtml(S){\n  return `\n    <div class=\"vb-combined-quote\">\n      <h3 class=\"vb-combined-quote-title\">${esc(S.combinedQuoteTitle)}<\/h3>\n      <p class=\"vb-combined-quote-intro\">${esc(S.combinedQuoteIntro)}<\/p>\n      <div class=\"vb-next-steps-grid\">\n        <button type=\"button\" class=\"vb-next-step-card\" data-vb-action=\"toggle-next-step\" data-form-id=\"vb-combined-quote-form\" data-other-form-id=\"vb-combined-email-form\" aria-controls=\"vb-combined-quote-form\" aria-expanded=\"false\">\n          <span class=\"vb-next-step-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.7\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M7 3.5h8l3 3v14h-11z\"\/><path d=\"M15 3.5v3h3\"\/><path d=\"M9.5 12h5M9.5 15h5M9.5 9h2.5\"\/><\/svg><\/span>\n          <span><span class=\"vb-next-step-label\">${esc(S.requestQuoteButton)}<\/span><span class=\"vb-next-step-desc\">${esc((UX_STRINGS[CURRENT_LANG]||UX_STRINGS.en).quoteDesc)}<\/span><\/span>\n        <\/button>\n        <button type=\"button\" class=\"vb-next-step-card vb-next-step-card-secondary\" data-vb-action=\"toggle-next-step\" data-form-id=\"vb-combined-email-form\" data-other-form-id=\"vb-combined-quote-form\" aria-controls=\"vb-combined-email-form\" aria-expanded=\"false\">\n          <span class=\"vb-next-step-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.7\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3.5\" y=\"5.5\" width=\"17\" height=\"13\" rx=\"1.6\"\/><path d=\"M4 7l8 6 8-6\"\/><\/svg><\/span>\n          <span><span class=\"vb-next-step-label\">${esc(S.emailResultButton)}<\/span><span class=\"vb-next-step-desc\">${esc((UX_STRINGS[CURRENT_LANG]||UX_STRINGS.en).emailDesc)}<\/span><\/span>\n        <\/button>\n      <\/div>\n      <div id=\"vb-combined-quote-form\" class=\"vb-collapsible\" aria-hidden=\"true\" inert><div class=\"vb-collapsible-inner\">\n        <form class=\"vb-email-form\" data-vb-form=\"quote\">\n        <input type=\"text\" id=\"vb-combined-quote-name\" placeholder=\"${esc(S.emailFormNameLabel)}\" aria-label=\"${esc(S.emailFormNameLabel)}\" autocomplete=\"name\" class=\"vb-email-input\" required>\n        <input type=\"email\" id=\"vb-combined-quote-email\" placeholder=\"${esc(S.emailFormEmailLabel)}\" aria-label=\"${esc(S.emailFormEmailLabel)}\" autocomplete=\"email\" class=\"vb-email-input\" required>\n        <input type=\"tel\" id=\"vb-combined-quote-phone\" placeholder=\"${esc(S.emailFormPhoneLabel)}\" aria-label=\"${esc(S.emailFormPhoneLabel)}\" autocomplete=\"tel\" class=\"vb-email-input\">\n        <input type=\"text\" id=\"vb-combined-quote-company\" placeholder=\"${esc(S.emailFormCompanyLabel)}\" aria-label=\"${esc(S.emailFormCompanyLabel)}\" autocomplete=\"organization\" class=\"vb-email-input\">\n        <div class=\"vb-email-form-actions\">\n          <button type=\"submit\" class=\"vb-cta-btn\">${esc(S.quoteFormSubmit)}<\/button>\n          <button type=\"button\" class=\"vb-cta-btn vb-cta-btn-secondary\" data-vb-action=\"close-form\" data-form-id=\"vb-combined-quote-form\">${esc(S.quoteFormCancel)}<\/button>\n        <\/div>\n        <div id=\"vb-combined-quote-status\" class=\"vb-email-status\" role=\"status\" aria-live=\"polite\"><\/div>\n        <\/form>\n      <\/div><\/div>\n      <div id=\"vb-combined-email-form\" class=\"vb-collapsible\" aria-hidden=\"true\" inert><div class=\"vb-collapsible-inner\">\n        <form class=\"vb-email-form\" data-vb-form=\"email\">\n        <input type=\"text\" id=\"vb-combined-email-name\" placeholder=\"${esc(S.emailFormNameLabel)}\" aria-label=\"${esc(S.emailFormNameLabel)}\" autocomplete=\"name\" class=\"vb-email-input\" required>\n        <input type=\"email\" id=\"vb-combined-email-email\" placeholder=\"${esc(S.emailFormEmailLabel)}\" aria-label=\"${esc(S.emailFormEmailLabel)}\" autocomplete=\"email\" class=\"vb-email-input\" required>\n        <input type=\"tel\" id=\"vb-combined-email-phone\" placeholder=\"${esc(S.emailFormPhoneLabel)}\" aria-label=\"${esc(S.emailFormPhoneLabel)}\" autocomplete=\"tel\" class=\"vb-email-input\">\n        <input type=\"text\" id=\"vb-combined-email-company\" placeholder=\"${esc(S.emailFormCompanyLabel)}\" aria-label=\"${esc(S.emailFormCompanyLabel)}\" autocomplete=\"organization\" class=\"vb-email-input\">\n        <div class=\"vb-email-form-actions\">\n          <button type=\"submit\" class=\"vb-cta-btn\">${esc(S.emailFormSubmit)}<\/button>\n          <button type=\"button\" class=\"vb-cta-btn vb-cta-btn-secondary\" data-vb-action=\"close-form\" data-form-id=\"vb-combined-email-form\">${esc(S.emailFormCancel)}<\/button>\n        <\/div>\n        <div id=\"vb-combined-email-status\" class=\"vb-email-status\" role=\"status\" aria-live=\"polite\"><\/div>\n        <\/form>\n      <\/div><\/div>\n    <\/div>`;\n}\n\n\/\/ Verzamelt de onderdelen-webshoplinks van alle getoonde (geslaagde)\n\/\/ resultaten en toont ze als allerlaatste onderdeel van de pagina, n\u00e1 de\n\/\/ offerte\/mail-knoppen \u2014 in plaats van tussen elke kaart en die knoppen in,\n\/\/ wat rommelig oogde. Dubbele links (bv. twee kaarten van dezelfde\n\/\/ productlijn) worden samengevoegd tot \u00e9\u00e9n regel.\nfunction buildSparePartsSummaryHtml(S){\n  const seen = new Map();\n  LAST_RENDERED_RESULTS.forEach((result) => {\n    if(result.error || !result.sparePartsUrl || seen.has(result.sparePartsUrl)) return;\n    seen.set(result.sparePartsUrl, result.typeName);\n  });\n  if(seen.size === 0) return '';\n  const showType = seen.size > 1;\n  const linksHtml = Array.from(seen.entries()).map(([url, typeName]) =>\n    `<a class=\"vb-spareparts-btn\" href=\"${url}\" target=\"_blank\" rel=\"noopener\">${esc(S.sparePartsLink)}${showType ? ' \u2014 ' + esc(typeName) : ''}<\/a>`\n  ).join('');\n  return `<div class=\"vb-spareparts-note\"><div class=\"vb-spareparts-text\">${esc(S.sparePartsNote)}<\/div><div class=\"vb-spareparts-links\">${linksHtml}<\/div><\/div>`;\n}\n\n\/\/ Bouwt het aantal-veldje met plus\/min-knoppen (prettiger en touch-\n\/\/ vriendelijker dan de kleine ingebouwde stappertjes van een number-input).\n\/\/ Wordt in zowel de Drumtainer- als de normale tak gebruikt.\nfunction buildQtyWidgetHtml(idx, S, initialQty){\n  const qty = normalizePartQty(initialQty || 1);\n  return `\n    <div class=\"vb-qty-wrap\">\n      <label for=\"vb-qty-input-${idx}\">${esc(S.quantityLabel)}<\/label>\n      <div class=\"vb-qty-stepper\">\n        <button type=\"button\" class=\"vb-qty-step-btn\" data-vb-action=\"qty\" data-idx=\"${idx}\" data-delta=\"-1\" aria-label=\"${esc(S.quantityDecrease)}\">\u2212<\/button>\n        <input type=\"number\" id=\"vb-qty-input-${idx}\" class=\"vb-qty-input\" min=\"1\" max=\"999\" step=\"1\" value=\"${qty}\" inputmode=\"numeric\" data-vb-qty-index=\"${idx}\">\n        <button type=\"button\" class=\"vb-qty-step-btn\" data-vb-action=\"qty\" data-idx=\"${idx}\" data-delta=\"1\" aria-label=\"${esc(S.quantityIncrease)}\">+<\/button>\n      <\/div>\n    <\/div>`;\n}\nfunction normalizeQtyInput(idx){\n  const input = document.getElementById('vb-qty-input-' + idx);\n  if(input) input.value = String(normalizePartQty(input.value));\n}\n\nfunction buildResultHtml(result, lang, idx, count, inputs){\n  const S = STRINGS[lang];\n  const U = UX_STRINGS[lang] || UX_STRINGS.en;\n  const infoId = 'vb-food-info-note-' + idx;\n  const detailsId = 'vb-technical-details-' + idx;\n  const qtyBadgeHtml = count > 1 ? `<span class=\"vb-qty-badge\">\u00d7${count}<\/span>` : '';\n\n  const groupOrSerialNoteHtml = (() => {\n    if(count > 1){\n      const MAX_LIST = 8;\n      const shown = inputs.slice(0, MAX_LIST).map(esc);\n      let listText = shown.join(', ');\n      if(inputs.length > MAX_LIST) listText += esc(S.groupNoteMore.replace('{more}', inputs.length - MAX_LIST));\n      return `<div class=\"vb-serial-note\">${rowIcon('layers')}${esc(S.groupNote).replace('{count}', count).replace('{list}', listText)}<\/div>`;\n    }\n    if(result.matchedSerial) return `<div class=\"vb-serial-note\">${rowIcon('barcode')}${esc(S.serialMatchNote.replace('{serial}', result.matchedSerial))}<\/div>`;\n    return '';\n  })();\n\n  if(result.error) return buildErrorState(result,S,U);\n  const shareValue = (count === 1 ? !!result.originalInput : false) ? result.originalInput : result.code;\n  const heroHtml = buildResultHero(result, S, U, shareValue, qtyBadgeHtml);\n\n  if(result.isDrumtainer){\n    const rowHtml = (char, matches, isColour) => matches.length === 0\n      ? `<div class=\"vb-value\"><span class=\"vb-segment\">${esc(char)}<\/span>${esc(S.unknownCode)}<\/div>`\n      : `<div class=\"vb-value\"><span class=\"vb-segment\">${esc(char)}<\/span>${isColour ? buildColorSwatch(char) : ''}${esc(matches[0][0])}<\/div>`;\n    const DIBT_TEXT = 'Allgemeine bauaufsichtliche Zulassung Z-40.22-478 (standard version only)';\n    const ADR_TEXT = 'Overpack certification. Within the framework of the regulation for the transport of dangerous goods by road.';\n    const VIBRATION_TEXT = 'According to the test standard ASTM 4169-08, DC2, Schedule E (vehicle vibration), assurance level II. \u00a712.4, ASTM D 4728-06 Method A and B';\n    const dibtHtml = `<div class=\"vb-value\">${result.dibtApplicable ? esc(DIBT_TEXT) : esc(S.dtNotApplicable)}<\/div>`;\n    const rows = `<div class=\"vb-rows\">\n      <div class=\"vb-row\"><div class=\"vb-label\">${rowIcon('type')}${esc(S.labelType)}<\/div><div class=\"vb-value\"><span class=\"vb-segment\">${esc(result.typeCode)}<\/span>${esc(result.typeName)}<\/div><\/div>\n      <div class=\"vb-row\"><div class=\"vb-label\">${rowIcon('trailer')}${esc(S.labelTrailer)}<\/div>${rowHtml(result.trailerChar,result.trailerMatches,false)}<\/div>\n      <div class=\"vb-row\"><div class=\"vb-label\">${rowIcon('combo')}${esc(S.labelCombo)}<\/div>${rowHtml(result.comboChar,result.comboMatches,false)}<\/div>\n      <div class=\"vb-row\"><div class=\"vb-label\">${rowIcon('kleur')}${esc(S.labelKleur)}<\/div>${rowHtml(result.kleurCode,result.kleurMatches,true)}<\/div>\n      <div class=\"vb-row\"><div class=\"vb-label\">${rowIcon('cert')}${esc(S.labelDIBt)}<\/div>${dibtHtml}<\/div>\n      <div class=\"vb-row\"><div class=\"vb-label\">${rowIcon('reg')}${esc(S.labelADR)}<\/div><div class=\"vb-value\">${esc(ADR_TEXT)}<\/div><\/div>\n      <div class=\"vb-row\"><div class=\"vb-label\">${rowIcon('test')}${esc(S.labelVibration)}<\/div><div class=\"vb-value\">${esc(VIBRATION_TEXT)}<\/div><\/div>\n    <\/div>`;\n    return `<div class=\"vb-card vb-result-card\">${heroHtml}${groupOrSerialNoteHtml}${buildTechnicalToggle(detailsId,U)}<div id=\"${detailsId}\" class=\"vb-collapsible vb-tech-collapse\" aria-hidden=\"true\" inert><div class=\"vb-collapsible-inner\">${rows}<\/div><\/div><\/div>${buildQtyWidgetHtml(idx,S,count)}`;\n  }\n\n  const pakkingHtml = (() => {\n    if(result.pakkingMatches.length === 0 ? result.specialMatches.length === 0 : false) return `<div class=\"vb-value\"><span class=\"vb-segment\">${esc(result.pakkingChar)}<\/span>${esc(S.unknownCode)}<\/div>`;\n    let html = `<div class=\"vb-value\"><span class=\"vb-segment\">${esc(result.pakkingChar)}<\/span>`;\n    if(result.pakkingMatches.length === 1) html += esc(result.pakkingMatches[0][0]);\n    else if(result.pakkingMatches.length > 1) html += result.pakkingMatches.map(m=>esc(m[0])).join(` <em>${esc(S.orWord)}<\/em> `);\n    else html += '&mdash;';\n    if(result.specialMatches.length > 0) html += `<ul class=\"vb-alt-list\">${result.specialMatches.map(m=>`<li>${esc(m[0])}<\/li>`).join('')}<\/ul>`;\n    return html + `<\/div>`;\n  })();\n  const zuigbuisHtml = (() => {\n    if(result.zuigbuisMatches.length === 0) return `<div class=\"vb-value\"><span class=\"vb-segment\">${esc(result.zuigbuisChar)}<\/span>${esc(S.unknownCode)}<\/div>`;\n    let html = `<div class=\"vb-value\"><span class=\"vb-segment\">${esc(result.zuigbuisChar)}<\/span>`;\n    html += result.zuigbuisMatches.length === 1 ? esc(result.zuigbuisMatches[0][0]) : `<ul class=\"vb-alt-list\">${result.zuigbuisMatches.map(m=>`<li>${esc(m[0])}<\/li>`).join('')}<\/ul>`;\n    return html + `<\/div>`;\n  })();\n  const sensorHtml = result.sensorMatches.length === 0\n    ? `<div class=\"vb-value\"><span class=\"vb-segment\">${esc(result.sensorChar)}<\/span>${esc(S.unknownCode)}<\/div>`\n    : `<div class=\"vb-value\"><span class=\"vb-segment\">${esc(result.sensorChar)}<\/span>${esc(result.sensorMatches[0][0])}<\/div>`;\n  const kleurHtml = result.kleurMatches.length === 0\n    ? `<div class=\"vb-value\"><span class=\"vb-segment\">${esc(result.kleurCode)}<\/span>${esc(S.unknownCode)}<\/div>`\n    : `<div class=\"vb-value\"><span class=\"vb-segment\">${esc(result.kleurCode)}<\/span>${buildColorSwatch(result.kleurCode)}${esc(result.kleurMatches[0][0])}<\/div>`;\n  const foodDocLinkHtml = (result.foodContact ? !!result.foodDocUrl : false) ? ` <a class=\"vb-doc-link\" href=\"${result.foodDocUrl}\" target=\"_blank\" rel=\"noopener\">${esc(S.foodDocLabel)}<\/a>` : '';\n  const foodContactHtml = `<div class=\"vb-value\">${result.foodContact ? `<span class=\"vb-value-yes\">${esc(S.yesWord)}<\/span>` : esc(S.noWord)}${foodDocLinkHtml}<\/div>`;\n  const certRows = result.certInfo ? `<div class=\"vb-row\"><div class=\"vb-label\">${rowIcon('cert')}${esc(S.labelUN)}<\/div><div class=\"vb-value\">${esc(result.certInfo.un)}<\/div><\/div><div class=\"vb-row\"><div class=\"vb-label\">${rowIcon('cert')}${esc(S.labelDIBt)}<\/div><div class=\"vb-value\">${esc(result.certInfo.dibt)}<\/div><\/div>` : '';\n  const rows = `<div class=\"vb-rows\">\n    <div class=\"vb-row\"><div class=\"vb-label\">${rowIcon('type')}${esc(S.labelType)}<\/div><div class=\"vb-value\"><span class=\"vb-segment\">${esc(result.typeCode)}<\/span>${esc(result.typeName)}<\/div><\/div>\n    <div class=\"vb-row\"><div class=\"vb-label\">${rowIcon('pakking')}${esc(S.labelPakking)}<\/div>${pakkingHtml}<\/div>\n    <div class=\"vb-row\"><div class=\"vb-label\">${rowIcon('zuigbuis')}${esc(S.labelZuigbuis)}<\/div>${zuigbuisHtml}<\/div>\n    <div class=\"vb-row\"><div class=\"vb-label\">${rowIcon('sensor')}${esc(S.labelSensor)}<\/div>${sensorHtml}<\/div>\n    <div class=\"vb-row\"><div class=\"vb-label\">${rowIcon('kleur')}${esc(S.labelKleur)}<\/div>${kleurHtml}<\/div>\n    <div class=\"vb-row\"><div class=\"vb-label\">${rowIcon('food')}${esc(S.labelFoodContact)} <button type=\"button\" class=\"vb-info-btn\" data-vb-action=\"toggle-info\" data-info-id=\"${infoId}\" aria-label=\"${esc(S.labelFoodContact + ' \u2013 ' + S.foodContactInfoLink)}\" aria-controls=\"${infoId}\" aria-expanded=\"false\">\u24d8<\/button><\/div>${foodContactHtml}<\/div>\n    <div id=\"${infoId}\" class=\"vb-collapsible\" aria-hidden=\"true\" inert><div class=\"vb-collapsible-inner\"><div class=\"vb-food-info-note\">${esc(S.foodContactInfo)} <a href=\"${FOOD_CONTACT_INFO_URL}\" target=\"_blank\" rel=\"noopener\">${esc(S.foodContactInfoLink)}<\/a><\/div><\/div><\/div>${certRows}\n  <\/div>`;\n  return `<div class=\"vb-card vb-result-card\">${heroHtml}${groupOrSerialNoteHtml}${buildTechnicalToggle(detailsId,U)}<div id=\"${detailsId}\" class=\"vb-collapsible vb-tech-collapse\" aria-hidden=\"true\" inert><div class=\"vb-collapsible-inner\">${rows}<\/div><\/div><\/div>${buildQtyWidgetHtml(idx,S,count)}${buildPartsPopupHtml(result,idx,S)}`;\n}\n\n\/\/ Verwerkt en toont \u00e9\u00e9n of meerdere resultaten tegelijk (bulk-invoer: \u00e9\u00e9n code\n\/\/ per regel, of gescheiden door komma's\/puntkomma's). Elke kaart krijgt een\n\/\/ eigen unieke ID voor het food-contact-info-knopje, zodat ze onafhankelijk\n\/\/ van elkaar werken wanneer er meerdere resultaten onder elkaar staan.\n\/\/ Bouwt de \"voeg alle geselecteerde onderdelen in \u00e9\u00e9n keer toe\"-knop die verschijnt zodra er\n\/\/ meerdere artikelnummers zijn ingevoerd (bulk) en er bij minstens \u00e9\u00e9n daarvan onderdelen\n\/\/ beschikbaar zijn. Verzamelt bij klikken de aangevinkte vakjes uit ALLE resultaatkaarten.\nfunction buildCombinedPartsHtml(S){\n  return `\n    <div class=\"vb-combined-parts\">\n      <button type=\"button\" id=\"vb-combined-parts-btn\" class=\"vb-cta-btn\" data-vb-action=\"add-all-parts\">${esc(S.partsAddAllButton)}<\/button>\n      <span class=\"vb-combined-parts-total\" id=\"vb-combined-parts-total\"><\/span>\n      <div id=\"vb-combined-parts-status\" class=\"vb-email-status\" role=\"status\" aria-live=\"polite\"><\/div>\n    <\/div>`;\n}\n\/\/ Telt het subtotaal van ALLE resultaatkaarten samen op tot \u00e9\u00e9n groot totaal, voor de\n\/\/ gecombineerde \"voeg alles toe\"-knop bij meerdere ingevoerde artikelnummers.\nfunction updateCombinedPartsTotal(){\n  const totalEl = document.getElementById('vb-combined-parts-total');\n  if(!totalEl) return;\n  const S = STRINGS[CURRENT_LANG];\n  const allPopups = document.querySelectorAll('[id^=\"vb-parts-popup-\"]');\n  let total = 0;\n  let anyKnown = false;\n  let refPrices = null;\n  allPopups.forEach(popup => {\n    const popupIdx = popup.id.replace('vb-parts-popup-', '');\n    popup.querySelectorAll('.vb-part-checkbox:checked').forEach(cb => {\n      const row = cb.closest('.vb-part-card');\n      const itemIdx = row ? row.dataset.itemIdx : null;\n      if(itemIdx === null) return;\n      const unit = ROW_UNIT_PRICE_STATE[popupIdx + '-' + itemIdx];\n      if(unit){\n        const qty = getPartQty(popupIdx, itemIdx);\n        total += unit.priceMinor * qty;\n        anyKnown = true;\n        refPrices = unit.refPrices;\n      }\n    });\n  });\n  if(anyKnown){\n    if(total > 0){\n      const formatted = formatStorePriceMinor(total, refPrices);\n      totalEl.textContent = S.partsGrandTotalLabel + ': ' + formatted;\n      return;\n    }\n  }\n  totalEl.textContent = '';\n}\nfunction render(results, lang){\n  const S = STRINGS[lang];\n  const el = document.getElementById('vb-result');\n  \/\/ Compact bulk view is a view-state for the current result set only; never leak it into a new search.\n  el.classList.remove('vb-compact-results');\n\n  if(results.length === 0){\n    el.innerHTML = '';\n    LAST_RENDERED_RESULTS = [];\n    LAST_RENDERED_GROUPS = [];\n    return;\n  }\n\n  \/\/ Maak de per-vakje aantal- en prijs-state leeg: idx\/itemIdx-sleutels worden bij elke nieuwe\n  \/\/ zoekopdracht opnieuw vanaf 0 uitgedeeld, dus oude waarden (bijv. \"aantal 3\" van een vorige\n  \/\/ zoekopdracht) mogen nooit blijven hangen onder dezelfde sleutel als de nu getoonde HTML\n  \/\/ weer \"1\" laat zien. PRODUCT_DATA_CACHE blijft w\u00e9l staan (SKU-gesleuteld, taal\/idx-onafhankelijk).\n  Object.keys(PART_QTY_STATE).forEach(k => delete PART_QTY_STATE[k]);\n  Object.keys(ROW_UNIT_PRICE_STATE).forEach(k => delete ROW_UNIT_PRICE_STATE[k]);\n\n  const groups = groupResults(results);\n  LAST_RENDERED_GROUPS = groups;\n  LAST_RENDERED_RESULTS = groups.map(g => g.result);\n  const cardsHtml = groups\n    .map((group, idx) => `<div class=\"vb-result-item\" data-vb-status=\"${group.result.error ? 'error' : 'ok'}\" style=\"--vb-item-order:${idx}\">${buildResultHtml(group.result, lang, idx, group.count, group.inputs)}<\/div>`)\n    .join('');\n\n  const U = UX_STRINGS[lang] || UX_STRINGS.en;\n  const summaryHtml = buildBulkOverview(results, groups, S, U);\n\n  const hasSuccess = LAST_RENDERED_RESULTS.some(r => !r.error);\n  const combinedQuoteHtml = hasSuccess ? buildCombinedQuoteHtml(S) : '';\n  let hasMultipleWithParts = false;\n  if(results.length > 1){\n    hasMultipleWithParts = LAST_RENDERED_RESULTS.some(r => getAvailablePartsForResult(r).some(item => item.skus));\n  }\n  const combinedPartsHtml = ''; \/\/ Bulk spare parts are handled centrally in the container overview.\n\n  el.innerHTML = `<div class=\"vb-result-anim\">${summaryHtml}${cardsHtml}${combinedPartsHtml}${combinedQuoteHtml}<\/div>`;\n  restorePartsSelectionState();\n  if(typeof enhanceV21Results === 'function') enhanceV21Results(results, groups, lang);\n}\n\nfunction applyStrings(lang){\n  const S = STRINGS[lang];\n  document.getElementById('vb-title').textContent = S.title;\n  document.getElementById('vb-intro-text').textContent = S.intro;\n  document.getElementById('vb-code').placeholder = S.placeholder;\n  document.getElementById('vb-code').setAttribute('aria-label', S.title);\n  document.getElementById('vb-submit').textContent = S.button;\n  document.getElementById('vb-example-intro').textContent = S.exampleIntro;\n  document.getElementById('vb-fill-example').textContent = S.exampleBtn;\n  document.getElementById('vb-bulk-hint').innerHTML = rowIcon('layers') + `<span>${esc(S.bulkHint)}<\/span>`;\n  document.getElementById('vb-lang').setAttribute('aria-label', S.langLabel);\n  document.getElementById('vb-code-clear').setAttribute('aria-label', S.clearInputLabel);\n  document.getElementById('vb-result').innerHTML = '';\n  LAST_RENDERED_RESULTS = [];\n  LAST_RENDERED_GROUPS = [];\n  if(typeof updateInputMeta === 'function') updateInputMeta();\n  if(typeof applyV21Strings === 'function') applyV21Strings();\n}\n\nfunction initLang(lang){\n  CURRENT_LANG = lang;\n  document.getElementById('vb-lang').value = lang;\n  applyStrings(lang);\n}\n\n\/\/ v21 standalone mini-app layer. No new VARIBOX business dataset is introduced here:\n\/\/ this module only reorganises data already decoded by the checker in the browser.\nconst VB_V21_SESSION_KEY = 'vb_checker_v21_session';\nconst VB_V21_HISTORY_KEY = 'vb_checker_v21_history';\nconst VB_V21_SESSION_MAX_AGE_MS = 4 * 60 * 60 * 1000;\nconst VB_V21_COMPARE_MAX = 4;\nconst VB_V21 = {\n  compareCodes: new Set(), bulkSelectedCodes: new Set(), bulkSearch: '', bulkSort: 'status',\n  scanStream: null, scanFrame: 0, scanDetector: null, scanFallbackReader: null, scanFallbackPromise: null, suppressUrlUpdate: false, restored: false, lastFocus: null\n};\nconst V21_STRINGS = {\n  nl:{scan:'Scan barcode',compare:'Vergelijk',export:'CSV export',print:'Print \/ PDF',previous:'Vorige zoekactie',shortcut:'zoek',command:'Containeroverzicht',commandSub:'Overzicht van de gevonden containers',searchRows:'Zoek in resultaten',sort:'Sorteren',sortStatus:'Status',sortCode:'Artikelnummer',sortType:'Type',sortQty:'Aantal',selectAll:'Selecteer alles',selectedRows:'{count} geselecteerd',view:'Bekijk',compareNow:'Vergelijk nu',clear:'Wissen',compareTitle:'Configuraties vergelijken',compareSub:'Verschillen zijn gemarkeerd',needTwo:'Selecteer minimaal 2 configuraties',maxFour:'Maximaal 4 configuraties',scanTitle:'Barcode \/ QR scannen',scanHint:'Richt de camera op een barcode of QR-code met een serienummer of artikelnummer.',scanUnsupported:'Deze browser ondersteunt geen ingebouwde barcodeherkenning. Gebruik de gewone invoer.',scanPermission:'Camera kon niet worden geopend. Controleer de browsertoestemming of gebruik de gewone invoer.',scanLooking:'Zoeken naar een ondersteunde barcode\u2026',scanFound:'Code gevonden \u2014 controleren\u2026',close:'Sluiten',privacy:'De camera wordt alleen lokaal in uw browser gebruikt; er wordt geen beeld ge\u00fcpload.',restored:'Vorige sessie hersteld',passport:'Productpaspoort',serials:'serienummers',articles:'artikelnummers',invalid:'onvolledig',noRows:'Geen resultaten voor deze filter.',exported:'CSV ge\u00ebxporteerd',scanTakePhoto:\"Maak foto\",scanChoosePhoto:\"Kies foto\",scanFallbackHint:\"Live scannen is hier niet beschikbaar. Maak een foto van de barcode of kies een bestaande foto.\",scanDecoding:\"Barcode lezen\u2026\",scanNoCode:\"Geen bruikbare barcode gevonden. Probeer opnieuw, dichterbij en scherp in beeld.\",scanWrongContent:\"De barcode is gelezen, maar bevat geen geldig VARIBOX-serie- of artikelnummer.\",scanLibraryError:\"De barcodelezer kon niet worden geladen. Gebruik de gewone invoer.\"},\n  en:{scan:'Scan barcode',compare:'Compare',export:'Export CSV',print:'Print \/ PDF',previous:'Previous search',shortcut:'search',command:'Container overview',commandSub:'Overview of the containers found',searchRows:'Search results',sort:'Sort',sortStatus:'Status',sortCode:'Article number',sortType:'Type',sortQty:'Quantity',selectAll:'Select all',selectedRows:'{count} selected',view:'View',compareNow:'Compare now',clear:'Clear',compareTitle:'Compare configurations',compareSub:'Differences are highlighted',needTwo:'Select at least 2 configurations',maxFour:'Maximum 4 configurations',scanTitle:'Scan barcode \/ QR',scanHint:'Point the camera at a barcode or QR code containing a serial or article number.',scanUnsupported:'This browser does not support built-in barcode detection. Use the normal input instead.',scanPermission:'The camera could not be opened. Check browser permission or use normal input.',scanLooking:'Looking for a supported barcode\u2026',scanFound:'Code found \u2014 checking\u2026',close:'Close',privacy:'The camera is used locally in your browser only; no image is uploaded.',restored:'Previous session restored',passport:'Product passport',serials:'serial numbers',articles:'article numbers',invalid:'incomplete',noRows:'No results match this filter.',exported:'CSV exported',scanTakePhoto:\"Take photo\",scanChoosePhoto:\"Choose photo\",scanFallbackHint:\"Live scanning is not available here. Take a photo of the barcode or choose an existing photo.\",scanDecoding:\"Reading barcode\u2026\",scanNoCode:\"No usable barcode found. Try again closer and with the code in sharp focus.\",scanWrongContent:\"The barcode was read, but it does not contain a valid VARIBOX serial or article number.\",scanLibraryError:\"The barcode reader could not be loaded. Please use the normal input.\"},\n  de:{scan:'Barcode scannen',compare:'Vergleichen',export:'CSV exportieren',print:'Drucken \/ PDF',previous:'Vorherige Suche',shortcut:'suchen',command:'Container\u00fcbersicht',commandSub:'\u00dcbersicht der gefundenen Container',searchRows:'Ergebnisse durchsuchen',sort:'Sortieren',sortStatus:'Status',sortCode:'Artikelnummer',sortType:'Typ',sortQty:'Anzahl',selectAll:'Alle ausw\u00e4hlen',selectedRows:'{count} ausgew\u00e4hlt',view:'Anzeigen',compareNow:'Jetzt vergleichen',clear:'Leeren',compareTitle:'Konfigurationen vergleichen',compareSub:'Unterschiede sind markiert',needTwo:'Mindestens 2 Konfigurationen ausw\u00e4hlen',maxFour:'Maximal 4 Konfigurationen',scanTitle:'Barcode \/ QR scannen',scanHint:'Kamera auf einen Barcode oder QR-Code mit Serien- oder Artikelnummer richten.',scanUnsupported:'Dieser Browser unterst\u00fctzt keine integrierte Barcode-Erkennung. Bitte normale Eingabe verwenden.',scanPermission:'Kamera konnte nicht ge\u00f6ffnet werden. Browser-Berechtigung pr\u00fcfen oder normale Eingabe verwenden.',scanLooking:'Suche nach unterst\u00fctztem Barcode\u2026',scanFound:'Code gefunden \u2014 wird gepr\u00fcft\u2026',close:'Schlie\u00dfen',privacy:'Die Kamera wird nur lokal im Browser verwendet; es wird kein Bild hochgeladen.',restored:'Vorherige Sitzung wiederhergestellt',passport:'Produktpass',serials:'Seriennummern',articles:'Artikelnummern',invalid:'unvollst\u00e4ndig',noRows:'Keine Ergebnisse f\u00fcr diesen Filter.',exported:'CSV exportiert',scanTakePhoto:\"Foto aufnehmen\",scanChoosePhoto:\"Foto ausw\u00e4hlen\",scanFallbackHint:\"Live-Scannen ist hier nicht verf\u00fcgbar. Fotografieren Sie den Barcode oder w\u00e4hlen Sie ein vorhandenes Foto.\",scanDecoding:\"Barcode wird gelesen\u2026\",scanNoCode:\"Kein verwendbarer Barcode gefunden. Bitte n\u00e4her und scharf fotografieren.\",scanWrongContent:\"Der Barcode wurde gelesen, enth\u00e4lt aber keine g\u00fcltige VARIBOX-Serien- oder Artikelnummer.\",scanLibraryError:\"Der Barcode-Leser konnte nicht geladen werden. Bitte normale Eingabe verwenden.\"},\n  fr:{scan:'Scanner code-barres',compare:'Comparer',export:'Exporter CSV',print:'Imprimer \/ PDF',previous:'Recherche pr\u00e9c\u00e9dente',shortcut:'rechercher',command:'Vue des conteneurs',commandSub:'Vue d\u2019ensemble des conteneurs trouv\u00e9s',searchRows:'Rechercher dans les r\u00e9sultats',sort:'Trier',sortStatus:'Statut',sortCode:\"Num\u00e9ro d\u2019article\",sortType:'Type',sortQty:'Quantit\u00e9',selectAll:'Tout s\u00e9lectionner',selectedRows:'{count} s\u00e9lectionn\u00e9(s)',view:'Voir',compareNow:'Comparer',clear:'Effacer',compareTitle:'Comparer les configurations',compareSub:'Les diff\u00e9rences sont mises en \u00e9vidence',needTwo:'S\u00e9lectionnez au moins 2 configurations',maxFour:'Maximum 4 configurations',scanTitle:'Scanner code-barres \/ QR',scanHint:\"Visez un code-barres ou QR contenant un num\u00e9ro de s\u00e9rie ou d\u2019article.\",scanUnsupported:\"Ce navigateur ne prend pas en charge la d\u00e9tection int\u00e9gr\u00e9e. Utilisez la saisie normale.\",scanPermission:\"La cam\u00e9ra n\u2019a pas pu \u00eatre ouverte. V\u00e9rifiez l\u2019autorisation ou utilisez la saisie normale.\",scanLooking:'Recherche d\u2019un code compatible\u2026',scanFound:'Code trouv\u00e9 \u2014 v\u00e9rification\u2026',close:'Fermer',privacy:\"La cam\u00e9ra est utilis\u00e9e uniquement localement dans le navigateur; aucune image n\u2019est envoy\u00e9e.\",restored:'Session pr\u00e9c\u00e9dente restaur\u00e9e',passport:'Passeport produit',serials:'num\u00e9ros de s\u00e9rie',articles:\"num\u00e9ros d\u2019article\",invalid:'incomplets',noRows:'Aucun r\u00e9sultat pour ce filtre.',exported:'CSV export\u00e9',scanTakePhoto:\"Prendre une photo\",scanChoosePhoto:\"Choisir une photo\",scanFallbackHint:\"Le scan en direct n\u2019est pas disponible ici. Prenez une photo du code-barres ou choisissez une photo existante.\",scanDecoding:\"Lecture du code-barres\u2026\",scanNoCode:\"Aucun code-barres utilisable trouv\u00e9. R\u00e9essayez de plus pr\u00e8s avec une image nette.\",scanWrongContent:\"Le code-barres a \u00e9t\u00e9 lu, mais il ne contient pas de num\u00e9ro de s\u00e9rie ou d\u2019article VARIBOX valide.\",scanLibraryError:\"Le lecteur de codes-barres n\u2019a pas pu \u00eatre charg\u00e9. Utilisez la saisie normale.\"},\n  it:{scan:'Scansiona barcode',compare:'Confronta',export:'Esporta CSV',print:'Stampa \/ PDF',previous:'Ricerca precedente',shortcut:'cerca',command:'Panoramica contenitori',commandSub:'Panoramica dei contenitori trovati',searchRows:'Cerca nei risultati',sort:'Ordina',sortStatus:'Stato',sortCode:'Numero articolo',sortType:'Tipo',sortQty:'Quantit\u00e0',selectAll:'Seleziona tutto',selectedRows:'{count} selezionati',view:'Vedi',compareNow:'Confronta ora',clear:'Cancella',compareTitle:'Confronta configurazioni',compareSub:'Le differenze sono evidenziate',needTwo:'Seleziona almeno 2 configurazioni',maxFour:'Massimo 4 configurazioni',scanTitle:'Scansiona barcode \/ QR',scanHint:'Inquadra un barcode o QR con numero di serie o articolo.',scanUnsupported:'Questo browser non supporta il rilevamento barcode integrato. Usa l\u2019inserimento normale.',scanPermission:'Impossibile aprire la fotocamera. Controlla i permessi o usa l\u2019inserimento normale.',scanLooking:'Ricerca di un barcode supportato\u2026',scanFound:'Codice trovato \u2014 controllo\u2026',close:'Chiudi',privacy:'La fotocamera viene usata solo localmente nel browser; nessuna immagine viene caricata.',restored:'Sessione precedente ripristinata',passport:'Passaporto prodotto',serials:'numeri di serie',articles:'numeri articolo',invalid:'incompleti',noRows:'Nessun risultato per questo filtro.',exported:'CSV esportato',scanTakePhoto:\"Scatta foto\",scanChoosePhoto:\"Scegli foto\",scanFallbackHint:\"La scansione live non \u00e8 disponibile qui. Scatta una foto del barcode o scegli una foto esistente.\",scanDecoding:\"Lettura barcode\u2026\",scanNoCode:\"Nessun barcode utilizzabile trovato. Riprova pi\u00f9 vicino e con l\u2019immagine a fuoco.\",scanWrongContent:\"Il barcode \u00e8 stato letto, ma non contiene un numero di serie o articolo VARIBOX valido.\",scanLibraryError:\"Impossibile caricare il lettore barcode. Usa l\u2019inserimento normale.\"},\n  es:{scan:'Escanear c\u00f3digo',compare:'Comparar',export:'Exportar CSV',print:'Imprimir \/ PDF',previous:'B\u00fasqueda anterior',shortcut:'buscar',command:'Resumen de contenedores',commandSub:'Resumen de los contenedores encontrados',searchRows:'Buscar en resultados',sort:'Ordenar',sortStatus:'Estado',sortCode:'N\u00famero de art\u00edculo',sortType:'Tipo',sortQty:'Cantidad',selectAll:'Seleccionar todo',selectedRows:'{count} seleccionados',view:'Ver',compareNow:'Comparar ahora',clear:'Borrar',compareTitle:'Comparar configuraciones',compareSub:'Las diferencias est\u00e1n resaltadas',needTwo:'Selecciona al menos 2 configuraciones',maxFour:'M\u00e1ximo 4 configuraciones',scanTitle:'Escanear c\u00f3digo \/ QR',scanHint:'Apunta la c\u00e1mara a un c\u00f3digo de barras o QR con un n\u00famero de serie o art\u00edculo.',scanUnsupported:'Este navegador no admite detecci\u00f3n integrada. Usa la entrada normal.',scanPermission:'No se pudo abrir la c\u00e1mara. Revisa el permiso o usa la entrada normal.',scanLooking:'Buscando un c\u00f3digo compatible\u2026',scanFound:'C\u00f3digo encontrado \u2014 comprobando\u2026',close:'Cerrar',privacy:'La c\u00e1mara se usa solo localmente en el navegador; no se sube ninguna imagen.',restored:'Sesi\u00f3n anterior restaurada',passport:'Pasaporte de producto',serials:'n\u00fameros de serie',articles:'n\u00fameros de art\u00edculo',invalid:'incompletos',noRows:'No hay resultados para este filtro.',exported:'CSV exportado',scanTakePhoto:\"Hacer foto\",scanChoosePhoto:\"Elegir foto\",scanFallbackHint:\"El escaneo en directo no est\u00e1 disponible aqu\u00ed. Haz una foto del c\u00f3digo o elige una imagen existente.\",scanDecoding:\"Leyendo c\u00f3digo\u2026\",scanNoCode:\"No se encontr\u00f3 un c\u00f3digo utilizable. Int\u00e9ntalo de nuevo m\u00e1s cerca y con la imagen enfocada.\",scanWrongContent:\"El c\u00f3digo se ley\u00f3, pero no contiene un n\u00famero de serie o art\u00edculo VARIBOX v\u00e1lido.\",scanLibraryError:\"No se pudo cargar el lector de c\u00f3digos. Usa la entrada normal.\"},\n  pl:{scan:'Skanuj kod',compare:'Por\u00f3wnaj',export:'Eksport CSV',print:'Drukuj \/ PDF',previous:'Poprzednie wyszukiwanie',shortcut:'szukaj',command:'Przegl\u0105d pojemnik\u00f3w',commandSub:'Przegl\u0105d znalezionych pojemnik\u00f3w',searchRows:'Szukaj w wynikach',sort:'Sortuj',sortStatus:'Status',sortCode:'Numer artyku\u0142u',sortType:'Typ',sortQty:'Ilo\u015b\u0107',selectAll:'Zaznacz wszystko',selectedRows:'Wybrano: {count}',view:'Poka\u017c',compareNow:'Por\u00f3wnaj',clear:'Wyczy\u015b\u0107',compareTitle:'Por\u00f3wnaj konfiguracje',compareSub:'R\u00f3\u017cnice s\u0105 wyr\u00f3\u017cnione',needTwo:'Wybierz co najmniej 2 konfiguracje',maxFour:'Maksymalnie 4 konfiguracje',scanTitle:'Skanuj kod \/ QR',scanHint:'Skieruj kamer\u0119 na kod kreskowy lub QR z numerem seryjnym albo artyku\u0142u.',scanUnsupported:'Ta przegl\u0105darka nie obs\u0142uguje wbudowanego wykrywania kod\u00f3w. U\u017cyj zwyk\u0142ego pola.',scanPermission:'Nie uda\u0142o si\u0119 otworzy\u0107 kamery. Sprawd\u017a uprawnienia lub u\u017cyj zwyk\u0142ego pola.',scanLooking:'Szukam obs\u0142ugiwanego kodu\u2026',scanFound:'Kod znaleziony \u2014 sprawdzanie\u2026',close:'Zamknij',privacy:'Kamera dzia\u0142a wy\u0142\u0105cznie lokalnie w przegl\u0105darce; \u017caden obraz nie jest wysy\u0142any.',restored:'Przywr\u00f3cono poprzedni\u0105 sesj\u0119',passport:'Paszport produktu',serials:'numery seryjne',articles:'numery artyku\u0142\u00f3w',invalid:'niepe\u0142ne',noRows:'Brak wynik\u00f3w dla tego filtra.',exported:'Wyeksportowano CSV',scanTakePhoto:\"Zr\u00f3b zdj\u0119cie\",scanChoosePhoto:\"Wybierz zdj\u0119cie\",scanFallbackHint:\"Skanowanie na \u017cywo nie jest tutaj dost\u0119pne. Zr\u00f3b zdj\u0119cie kodu lub wybierz istniej\u0105ce zdj\u0119cie.\",scanDecoding:\"Odczytywanie kodu\u2026\",scanNoCode:\"Nie znaleziono u\u017cytecznego kodu. Spr\u00f3buj ponownie z bliska i z ostrym obrazem.\",scanWrongContent:\"Kod zosta\u0142 odczytany, ale nie zawiera prawid\u0142owego numeru seryjnego lub artyku\u0142u VARIBOX.\",scanLibraryError:\"Nie uda\u0142o si\u0119 za\u0142adowa\u0107 czytnika kod\u00f3w. U\u017cyj zwyk\u0142ego pola.\"}\n};\nfunction v21T(){ return V21_STRINGS[CURRENT_LANG] || V21_STRINGS.en; }\nfunction v21Svg(name){\n  const paths={scan:'<path d=\"M3 6V3h3M12 3h3v3M15 12v3h-3M6 15H3v-3\"\/><path d=\"M6 7v4M8.5 7v4M11 7v4\"\/>',compare:'<path d=\"M3 5h12M3 13h12\"\/><path d=\"M6 2v6M12 10v6\"\/>',export:'<path d=\"M9 2v9M5.5 7.5L9 11l3.5-3.5\"\/><path d=\"M3 13v2h12v-2\"\/>',print:'<path d=\"M5 6V2h8v4M5 12H3V7h12v5h-2\"\/><path d=\"M5 10h8v6H5z\"\/>',back:'<path d=\"M13 4L7 9l6 5\"\/><path d=\"M7 9h8\"\/>'};\n  return `<svg viewBox=\"0 0 18 18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${paths[name]||''}<\/svg>`;\n}\nfunction applyV21Strings(){\n  const T=v21T();\n  const scan=document.getElementById('vb-v21-scan-btn');if(scan)scan.innerHTML=v21Svg('scan')+`<span>${esc(T.scan)}<\/span>`;\n  document.querySelectorAll('.vb-v21-dialog-close').forEach(btn=>btn.setAttribute('aria-label',T.close));\n  renderV21CompareDock();\n}\nfunction classifyV21Entries(raw){\n  const entries=String(raw||'').split(\/[\\n,;]+\/).map(v=>v.trim().toUpperCase().replace(\/\\s+\/g,'')).filter(Boolean).slice(0,MAX_BULK_CODES);\n  let serials=0,articles=0,invalid=0;\n  entries.forEach(v=>{if(v.length===8)serials++;else if(v.length===12)articles++;else invalid++;});\n  return {entries,serials,articles,invalid};\n}\nfunction v21SessionRead(){\n  try{const raw=sessionStorage.getItem(VB_V21_SESSION_KEY);if(!raw)return null;const s=JSON.parse(raw);if(!s||typeof s.raw!=='string'||Date.now()-Number(s.at||0)>VB_V21_SESSION_MAX_AGE_MS){sessionStorage.removeItem(VB_V21_SESSION_KEY);return null;}return s;}catch(e){return null;}\n}\nfunction v21SessionSave(raw,lang){\n  try{sessionStorage.setItem(VB_V21_SESSION_KEY,JSON.stringify({raw:String(raw||'').slice(0,5000),lang:STRINGS[lang]?lang:CURRENT_LANG,at:Date.now()}));}catch(e){}\n}\nfunction v21HistoryRead(){try{const p=JSON.parse(sessionStorage.getItem(VB_V21_HISTORY_KEY)||'[]');return Array.isArray(p)?p.filter(x=>x?typeof x.raw==='string':false).slice(0,10):[];}catch(e){return[];}}\nfunction v21HistoryPush(raw,lang){\n  const text=String(raw||'').trim(); if(!text)return;\n  let h=v21HistoryRead().filter(x=>x.raw!==text||x.lang!==lang); h.unshift({raw:text.slice(0,5000),lang,at:Date.now()}); h=h.slice(0,10);\n  try{sessionStorage.setItem(VB_V21_HISTORY_KEY,JSON.stringify(h));}catch(e){}\n  updateV21ToolbarState();\n}\nfunction v21PreviousSearch(){\n  const h=v21HistoryRead(); if(h.length<2)return; const target=h[1]; h.splice(1,1); h.unshift(target); try{sessionStorage.setItem(VB_V21_HISTORY_KEY,JSON.stringify(h));}catch(e){}\n  const code=document.getElementById('vb-code'); if(!code)return; if(STRINGS[target.lang]){CURRENT_LANG=target.lang;document.getElementById('vb-lang').value=target.lang;applyStrings(target.lang);applyV21Strings();}\n  code.value=target.raw; updateClearBtnVisibility(); updateInputMeta(); runSearch(target.raw,'recent');\n}\nfunction v21UpdateUrl(raw,lang,replace){\n  if(VB_V21.suppressUrlUpdate || !window.history || !window.history.pushState)return;\n  try{const u=new URL(window.location.href);const text=String(raw||'').trim().slice(0,5000);\/* Automatic app history must not leak serial\/article values into the URL. Explicit Share keeps using vbcode. *\/u.searchParams.delete('vbcode');u.searchParams.delete('vblang');u.hash='';window.history[replace?'replaceState':'pushState']({varibox:true,raw:text,lang},'',u.toString());}catch(e){}\n}\nfunction v21AfterSearch(raw,results,source,lang){\n  const text=String(raw||'').trim(); v21SessionSave(text,lang); v21HistoryPush(text,lang);\n  if(source==='language_change') v21UpdateUrl(text,lang,true);\n  else if(!['shared_link','history','restore'].includes(source||'')) v21UpdateUrl(text,lang,false);\n  updateV21ToolbarState();\n}\nfunction updateV21ToolbarState(){}\nfunction resetV21ResultState(clearSession){VB_V21.compareCodes.clear();VB_V21.bulkSelectedCodes.clear();VB_V21.bulkSearch='';VB_V21.bulkSort='status';if(clearSession){try{sessionStorage.removeItem(VB_V21_SESSION_KEY);}catch(e){}v21UpdateUrl('',CURRENT_LANG,false);}renderV21CompareDock();updateV21ToolbarState();}\nfunction v21ResultForCode(code){const group=LAST_RENDERED_GROUPS.find(g=>g?(g.result?(!g.result.error?g.result.code===code:false):false):false);return group||null;}\nfunction toggleV21Compare(code){\n  if(!code||!v21ResultForCode(code))return;\n  if(VB_V21.compareCodes.has(code))VB_V21.compareCodes.delete(code);else{if(VB_V21.compareCodes.size>=VB_V21_COMPARE_MAX){showFormFeedbackToast(v21T().maxFour,false);return;}VB_V21.compareCodes.add(code);}\n  updateV21CompareVisuals(); renderV21CompareDock(); vbMetric('feature_used',{feature:'compare',interaction:VB_V21.compareCodes.has(code)?'select':'deselect',language:CURRENT_LANG,compare_count:VB_V21.compareCodes.size});\n}\nfunction updateV21CompareVisuals(){\n  document.querySelectorAll('[data-vb-action=\"toggle-compare\"]').forEach(btn=>{const active=VB_V21.compareCodes.has(btn.dataset.code);btn.setAttribute('aria-pressed',String(active));const card=btn.closest('.vb-result-item')?.querySelector('.vb-result-card');if(card)card.classList.toggle('vb-compare-picked',active);});\n}\nfunction renderV21CompareDock(){\n  const host=document.getElementById('vb-v21-compare-dock'); if(!host)return; const T=v21T(),n=VB_V21.compareCodes.size;\n  host.classList.toggle('vb-visible',n>0);host.innerHTML=n?`<div><strong>${esc(T.compare)}<\/strong><br><span>${esc(T.selectedRows.replace('{count}',n))}<\/span><\/div><div class=\"vb-v21-dock-actions\"><button type=\"button\" class=\"vb-v21-dock-btn\" data-vb-action=\"clear-compare\">${esc(T.clear)}<\/button><button type=\"button\" class=\"vb-v21-dock-btn vb-v21-dock-btn-primary\" data-vb-action=\"open-compare\" ${n<2?'disabled':''}>${esc(T.compareNow)}<\/button><\/div>`:'';\n}\nfunction v21Value(result,field,S){\n  const first=m=>(m?m[0]:false)?m[0][0]:S.unknownCode;\n  if(field==='type')return result.typeName||''; if(field==='gasket')return result.isDrumtainer?'\u2014':first(result.pakkingMatches); if(field==='tube')return result.isDrumtainer?'\u2014':first(result.zuigbuisMatches); if(field==='sensor')return result.isDrumtainer?'\u2014':first(result.sensorMatches); if(field==='colour')return first(result.kleurMatches); if(field==='food')return result.isDrumtainer?'\u2014':(result.foodContact?S.yesWord:S.noWord); if(field==='trailer')return result.isDrumtainer?first(result.trailerMatches):'\u2014'; if(field==='combo')return result.isDrumtainer?first(result.comboMatches):'\u2014'; return '';\n}\nfunction openV21Compare(){\n  const groups=[...VB_V21.compareCodes].map(v21ResultForCode).filter(Boolean); if(groups.length<2){showFormFeedbackToast(v21T().needTwo,false);return;}\n  const T=v21T(),S=STRINGS[CURRENT_LANG],fields=[['type',S.labelType],['gasket',S.labelPakking],['tube',S.labelZuigbuis],['sensor',S.labelSensor],['colour',S.labelKleur],['food',S.labelFoodContact],['trailer',S.labelTrailer],['combo',S.labelCombo]];\n  const rows=fields.map(([key,label])=>{const vals=groups.map(g=>v21Value(g.result,key,S));const diff=new Set(vals).size>1;return `<tr class=\"${diff?'vb-v21-diff-row':''}\"><td>${esc(label)}<\/td>${vals.map(v=>`<td>${esc(v)}<\/td>`).join('')}<\/tr>`;}).join('');\n  const modal=document.getElementById('vb-v21-compare-modal');const body=document.getElementById('vb-v21-compare-body');if(!modal||!body)return;VB_V21.lastFocus=document.activeElement;\n  body.innerHTML=`<div class=\"vb-v21-compare-grid\"><table class=\"vb-v21-compare-table\"><thead><tr><th>${esc(T.passport)}<\/th>${groups.map(g=>`<th>${esc(g.result.typeName)}<span class=\"vb-v21-compare-code\">${esc(g.result.code)}<\/span><\/th>`).join('')}<\/tr><\/thead><tbody>${rows}<\/tbody><\/table><\/div>`;\n  document.getElementById('vb-v21-compare-title').textContent=T.compareTitle;document.getElementById('vb-v21-compare-sub').textContent=T.compareSub;modal.classList.add('vb-open');modal.setAttribute('aria-hidden','false');document.body.style.overflow='hidden';setTimeout(()=>{const close=modal.querySelector('.vb-v21-dialog-close');if(close)close.focus();},0);vbMetric('feature_used',{feature:'compare',interaction:'open',language:CURRENT_LANG,compare_count:groups.length});\n}\nfunction closeV21Modal(id){const modal=document.getElementById(id);if(!modal||!modal.classList.contains('vb-open'))return;modal.classList.remove('vb-open');modal.setAttribute('aria-hidden','true');if(!document.querySelector('.vb-v21-modal.vb-open'))document.body.style.overflow='';if(id==='vb-v21-scan-modal')stopV21Scanner();const previous=VB_V21.lastFocus;VB_V21.lastFocus=null;if(previous?(previous.isConnected?typeof previous.focus==='function':false):false)setTimeout(()=>previous.focus(),0);}\nfunction clearV21Compare(){VB_V21.compareCodes.clear();updateV21CompareVisuals();renderV21CompareDock();closeV21Modal('vb-v21-compare-modal');}\nfunction v21GroupText(group){const r=group.result;return `${r.code||''} ${r.typeName||''} ${(group.inputs||[]).join(' ')}`.toLowerCase();}\nfunction v24BulkMeta(){\n  const groups=LAST_RENDERED_GROUPS||[];\n  const successful=groups.filter(g=>g?(g.result?!g.result.error:false):false);\n  return {\n    showTools:groups.length>=6,\n    showStatus:groups.some(g=>g?(g.result?g.result.error:false):false),\n    totalContainers:groups.reduce((n,g)=>n+Math.max(1,Number(g?g.count:g)||1),0),\n    successfulCodes:successful.map(g=>g.result.code).filter(Boolean)\n  };\n}\nfunction renderV21CommandRows(){\n  const tbody=document.getElementById('vb-v21-command-body'); if(!tbody)return; const T=v21T(),q=VB_V21.bulkSearch.trim().toLowerCase(),meta=v24BulkMeta();\n  let groups=LAST_RENDERED_GROUPS.map((g,i)=>({g,i}));\n  groups.sort((a,b)=>{const ar=a.g.result,br=b.g.result;if(VB_V21.bulkSort==='code')return String(ar.code||'').localeCompare(String(br.code||''));if(VB_V21.bulkSort==='type')return String(ar.typeName||'').localeCompare(String(br.typeName||''));if(VB_V21.bulkSort==='qty')return b.g.count-a.g.count;return Number(!!ar.error)-Number(!!br.error);});\n  const shown=groups.filter(({g})=>!q||v21GroupText(g).includes(q));\n  const statusCell=(ok)=>meta.showStatus?`<td><span class=\"vb-v21-status ${ok?'':'vb-v21-status-error'}\">${esc(ok?(UX_STRINGS[CURRENT_LANG]||UX_STRINGS.en).recognized:(UX_STRINGS[CURRENT_LANG]||UX_STRINGS.en).attention)}<\/span><\/td>`:'';\n  const colspan=meta.showStatus?6:5;\n  tbody.innerHTML=shown.length?shown.map(({g,i})=>{const r=g.result,ok=!r.error,code=ok?r.code:(r.originalInput||'\u2014'),checked=ok?VB_V21.bulkSelectedCodes.has(r.code):false;return `<tr data-vb-command-index=\"${i}\"><td>${ok?`<input class=\"vb-v21-bulk-check\" type=\"checkbox\" data-vb-action=\"bulk-select\" data-code=\"${esc(r.code)}\" ${checked?'checked':''} aria-label=\"${esc(r.code)}\">`:''}<\/td><td><span class=\"vb-v21-table-code\">${esc(code)}<\/span><\/td><td>${esc(ok?r.typeName:'\u2014')}<\/td><td>${g.count}<\/td>${statusCell(ok)}<td><button type=\"button\" class=\"vb-v21-row-view\" data-vb-action=\"view-result\" data-result-index=\"${i}\">${esc(T.view)}<\/button><\/td><\/tr>`;}).join(''):`<tr><td colspan=\"${colspan}\"><div class=\"vb-v21-command-empty\">${esc(T.noRows)}<\/div><\/td><\/tr>`;\n  const all=document.getElementById('vb-v24-select-all');\n  if(all){const valid=meta.successfulCodes,selected=valid.filter(c=>VB_V21.bulkSelectedCodes.has(c)).length;all.checked=valid.length>0?selected===valid.length:false;all.indeterminate=selected>0?selected<valid.length:false;}\n  updateV21CommandFooter();\n}\nfunction buildV21CommandCenter(groups){\n  if(groups.length<=1)return ''; const T=v21T(),meta={showTools:groups.length>=6,showStatus:groups.some(g=>g?(g.result?g.result.error:false):false),totalContainers:groups.reduce((n,g)=>n+Math.max(1,Number(g?g.count:g)||1),0)};\n  const summary=`${groups.filter(g=>g?(g.result?!g.result.error:false):false).length} ${CURRENT_LANG==='nl'?'configuraties':CURRENT_LANG==='de'?'Konfigurationen':CURRENT_LANG==='fr'?'configurations':CURRENT_LANG==='it'?'configurazioni':CURRENT_LANG==='es'?'configuraciones':CURRENT_LANG==='pl'?'konfiguracji':'configurations'} \u00b7 ${meta.totalContainers} ${CURRENT_LANG==='de'?'Container':CURRENT_LANG==='fr'?'conteneurs':CURRENT_LANG==='it'?'contenitori':CURRENT_LANG==='es'?'contenedores':CURRENT_LANG==='pl'?'pojemnik\u00f3w':'containers'}`;\n  const controls=meta.showTools?`<div class=\"vb-v21-command-controls\"><input id=\"vb-v21-command-search\" class=\"vb-v21-command-search\" type=\"search\" placeholder=\"${esc(T.searchRows)}\" aria-label=\"${esc(T.searchRows)}\"><select id=\"vb-v21-command-sort\" class=\"vb-v21-command-sort\" aria-label=\"${esc(T.sort)}\"><option value=\"status\">${esc(T.sortStatus)}<\/option><option value=\"code\">${esc(T.sortCode)}<\/option><option value=\"type\">${esc(T.sortType)}<\/option><option value=\"qty\">${esc(T.sortQty)}<\/option><\/select><\/div>`:'';\n  const statusHead=meta.showStatus?`<th>${esc(T.sortStatus)}<\/th>`:'';\n  return `<section class=\"vb-v21-command\" id=\"vb-v21-command\"><div class=\"vb-v21-command-head\"><div><h3 class=\"vb-v21-command-title\">${esc(T.command)}<\/h3><p class=\"vb-v21-command-sub\">${esc(summary)}<\/p><\/div>${rowIcon('layers')}<\/div>${controls}<div class=\"vb-v21-table-wrap\"><table class=\"vb-v21-table\"><thead><tr><th><input id=\"vb-v24-select-all\" class=\"vb-v21-bulk-check\" type=\"checkbox\" data-vb-action=\"bulk-select-all\" aria-label=\"${esc(T.selectAll)}\"><\/th><th>${esc(T.sortCode)}<\/th><th>${esc(T.sortType)}<\/th><th>${esc(T.sortQty)}<\/th>${statusHead}<th><\/th><\/tr><\/thead><tbody id=\"vb-v21-command-body\"><\/tbody><\/table><\/div><div class=\"vb-v21-command-foot\"><span id=\"vb-v21-selection-count\" class=\"vb-v21-selection-count\"><\/span><button type=\"button\" class=\"vb-app-tool\" data-vb-action=\"compare-selected\">${v21Svg('compare')}<span>${esc(T.compare)}<\/span><\/button><button type=\"button\" class=\"vb-app-tool\" data-vb-action=\"export-selected\">${v21Svg('export')}<span>${esc(T.export)}<\/span><\/button><\/div><\/section>`;\n}\nfunction updateV21CommandFooter(){const el=document.getElementById('vb-v21-selection-count');if(el){const n=VB_V21.bulkSelectedCodes.size;el.textContent=n?v21T().selectedRows.replace('{count}',n):'';el.hidden=!n;}const all=document.getElementById('vb-v24-select-all');if(all){const valid=v24BulkMeta().successfulCodes,selected=valid.filter(c=>VB_V21.bulkSelectedCodes.has(c)).length;all.checked=valid.length>0?selected===valid.length:false;all.indeterminate=selected>0?selected<valid.length:false;}}\nfunction toggleV21BulkSelection(code,checked){if(!code)return;if(checked)VB_V21.bulkSelectedCodes.add(code);else VB_V21.bulkSelectedCodes.delete(code);updateV21CommandFooter();}\nfunction v21SelectAllBulk(){const valid=LAST_RENDERED_GROUPS.filter(g=>!g.result.error).map(g=>g.result.code);const all=valid.length>0?valid.every(c=>VB_V21.bulkSelectedCodes.has(c)):false;if(all)valid.forEach(c=>VB_V21.bulkSelectedCodes.delete(c));else valid.forEach(c=>VB_V21.bulkSelectedCodes.add(c));renderV21CommandRows();}\nfunction v21CompareSelected(){const all=[...VB_V21.bulkSelectedCodes];if(all.length<2){showFormFeedbackToast(v21T().needTwo,false);return;}if(all.length>VB_V21_COMPARE_MAX){showFormFeedbackToast(v21T().maxFour,false);return;}VB_V21.compareCodes=new Set(all);updateV21CompareVisuals();renderV21CompareDock();openV21Compare();}\nfunction v21CsvCell(value){const s=String(value==null?'':value);return \/[\",\\n\\r;]\/.test(s)?`\"${s.replace(\/\"\/g,'\"\"')}\"`:s;}\nfunction buildV21ExportRows(groups,lang){\n  const S=STRINGS[lang]||STRINGS.en;return groups.filter(g=>g?!g.result.error:false).map(g=>{const r=g.result,first=m=>(m?m[0]:false)?m[0][0]:'';return {quantity:g.count,inputs:(g.inputs||[]).join(' | '),article_number:r.code,type:r.typeName,gasket:r.isDrumtainer?'':first(r.pakkingMatches),extractor:r.isDrumtainer?'':first(r.zuigbuisMatches),sensor:r.isDrumtainer?'':first(r.sensorMatches),colour:first(r.kleurMatches),food_contact:r.isDrumtainer?'':(r.foodContact?S.yesWord:S.noWord),trailer:r.isDrumtainer?first(r.trailerMatches):'',combination:r.isDrumtainer?first(r.comboMatches):''};});\n}\nfunction buildV21Csv(groups,lang){const rows=buildV21ExportRows(groups,lang),headers=['quantity','inputs','article_number','type','gasket','extractor','sensor','colour','food_contact','trailer','combination'];return [headers.join(','),...rows.map(r=>headers.map(h=>v21CsvCell(r[h])).join(','))].join('\\r\\n');}\nfunction exportV21Csv(selectedOnly){\n  let groups=LAST_RENDERED_GROUPS.filter(g=>!g.result.error);if(selectedOnly?VB_V21.bulkSelectedCodes.size:false)groups=groups.filter(g=>VB_V21.bulkSelectedCodes.has(g.result.code));if(!groups.length)return;\n  const csv='\\uFEFF'+buildV21Csv(groups,CURRENT_LANG);const blob=new Blob([csv],{type:'text\/csv;charset=utf-8'});const url=URL.createObjectURL(blob);const a=document.createElement('a');a.href=url;a.download=`varibox-checker-${new Date().toISOString().slice(0,10)}.csv`;document.body.appendChild(a);a.click();a.remove();setTimeout(()=>URL.revokeObjectURL(url),1000);showFormFeedbackToast(v21T().exported,true);vbMetric('feature_used',{feature:'export',format:'csv',language:CURRENT_LANG,result_count:groups.length,outcome:'success'});\n}\nfunction invokeV21Print(printClass){\n  if(!document.body||!document.body.classList)return false;\n  document.body.classList.add(printClass);\n  const cleanup=()=>document.body.classList.remove(printClass);\n  window.addEventListener('afterprint',cleanup,{once:true});\n  \/\/ Keep the call in the original click\/tap user-activation turn. Mobile Safari and\n  \/\/ embedded browsers can ignore print dialogs once the gesture is lost to a timer.\n  try{ void document.body.offsetHeight; }catch(e){}\n  let attempted=false;\n  try{\n    if(typeof window.print==='function'){ attempted=true; window.print(); }\n    else if(document.execCommand){ attempted=!!document.execCommand('print'); }\n  }catch(e){\n    try{ if(document.execCommand)attempted=!!document.execCommand('print'); }catch(ignore){}\n  }\n  setTimeout(cleanup,1500);\n  return attempted;\n}\nfunction printV21(){vbMetric('feature_used',{feature:'print',format:'pdf',language:CURRENT_LANG,result_count:LAST_RENDERED_GROUPS.length,interaction:'open'});return invokeV21Print('vb-v21-printing');}\nfunction decorateV21Cards(){\n  LAST_RENDERED_GROUPS.forEach((g,i)=>{if(!g||g.result.error)return;const item=document.querySelector(`.vb-result-item:nth-of-type(${i+1})`);const card=item?item.querySelector('.vb-result-card'):item;if(!card||card.querySelector('.vb-v21-card-tools'))return;const hero=card.querySelector('.vb-hero-title-row');if(!hero)return;const tools=document.createElement('div');tools.className='vb-v21-card-tools';tools.innerHTML=`<button type=\"button\" class=\"vb-v21-compare-btn\" data-vb-action=\"toggle-compare\" data-code=\"${esc(g.result.code)}\" aria-pressed=\"${VB_V21.compareCodes.has(g.result.code)}\">${v21Svg('compare')}<span>${esc(v21T().compare)}<\/span><\/button>`;hero.appendChild(tools);}); updateV21CompareVisuals();\n}\nfunction enhanceV21Results(results,groups,lang){\n  const root=document.getElementById('vb-result');if(!root)return;VB_V21.bulkSelectedCodes=new Set([...VB_V21.bulkSelectedCodes].filter(c=>groups.some(g=>!g.result.error?g.result.code===c:false)));VB_V21.compareCodes=new Set([...VB_V21.compareCodes].filter(c=>groups.some(g=>!g.result.error?g.result.code===c:false)));\n  const overview=root.querySelector('.vb-bulk-overview');if(groups.length>1?overview:false){overview.insertAdjacentHTML('afterend',buildV21CommandCenter(groups));renderV21CommandRows();if(groups.length>6)root.classList.add('vb-compact-results');}\n  decorateV21Cards();renderV21CompareDock();updateV21ToolbarState();\n}\nfunction normalizeV21ScannedValue(raw){const cleaned=String(raw||'').trim().toUpperCase().replace(\/\\s+\/g,'');const direct=cleaned.match(\/(?:^|[^A-Z0-9])([A-Z0-9]{8}|(?:VB|VC|VI|VK|DT)[A-Z0-9]{10})(?:$|[^A-Z0-9])\/);return direct?direct[1]:(cleaned.length===8||cleaned.length===12?cleaned:'');}\nconst VB_V21_ZXING_FALLBACK_URLS=['https:\/\/cdn.jsdelivr.net\/npm\/@zxing\/library@0.23.0\/umd\/index.min.js','https:\/\/unpkg.com\/@zxing\/library@0.23.0\/umd\/index.min.js'];\nfunction loadV21ScannerFallback(){\n  if(window.ZXing?!!window.ZXing.BrowserMultiFormatReader:false)return Promise.resolve(window.ZXing);\n  if(VB_V21.scanFallbackPromise)return VB_V21.scanFallbackPromise;\n  const override=String(window.VARIBOX_CHECKER_SCANNER_LIB_URL||'').trim();\n  const urls=override?[override]:VB_V21_ZXING_FALLBACK_URLS.slice();\n  VB_V21.scanFallbackPromise=new Promise((resolve,reject)=>{\n    const attempt=index=>{\n      if(window.ZXing?!!window.ZXing.BrowserMultiFormatReader:false){resolve(window.ZXing);return;}\n      if(index>=urls.length){reject(new Error('scanner library load failed'));return;}\n      const script=document.createElement('script');\n      script.src=urls[index];script.async=true;script.dataset.vbScannerFallback='1';\n      script.onload=()=>(window.ZXing?window.ZXing.BrowserMultiFormatReader:false)?resolve(window.ZXing):(script.remove(),attempt(index+1));\n      script.onerror=()=>{script.remove();attempt(index+1);};\n      document.head.appendChild(script);\n    };\n    attempt(0);\n  }).catch(err=>{VB_V21.scanFallbackPromise=null;throw err;});\n  return VB_V21.scanFallbackPromise;\n}\nfunction acceptV21ScannedValue(raw){\n  const value=normalizeV21ScannedValue(raw);if(!value)return false;const status=document.getElementById('vb-v21-scan-status');if(status)status.textContent=v21T().scanFound;if(typeof v22ScanSuccessFeedback==='function')v22ScanSuccessFeedback();stopV21Scanner();setTimeout(()=>{closeV21Modal('vb-v21-scan-modal');const input=document.getElementById('vb-code');if(!input)return;input.value=value;updateClearBtnVisibility();updateInputMeta();runSearch(value,'scanner');},180);return true;\n}\nasync function startV21NativeScanner(stage,status,T){\n  const formats=typeof BarcodeDetector.getSupportedFormats==='function'?await BarcodeDetector.getSupportedFormats():[];const preferred=['qr_code','code_128','code_39','data_matrix','ean_13','ean_8'].filter(f=>!formats.length||formats.includes(f));VB_V21.scanDetector=preferred.length?new BarcodeDetector({formats:preferred}):new BarcodeDetector();\n  VB_V21.scanStream=await navigator.mediaDevices.getUserMedia({video:{facingMode:{ideal:'environment'}},audio:false});stage.innerHTML='<video id=\"vb-v21-scan-video\" playsinline muted><\/video><div class=\"vb-v21-scan-frame\" aria-hidden=\"true\"><\/div>';const video=document.getElementById('vb-v21-scan-video');video.srcObject=VB_V21.scanStream;await video.play();status.textContent=T.scanLooking;if(typeof v22EnhanceScannerControls==='function')v22EnhanceScannerControls();vbMetric('scanner_opened',{feature:'scanner',scanner_supported:true,language:CURRENT_LANG,outcome:'success'});scanV21Frame();\n}\nasync function startV21CompatibilityScanner(stage,status,T){\n  const ZXing=await loadV21ScannerFallback();stage.innerHTML='<video id=\"vb-v21-scan-video\" playsinline muted><\/video><div class=\"vb-v21-scan-frame\" aria-hidden=\"true\"><\/div>';const video=document.getElementById('vb-v21-scan-video');const reader=new ZXing.BrowserMultiFormatReader();VB_V21.scanFallbackReader=reader;status.textContent=T.scanLooking;\n  const promise=reader.decodeFromVideoDevice(undefined,video,(result,err)=>{if(result){const raw=typeof result.getText==='function'?result.getText():result.text;acceptV21ScannedValue(raw);}});\n  if(promise?typeof promise.catch==='function':false)promise.catch(()=>{});\n  \/\/ The fallback reader owns the camera stream. Expose it when available so v22 torch\/zoom\n  \/\/ controls can still work on browsers that support track capabilities.\n  setTimeout(()=>{if(VB_V21.scanFallbackReader?VB_V21.scanFallbackReader.stream:false){VB_V21.scanStream=VB_V21.scanFallbackReader.stream;if(typeof v22EnhanceScannerControls==='function')v22EnhanceScannerControls();}},300);\n  vbMetric('scanner_opened',{feature:'scanner',scanner_supported:true,language:CURRENT_LANG,outcome:'success'});\n}\nfunction renderV21CaptureFallback(stage,status,T,reason){\n  stopV21Scanner();\n  stage.classList.add('vb-v21-scan-capture-mode');\n  stage.innerHTML=`<div class=\"vb-v21-capture-panel\"><div class=\"vb-v21-scan-message\">${esc(T.scanFallbackHint)}<\/div><div class=\"vb-v21-capture-actions\"><label class=\"vb-app-tool vb-app-tool-primary vb-v21-capture-button\"><span>${esc(T.scanTakePhoto)}<\/span><input class=\"vb-v21-capture-input\" type=\"file\" accept=\"image\/*\" capture=\"environment\"><\/label><label class=\"vb-app-tool vb-v21-capture-button\"><span>${esc(T.scanChoosePhoto)}<\/span><input class=\"vb-v21-capture-input\" type=\"file\" accept=\"image\/*\"><\/label><\/div><\/div>`;\n  status.textContent=reason==='permission'?T.scanPermission:'';\n  stage.querySelectorAll('.vb-v21-capture-input').forEach(input=>input.addEventListener('change',()=>{const file=input.files?input.files[0]:input.files;if(file)decodeV21CapturedImage(file,stage,status,T);input.value='';}));\n  vbMetric('scanner_opened',{feature:'scanner',scanner_supported:false,language:CURRENT_LANG,outcome:'success'});\n}\nasync function decodeV21CapturedImage(file,stage,status,T){\n  if(!file)return;status.textContent=T.scanDecoding;stage.classList.add('vb-v21-scan-decoding');\n  let url='';let reader=null;\n  try{\n    if('BarcodeDetector' in window ? typeof createImageBitmap==='function' : false){\n      const bitmap=await createImageBitmap(file);\n      try{\n        const detector=new BarcodeDetector();const codes=await detector.detect(bitmap);\n        for(const found of codes){if(acceptV21ScannedValue(found.rawValue))return;}\n        if(codes.length){status.textContent=T.scanWrongContent;return;}\n      }finally{if(bitmap?typeof bitmap.close==='function':false)bitmap.close();}\n    }\n    let ZXing;\n    try{ZXing=await loadV21ScannerFallback();}catch(loadError){status.textContent=T.scanLibraryError;return;}\n    reader=new ZXing.BrowserMultiFormatReader();url=URL.createObjectURL(file);\n    const result=await reader.decodeFromImageUrl(url);const raw=result?(typeof result.getText==='function'?result.getText():result.text):result;\n    if(raw?!acceptV21ScannedValue(raw):false)status.textContent=T.scanWrongContent;\n  }catch(e){status.textContent=T.scanNoCode;}\n  finally{stage.classList.remove('vb-v21-scan-decoding');if(reader?typeof reader.reset==='function':false){try{reader.reset();}catch(e){}}if(url)URL.revokeObjectURL(url);}\n}\nasync function openV21Scanner(){\n  const modal=document.getElementById('vb-v21-scan-modal'),stage=document.getElementById('vb-v21-scan-stage'),status=document.getElementById('vb-v21-scan-status');if(!modal||!stage||!status)return;const T=v21T();\n  document.getElementById('vb-v21-scan-title').textContent=T.scanTitle;document.getElementById('vb-v21-scan-hint').textContent=T.scanHint;document.getElementById('vb-v21-scan-privacy').textContent=T.privacy;VB_V21.lastFocus=document.activeElement;modal.classList.add('vb-open');modal.setAttribute('aria-hidden','false');document.body.style.overflow='hidden';stage.classList.remove('vb-v21-scan-capture-mode','vb-v21-scan-decoding');setTimeout(()=>{const close=modal.querySelector('.vb-v21-dialog-close');if(close)close.focus();},0);\n  \/\/ Some mobile\/private\/in-app browser contexts expose no getUserMedia at all. Do not dead-end:\n  \/\/ use the OS camera\/file picker and decode the still image locally instead.\n  if(!navigator.mediaDevices||!navigator.mediaDevices.getUserMedia){renderV21CaptureFallback(stage,status,T,'no_live_camera');return;}\n  try{\n    if('BarcodeDetector' in window){await startV21NativeScanner(stage,status,T);return;}\n    await startV21CompatibilityScanner(stage,status,T);\n  }catch(e){\n    stopV21Scanner();\n    if('BarcodeDetector' in window ? (e ? !['NotAllowedError','SecurityError','NotReadableError','NotFoundError'].includes(e.name||'') : false) : false){\n      try{await startV21CompatibilityScanner(stage,status,T);return;}catch(ignore){}\n    }\n    renderV21CaptureFallback(stage,status,T,(e?e.name==='NotAllowedError':false)?'permission':'live_failed');\n  }\n}\nasync function scanV21Frame(){const video=document.getElementById('vb-v21-scan-video');if(!video||!VB_V21.scanDetector)return;try{const codes=await VB_V21.scanDetector.detect(video);for(const found of codes){if(acceptV21ScannedValue(found.rawValue))return;}}catch(e){}VB_V21.scanFrame=requestAnimationFrame(scanV21Frame);}\nfunction stopV21Scanner(){if(VB_V21.scanFrame)cancelAnimationFrame(VB_V21.scanFrame);VB_V21.scanFrame=0;if(VB_V21.scanFallbackReader){try{VB_V21.scanFallbackReader.reset();}catch(e){}VB_V21.scanFallbackReader=null;}if(VB_V21.scanStream){try{VB_V21.scanStream.getTracks().forEach(t=>t.stop());}catch(e){}VB_V21.scanStream=null;}VB_V21.scanDetector=null;}\nfunction trapV21ModalFocus(event){const modal=document.querySelector('.vb-v21-modal.vb-open');if(!modal||event.key!=='Tab')return false;const nodes=[...modal.querySelectorAll('button:not([disabled]),a[href],input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex=\"-1\"])')].filter(el=>el.offsetParent!==null);if(!nodes.length)return false;const first=nodes[0],last=nodes[nodes.length-1];if(event.shiftKey?document.activeElement===first:false){event.preventDefault();last.focus();return true;}if(!event.shiftKey?document.activeElement===last:false){event.preventDefault();first.focus();return true;}return false;}\nfunction initV21App(){applyV21Strings();updateV21ToolbarState();document.querySelectorAll('.vb-v21-modal').forEach(modal=>modal.addEventListener('click',e=>{if(e.target===modal)closeV21Modal(modal.id);}));}\n\/\/ v22 power layer. Everything here is derived from data\/state the standalone checker already has.\n\/\/ No new VARIBOX business\/customer\/backend dataset is introduced.\nconst VB_V22_WORKSPACE_KEY = 'vb_checker_v22_workspaces';\nconst VB_V22_COACH_KEY = 'vb_checker_v22_coach_seen';\nconst VB_V22_WORKSPACE_MAX = 5;\nconst VB_V22 = {\n  services: { serial: SERIAL_LOOKUP_CACHE ? 'ok' : 'unknown', commerce:'unknown' },\n  compareDiffOnly:false,\n  bulkKeyboardIndex:-1,\n  scannerTrack:null,\n  scannerTorch:false,\n  scannerAudio:null,\n  pendingShared:null,\n  currentPassportCode:null\n};\n\nconst V22_BASE_STRINGS = {\n  recent:'Recent workspaces',diagnose:'Diagnose',healthOnline:'Online',healthOffline:'Offline \u2014 artikelcodes werken lokaal',healthIssue:'Live diensten beperkt',healthDetails:'Details',\n  coachTitle:'Nieuw in de checker:',coachText:'vergelijk alleen verschillen, productpaspoort, recente workspaces, diagnose, krachtigere bulkbediening en verbeterde scanner.',coachClose:'Sluiten',\n  didYouMean:'Bedoelde u dit artikelnummer?',useSuggestion:'Gebruik suggestie',explain:'Leg deze VARIBOX uit',passport:'Productpaspoort',hideExplain:'Verberg uitleg',\n  differencesOnly:'Alleen verschillen',allProperties:'Alle eigenschappen',differenceCount:'{count} verschillen',compareExport:'Vergelijking CSV',comparePrint:'Vergelijking printen',compareShare:'Vergelijking delen',\n  fromTo:'{label}: {from} \u2192 {to}',noDifference:'Geen verschillen tussen deze configuraties.',\n  workspaceTitle:'Recente workspaces',workspaceEmpty:'Nog geen recente workspaces in deze tab.',restore:'Herstel',recognized:'{ok} herkend',errors:'{errors} aandacht',configs:'{configs} configuraties',\n  diagnosticsTitle:'Technische diagnose',diagnosticsIntro:'Bevat geen serienummers, artikelnummers, SKU\u2019s of formulierwaarden.',copyDiagnosis:'Kopieer diagnose',copied:'Gekopieerd',\n  network:'Netwerk',serialService:'Serienummerdatabase',commerceService:'WooCommerce live data',barcode:'Barcode scanner',camera:'Camera API',clipboard:'Clipboard API',gravity:'Gravity Forms',results:'Resultaten',\n  available:'Beschikbaar',unavailable:'Niet beschikbaar',unknown:'Nog niet getest',degraded:'Beperkt',\n  selectFamily:'Selecteer {family}',showAttention:'Toon aandacht',shareSelected:'Deel selectie',details:'Details',hideDetails:'Sluit details',keyboardHint:'Bulk: \u2191\u2193 navigeren \u00b7 spatie selecteren \u00b7 Enter openen \u00b7 Ctrl+A alles',\n  partsRetry:'Live prijs\/voorraad kon niet worden geladen.',retry:'Opnieuw proberen',\n  torch:'Zaklamp',zoom:'Zoom',scanLocal:'Camera blijft lokaal',\n  passportTitle:'VARIBOX productpaspoort',printPassport:'Print paspoort',shareResult:'Deel resultaat',\n  shareCopied:'Deellink gekopieerd',bulkShared:'Selectie-link gekopieerd',comparisonShared:'Vergelijkingslink gekopieerd',\n  localDecode:'Configuratie lokaal herkend. Live serienummer-\/webshopdata kan offline niet worden bijgewerkt.',\n  foodYes:'Geschikt voor Food Contact volgens de huidige checkerregels.',foodNo:'Niet geschikt voor Food Contact volgens de huidige checkerregels.',\n  statusOk:'OK',statusError:'Probleem',statusUnknown:'Onbekend',\n  sessionAge:'{minutes} min geleden'\n};\nconst V22_OVERRIDES = {\n  en:{recent:'Recent workspaces',diagnose:'Diagnostics',healthOnline:'Online',healthOffline:'Offline \u2014 article codes still decode locally',healthIssue:'Live services limited',healthDetails:'Details',coachTitle:'New in the checker:',coachText:'differences-only compare, product passports, recent workspaces, diagnostics, stronger bulk controls and scanner polish.',coachClose:'Close',didYouMean:'Did you mean this article number?',useSuggestion:'Use suggestion',explain:'Explain this VARIBOX',passport:'Product passport',hideExplain:'Hide explanation',differencesOnly:'Differences only',allProperties:'All properties',differenceCount:'{count} differences',compareExport:'Export comparison CSV',comparePrint:'Print comparison',compareShare:'Share comparison',fromTo:'{label}: {from} \u2192 {to}',noDifference:'No differences between these configurations.',workspaceTitle:'Recent workspaces',workspaceEmpty:'No recent workspaces in this tab yet.',restore:'Restore',recognized:'{ok} recognised',errors:'{errors} need attention',configs:'{configs} configurations',diagnosticsTitle:'Technical diagnostics',diagnosticsIntro:'Contains no serial numbers, article numbers, SKUs or form values.',copyDiagnosis:'Copy diagnostics',copied:'Copied',network:'Network',serialService:'Serial-number database',commerceService:'WooCommerce live data',barcode:'Barcode scanner',camera:'Camera API',clipboard:'Clipboard API',gravity:'Gravity Forms',results:'Results',available:'Available',unavailable:'Unavailable',unknown:'Not tested yet',degraded:'Limited',selectFamily:'Select {family}',showAttention:'Show attention',shareSelected:'Share selection',details:'Details',hideDetails:'Hide details',keyboardHint:'Bulk: \u2191\u2193 navigate \u00b7 Space select \u00b7 Enter open \u00b7 Ctrl+A all',partsRetry:'Live price\/stock could not be loaded.',retry:'Retry',torch:'Torch',zoom:'Zoom',scanLocal:'Camera stays local',passportTitle:'VARIBOX product passport',printPassport:'Print passport',shareResult:'Share result',shareCopied:'Share link copied',bulkShared:'Selection link copied',comparisonShared:'Comparison link copied',localDecode:'Configuration decoded locally. Live serial\/shop data cannot be refreshed while offline.',foodYes:'Suitable for Food Contact under the current checker rules.',foodNo:'Not suitable for Food Contact under the current checker rules.',statusOk:'OK',statusError:'Issue',statusUnknown:'Unknown',sessionAge:'{minutes} min ago'},\n  de:{recent:'Letzte Workspaces',diagnose:'Diagnose',healthOnline:'Online',healthOffline:'Offline \u2014 Artikelcodes funktionieren lokal',healthIssue:'Live-Dienste eingeschr\u00e4nkt',didYouMean:'Meinten Sie diese Artikelnummer?',useSuggestion:'Vorschlag verwenden',explain:'Diese VARIBOX erkl\u00e4ren',passport:'Produktpass',differencesOnly:'Nur Unterschiede',allProperties:'Alle Eigenschaften',differenceCount:'{count} Unterschiede',compareExport:'Vergleich CSV',comparePrint:'Vergleich drucken',compareShare:'Vergleich teilen',workspaceTitle:'Letzte Workspaces',workspaceEmpty:'Noch keine Workspaces in diesem Tab.',restore:'Wiederherstellen',diagnosticsTitle:'Technische Diagnose',copyDiagnosis:'Diagnose kopieren',selectFamily:'{family} ausw\u00e4hlen',showAttention:'Probleme anzeigen',shareSelected:'Auswahl teilen',partsRetry:'Live-Preis\/Bestand konnte nicht geladen werden.',retry:'Erneut versuchen',torch:'Taschenlampe',zoom:'Zoom',passportTitle:'VARIBOX Produktpass',printPassport:'Produktpass drucken',shareResult:'Ergebnis teilen'},\n  fr:{recent:'Espaces r\u00e9cents',diagnose:'Diagnostic',healthOnline:'En ligne',healthOffline:'Hors ligne \u2014 les num\u00e9ros d\u2019article fonctionnent localement',healthIssue:'Services en direct limit\u00e9s',didYouMean:'Vouliez-vous dire ce num\u00e9ro d\u2019article ?',useSuggestion:'Utiliser la suggestion',explain:'Expliquer cette VARIBOX',passport:'Passeport produit',differencesOnly:'Diff\u00e9rences uniquement',allProperties:'Toutes les propri\u00e9t\u00e9s',differenceCount:'{count} diff\u00e9rences',compareExport:'CSV comparaison',comparePrint:'Imprimer la comparaison',compareShare:'Partager la comparaison',workspaceTitle:'Espaces r\u00e9cents',workspaceEmpty:'Aucun espace r\u00e9cent dans cet onglet.',restore:'Restaurer',diagnosticsTitle:'Diagnostic technique',copyDiagnosis:'Copier le diagnostic',selectFamily:'S\u00e9lectionner {family}',showAttention:'Voir les \u00e9l\u00e9ments \u00e0 v\u00e9rifier',shareSelected:'Partager la s\u00e9lection',partsRetry:'Prix\/stock en direct indisponible.',retry:'R\u00e9essayer',torch:'Lampe',zoom:'Zoom',passportTitle:'Passeport produit VARIBOX',printPassport:'Imprimer le passeport',shareResult:'Partager le r\u00e9sultat'},\n  it:{recent:'Workspace recenti',diagnose:'Diagnostica',healthOnline:'Online',healthOffline:'Offline \u2014 i codici articolo funzionano localmente',healthIssue:'Servizi live limitati',didYouMean:'Intendevi questo numero articolo?',useSuggestion:'Usa suggerimento',explain:'Spiega questa VARIBOX',passport:'Passaporto prodotto',differencesOnly:'Solo differenze',allProperties:'Tutte le propriet\u00e0',differenceCount:'{count} differenze',compareExport:'CSV confronto',comparePrint:'Stampa confronto',compareShare:'Condividi confronto',workspaceTitle:'Workspace recenti',workspaceEmpty:'Nessun workspace recente in questa scheda.',restore:'Ripristina',diagnosticsTitle:'Diagnostica tecnica',copyDiagnosis:'Copia diagnostica',selectFamily:'Seleziona {family}',showAttention:'Mostra attenzione',shareSelected:'Condividi selezione',partsRetry:'Prezzo\/stock live non disponibile.',retry:'Riprova',torch:'Torcia',zoom:'Zoom',passportTitle:'Passaporto prodotto VARIBOX',printPassport:'Stampa passaporto',shareResult:'Condividi risultato'},\n  es:{recent:'Espacios recientes',diagnose:'Diagn\u00f3stico',healthOnline:'Online',healthOffline:'Sin conexi\u00f3n \u2014 los art\u00edculos se decodifican localmente',healthIssue:'Servicios en vivo limitados',didYouMean:'\u00bfQuer\u00eda decir este n\u00famero de art\u00edculo?',useSuggestion:'Usar sugerencia',explain:'Explicar esta VARIBOX',passport:'Pasaporte de producto',differencesOnly:'Solo diferencias',allProperties:'Todas las propiedades',differenceCount:'{count} diferencias',compareExport:'CSV comparaci\u00f3n',comparePrint:'Imprimir comparaci\u00f3n',compareShare:'Compartir comparaci\u00f3n',workspaceTitle:'Espacios recientes',workspaceEmpty:'A\u00fan no hay espacios recientes en esta pesta\u00f1a.',restore:'Restaurar',diagnosticsTitle:'Diagn\u00f3stico t\u00e9cnico',copyDiagnosis:'Copiar diagn\u00f3stico',selectFamily:'Seleccionar {family}',showAttention:'Mostrar atenci\u00f3n',shareSelected:'Compartir selecci\u00f3n',partsRetry:'No se pudo cargar precio\/stock en vivo.',retry:'Reintentar',torch:'Linterna',zoom:'Zoom',passportTitle:'Pasaporte VARIBOX',printPassport:'Imprimir pasaporte',shareResult:'Compartir resultado'},\n  pl:{recent:'Ostatnie obszary',diagnose:'Diagnostyka',healthOnline:'Online',healthOffline:'Offline \u2014 kody artyku\u0142\u00f3w dzia\u0142aj\u0105 lokalnie',healthIssue:'Us\u0142ugi live ograniczone',didYouMean:'Czy chodzi\u0142o o ten numer artyku\u0142u?',useSuggestion:'U\u017cyj sugestii',explain:'Wyja\u015bnij t\u0119 VARIBOX',passport:'Paszport produktu',differencesOnly:'Tylko r\u00f3\u017cnice',allProperties:'Wszystkie w\u0142a\u015bciwo\u015bci',differenceCount:'{count} r\u00f3\u017cnic',compareExport:'CSV por\u00f3wnania',comparePrint:'Drukuj por\u00f3wnanie',compareShare:'Udost\u0119pnij por\u00f3wnanie',workspaceTitle:'Ostatnie obszary',workspaceEmpty:'Brak ostatnich obszar\u00f3w w tej karcie.',restore:'Przywr\u00f3\u0107',diagnosticsTitle:'Diagnostyka techniczna',copyDiagnosis:'Kopiuj diagnostyk\u0119',selectFamily:'Wybierz {family}',showAttention:'Poka\u017c wymagaj\u0105ce uwagi',shareSelected:'Udost\u0119pnij wyb\u00f3r',partsRetry:'Nie uda\u0142o si\u0119 pobra\u0107 ceny\/stanu live.',retry:'Spr\u00f3buj ponownie',torch:'Latarka',zoom:'Zoom',passportTitle:'Paszport produktu VARIBOX',printPassport:'Drukuj paszport',shareResult:'Udost\u0119pnij wynik'}\n};\nfunction v22T(){ return Object.assign({}, V22_BASE_STRINGS, V22_OVERRIDES[CURRENT_LANG] || V22_OVERRIDES.en || {}); }\n\n\/\/ Extend the privacy-safe event vocabulary. No raw codes are added to metrics.\ntry{\n  ['passport','diagnostics','workspace','network','coachmark','correction','bulk_power'].forEach(v=>VB_METRIC_ENUM_FIELDS.feature.add(v));\n  ['retry','restore','copy','navigate','suggest','filter','toggle'].forEach(v=>VB_METRIC_ENUM_FIELDS.interaction.add(v));\n  ['compare_link','bulk_link','diagnostic'].forEach(v=>VB_METRIC_ENUM_FIELDS.copy_kind.add(v));\n  ['workspace','share_state'].forEach(v=>VB_METRIC_ENUM_FIELDS.source.add(v));\n}catch(e){}\n\nfunction v22StatusLabel(status){ const T=v22T(); return status==='ok'?T.statusOk:(status==='error'?T.statusError:T.statusUnknown); }\nfunction v22ReportService(service,status){\n  if(!VB_V22.services[service] ? VB_V22.services[service] !== 'unknown' : false) return;\n  VB_V22.services[service]=status;\n  renderV22Health();\n}\nconst V22_BASE_LOAD_SERIAL = loadSerialLookup;\nloadSerialLookup = function(){\n  return V22_BASE_LOAD_SERIAL().then(data=>{v22ReportService('serial','ok');return data;}).catch(err=>{v22ReportService('serial','error');throw err;});\n};\nconst V22_BASE_FETCH_PRODUCTS = fetchProductData;\nfetchProductData = async function(skus){\n  const requested=[...new Set((skus||[]).filter(Boolean))];\n  const result=await V22_BASE_FETCH_PRODUCTS(skus);\n  const resolved=requested.filter(sku=>PRODUCT_DATA_CACHE[sku] || isProductDataMissingFresh(sku));\n  if(requested.length) v22ReportService('commerce', resolved.length ? 'ok' : 'error');\n  return result;\n};\nconst V22_BASE_TOGGLE_PARTS = togglePartsPopup;\ntogglePartsPopup = async function(idx){ await V22_BASE_TOGGLE_PARTS(idx); v22InspectPartsRetry(idx); };\n\nfunction v22InjectShell(){\n  const layer=document.getElementById('vb-v21-layer');\n  if(!layer||document.getElementById('vb-v22-passport-modal')) return;\n  layer.insertAdjacentHTML('beforeend',`\n    <div id=\"vb-v22-passport-modal\" class=\"vb-v21-modal\" aria-hidden=\"true\"><div class=\"vb-v21-dialog\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"vb-v22-passport-title\"><div class=\"vb-v21-dialog-head\"><div><h3 id=\"vb-v22-passport-title\"><\/h3><p>${esc(v22T().passport)}<\/p><\/div><button type=\"button\" class=\"vb-v21-dialog-close\" data-vb-action=\"close-modal\" data-modal-id=\"vb-v22-passport-modal\" aria-label=\"Close\">\u00d7<\/button><\/div><div id=\"vb-v22-passport-body\" class=\"vb-v21-dialog-body\"><\/div><\/div><\/div>`);\n}\nfunction applyV22Strings(){\n  const T=v22T();\n  const pt=document.getElementById('vb-v22-passport-title');if(pt)pt.textContent=T.passportTitle;\n  document.querySelectorAll('#vb-v22-passport-modal .vb-v21-dialog-close').forEach(btn=>btn.setAttribute('aria-label',T.coachClose));\n}\nfunction renderV22Health(){\n  const host=document.getElementById('vb-v22-health'),text=document.getElementById('vb-v22-health-text');if(!host||!text)return;const T=v22T();\n  const online=typeof navigator==='undefined'?true:navigator.onLine!==false;let state='ok',label=T.healthOnline;\n  if(!online){state='warn';label=T.healthOffline;}\n  else if(VB_V22.services.serial==='error'||VB_V22.services.commerce==='error'){state='warn';label=T.healthIssue;}\n  host.dataset.state=state;text.textContent=label;\n}\nfunction renderV22Coach(){\n  const host=document.getElementById('vb-v22-coach-host');if(!host)return;let seen=false;try{seen=localStorage.getItem(VB_V22_COACH_KEY)==='1';}catch(e){}\n  if(seen){host.innerHTML='';return;}const T=v22T();host.innerHTML=`<div class=\"vb-v22-coach\"><strong>${esc(T.coachTitle)}<\/strong> ${esc(T.coachText)}<button type=\"button\" class=\"vb-v22-coach-close\" data-vb-action=\"dismiss-coach\" aria-label=\"${esc(T.coachClose)}\">\u00d7<\/button><\/div>`;\n}\nfunction v22DismissCoach(){try{localStorage.setItem(VB_V22_COACH_KEY,'1');}catch(e){}const h=document.getElementById('vb-v22-coach-host');if(h)h.innerHTML='';vbMetric('feature_used',{feature:'coachmark',interaction:'close',language:CURRENT_LANG});}\n\nfunction v22OpenModal(id){const modal=document.getElementById(id);if(!modal)return;VB_V21.lastFocus=document.activeElement;modal.classList.add('vb-open');modal.setAttribute('aria-hidden','false');document.body.style.overflow='hidden';setTimeout(()=>{const close=modal.querySelector('.vb-v21-dialog-close');if(close)close.focus();},0);}\nfunction v22CopyText(text,success,kind){\n  const done=()=>{showFormFeedbackToast(success||v22T().copied,true);vbMetric('copy_completed',{copy_kind:kind||'share_link',language:CURRENT_LANG,outcome:'success'});};\n  const fallback=()=>{const ta=document.createElement('textarea');ta.value=text;ta.setAttribute('readonly','');ta.style.position='fixed';ta.style.opacity='0';document.body.appendChild(ta);ta.select();let ok=false;try{ok=document.execCommand('copy');}catch(e){}ta.remove();if(ok)done();};\n  if(navigator.clipboard?navigator.clipboard.writeText:false) navigator.clipboard.writeText(text).then(done).catch(fallback); else fallback();\n}\n\nfunction v22First(matches, fallback){return (matches?matches[0]:false)?matches[0][0]:(fallback||'\u2014');}\nfunction v22ResultFields(result,lang){\n  const S=STRINGS[lang]||STRINGS.en;\n  if(result.isDrumtainer) return [\n    ['type',S.labelType,result.typeName],['trailer',S.labelTrailer,v22First(result.trailerMatches,S.unknownCode)],['combo',S.labelCombo,v22First(result.comboMatches,S.unknownCode)],['colour',S.labelKleur,v22First(result.kleurMatches,S.unknownCode)]\n  ];\n  const rows=[['type',S.labelType,result.typeName],['gasket',S.labelPakking,v22First(result.pakkingMatches,S.unknownCode)],['tube',S.labelZuigbuis,v22First(result.zuigbuisMatches,S.unknownCode)],['sensor',S.labelSensor,v22First(result.sensorMatches,S.unknownCode)],['colour',S.labelKleur,v22First(result.kleurMatches,S.unknownCode)],['food',S.labelFoodContact,result.foodContact?S.yesWord:S.noWord]];\n  if(result.certInfo?result.certInfo.un:false) rows.push(['un',S.labelUN||'UN',result.certInfo.un]);\n  if(result.certInfo?result.certInfo.dibt:false) rows.push(['dibt',S.labelDIBt||'DIBt',result.certInfo.dibt]);\n  return rows;\n}\nfunction v22ExplainResult(result,lang){\n  const S=STRINGS[lang]||STRINGS.en,T=v22T();\n  if(result.isDrumtainer){return `${result.typeName}. ${S.labelTrailer}: ${v22First(result.trailerMatches,S.unknownCode)}. ${S.labelCombo}: ${v22First(result.comboMatches,S.unknownCode)}. ${S.labelKleur}: ${v22First(result.kleurMatches,S.unknownCode)}.`;}\n  return `${result.typeName}. ${S.labelPakking}: ${v22First(result.pakkingMatches,S.unknownCode)}. ${S.labelZuigbuis}: ${v22First(result.zuigbuisMatches,S.unknownCode)}. ${S.labelSensor}: ${v22First(result.sensorMatches,S.unknownCode)}. ${S.labelKleur}: ${v22First(result.kleurMatches,S.unknownCode)}. ${result.foodContact?T.foodYes:T.foodNo}`;\n}\nfunction decorateV22Cards(){\n  const items=[...document.querySelectorAll('#vb-result .vb-result-item')];\n  LAST_RENDERED_GROUPS.forEach((g,i)=>{if(!g||g.result.error)return;const item=items[i],card=item?item.querySelector('.vb-result-card'):item;if(!card||card.querySelector('.vb-v22-card-actions'))return;const target=card.querySelector('.vb-product-hero')||card.querySelector('.vb-hero')||card.querySelector('.vb-card-head');if(!target)return;\n    const actions=document.createElement('div');actions.className='vb-v22-card-actions';actions.innerHTML=`<button type=\"button\" class=\"vb-v22-card-action\" data-vb-action=\"open-passport\" data-code=\"${esc(g.result.code)}\">${esc(v22T().passport)}<\/button>`;target.appendChild(actions);\n  });\n}\nfunction toggleV22Explain(code,button){const el=document.querySelector(`[data-vb-explain-code=\"${code}\"]`);if(!el)return;el.hidden=!el.hidden;if(button)button.textContent=el.hidden?v22T().explain:v22T().hideExplain;vbMetric('feature_used',{feature:'passport',interaction:el.hidden?'close':'open',language:CURRENT_LANG});}\nfunction openV22Passport(code){\n  const g=v21ResultForCode(code);if(!g)return;VB_V22.currentPassportCode=code;const r=g.result,S=STRINGS[CURRENT_LANG],T=v22T();const rows=v22ResultFields(r,CURRENT_LANG);\n  const body=document.getElementById('vb-v22-passport-body');if(!body)return;const serialInfo=(g.inputs||[]).filter(v=>v?v.length===8:false).length;\n  body.innerHTML=`<article class=\"vb-v22-passport\"><div class=\"vb-v22-passport-hero\"><div class=\"vb-v22-passport-mark\">VB<\/div><div><h4>${esc(r.typeName)}<\/h4><div class=\"vb-v22-passport-code\">${esc(r.code)}<\/div>${serialInfo?`<div class=\"vb-v21-compare-code\">${serialInfo} ${esc(v21T().serials)}<\/div>`:''}<\/div><\/div><div class=\"vb-v22-passport-summary\">${esc(v22ExplainResult(r,CURRENT_LANG))}<\/div><div class=\"vb-v22-passport-grid\">${rows.map(([,label,value])=>`<div class=\"vb-v22-passport-row\"><small>${esc(label)}<\/small><strong>${esc(value)}<\/strong><\/div>`).join('')}<\/div><div class=\"vb-v22-passport-actions\"><button type=\"button\" class=\"vb-app-tool vb-app-tool-primary\" data-vb-action=\"print-passport\">${esc(T.printPassport)}<\/button><\/div><\/article>`;\n  v22OpenModal('vb-v22-passport-modal');vbMetric('feature_used',{feature:'passport',interaction:'open',language:CURRENT_LANG,result_count:1});\n}\nfunction v22PrintPassport(){return invokeV21Print('vb-v22-passport-printing');}\nfunction v22ShareUrl(mode,codes){\n  const url=new URL(window.location.href);['vbcode','vbcompare','vbbulk'].forEach(k=>url.searchParams.delete(k));url.searchParams.set('vblang',CURRENT_LANG);url.hash='';\n  if(mode==='compare')url.searchParams.set('vbcompare',codes.join(','));else if(mode==='bulk')url.searchParams.set('vbbulk',codes.join(','));else url.searchParams.set('vbcode',codes[0]||'');return url.toString();\n}\nfunction v22SharePassport(code){v22CopyText(v22ShareUrl('result',[code]),v22T().shareCopied,'share_link');}\n\nfunction v22CompareData(){\n  const groups=[...VB_V21.compareCodes].map(v21ResultForCode).filter(Boolean),S=STRINGS[CURRENT_LANG];\n  const keys=[['type',S.labelType],['gasket',S.labelPakking],['tube',S.labelZuigbuis],['sensor',S.labelSensor],['colour',S.labelKleur],['food',S.labelFoodContact],['trailer',S.labelTrailer],['combo',S.labelCombo]];\n  const rows=keys.map(([key,label])=>{const values=groups.map(g=>v21Value(g.result,key,S));return {key,label,values,diff:new Set(values).size>1};});\n  return {groups,rows,diffs:rows.filter(r=>r.diff)};\n}\nconst V22_BASE_OPEN_COMPARE=openV21Compare;\nopenV21Compare=function(){\n  VB_V22.compareDiffOnly=false;\n  const data=v22CompareData();if(data.groups.length<2){showFormFeedbackToast(v21T().needTwo,false);return;}const T=v22T(),modal=document.getElementById('vb-v21-compare-modal'),body=document.getElementById('vb-v21-compare-body');if(!modal||!body)return;VB_V21.lastFocus=document.activeElement;\n  const sentence=data.diffs.length?data.diffs.slice(0,4).map(row=>data.groups.length===2?T.fromTo.replace('{label}',row.label).replace('{from}',row.values[0]).replace('{to}',row.values[1]):`${row.label}: ${[...new Set(row.values)].join(' \/ ')}`).join(' \u00b7 '):T.noDifference;\n  body.innerHTML=`<div class=\"vb-v22-diff-summary\"><strong>${esc(T.differenceCount.replace('{count}',data.diffs.length))}<\/strong><br>${esc(sentence)}<\/div><div class=\"vb-v21-compare-grid\" id=\"vb-v22-compare-grid\"><table class=\"vb-v21-compare-table\"><thead><tr><th>${esc(v21T().passport)}<\/th>${data.groups.map(g=>`<th>${esc(g.result.typeName)}<span class=\"vb-v21-compare-code\">${esc(g.result.code)}<\/span><\/th>`).join('')}<\/tr><\/thead><tbody>${data.rows.map(row=>`<tr class=\"${row.diff?'vb-v21-diff-row':''}\"><td>${esc(row.label)}<\/td>${row.values.map(v=>`<td>${esc(v)}<\/td>`).join('')}<\/tr>`).join('')}<\/tbody><\/table><\/div>`;\n  document.getElementById('vb-v21-compare-title').textContent=v21T().compareTitle;document.getElementById('vb-v21-compare-sub').textContent=v21T().compareSub;modal.classList.add('vb-open');modal.setAttribute('aria-hidden','false');document.body.style.overflow='hidden';setTimeout(()=>{const close=modal.querySelector('.vb-v21-dialog-close');if(close)close.focus();},0);vbMetric('feature_used',{feature:'compare',interaction:'open',language:CURRENT_LANG,compare_count:data.groups.length});\n};\nfunction v22ToggleDiffOnly(button){VB_V22.compareDiffOnly=!VB_V22.compareDiffOnly;const grid=document.getElementById('vb-v22-compare-grid');if(grid)grid.classList.toggle('vb-v22-hide-equal',VB_V22.compareDiffOnly);if(button){button.setAttribute('aria-pressed',String(VB_V22.compareDiffOnly));button.textContent=VB_V22.compareDiffOnly?v22T().allProperties:v22T().differencesOnly;}vbMetric('feature_used',{feature:'compare',interaction:'filter',language:CURRENT_LANG});}\nfunction exportV22Compare(){const data=v22CompareData();if(data.groups.length<2)return;const headers=['property',...data.groups.map(g=>g.result.code)];const lines=[headers.map(v21CsvCell).join(',')];data.rows.forEach(row=>lines.push([row.label,...row.values].map(v21CsvCell).join(',')));const blob=new Blob(['\\uFEFF'+lines.join('\\r\\n')],{type:'text\/csv;charset=utf-8'}),url=URL.createObjectURL(blob),a=document.createElement('a');a.href=url;a.download=`varibox-comparison-${new Date().toISOString().slice(0,10)}.csv`;document.body.appendChild(a);a.click();a.remove();setTimeout(()=>URL.revokeObjectURL(url),1000);vbMetric('feature_used',{feature:'export',format:'csv',interaction:'submit',language:CURRENT_LANG,compare_count:data.groups.length});}\nfunction printV22Compare(){return invokeV21Print('vb-v22-passport-printing');}\nfunction shareV22Compare(){const codes=[...VB_V21.compareCodes];if(codes.length<2)return;v22CopyText(v22ShareUrl('compare',codes),v22T().comparisonShared,'compare_link');}\n\nfunction v22WorkspaceRead(){try{const raw=sessionStorage.getItem(VB_V22_WORKSPACE_KEY),arr=raw?JSON.parse(raw):[];return Array.isArray(arr)?arr.filter(x=>x?typeof x.raw==='string':false).slice(0,VB_V22_WORKSPACE_MAX):[];}catch(e){return[];}}\nfunction v22WorkspaceSave(raw,results,lang){\n  const text=String(raw||'').trim();if(!text)return;const list=Array.isArray(results)?results:[],ok=list.filter(r=>r?!r.error:false).length,errors=list.length-ok,configs=typeof groupResults==='function'?groupResults(list).filter(g=>!g.result.error).length:ok;let arr=v22WorkspaceRead().filter(x=>x.raw!==text||x.lang!==lang);arr.unshift({raw:text.slice(0,5000),lang,at:Date.now(),ok,errors,configs});arr=arr.slice(0,VB_V22_WORKSPACE_MAX);try{sessionStorage.setItem(VB_V22_WORKSPACE_KEY,JSON.stringify(arr));}catch(e){}\n}\nfunction v22AgeText(at){const mins=Math.max(0,Math.round((Date.now()-Number(at||Date.now()))\/60000));return v22T().sessionAge.replace('{minutes}',mins);}\nfunction openV22Workspaces(){const body=document.getElementById('vb-v22-workspace-body');if(!body)return;const T=v22T(),arr=v22WorkspaceRead();body.innerHTML=arr.length?`<div class=\"vb-v22-workspaces\">${arr.map((w,i)=>`<div class=\"vb-v22-workspace\"><div><div class=\"vb-v22-workspace-title\">${esc(w.raw.split(\/[\\n,;]+\/).slice(0,2).join(' \u00b7 '))}${w.raw.split(\/[\\n,;]+\/).filter(Boolean).length>2?' \u2026':''}<\/div><div class=\"vb-v22-workspace-meta\">${esc(v22AgeText(w.at))} \u00b7 ${esc(T.recognized.replace('{ok}',w.ok))} \u00b7 ${esc(T.errors.replace('{errors}',w.errors))} \u00b7 ${esc(T.configs.replace('{configs}',w.configs))}<\/div><\/div><button type=\"button\" data-vb-action=\"restore-workspace\" data-workspace-index=\"${i}\">${esc(T.restore)}<\/button><\/div>`).join('')}<\/div>`:`<div class=\"vb-v22-empty-note\">${esc(T.workspaceEmpty)}<\/div>`;v22OpenModal('vb-v22-workspace-modal');vbMetric('feature_used',{feature:'workspace',interaction:'open',language:CURRENT_LANG});}\nfunction restoreV22Workspace(index){const w=v22WorkspaceRead()[Number(index)];if(!w)return;if(STRINGS[w.lang]){CURRENT_LANG=w.lang;document.getElementById('vb-lang').value=w.lang;applyStrings(w.lang);applyV21Strings();applyV22Strings();}const input=document.getElementById('vb-code');input.value=w.raw;updateClearBtnVisibility();updateInputMeta();closeV21Modal('vb-v22-workspace-modal');runSearch(w.raw,'workspace');vbMetric('feature_used',{feature:'workspace',interaction:'restore',language:CURRENT_LANG});}\n\nfunction v22DiagnosticObject(){\n  const gravity=!!(document.getElementById('gform_'+GF_RESULT_FORM_ID)?document.getElementById('gform_'+GF_QUOTE_FORM_ID):null);\n  return {online:navigator.onLine!==false,language:CURRENT_LANG,serial_service:VB_V22.services.serial,commerce_service:VB_V22.services.commerce,serial_cache_loaded:!!SERIAL_LOOKUP_CACHE,barcode_detector:'BarcodeDetector' in window,scanner_fallback:!!(window.ZXing?window.ZXing.BrowserMultiFormatReader:false),camera_api:!!(navigator.mediaDevices?navigator.mediaDevices.getUserMedia:false),clipboard_api:!!(navigator.clipboard?navigator.clipboard.writeText:false),history_api:!!(window.history?window.history.pushState:false),session_storage:(()=>{try{const k='__vb22';sessionStorage.setItem(k,'1');sessionStorage.removeItem(k);return true;}catch(e){return false;}})(),gravity_forms:gravity,result_count:LAST_RENDERED_GROUPS.length,successful_results:LAST_RENDERED_GROUPS.filter(g=>!g.result.error).length};\n}\nfunction v22DiagnosticText(){const d=v22DiagnosticObject();return ['VARIBOX Checker diagnostics','Version: v22','Language: '+d.language,'Online: '+d.online,'Serial service: '+d.serial_service,'Commerce service: '+d.commerce_service,'Serial cache loaded: '+d.serial_cache_loaded,'BarcodeDetector: '+d.barcode_detector,'Scanner fallback loaded: '+d.scanner_fallback,'Camera API: '+d.camera_api,'Clipboard API: '+d.clipboard_api,'History API: '+d.history_api,'Session storage: '+d.session_storage,'Gravity Forms present: '+d.gravity_forms,'Rendered results: '+d.result_count,'Successful results: '+d.successful_results].join('\\n');}\nfunction openV22Diagnostics(){const body=document.getElementById('vb-v22-diagnostic-body');if(!body)return;const T=v22T(),d=v22DiagnosticObject(),item=(label,value)=>`<div class=\"vb-v22-diag\"><small>${esc(label)}<\/small><strong>${esc(String(value))}<\/strong><\/div>`;body.innerHTML=`<div class=\"vb-v22-diagnostics\"><div class=\"vb-v22-diagnostic-grid\">${item(T.network,d.online?T.available:T.unavailable)}${item(T.serialService,v22StatusLabel(d.serial_service))}${item(T.commerceService,v22StatusLabel(d.commerce_service))}${item(T.barcode,d.barcode_detector?T.available:T.unavailable)}${item(T.camera,d.camera_api?T.available:T.unavailable)}${item(T.clipboard,d.clipboard_api?T.available:T.unavailable)}${item(T.gravity,d.gravity_forms?T.available:T.unavailable)}${item(T.results,d.result_count)}<\/div><pre>${esc(v22DiagnosticText())}<\/pre><button type=\"button\" class=\"vb-app-tool vb-app-tool-primary\" data-vb-action=\"copy-diagnostics\">${esc(T.copyDiagnosis)}<\/button><\/div>`;v22OpenModal('vb-v22-diagnostic-modal');vbMetric('feature_used',{feature:'diagnostics',interaction:'open',language:CURRENT_LANG});}\nfunction copyV22Diagnostics(){v22CopyText(v22DiagnosticText(),v22T().copied,'diagnostic');vbMetric('feature_used',{feature:'diagnostics',interaction:'copy',language:CURRENT_LANG});}\n\nfunction v22FullyRecognized(result){\n  if(!result||result.error)return false;if(result.isDrumtainer){const okT=!!(result.trailerMatches?result.trailerMatches.length===1:false);const okC=!!(result.comboMatches?result.comboMatches.length===1:false);const okK=!!(result.kleurMatches?result.kleurMatches.length===1:false);return okT?(okC?okK:false):false;}\n  return (result.pakkingMatches?result.pakkingMatches.length===1:false)?(result.zuigbuisMatches?result.zuigbuisMatches.length===1:false):false?(result.sensorMatches?result.sensorMatches.length===1:false):false?(result.kleurMatches?result.kleurMatches.length===1:false):false;\n}\nfunction suggestV22Correction(raw,lang){\n  const input=String(raw||'').trim().toUpperCase().replace(\/\\s+\/g,'');if(input.length!==12)return null;const current=decode(input,lang);if(v22FullyRecognized(current))return null;\n  const map={O:['0'],I:['1'],L:['1'],S:['5'],Z:['2'],G:['6'],B:['8']};let candidates=[''];\n  for(const ch of input){const variants=[ch,...(map[ch]||[])];const next=[];for(const prefix of candidates){for(const v of variants){next.push(prefix+v);if(next.length>128)break;}if(next.length>128)break;}candidates=next.slice(0,128);}\n  const valid=[...new Set(candidates.filter(c=>c!==input).filter(c=>v22FullyRecognized(decode(c,lang))))];return valid.length===1?valid[0]:null;\n}\nfunction renderV22Correction(){const root=document.getElementById('vb-result');if(!root)return;root.querySelectorAll('.vb-v22-correction').forEach(n=>n.remove());const raw=document.getElementById('vb-code').value;const entries=raw.split(\/[\\n,;]+\/).map(s=>s.trim()).filter(Boolean);if(entries.length!==1)return;const suggestion=suggestV22Correction(entries[0],CURRENT_LANG);if(!suggestion)return;const T=v22T(),box=document.createElement('div');box.className='vb-v22-correction';box.innerHTML=`<span>${esc(T.didYouMean)} <code>${esc(suggestion)}<\/code><\/span><button type=\"button\" data-vb-action=\"use-correction\" data-code=\"${esc(suggestion)}\">${esc(T.useSuggestion)}<\/button>`;root.prepend(box);vbMetric('feature_used',{feature:'correction',interaction:'suggest',language:CURRENT_LANG});}\nfunction useV22Correction(code){const input=document.getElementById('vb-code');input.value=code;updateClearBtnVisibility();updateInputMeta();runSearch(code,'button');}\n\nfunction v22InspectPartsRetry(idx){\n  const popup=document.getElementById('vb-parts-popup-'+idx);if(!popup||!popup.classList.contains('vb-open'))return;popup.querySelectorAll('.vb-v22-retry').forEach(n=>n.remove());const skus=[];popup.querySelectorAll('.vb-part-card[data-skus]').forEach(row=>skus.push(...String(row.dataset.skus||'').split(',').filter(Boolean)));const unresolved=[...new Set(skus)].filter(sku=>!PRODUCT_DATA_CACHE[sku]?!isProductDataMissingFresh(sku):false);if(!unresolved.length)return;const status=document.getElementById('vb-parts-status-'+idx)||popup.querySelector('.vb-parts-actions');if(!status)return;const box=document.createElement('div');box.className='vb-v22-retry';box.innerHTML=`<span>${esc(v22T().partsRetry)}<\/span><button type=\"button\" data-vb-action=\"retry-parts\" data-idx=\"${idx}\">${esc(v22T().retry)}<\/button>`;status.parentNode.insertBefore(box,status);}\nasync function retryV22Parts(idx){const popup=document.getElementById('vb-parts-popup-'+idx);if(!popup)return;const skus=[];popup.querySelectorAll('.vb-part-card[data-skus]').forEach(row=>skus.push(...String(row.dataset.skus||'').split(',').filter(Boolean)));if(!skus.length)return;setPartsPopupLoading(popup,true);try{await fetchProductData(skus);if(popup.isConnected)populatePartsRowData(idx);}finally{setPartsPopupLoading(popup,false);v22InspectPartsRetry(idx);}vbMetric('feature_used',{feature:'network',interaction:'retry',language:CURRENT_LANG});}\n\nfunction v22FamilyLabel(line){return ({fc1000:'FC 1000',fc800:'FC 800',cc250:'CC 250',drumtainer:'Drumtainer'})[line]||line;}\nfunction enhanceV22CommandCenter(){\n  const command=document.getElementById('vb-v21-command');if(!command)return;command.querySelectorAll('.vb-v22-command-summary,.vb-v22-command-actions').forEach(n=>n.remove());const counts={};LAST_RENDERED_GROUPS.filter(g=>!g.result.error).forEach(g=>{const line=getProductLine(g.result.typeCode)||'unknown';counts[line]=(counts[line]||0)+g.count;});const head=command.querySelector('.vb-v21-command-head');if(head){const s=document.createElement('div');s.className='vb-v22-command-summary';s.innerHTML=Object.entries(counts).map(([line,count])=>`<button type=\"button\" class=\"vb-v22-family-chip\" data-vb-action=\"select-family\" data-family=\"${esc(line)}\">${esc(v22T().selectFamily.replace('{family}',v22FamilyLabel(line)))} \u00b7 ${count}<\/button>`).join('');head.insertAdjacentElement('afterend',s);}\n  \/\/ v23.4: no extra bulk action strip here. Attention already has a dedicated\n  \/\/ result filter, sharing is not a primary factory-check task, and keyboard\n  \/\/ shortcuts remain available without permanently advertising them.\n  decorateV22CommandRows();\n}\nfunction decorateV22CommandRows(){const wrap=document.querySelector('.vb-v21-table-wrap');if(wrap?!wrap.hasAttribute('tabindex'):false){wrap.tabIndex=0;wrap.setAttribute('aria-label',v22T().keyboardHint);}document.querySelectorAll('#vb-v21-command-body tr[data-vb-command-index]').forEach(row=>{row.tabIndex=-1;});}\nfunction selectV22Family(line){VB_V21.bulkSelectedCodes.clear();LAST_RENDERED_GROUPS.filter(g=>!g.result.error?getProductLine(g.result.typeCode)===line:false).forEach(g=>VB_V21.bulkSelectedCodes.add(g.result.code));renderV21CommandRows();vbMetric('feature_used',{feature:'bulk_power',interaction:'filter',language:CURRENT_LANG,selected_count:VB_V21.bulkSelectedCodes.size});}\nfunction showV22Attention(){const btn=document.querySelector('.vb-filter-btn[data-filter=\"error\"]');if(btn)filterResultCards('error',btn);const first=document.querySelector('.vb-result-item[data-vb-status=\"error\"]');if(first)first.scrollIntoView({behavior:'smooth',block:'center'});}\nfunction shareV22Selected(){const codes=[...VB_V21.bulkSelectedCodes];if(!codes.length)return;v22CopyText(v22ShareUrl('bulk',codes),v22T().bulkShared,'bulk_link');}\nfunction toggleV22Inline(index,button){const row=document.querySelector(`#vb-v21-command-body tr[data-vb-command-index=\"${Number(index)}\"]`);if(!row)return;const next=row.nextElementSibling;if(next?next.classList.contains('vb-v22-inline-row'):false){next.remove();if(button)button.textContent=v22T().details;return;}const g=LAST_RENDERED_GROUPS[Number(index)];if(!g)return;const r=g.result,S=STRINGS[CURRENT_LANG];const detail=document.createElement('tr');detail.className='vb-v22-inline-row';detail.innerHTML=`<td colspan=\"6\" class=\"vb-v22-inline-details\">${r.error?esc(r.error):v22ResultFields(r,CURRENT_LANG).slice(1,6).map(([,l,v])=>`<strong>${esc(l)}<\/strong>: ${esc(v)}`).join(' \u00b7 ')}<\/td>`;row.insertAdjacentElement('afterend',detail);if(button)button.textContent=v22T().hideDetails;}\nfunction v22BulkKeyboard(event){const wrap=event.target.closest?event.target.closest('.vb-v21-table-wrap'):event.target.closest;if(!wrap)return;const rows=[...wrap.querySelectorAll('tbody tr[data-vb-command-index]')];if(!rows.length)return;if(event.key==='\/'){event.preventDefault();event.stopPropagation();const s=document.getElementById('vb-v21-command-search');if(s){s.focus();s.select();}return;}if((event.ctrlKey||event.metaKey)?event.key.toLowerCase()==='a':false){event.preventDefault();event.stopPropagation();rows.forEach(row=>{const cb=row.querySelector('.vb-v21-bulk-check');if(cb){cb.checked=true;VB_V21.bulkSelectedCodes.add(cb.dataset.code);}});updateV21CommandFooter();return;}if(!['ArrowDown','ArrowUp',' ','Enter'].includes(event.key))return;event.preventDefault();event.stopPropagation();if(VB_V22.bulkKeyboardIndex<0)VB_V22.bulkKeyboardIndex=0;VB_V22.bulkKeyboardIndex=Math.min(rows.length-1,Math.max(0,VB_V22.bulkKeyboardIndex));if(event.key==='ArrowDown')VB_V22.bulkKeyboardIndex=Math.min(rows.length-1,VB_V22.bulkKeyboardIndex+1);else if(event.key==='ArrowUp')VB_V22.bulkKeyboardIndex=Math.max(0,VB_V22.bulkKeyboardIndex-1);rows.forEach((r,i)=>r.classList.toggle('vb-v22-key-active',i===VB_V22.bulkKeyboardIndex));const row=rows[VB_V22.bulkKeyboardIndex];row.scrollIntoView({block:'nearest'});if(event.key===' '){const cb=row.querySelector('.vb-v21-bulk-check');if(cb){cb.checked=!cb.checked;toggleV21BulkSelection(cb.dataset.code,cb.checked);}}else if(event.key==='Enter'){const view=row.querySelector('[data-vb-action=\"view-result\"]');if(view)view.click();}}\n\nfunction v22ScanSuccessFeedback(){\n  try{if(navigator.vibrate)navigator.vibrate(40);}catch(e){}\n  try{if(!VB_V22.scannerAudio)VB_V22.scannerAudio=new (window.AudioContext||window.webkitAudioContext)();const ctx=VB_V22.scannerAudio,osc=ctx.createOscillator(),gain=ctx.createGain();osc.frequency.value=880;gain.gain.setValueAtTime(.06,ctx.currentTime);gain.gain.exponentialRampToValueAtTime(.001,ctx.currentTime+.08);osc.connect(gain);gain.connect(ctx.destination);osc.start();osc.stop(ctx.currentTime+.08);}catch(e){}\n  const stage=document.getElementById('vb-v21-scan-stage');if(stage){stage.classList.add('vb-v22-scan-found');setTimeout(()=>stage.classList.remove('vb-v22-scan-found'),450);}\n}\nfunction v22EnhanceScannerControls(){\n  const stream=VB_V21.scanStream,stage=document.getElementById('vb-v21-scan-stage');if(!stream||!stage)return;const track=stream.getVideoTracks?stream.getVideoTracks()[0]:undefined;if(!track)return;VB_V22.scannerTrack=track;let cap={};try{cap=track.getCapabilities?track.getCapabilities():{};}catch(e){}\n  const status=document.getElementById('vb-v21-scan-status');if(!status)return;let html='';if(cap.torch)html+=`<button type=\"button\" data-vb-action=\"scanner-torch\" aria-pressed=\"false\">${esc(v22T().torch)}<\/button>`;let zoomOk=false;if(cap.zoom){if(Number.isFinite(cap.zoom.min)){if(Number.isFinite(cap.zoom.max)){if(cap.zoom.max>cap.zoom.min)zoomOk=true;}}}if(zoomOk)html+=`<label>${esc(v22T().zoom)} <input type=\"range\" min=\"${cap.zoom.min}\" max=\"${cap.zoom.max}\" step=\"${cap.zoom.step||.1}\" value=\"${cap.zoom.min}\" data-vb-action=\"scanner-zoom\"><\/label>`;if(html){let controls=document.getElementById('vb-v22-scan-controls');if(!controls){controls=document.createElement('div');controls.id='vb-v22-scan-controls';controls.className='vb-v22-scan-controls';status.insertAdjacentElement('afterend',controls);}controls.innerHTML=html;}\n}\nasync function toggleV22Torch(button){const track=VB_V22.scannerTrack;if(!track)return;VB_V22.scannerTorch=!VB_V22.scannerTorch;try{await track.applyConstraints({advanced:[{torch:VB_V22.scannerTorch}]});if(button)button.setAttribute('aria-pressed',String(VB_V22.scannerTorch));}catch(e){VB_V22.scannerTorch=false;}}\nasync function setV22Zoom(value){const track=VB_V22.scannerTrack;if(!track)return;const n=Number(value);if(!Number.isFinite(n))return;try{await track.applyConstraints({advanced:[{zoom:n}]});}catch(e){}}\nconst V22_BASE_STOP_SCANNER=stopV21Scanner;\nstopV21Scanner=function(){VB_V22.scannerTrack=null;VB_V22.scannerTorch=false;const controls=document.getElementById('vb-v22-scan-controls');if(controls)controls.remove();return V22_BASE_STOP_SCANNER();};\n\nfunction v22AfterRendered(){decorateV22Cards();renderV22Correction();enhanceV22CommandCenter();renderV22Health();}\nconst V22_BASE_ENHANCE_RESULTS=enhanceV21Results;\nenhanceV21Results=function(results,groups,lang){V22_BASE_ENHANCE_RESULTS(results,groups,lang);v22AfterRendered();};\nconst V22_BASE_RENDER_COMMAND=renderV21CommandRows;\nrenderV21CommandRows=function(){V22_BASE_RENDER_COMMAND();decorateV22CommandRows();};\nconst V22_BASE_AFTER_SEARCH=v21AfterSearch;\nv21AfterSearch=function(raw,results,source,lang){V22_BASE_AFTER_SEARCH(raw,results,source,lang);v22WorkspaceSave(raw,results,lang);if(navigator.onLine===false?results.some(r=>!r.error?String(r.originalInput||'').length===12:false):false)showFormFeedbackToast(v22T().localDecode,true);if(VB_V22.pendingShared){const pending=VB_V22.pendingShared;VB_V22.pendingShared=null;if(pending.mode==='compare'){VB_V21.compareCodes=new Set(pending.codes.filter(c=>v21ResultForCode(c)).slice(0,VB_V21_COMPARE_MAX));updateV21CompareVisuals();renderV21CompareDock();if(VB_V21.compareCodes.size>=2)setTimeout(openV21Compare,80);}else if(pending.mode==='bulk'){VB_V21.bulkSelectedCodes=new Set(pending.codes.filter(c=>v21ResultForCode(c)));renderV21CommandRows();}}};\n\nfunction v22ParseExtendedShare(){try{const p=new URLSearchParams(location.search),comp=(p.get('vbcompare')||'').split(',').map(s=>s.trim().toUpperCase()).filter(v=>v.length===12).slice(0,4),bulk=(p.get('vbbulk')||'').split(',').map(s=>s.trim().toUpperCase()).filter(v=>v.length===12).slice(0,25);if(comp.length>=2)return {mode:'compare',codes:comp};if(bulk.length)return {mode:'bulk',codes:bulk};}catch(e){}return null;}\nconst V22_EXTENDED_SHARE=v22ParseExtendedShare();\nif(V22_EXTENDED_SHARE){const V22_BASE_SESSION_READ=v21SessionRead;v21SessionRead=function(){return null;};}\nfunction bootV22ExtendedShare(){if(!V22_EXTENDED_SHARE)return;VB_V22.pendingShared=V22_EXTENDED_SHARE;setTimeout(()=>{const raw=V22_EXTENDED_SHARE.codes.join('\\n'),input=document.getElementById('vb-code');if(input){input.value=raw;updateClearBtnVisibility();updateInputMeta();runSearch(raw,'shared_link');}},0);}\n\nfunction initV22(){\n  v22InjectShell();applyV22Strings();\n  document.addEventListener('varibox:metric',e=>{const d=e?e.detail:e;if(!d)return;if(d.event==='varibox_cart_completed')v22ReportService('commerce',d.outcome==='failure'?'error':'ok');});\n  const root=document.querySelector('.vb-check');if(root){root.addEventListener('click',v22HandleClick);root.addEventListener('input',v22HandleInput);root.addEventListener('keydown',v22BulkKeyboard,true);}\n  bootV22ExtendedShare();\n}\nfunction v22HandleClick(event){const target=event.target.closest('[data-vb-action]');if(!target)return;const action=target.dataset.vbAction;if(action==='open-passport')openV22Passport(target.dataset.code||'');else if(action==='print-passport')v22PrintPassport();else if(action==='use-correction')useV22Correction(target.dataset.code||'');else if(action==='retry-parts')retryV22Parts(Number(target.dataset.idx));else if(action==='select-family')selectV22Family(target.dataset.family||'');else if(action==='scanner-torch')toggleV22Torch(target);else if(action==='scanner-zoom')setV22Zoom(target.value);}\nfunction v22HandleInput(event){const target=event.target;if(target?(target.dataset?target.dataset.vbAction==='scanner-zoom':false):false)setV22Zoom(target.value);}\n\nconst V22_BASE_APPLY_V21_STRINGS=applyV21Strings;\napplyV21Strings=function(){V22_BASE_APPLY_V21_STRINGS();applyV22Strings();};\nconst V22_BASE_INIT_LANG=initLang;\ninitLang=function(lang){V22_BASE_INIT_LANG(lang);if(document.getElementById('vb-app-toolbar'))applyV21Strings();};\nconst V22_BASE_INIT_V21=initV21App;\ninitV21App=function(){V22_BASE_INIT_V21();initV22();};\n\/\/ v23 Field Edition: progressive enhancement for real mobile\/warehouse use.\n\/\/ No new VARIBOX product\/customer\/backend data is introduced in this layer.\nconst VB_V23_STATE_KEY='vb_checker_v23_state';\nconst VB_V23_RETRY_KEY='vb_checker_v23_retry';\nconst VB_V23_STATE_MAX_AGE_MS=4*60*60*1000;\nconst VB_V23_UNDO_MAX=8;\nconst VB_V23_SCAN_MAX=MAX_BULK_CODES;\nconst VB_V23={\n  warehouseActive:false,scanQueue:[],lastScanValue:'',lastScanAt:0,scannerPaused:false,\n  pendingRestore:null,undo:[],restoring:false,pendingRetry:null,retryInFlight:false,lastRetryAt:0,\n  highContrast:false,selfCheck:null,committedState:null\n};\nconst V23_BASE_STRINGS={\n  fieldScan:'Scanlijst',fieldScanTitle:'Magazijn-scanlijst',fieldScanHint:'Scan meerdere VARIBOX-codes achter elkaar en verwerk ze daarna als \u00e9\u00e9n bulkcontrole.',\n  scanned:'{count} gescand',finishScan:'Gereed \u2014 controleer lijst',clearScan:'Lijst wissen',removeScan:'Verwijder',duplicateSerial:'Dit serienummer staat al in de scanlijst.',rapidDuplicate:'Dezelfde code is net al gelezen \u2014 ga naar het volgende label.',scanLimit:'Maximum van {max} scans bereikt.',scanAdded:'Toegevoegd \u00b7 {count}\/{max}',\n  scannerRoute:'Scannerroute',routeNative:'Live camera \u00b7 native barcodeherkenning',routeCompat:'Live camera \u00b7 compatibiliteitsdecoder',routePhoto:'Foto\/camerafallback',routeUnavailable:'Alleen handmatige invoer',resumeCamera:'Camera hervatten',cameraPaused:'Camera gepauzeerd omdat de pagina niet actief was.',\n  undo:'Ongedaan maken',nothingToUndo:'Niets om ongedaan te maken.',restoredState:'Vorige werkstatus hersteld.',\n  retryLookup:'Serienummerlookup opnieuw proberen',retryWaiting:'Live serienummerdata kon niet worden opgehaald. Uw invoer blijft bewaard.',retryOnline:'Verbinding terug \u2014 lookup wordt opnieuw geprobeerd.',\n  fieldTest:'Field test',fieldTestTitle:'Device & field self-test',fieldTestIntro:'Controleert lokale browsermogelijkheden zonder serienummers, artikelnummers of formulierdata op te nemen.',copyReport:'Kopieer field report',testScanner:'Test scanner',testPrint:'Test print',contrastOn:'Hoog contrast aan',contrastOff:'Hoog contrast uit',\n  secureContext:'Beveiligde HTTPS-context',cameraApi:'Live camera API',barcodeNative:'Native barcodeherkenning',photoFallback:'Foto\/camera fallback',printApi:'Print API',storage:'Sessieherstel',touch:'Touchbediening',visibility:'Pagina actief',network:'Netwerk',selfCheck:'App self-check',ok:'OK',limited:'Beperkt',unavailable:'Niet beschikbaar',\n  printTitle:'VARIBOX Checker \u2014 productoverzicht',printCompareTitle:'VARIBOX Checker \u2014 vergelijking',printPassportTitle:'VARIBOX productpaspoort',printDiagnosticTitle:'VARIBOX Checker \u2014 field test',generated:'Aangemaakt',printFooter:'Standalone VARIBOX Checker \u00b7 lokaal gegenereerd vanuit het getoonde resultaat.',\n  workspaceSaved:'Werkstatus automatisch opgeslagen',fieldMode:'Field mode'\n};\nconst V23_OVERRIDES={\n  en:{fieldScan:'Scan list',fieldScanTitle:'Warehouse scan list',fieldScanHint:'Scan multiple VARIBOX codes one after another, then process them as one bulk check.',scanned:'{count} scanned',finishScan:'Done \u2014 check list',clearScan:'Clear list',removeScan:'Remove',duplicateSerial:'This serial number is already in the scan list.',rapidDuplicate:'The same code was just read \u2014 move to the next label.',scanLimit:'Maximum of {max} scans reached.',scanAdded:'Added \u00b7 {count}\/{max}',scannerRoute:'Scanner route',routeNative:'Live camera \u00b7 native barcode detection',routeCompat:'Live camera \u00b7 compatibility decoder',routePhoto:'Photo\/camera fallback',routeUnavailable:'Manual input only',resumeCamera:'Resume camera',cameraPaused:'Camera paused because the page was not active.',undo:'Undo',nothingToUndo:'Nothing to undo.',restoredState:'Previous workspace state restored.',retryLookup:'Retry serial-number lookup',retryWaiting:'Live serial-number data could not be loaded. Your input is kept.',retryOnline:'Connection restored \u2014 retrying lookup.',fieldTest:'Field test',fieldTestTitle:'Device & field self-test',fieldTestIntro:'Checks local browser capabilities without including serial numbers, article numbers or form data.',copyReport:'Copy field report',testScanner:'Test scanner',testPrint:'Test print',contrastOn:'High contrast on',contrastOff:'High contrast off',secureContext:'Secure HTTPS context',cameraApi:'Live camera API',barcodeNative:'Native barcode detection',photoFallback:'Photo\/camera fallback',printApi:'Print API',storage:'Session restore',touch:'Touch controls',visibility:'Page active',network:'Network',selfCheck:'App self-check',ok:'OK',limited:'Limited',unavailable:'Unavailable',printTitle:'VARIBOX Checker \u2014 product overview',printCompareTitle:'VARIBOX Checker \u2014 comparison',printPassportTitle:'VARIBOX product passport',printDiagnosticTitle:'VARIBOX Checker \u2014 field test',generated:'Generated',printFooter:'Standalone VARIBOX Checker \u00b7 generated locally from the displayed result.',workspaceSaved:'Workspace automatically saved',fieldMode:'Field mode'},\n  de:{fieldScan:'Scanliste',fieldScanTitle:'Lager-Scanliste',fieldScanHint:'Mehrere VARIBOX-Codes nacheinander scannen und anschlie\u00dfend gemeinsam pr\u00fcfen.',scanned:'{count} gescannt',finishScan:'Fertig \u2014 Liste pr\u00fcfen',clearScan:'Liste leeren',duplicateSerial:'Diese Seriennummer steht bereits in der Scanliste.',rapidDuplicate:'Derselbe Code wurde gerade gelesen \u2014 zum n\u00e4chsten Etikett wechseln.',undo:'R\u00fcckg\u00e4ngig',fieldTest:'Field-Test',testScanner:'Scanner testen',testPrint:'Druck testen',contrastOn:'Hoher Kontrast an',contrastOff:'Hoher Kontrast aus',retryLookup:'Seriennummer erneut versuchen'},\n  fr:{fieldScan:'Liste de scan',fieldScanTitle:'Liste de scan entrep\u00f4t',fieldScanHint:'Scannez plusieurs codes VARIBOX puis traitez-les ensemble.',scanned:'{count} scann\u00e9s',finishScan:'Termin\u00e9 \u2014 v\u00e9rifier la liste',clearScan:'Effacer la liste',duplicateSerial:'Ce num\u00e9ro de s\u00e9rie est d\u00e9j\u00e0 dans la liste.',rapidDuplicate:'Le m\u00eame code vient d\u2019\u00eatre lu \u2014 passez \u00e0 l\u2019\u00e9tiquette suivante.',undo:'Annuler',fieldTest:'Test terrain',testScanner:'Tester le scanner',testPrint:'Tester l\u2019impression',contrastOn:'Contraste \u00e9lev\u00e9 activ\u00e9',contrastOff:'Contraste \u00e9lev\u00e9 d\u00e9sactiv\u00e9',retryLookup:'R\u00e9essayer la recherche du num\u00e9ro de s\u00e9rie'},\n  it:{fieldScan:'Lista scansioni',fieldScanTitle:'Lista scansioni magazzino',fieldScanHint:'Scansiona pi\u00f9 codici VARIBOX e poi controllali insieme.',scanned:'{count} scansionati',finishScan:'Fine \u2014 controlla lista',clearScan:'Svuota lista',duplicateSerial:'Questo numero di serie \u00e8 gi\u00e0 nella lista.',rapidDuplicate:'Lo stesso codice \u00e8 appena stato letto \u2014 passa all\u2019etichetta successiva.',undo:'Annulla',fieldTest:'Test sul campo',testScanner:'Prova scanner',testPrint:'Prova stampa',contrastOn:'Contrasto alto attivo',contrastOff:'Contrasto alto disattivo',retryLookup:'Riprova ricerca seriale'},\n  es:{fieldScan:'Lista de escaneo',fieldScanTitle:'Lista de escaneo de almac\u00e9n',fieldScanHint:'Escanea varios c\u00f3digos VARIBOX y proc\u00e9salos juntos.',scanned:'{count} escaneados',finishScan:'Listo \u2014 revisar lista',clearScan:'Borrar lista',duplicateSerial:'Este n\u00famero de serie ya est\u00e1 en la lista.',rapidDuplicate:'El mismo c\u00f3digo acaba de leerse \u2014 pasa a la siguiente etiqueta.',undo:'Deshacer',fieldTest:'Prueba de campo',testScanner:'Probar esc\u00e1ner',testPrint:'Probar impresi\u00f3n',contrastOn:'Alto contraste activado',contrastOff:'Alto contraste desactivado',retryLookup:'Reintentar b\u00fasqueda de serie'},\n  pl:{fieldScan:'Lista skan\u00f3w',fieldScanTitle:'Magazynowa lista skan\u00f3w',fieldScanHint:'Skanuj kolejne kody VARIBOX, a nast\u0119pnie sprawd\u017a je razem.',scanned:'Zeskanowano: {count}',finishScan:'Gotowe \u2014 sprawd\u017a list\u0119',clearScan:'Wyczy\u015b\u0107 list\u0119',duplicateSerial:'Ten numer seryjny jest ju\u017c na li\u015bcie.',rapidDuplicate:'Ten sam kod zosta\u0142 w\u0142a\u015bnie odczytany \u2014 przejd\u017a do kolejnej etykiety.',undo:'Cofnij',fieldTest:'Test terenowy',testScanner:'Testuj skaner',testPrint:'Testuj druk',contrastOn:'Wysoki kontrast w\u0142\u0105czony',contrastOff:'Wysoki kontrast wy\u0142\u0105czony',retryLookup:'Pon\u00f3w wyszukiwanie numeru seryjnego'}\n};\nfunction v23T(){return Object.assign({},V23_BASE_STRINGS,V23_OVERRIDES[CURRENT_LANG]||V23_OVERRIDES.en||{});}\n\ntry{\n  ['field_scan','self_test','workspace_state','field_print','contrast'].forEach(v=>VB_METRIC_ENUM_FIELDS.feature.add(v));\n  ['finish','remove','resume','pause','undo'].forEach(v=>VB_METRIC_ENUM_FIELDS.interaction.add(v));\n  ['field_report'].forEach(v=>VB_METRIC_ENUM_FIELDS.copy_kind.add(v));\n}catch(e){}\n\nfunction v23CapabilitySnapshot(overrides){\n  const o=overrides||{};\n  const secure='secureContext' in o?o.secureContext:(typeof window!=='undefined'?(typeof window.isSecureContext==='boolean'?window.isSecureContext:null):null);\n  const camera='cameraApi' in o?o.cameraApi:!!(typeof navigator!=='undefined'?(navigator.mediaDevices?navigator.mediaDevices.getUserMedia:false):false);\n  const native='barcodeDetector' in o?o.barcodeDetector:(typeof window!=='undefined'?'BarcodeDetector' in window:false);\n  const online='online' in o?o.online:(typeof navigator==='undefined'||navigator.onLine!==false);\n  return {secureContext:secure,cameraApi:camera,barcodeDetector:native,online};\n}\nfunction v23ScannerRoute(overrides){\n  const c=v23CapabilitySnapshot(overrides);\n  if(c.cameraApi?c.barcodeDetector:false)return 'live_native';\n  if(c.cameraApi)return 'live_compat';\n  if(typeof document!=='undefined')return 'photo';\n  return 'manual';\n}\nfunction v23ScannerRouteLabel(route){const T=v23T();return route==='live_native'?T.routeNative:(route==='live_compat'?T.routeCompat:(route==='photo'?T.routePhoto:T.routeUnavailable));}\nfunction v23QueueDecision(value,queue,now,lastValue,lastAt){\n  const code=normalizeV21ScannedValue(value),list=Array.isArray(queue)?queue:[],ts=Number(now)||Date.now();\n  if(!code)return {accept:false,reason:'invalid',value:''};\n  if(list.length>=VB_V23_SCAN_MAX)return {accept:false,reason:'limit',value:code};\n  if(code.length===8?list.includes(code):false)return {accept:false,reason:'duplicate_serial',value:code};\n  if(code===lastValue?ts-Number(lastAt||0)<3000:false)return {accept:false,reason:'rapid_duplicate',value:code};\n  return {accept:true,reason:'ok',value:code};\n}\nfunction v23StorageWorks(){try{const k='__vb23';sessionStorage.setItem(k,'1');sessionStorage.removeItem(k);return true;}catch(e){return false;}}\nfunction v23CurrentState(){\n  const input=document.getElementById('vb-code');\n  return {version:1,raw:input?String(input.value||'').slice(0,5000):'',lang:CURRENT_LANG,compare:[...VB_V21.compareCodes],bulk:[...VB_V21.bulkSelectedCodes],bulkSearch:String(VB_V21.bulkSearch||'').slice(0,100),bulkSort:VB_V21.bulkSort||'status',contrast:!!VB_V23.highContrast,at:Date.now()};\n}\nfunction v23StateRead(){try{const raw=sessionStorage.getItem(VB_V23_STATE_KEY);if(!raw)return null;const s=JSON.parse(raw);if(!s||typeof s.raw!=='string'||Date.now()-Number(s.at||0)>VB_V23_STATE_MAX_AGE_MS){sessionStorage.removeItem(VB_V23_STATE_KEY);return null;}return s;}catch(e){return null;}}\nfunction v23StateSave(){if(VB_V23.restoring)return;try{const snap=v23CurrentState();VB_V23.committedState=snap;sessionStorage.setItem(VB_V23_STATE_KEY,JSON.stringify(snap));}catch(e){}}\nfunction v23PushUndo(){\n  if(VB_V23.restoring)return;let snap;try{snap=VB_V23.committedState?JSON.parse(JSON.stringify(VB_V23.committedState)):v23CurrentState();}catch(e){return;}const last=VB_V23.undo[VB_V23.undo.length-1];\n  if(last?JSON.stringify({...last,at:0})===JSON.stringify({...snap,at:0}):false)return;\n  VB_V23.undo.push(snap);if(VB_V23.undo.length>VB_V23_UNDO_MAX)VB_V23.undo.shift();v23UpdateUndoButton();\n}\nfunction v23UpdateUndoButton(){const b=document.getElementById('vb-v23-undo-btn');if(!b)return;b.disabled=VB_V23.undo.length===0;b.classList.toggle('vb-v23-undo-ready',VB_V23.undo.length>0);}\nfunction v23ApplyStateAfterSearch(state){\n  if(!state)return;const valid=new Set(LAST_RENDERED_GROUPS.filter(g=>g?!g.result.error:false).map(g=>g.result.code));\n  VB_V21.compareCodes=new Set((state.compare||[]).filter(c=>valid.has(c)).slice(0,VB_V21_COMPARE_MAX));\n  VB_V21.bulkSelectedCodes=new Set((state.bulk||[]).filter(c=>valid.has(c)));\n  VB_V21.bulkSearch=String(state.bulkSearch||'').slice(0,100);VB_V21.bulkSort=state.bulkSort||'status';\n  if(document.getElementById('vb-v21-command'))renderV21CommandRows();updateV21CompareVisuals();renderV21CompareDock();\n  const search=document.getElementById('vb-v21-command-search');if(search)search.value=VB_V21.bulkSearch;const sort=document.getElementById('vb-v21-command-sort');if(sort)sort.value=VB_V21.bulkSort;\n  v23SetContrast(!!state.contrast,false);\n}\nfunction v23RestoreSnapshot(state){\n  if(!state){showFormFeedbackToast(v23T().nothingToUndo,false);return;}VB_V23.restoring=true;VB_V23.pendingRestore=state;\n  if(STRINGS[state.lang]){CURRENT_LANG=state.lang;const lang=document.getElementById('vb-lang');if(lang)lang.value=state.lang;applyStrings(state.lang);applyV21Strings();}\n  const input=document.getElementById('vb-code');if(input){input.value=state.raw||'';updateClearBtnVisibility();updateInputMeta();}\n  if(state.raw){Promise.resolve(runSearch(state.raw,'restore')).finally(()=>{VB_V23.restoring=false;v23StateSave();});}\n  else{const result=document.getElementById('vb-result');if(result)result.innerHTML='';LAST_RENDERED_RESULTS=[];LAST_RENDERED_GROUPS=[];resetV21ResultState(false);VB_V23.restoring=false;v23SetContrast(!!state.contrast,false);v23StateSave();}\n}\nfunction v23Undo(){const state=VB_V23.undo.pop();v23UpdateUndoButton();if(!state){showFormFeedbackToast(v23T().nothingToUndo,false);return;}v23RestoreSnapshot(state);vbMetric('feature_used',{feature:'workspace_state',interaction:'undo',language:CURRENT_LANG});}\n\nfunction v23Pulse(kind){\n  try{if(navigator.vibrate)navigator.vibrate(kind==='duplicate'?[20,45,20]:(kind==='error'?[60,40,60]:35));}catch(e){}\n  try{const AC=window.AudioContext||window.webkitAudioContext;if(!AC)return;if(!VB_V23.audio)VB_V23.audio=new AC();const ctx=VB_V23.audio,o=ctx.createOscillator(),g=ctx.createGain();o.frequency.value=kind==='duplicate'?420:(kind==='error'?260:900);g.gain.setValueAtTime(.045,ctx.currentTime);g.gain.exponentialRampToValueAtTime(.001,ctx.currentTime+.09);o.connect(g);g.connect(ctx.destination);o.start();o.stop(ctx.currentTime+.09);}catch(e){}\n}\nfunction v23RenderScanQueue(){\n  const body=document.querySelector('#vb-v21-scan-modal .vb-v21-dialog-body');if(!body)return;let box=document.getElementById('vb-v23-scan-queue');\n  if(!VB_V23.warehouseActive){if(box)box.remove();return;}const T=v23T();if(!box){box=document.createElement('div');box.id='vb-v23-scan-queue';box.className='vb-v23-scan-queue';body.prepend(box);}\n  const chips=VB_V23.scanQueue.length?VB_V23.scanQueue.map((code,i)=>`<span class=\"vb-v23-scan-chip\"><small>${i+1}<\/small>${esc(code)}<button type=\"button\" data-vb-action=\"remove-field-scan\" data-scan-index=\"${i}\" aria-label=\"${esc(T.removeScan)}\">\u00d7<\/button><\/span>`).join(''):`<div class=\"vb-v23-scan-empty\">${esc(T.fieldScanHint)}<\/div>`;\n  box.innerHTML=`<div class=\"vb-v23-scan-queue-head\"><strong>${esc(T.fieldScanTitle)}<\/strong><span class=\"vb-v23-scan-counter\">${esc(T.scanned.replace('{count}',VB_V23.scanQueue.length))} \u00b7 ${VB_V23.scanQueue.length}\/${VB_V23_SCAN_MAX}<\/span><\/div><div class=\"vb-v23-scan-list\">${chips}<\/div><div class=\"vb-v23-scan-queue-actions\"><button type=\"button\" class=\"vb-app-tool vb-app-tool-primary\" data-vb-action=\"finish-field-scan\" ${VB_V23.scanQueue.length?'':'disabled'}>${esc(T.finishScan)}<\/button><button type=\"button\" class=\"vb-app-tool\" data-vb-action=\"clear-field-scan\" ${VB_V23.scanQueue.length?'':'disabled'}>${esc(T.clearScan)}<\/button><\/div>`;\n  box.classList.remove('vb-v23-scan-flash');void box.offsetWidth;box.classList.add('vb-v23-scan-flash');v23UpdateFieldScanButton();\n}\nfunction v23UpdateFieldScanButton(){const b=document.getElementById('vb-v23-field-scan-btn');if(!b)return;const T=v23T();b.innerHTML=`${v21Svg('scan')}<span>${esc(T.fieldScan)}${VB_V23.scanQueue.length?` \u00b7 ${VB_V23.scanQueue.length}`:''}<\/span>`;}\nfunction v23StartFieldScan(){VB_V23.warehouseActive=true;VB_V23.lastScanValue='';VB_V23.lastScanAt=0;openV21Scanner();v23RenderScanQueue();vbMetric('feature_used',{feature:'field_scan',interaction:'open',language:CURRENT_LANG});}\nfunction v23ClearFieldScan(){VB_V23.scanQueue=[];VB_V23.lastScanValue='';VB_V23.lastScanAt=0;v23RenderScanQueue();}\nfunction v23RemoveFieldScan(index){const i=Number(index);if(i>=0?i<VB_V23.scanQueue.length:false){VB_V23.scanQueue.splice(i,1);v23RenderScanQueue();vbMetric('feature_used',{feature:'field_scan',interaction:'remove',language:CURRENT_LANG});}}\nfunction v23FinishFieldScan(){\n  const T=v23T();if(!VB_V23.scanQueue.length){showFormFeedbackToast(T.fieldScanHint,false);return;}const raw=VB_V23.scanQueue.join('\\n');v23PushUndo();VB_V23.warehouseActive=false;stopV21Scanner();closeV21Modal('vb-v21-scan-modal');const input=document.getElementById('vb-code');if(input){input.value=raw;updateClearBtnVisibility();updateInputMeta();}runSearch(raw,'scanner');vbMetric('feature_used',{feature:'field_scan',interaction:'finish',language:CURRENT_LANG,entry_count:VB_V23.scanQueue.length,mode:'bulk'});v23UpdateFieldScanButton();\n}\nfunction v23AcceptBatchScan(raw){\n  const now=Date.now(),d=v23QueueDecision(raw,VB_V23.scanQueue,now,VB_V23.lastScanValue,VB_V23.lastScanAt),T=v23T(),status=document.getElementById('vb-v21-scan-status');\n  if(!d.accept){if(d.reason==='duplicate_serial'){if(status)status.textContent=T.duplicateSerial;v23Pulse('duplicate');}else if(d.reason==='rapid_duplicate'){if(status)status.textContent=T.rapidDuplicate;v23Pulse('duplicate');}else if(d.reason==='limit'){if(status)status.textContent=T.scanLimit.replace('{max}',VB_V23_SCAN_MAX);v23Pulse('error');}return d.reason!=='invalid';}\n  VB_V23.scanQueue.push(d.value);VB_V23.lastScanValue=d.value;VB_V23.lastScanAt=now;if(status)status.textContent=T.scanAdded.replace('{count}',VB_V23.scanQueue.length).replace('{max}',VB_V23_SCAN_MAX);v23Pulse('ok');v23RenderScanQueue();\n  \/\/ Native BarcodeDetector loop returns immediately after a hit; re-arm it after a short cooldown.\n  if(VB_V21.scanDetector?!VB_V21.scanFallbackReader:false){VB_V21.scanFrame=0;setTimeout(()=>{if(VB_V23.warehouseActive?(document.getElementById('vb-v21-scan-video')?!VB_V21.scanFrame:false):false)VB_V21.scanFrame=requestAnimationFrame(scanV21Frame);},650);}\n  return true;\n}\nconst V23_BASE_ACCEPT_SCAN=acceptV21ScannedValue;\nacceptV21ScannedValue=function(raw){return VB_V23.warehouseActive?v23AcceptBatchScan(raw):V23_BASE_ACCEPT_SCAN(raw);};\n\nfunction v23RenderScannerRoute(){const modal=document.getElementById('vb-v21-scan-modal');if(!modal)return;let badge=document.getElementById('vb-v23-scanner-route');const route=v23ScannerRoute();if(!badge){badge=document.createElement('div');badge.id='vb-v23-scanner-route';badge.className='vb-v23-field-badge';const hint=document.getElementById('vb-v21-scan-hint');if(hint)hint.insertAdjacentElement('afterend',badge);}badge.textContent=v23ScannerRouteLabel(route);badge.dataset.state=route==='manual'?'error':(route==='photo'?'warn':'ok');}\nconst V23_BASE_OPEN_SCANNER=openV21Scanner;\nopenV21Scanner=async function(){const promise=V23_BASE_OPEN_SCANNER();v23RenderScannerRoute();v23RenderScanQueue();try{return await promise;}finally{v23RenderScannerRoute();v23RenderScanQueue();}};\nconst V23_BASE_CLOSE_MODAL=closeV21Modal;\ncloseV21Modal=function(id){const result=V23_BASE_CLOSE_MODAL(id);if(id==='vb-v21-scan-modal'){VB_V23.scannerPaused=false;if(VB_V23.warehouseActive){VB_V23.warehouseActive=false;v23UpdateFieldScanButton();}}return result;};\nfunction v23PauseScanner(){\n  const modal=document.getElementById('vb-v21-scan-modal');if(!modal||!modal.classList.contains('vb-open'))return;if(!(VB_V21.scanStream||VB_V21.scanDetector||VB_V21.scanFallbackReader))return;stopV21Scanner();VB_V23.scannerPaused=true;const stage=document.getElementById('vb-v21-scan-stage');if(stage)stage.innerHTML=`<div class=\"vb-v23-resume\"><p>${esc(v23T().cameraPaused)}<\/p><button type=\"button\" class=\"vb-app-tool\" data-vb-action=\"resume-scanner\">${esc(v23T().resumeCamera)}<\/button><\/div>`;vbMetric('feature_used',{feature:'field_scan',interaction:'pause',language:CURRENT_LANG});\n}\nfunction v23ResumeScanner(){VB_V23.scannerPaused=false;openV21Scanner();vbMetric('feature_used',{feature:'field_scan',interaction:'resume',language:CURRENT_LANG});}\n\nfunction v23SetContrast(enabled,save=true){VB_V23.highContrast=!!enabled;const root=document.querySelector('.vb-check');if(root)root.classList.toggle('vb-v23-contrast',VB_V23.highContrast);if(save)v23StateSave();}\nfunction v23ToggleContrast(){v23SetContrast(!VB_V23.highContrast,true);openV23SelfTest();vbMetric('feature_used',{feature:'contrast',interaction:'toggle',language:CURRENT_LANG});}\n\nfunction v23CriticalSelfCheck(){\n  const ids=['vb-code','vb-submit','vb-result','vb-app-toolbar','vb-v21-scan-modal'];const missing=ids.filter(id=>!document.getElementById(id));\n  const functions=[typeof decode==='function',typeof runSearch==='function',typeof openV21Scanner==='function',typeof invokeV21Print==='function'];\n  return {ok:missing.length===0?functions.every(Boolean):false,missing,functions_ok:functions.every(Boolean)};\n}\nfunction v23DeviceReport(){\n  const c=v23CapabilitySnapshot(),self=v23CriticalSelfCheck();let touch=0;try{touch=Number(navigator.maxTouchPoints||0);}catch(e){}\n  return {version:'v23',online:c.online,secure_context:c.secureContext,camera_api:c.cameraApi,barcode_detector:c.barcodeDetector,scanner_route:v23ScannerRoute(),photo_fallback:true,print_api:typeof window.print==='function',session_storage:v23StorageWorks(),touch_points:touch,page_visible:typeof document.visibilityState==='string'?document.visibilityState:'unknown',self_check:self.ok,missing_nodes:self.missing.length};\n}\nfunction v23ReportText(){const d=v23DeviceReport();return ['VARIBOX Checker diagnostics \u2014 field report','Version: '+d.version,'Online: '+d.online,'Secure context: '+d.secure_context,'Live camera API: '+d.camera_api,'BarcodeDetector: '+d.barcode_detector,'Scanner route: '+d.scanner_route,'Photo fallback: '+d.photo_fallback,'Print API: '+d.print_api,'Session storage: '+d.session_storage,'Touch points: '+d.touch_points,'Visibility: '+d.page_visible,'Self-check: '+d.self_check,'Missing critical nodes: '+d.missing_nodes].join('\\n');}\nfunction v23TestItem(label,state,value){return `<div class=\"vb-v23-test\" data-state=\"${state}\"><span>${esc(label)}<\/span><strong>${esc(value)}<\/strong><\/div>`;}\nfunction openV23SelfTest(){\n  const body=document.getElementById('vb-v23-selftest-body');if(!body)return;const T=v23T(),d=v23DeviceReport(),yes=v=>v===true?[T.ok,'ok']:(v===false?[T.unavailable,'error']:[T.limited,'warn']),secure=yes(d.secure_context),cam=yes(d.camera_api),native=d.barcode_detector?[T.ok,'ok']:[T.limited,'warn'],print=yes(d.print_api),storage=yes(d.session_storage),touch=d.touch_points>0?[T.ok,'ok']:[T.limited,'warn'],visible=d.page_visible==='visible'?[T.ok,'ok']:[T.limited,'warn'],net=d.online?[T.ok,'ok']:[T.limited,'warn'],self=d.self_check?[T.ok,'ok']:[T.unavailable,'error'];\n  body.innerHTML=`<div class=\"vb-v23-selftest\"><div class=\"vb-v23-selftest-summary\">${esc(T.fieldTestIntro)}<br><strong>${esc(T.scannerRoute)}:<\/strong> ${esc(v23ScannerRouteLabel(d.scanner_route))}<\/div><div class=\"vb-v23-selftest-grid\">${v23TestItem(T.secureContext,secure[1],secure[0])}${v23TestItem(T.cameraApi,cam[1],cam[0])}${v23TestItem(T.barcodeNative,native[1],native[0])}${v23TestItem(T.photoFallback,'ok',T.ok)}${v23TestItem(T.printApi,print[1],print[0])}${v23TestItem(T.storage,storage[1],storage[0])}${v23TestItem(T.touch,touch[1],touch[0])}${v23TestItem(T.visibility,visible[1],visible[0])}${v23TestItem(T.network,net[1],net[0])}${v23TestItem(T.selfCheck,self[1],self[0])}<\/div><div class=\"vb-v23-selftest-actions\"><button type=\"button\" class=\"vb-app-tool vb-app-tool-primary\" data-vb-action=\"selftest-scanner\">${esc(T.testScanner)}<\/button><button type=\"button\" class=\"vb-app-tool\" data-vb-action=\"selftest-print\">${esc(T.testPrint)}<\/button><button type=\"button\" class=\"vb-app-tool\" data-vb-action=\"toggle-contrast\">${esc(VB_V23.highContrast?T.contrastOff:T.contrastOn)}<\/button><button type=\"button\" class=\"vb-app-tool\" data-vb-action=\"copy-field-report\">${esc(T.copyReport)}<\/button><\/div><pre>${esc(v23ReportText())}<\/pre><\/div>`;\n  document.getElementById('vb-v23-selftest-title').textContent=T.fieldTestTitle;document.getElementById('vb-v23-selftest-intro').textContent=T.fieldTestIntro;v22OpenModal('vb-v23-selftest-modal');vbMetric('feature_used',{feature:'self_test',interaction:'open',language:CURRENT_LANG});\n}\nfunction v23CopyReport(){v22CopyText(v23ReportText(),v22T().copied,'field_report');}\n\nfunction v23PrintFieldLabel(mode){const T=v23T();return mode==='compare'?T.printCompareTitle:(mode==='passport'?T.printPassportTitle:(mode==='diagnostic'?T.printDiagnosticTitle:T.printTitle));}\nfunction v23BuildPrintCard(group){const r=group.result,rows=v22ResultFields(r,CURRENT_LANG),inputs=(group.inputs||[]).filter(Boolean);return `<section class=\"vb-v23-print-card\"><h2>${esc(r.typeName)}<\/h2><div class=\"vb-v23-print-code\">${esc(r.code)}${group.count>1?` \u00b7 \u00d7${group.count}`:''}<\/div><div class=\"vb-v23-print-summary\">${esc(v22ExplainResult(r,CURRENT_LANG))}${inputs.length?`<br><strong>${esc(inputs.length+' '+(inputs[0].length===8?v21T().serials:v21T().articles))}<\/strong>`:''}<\/div><div class=\"vb-v23-print-grid\">${rows.map(([,label,value])=>`<div class=\"vb-v23-print-row\"><small>${esc(label)}<\/small><strong>${esc(value)}<\/strong><\/div>`).join('')}<\/div><\/section>`;}\nfunction v23PreparePrintSheet(mode,groups){\n  let sheet=document.getElementById('vb-v23-print-sheet');if(!sheet){sheet=document.createElement('div');sheet.id='vb-v23-print-sheet';const root=document.querySelector('.vb-check');(root||document.body).appendChild(sheet);}const T=v23T(),date=new Date().toLocaleString();let content='';\n  if(mode==='compare'){\n    const data=v22CompareData();content=`<table class=\"vb-v23-print-compare\"><thead><tr><th>${esc(v21T().passport)}<\/th>${data.groups.map(g=>`<th>${esc(g.result.typeName)}<br>${esc(g.result.code)}<\/th>`).join('')}<\/tr><\/thead><tbody>${data.rows.map(row=>`<tr class=\"${row.diff?'vb-v23-print-diff':''}\"><td>${esc(row.label)}<\/td>${row.values.map(v=>`<td>${esc(v)}<\/td>`).join('')}<\/tr>`).join('')}<\/tbody><\/table>`;\n  }else if(mode==='diagnostic'){\n    content=`<section class=\"vb-v23-print-card\"><h2>${esc(T.fieldTestTitle)}<\/h2><div class=\"vb-v23-print-summary\"><pre>${esc(v23ReportText())}<\/pre><\/div><\/section>`;\n  }else content=(groups||[]).filter(g=>g?!g.result.error:false).map(v23BuildPrintCard).join('');\n  sheet.innerHTML=`<header class=\"vb-v23-print-head\"><div><h1>${esc(v23PrintFieldLabel(mode))}<\/h1><p>VARIBOX Checker<\/p><\/div><div class=\"vb-v23-print-date\">${esc(T.generated)}<br>${esc(date)}<\/div><\/header>${content}<footer class=\"vb-v23-print-foot\">${esc(T.printFooter)}<\/footer>`;\n}\nfunction v23DoPrint(mode,groups){v23PreparePrintSheet(mode,groups);vbMetric('feature_used',{feature:'field_print',interaction:'open',format:'pdf',language:CURRENT_LANG,result_count:(groups||[]).length});return invokeV21Print('vb-v23-printing');}\nfunction v23PrintResults(){return v23DoPrint('results',LAST_RENDERED_GROUPS.filter(g=>!g.result.error));}\nfunction v23PrintPassport(){const g=v21ResultForCode(VB_V22.currentPassportCode);return g?v23DoPrint('passport',[g]):false;}\nfunction v23PrintCompare(){const data=v22CompareData();return data.groups.length>=2?v23DoPrint('compare',data.groups):false;}\nfunction v23PrintSelfTest(){return v23DoPrint('diagnostic',[]);}\nprintV21=v23PrintResults;v22PrintPassport=v23PrintPassport;printV22Compare=v23PrintCompare;\n\nconst V23_BASE_DIAG_OBJECT=v22DiagnosticObject;\nv22DiagnosticObject=function(){return Object.assign({},V23_BASE_DIAG_OBJECT(),v23DeviceReport());};\nv22DiagnosticText=function(){return v23ReportText();};\nconst V23_BASE_OPEN_DIAGNOSTICS=openV22Diagnostics;\nopenV22Diagnostics=function(){V23_BASE_OPEN_DIAGNOSTICS();const body=document.getElementById('vb-v22-diagnostic-body');if(body?!body.querySelector('[data-vb-action=\"open-selftest\"]'):false){const b=document.createElement('button');b.type='button';b.className='vb-app-tool';b.dataset.vbAction='open-selftest';b.textContent=v23T().fieldTest;body.appendChild(b);}};\n\nfunction v23SetPendingRetry(raw,lang){VB_V23.pendingRetry={raw:String(raw||'').slice(0,5000),lang:STRINGS[lang]?lang:CURRENT_LANG,at:Date.now()};try{sessionStorage.setItem(VB_V23_RETRY_KEY,JSON.stringify(VB_V23.pendingRetry));}catch(e){}v23RenderRetryBanner();}\nfunction v23ClearPendingRetry(){VB_V23.pendingRetry=null;try{sessionStorage.removeItem(VB_V23_RETRY_KEY);}catch(e){}const b=document.getElementById('vb-v23-retry-banner');if(b)b.remove();}\nfunction v23LoadPendingRetry(){try{const raw=sessionStorage.getItem(VB_V23_RETRY_KEY);if(!raw)return;const p=JSON.parse(raw);if(p?(typeof p.raw==='string'?Date.now()-Number(p.at||0)<30*60*1000:false):false)VB_V23.pendingRetry=p;}catch(e){}}\nfunction v23RenderRetryBanner(){const root=document.getElementById('vb-result');if(!root)return;let b=document.getElementById('vb-v23-retry-banner');if(!VB_V23.pendingRetry){if(b)b.remove();return;}if(!b){b=document.createElement('div');b.id='vb-v23-retry-banner';b.className='vb-v23-retry-banner';root.prepend(b);}b.innerHTML=`<span>${esc(v23T().retryWaiting)}<\/span><button type=\"button\" data-vb-action=\"retry-live-lookup\">${esc(v23T().retryLookup)}<\/button>`;}\nfunction v23RetryPending(auto){const p=VB_V23.pendingRetry;if(!p||VB_V23.retryInFlight)return;if(navigator.onLine===false){showFormFeedbackToast(v22T().healthOffline,false);return;}const input=document.getElementById('vb-code');if(input?(String(input.value||'').trim()!==String(p.raw||'').trim()?auto:false):false)return;VB_V23.retryInFlight=true;VB_V23.lastRetryAt=Date.now();if(auto)showFormFeedbackToast(v23T().retryOnline,true);Promise.resolve(runSearch(p.raw,'restore')).finally(()=>{VB_V23.retryInFlight=false;});}\nconst V23_BASE_AFTER_SEARCH=v21AfterSearch;\nv21AfterSearch=function(raw,results,source,lang){\n  V23_BASE_AFTER_SEARCH(raw,results,source,lang);\n  if(VB_V23.pendingRestore?String(VB_V23.pendingRestore.raw||'').trim()===String(raw||'').trim():false){const s=VB_V23.pendingRestore;VB_V23.pendingRestore=null;v23ApplyStateAfterSearch(s);if(source==='restore')showFormFeedbackToast(v23T().restoredState,true);}\n  const serviceError=(results||[]).some(r=>r?(r.error?(r.errorType==='service'?String(r.originalInput||'').length===8:false):false):false);if(serviceError)v23SetPendingRetry(raw,lang);else v23ClearPendingRetry();v23StateSave();\n};\n\nfunction v23InjectShell(){\n  const toolbar=document.getElementById('vb-app-toolbar');if(!toolbar||document.getElementById('vb-v23-field-scan-btn'))return;\n  const scanBtn=document.createElement('button');scanBtn.type='button';scanBtn.id='vb-v23-field-scan-btn';scanBtn.className='vb-app-tool';scanBtn.dataset.vbAction='open-field-scan';\n  const undo=document.createElement('button');undo.type='button';undo.id='vb-v23-undo-btn';undo.className='vb-app-tool';undo.dataset.vbAction='undo-field';undo.disabled=true;\n  toolbar.append(scanBtn,undo);\n}\nfunction applyV23Strings(){v23UpdateFieldScanButton();const undo=document.getElementById('vb-v23-undo-btn');if(undo)undo.innerHTML=`<span aria-hidden=\"true\">\u21b6<\/span><span>${esc(v23T().undo)}<\/span>`;document.querySelectorAll('#vb-v23-selftest-modal .vb-v21-dialog-close').forEach(b=>b.setAttribute('aria-label',v21T().close));v23UpdateUndoButton();}\nfunction v23InstallEvents(){\n  const root=document.querySelector('.vb-check');if(!root)return;\n  root.addEventListener('click',event=>{const target=event.target.closest('[data-vb-action]');if(!target)return;const a=target.dataset.vbAction;if(a==='open-field-scan')v23StartFieldScan();else if(a==='finish-field-scan')v23FinishFieldScan();else if(a==='clear-field-scan')v23ClearFieldScan();else if(a==='remove-field-scan')v23RemoveFieldScan(target.dataset.scanIndex);else if(a==='resume-scanner')v23ResumeScanner();else if(a==='undo-field')v23Undo();else if(a==='retry-live-lookup')v23RetryPending(false);},false);\n  root.addEventListener('click',event=>{const t=event.target.closest('button,[data-vb-action]');if(!t)return;const action=t.dataset.vbAction||'';if(t.id==='vb-code-clear'||t.id==='vb-submit'||t.id==='vb-fill-example'||['toggle-compare','clear-compare','bulk-select-all','use-correction','previous-search','fill-search','restore-workspace'].includes(action))v23PushUndo();if(t.id==='vb-code-clear')setTimeout(()=>{try{sessionStorage.removeItem(VB_V23_STATE_KEY);}catch(e){}VB_V23.pendingRestore=null;VB_V23.committedState=null;},0);},true);\n  root.addEventListener('change',event=>{if(event.target?event.target.matches('.vb-v21-bulk-check'):false){v23PushUndo();setTimeout(v23StateSave,0);}},true);\n  root.addEventListener('input',event=>{if(event.target?event.target.id==='vb-v21-command-search':false)setTimeout(v23StateSave,0);});\n  window.addEventListener('online',()=>{if(VB_V23.pendingRetry?Date.now()-VB_V23.lastRetryAt>10000:false)setTimeout(()=>v23RetryPending(true),350);});\n  document.addEventListener('visibilitychange',()=>{if(document.visibilityState==='hidden')v23PauseScanner();else if(VB_V23.scannerPaused){const stage=document.getElementById('vb-v21-scan-stage');if(stage)stage.innerHTML=`<div class=\"vb-v23-resume\"><p>${esc(v23T().cameraPaused)}<\/p><button type=\"button\" class=\"vb-app-tool\" data-vb-action=\"resume-scanner\">${esc(v23T().resumeCamera)}<\/button><\/div>`;}});\n  window.addEventListener('pagehide',()=>{try{stopV21Scanner();}catch(e){}});\n}\nconst V23_BASE_TOGGLE_COMPARE=toggleV21Compare;toggleV21Compare=function(code){const r=V23_BASE_TOGGLE_COMPARE(code);v23StateSave();return r;};\nconst V23_BASE_CLEAR_COMPARE=clearV21Compare;clearV21Compare=function(){const r=V23_BASE_CLEAR_COMPARE();v23StateSave();return r;};\nconst V23_BASE_BULK_SELECTION=toggleV21BulkSelection;toggleV21BulkSelection=function(code,checked){const r=V23_BASE_BULK_SELECTION(code,checked);v23StateSave();return r;};\nconst V23_BASE_SELECT_ALL=v21SelectAllBulk;v21SelectAllBulk=function(){const r=V23_BASE_SELECT_ALL();v23StateSave();return r;};\nconst V23_BASE_APPLY_V21_STRINGS=applyV21Strings;applyV21Strings=function(){V23_BASE_APPLY_V21_STRINGS();applyV23Strings();};\nfunction initV23(){v23InjectShell();const saved=v23StateRead();if(saved){VB_V23.pendingRestore=saved;VB_V23.committedState=saved;v23SetContrast(!!saved.contrast,false);}v23LoadPendingRetry();applyV23Strings();v23InstallEvents();v23RenderRetryBanner();VB_V23.selfCheck=v23CriticalSelfCheck();}\nconst V23_BASE_INIT_V21=initV21App;initV21App=function(){V23_BASE_INIT_V21();initV23();};\n\/\/ v23.1 UX Cleanup: keep advanced capabilities, reveal them only when the current task needs them.\nconst VB_V231_DEBUG = false;\nconst V231_STRINGS={\n  nl:{scanMultiple:'Meerdere containers scannen'},\n  en:{scanMultiple:'Scan multiple containers'},\n  de:{scanMultiple:'Mehrere Container scannen'},\n  fr:{scanMultiple:'Scanner plusieurs conteneurs'},\n  it:{scanMultiple:'Scansiona pi\u00f9 contenitori'},\n  es:{scanMultiple:'Escanear varios contenedores'},\n  pl:{scanMultiple:'Skanuj wiele pojemnik\u00f3w'}\n};\nfunction v231T(){return V231_STRINGS[CURRENT_LANG]||V231_STRINGS.en;}\nfunction v231SuccessfulGroups(){return LAST_RENDERED_GROUPS.filter(g=>g?(g.result?!g.result.error:false):false);}\nfunction v231UniqueConfigurationCount(){return new Set(v231SuccessfulGroups().map(g=>g.result.code).filter(Boolean)).size;}\nfunction v231CanCompare(){return v231UniqueConfigurationCount()>=2;}\nfunction v231RefreshProgressiveUi(){\n  const canCompare=v231CanCompare();\n  document.querySelectorAll('[data-vb-action=\"toggle-compare\"],[data-vb-action=\"compare-selected\"]').forEach(btn=>{btn.hidden=!canCompare;});\n  if(!canCompare?VB_V21.compareCodes.size:false){VB_V21.compareCodes.clear();updateV21CompareVisuals();renderV21CompareDock();}\n  const multi=document.getElementById('vb-v231-scan-multiple');if(multi)multi.hidden=!!VB_V23.warehouseActive;\n}\nfunction v231InstallScannerContextAction(){\n  const body=document.querySelector('#vb-v21-scan-modal .vb-v21-dialog-body');if(!body)return;\n  let wrap=document.getElementById('vb-v231-scan-multiple');\n  if(!wrap){\n    wrap=document.createElement('div');wrap.id='vb-v231-scan-multiple';wrap.className='vb-v231-scan-multiple';\n    wrap.innerHTML='<button type=\"button\" class=\"vb-app-tool\" data-vb-action=\"switch-field-scan\"><\/button>';\n    const privacy=body.querySelector('.vb-v21-privacy-note');if(privacy)privacy.insertAdjacentElement('afterend',wrap);else body.appendChild(wrap);\n  }\n  const btn=wrap.querySelector('button');if(btn)btn.textContent=v231T().scanMultiple;\n  wrap.hidden=!!VB_V23.warehouseActive;\n}\nfunction v231SwitchToFieldScan(){\n  if(VB_V23.warehouseActive)return;\n  VB_V23.warehouseActive=true;VB_V23.lastScanValue='';VB_V23.lastScanAt=0;\n  v23RenderScanQueue();v231RefreshProgressiveUi();\n  vbMetric('feature_used',{feature:'field_scan',interaction:'open',language:CURRENT_LANG});\n}\nfunction v231InstallCleanup(){\n  const root=document.querySelector('.vb-check');if(!root)return;\n  root.addEventListener('click',event=>{const target=event.target.closest('[data-vb-action]');if(target?target.dataset.vbAction==='switch-field-scan':false)v231SwitchToFieldScan();});\n  v231RefreshProgressiveUi();\n}\n\nconst V231_BASE_OPEN_SCANNER=openV21Scanner;\nopenV21Scanner=async function(){v231InstallScannerContextAction();const p=V231_BASE_OPEN_SCANNER();v231InstallScannerContextAction();try{return await p;}finally{v231InstallScannerContextAction();v231RefreshProgressiveUi();}};\nconst V231_BASE_ENHANCE_RESULTS=enhanceV21Results;\nenhanceV21Results=function(results,groups,lang){const r=V231_BASE_ENHANCE_RESULTS(results,groups,lang);v231RefreshProgressiveUi();return r;};\nconst V231_BASE_RENDER_COMMAND_ROWS=renderV21CommandRows;\nrenderV21CommandRows=function(){const r=V231_BASE_RENDER_COMMAND_ROWS();v231RefreshProgressiveUi();return r;};\nconst V231_BASE_APPLY_V21_STRINGS=applyV21Strings;\napplyV21Strings=function(){V231_BASE_APPLY_V21_STRINGS();v231InstallScannerContextAction();v231RefreshProgressiveUi();};\nconst V231_BASE_INIT_V21=initV21App;\ninitV21App=function(){V231_BASE_INIT_V21();v231InstallCleanup();};\n\/\/ Contextual tools: keep the top input area limited to Scan barcode + Scan list.\nfunction v232ArrangeToolbar(){\n  const toolbar=document.getElementById('vb-app-toolbar');\n  const scan=document.getElementById('vb-v21-scan-btn');\n  const scanList=document.getElementById('vb-v23-field-scan-btn');\n  if(!toolbar)return;\n  if(scan?(scanList?scanList.previousElementSibling!==scan:false):false)scan.insertAdjacentElement('afterend',scanList);\n}\nconst V232_BASE_APPLY_V21_STRINGS=applyV21Strings;\napplyV21Strings=function(){V232_BASE_APPLY_V21_STRINGS();v232ArrangeToolbar();};\nfunction v232Install(){v232ArrangeToolbar();}\nconst V232_BASE_INIT_V21=initV21App;\ninitV21App=function(){V232_BASE_INIT_V21();v232Install();};\n\/\/ Bulk spare parts: aggregate matching webshop parts across the current container scope.\nconst V2312_STRINGS={\n  nl:{button:'Reserveonderdelen',title:'Reserveonderdelen',allScope:'Alle containers',selectedScope:'Geselecteerde containers',intro:'Gecombineerd overzicht voor {count} containers. Identieke onderdelen zijn samengevoegd.',fits:'Past op {count} container(s)',onePer:'1 per passende container',add:'Voeg geselecteerde onderdelen toe aan winkelwagen',empty:'Geen bestelbare reserveonderdelen gevonden voor deze selectie.',loading:'Live prijs en voorraad laden\u2026',liveUnavailable:'Live winkelgegevens niet beschikbaar',outOfStock:'Tijdelijk niet op voorraad',total:'Totaal'},\n  en:{button:'Spare parts',title:'Spare parts',allScope:'All containers',selectedScope:'Selected containers',intro:'Combined overview for {count} containers. Identical parts are merged.',fits:'Fits {count} container(s)',onePer:'1 per matching container',add:'Add selected parts to cart',empty:'No orderable spare parts found for this selection.',loading:'Loading live price and stock\u2026',liveUnavailable:'Live shop data unavailable',outOfStock:'Temporarily out of stock',total:'Total'},\n  de:{button:'Ersatzteile',title:'Ersatzteile',allScope:'Alle Container',selectedScope:'Ausgew\u00e4hlte Container',intro:'Kombinierte \u00dcbersicht f\u00fcr {count} Container. Identische Teile sind zusammengefasst.',fits:'Passend f\u00fcr {count} Container',onePer:'1 pro passendem Container',add:'Ausgew\u00e4hlte Teile in den Warenkorb',empty:'Keine bestellbaren Ersatzteile f\u00fcr diese Auswahl gefunden.',loading:'Live-Preis und Bestand werden geladen\u2026',liveUnavailable:'Live-Shopdaten nicht verf\u00fcgbar',outOfStock:'Vor\u00fcbergehend nicht auf Lager',total:'Gesamt'},\n  fr:{button:'Pi\u00e8ces de rechange',title:'Pi\u00e8ces de rechange',allScope:'Tous les conteneurs',selectedScope:'Conteneurs s\u00e9lectionn\u00e9s',intro:'Vue combin\u00e9e pour {count} conteneurs. Les pi\u00e8ces identiques sont regroup\u00e9es.',fits:'Convient \u00e0 {count} conteneur(s)',onePer:'1 par conteneur compatible',add:'Ajouter les pi\u00e8ces s\u00e9lectionn\u00e9es au panier',empty:'Aucune pi\u00e8ce de rechange commandable trouv\u00e9e pour cette s\u00e9lection.',loading:'Chargement du prix et du stock en direct\u2026',liveUnavailable:'Donn\u00e9es boutique en direct indisponibles',outOfStock:'Temporairement en rupture de stock',total:'Total'},\n  it:{button:'Ricambi',title:'Ricambi',allScope:'Tutti i contenitori',selectedScope:'Contenitori selezionati',intro:'Panoramica combinata per {count} contenitori. I ricambi identici sono raggruppati.',fits:'Compatibile con {count} contenitore\/i',onePer:'1 per contenitore compatibile',add:'Aggiungi i ricambi selezionati al carrello',empty:'Nessun ricambio ordinabile trovato per questa selezione.',loading:'Caricamento di prezzo e disponibilit\u00e0\u2026',liveUnavailable:'Dati live del negozio non disponibili',outOfStock:'Temporaneamente esaurito',total:'Totale'},\n  es:{button:'Repuestos',title:'Repuestos',allScope:'Todos los contenedores',selectedScope:'Contenedores seleccionados',intro:'Resumen combinado para {count} contenedores. Las piezas id\u00e9nticas se agrupan.',fits:'Compatible con {count} contenedor(es)',onePer:'1 por contenedor compatible',add:'A\u00f1adir repuestos seleccionados al carrito',empty:'No se encontraron repuestos disponibles para esta selecci\u00f3n.',loading:'Cargando precio y stock en directo\u2026',liveUnavailable:'Datos de tienda en directo no disponibles',outOfStock:'Temporalmente sin existencias',total:'Total'},\n  pl:{button:'Cz\u0119\u015bci zamienne',title:'Cz\u0119\u015bci zamienne',allScope:'Wszystkie pojemniki',selectedScope:'Wybrane pojemniki',intro:'Zbiorczy przegl\u0105d dla {count} pojemnik\u00f3w. Identyczne cz\u0119\u015bci s\u0105 \u0142\u0105czone.',fits:'Pasuje do {count} pojemnika\/pojemnik\u00f3w',onePer:'1 na pasuj\u0105cy pojemnik',add:'Dodaj wybrane cz\u0119\u015bci do koszyka',empty:'Brak cz\u0119\u015bci zamiennych do zam\u00f3wienia dla tego wyboru.',loading:'\u0141adowanie aktualnej ceny i stanu\u2026',liveUnavailable:'Dane sklepu na \u017cywo s\u0105 niedost\u0119pne',outOfStock:'Tymczasowo niedost\u0119pne',total:'Razem'}\n};\nconst VB_V2312={open:false,loading:false,state:new Map(),entries:[]};\nfunction v2312T(){return V2312_STRINGS[CURRENT_LANG]||V2312_STRINGS.en;}\nfunction v2312RoleLabel(role){const S=STRINGS[CURRENT_LANG]||STRINGS.en;return ({zuigbuis:S.partsRoleZuigbuis,sensor:S.partsRoleSensor,deksel:S.partsRoleDeksel,coupler:S.partsRoleCoupler,cap:S.partsRoleCap,sensorConnector:S.partsRoleSensorConnector,sensorCounterConnector:S.partsRoleSensorCounterConnector})[role]||role;}\nfunction v2312ScopeGroups(){\n  const success=LAST_RENDERED_GROUPS.filter(g=>g?(g.result?!g.result.error:false):false);\n  if(VB_V21.bulkSelectedCodes.size){const chosen=success.filter(g=>VB_V21.bulkSelectedCodes.has(g.result.code));if(chosen.length)return {groups:chosen,selected:true};}\n  return {groups:success,selected:false};\n}\nfunction v2312Aggregate(){\n  const scope=v2312ScopeGroups(),map=new Map();let totalContainers=0;\n  scope.groups.forEach(group=>{\n    const count=Math.max(1,Number(group.count)||1);totalContainers+=count;const seen=new Set();\n    getAvailablePartsForResult(group.result).forEach(item=>{\n      if(!item.skus||!item.skus.length)return;const skus=[...item.skus].map(String).filter(Boolean).sort();if(!skus.length)return;const key=skus.join('|');if(seen.has(key))return;seen.add(key);\n      let entry=map.get(key);if(!entry){entry={key,skus,role:item.role,label:item.label||'',family:item.family||'',containerCount:0,configCodes:new Set()};map.set(key,entry);}\n      entry.containerCount+=count;entry.configCodes.add(group.result.code);\n    });\n  });\n  const order={zuigbuis:1,sensor:2,deksel:3,sensorConnector:4,sensorCounterConnector:5,coupler:6,cap:7};\n  const entries=[...map.values()].sort((a,b)=>(order[a.role]||99)-(order[b.role]||99)||String(a.label).localeCompare(String(b.label)));\n  entries.forEach(entry=>{let st=VB_V2312.state.get(entry.key);if(!st){st={checked:false,qty:entry.containerCount,auto:true};VB_V2312.state.set(entry.key,st);}if(st.auto)st.qty=entry.containerCount;st.qty=normalizePartQty(st.qty);});\n  VB_V2312.entries=entries;return {entries,totalContainers,selected:scope.selected};\n}\nfunction v2312EntryIds(entry){const ids=entry.skus.map(s=>(PRODUCT_DATA_CACHE[s]?PRODUCT_DATA_CACHE[s].id:false)?String(PRODUCT_DATA_CACHE[s].id):'').filter(Boolean);return ids.length===entry.skus.length?ids:[];}\nfunction v2312EntryStock(entry){\n  const data=entry.skus.map(s=>PRODUCT_DATA_CACHE[s]);if(data.some(d=>!d))return {ready:false,ok:false};\n  return {ready:true,ok:data.every(d=>d.inStock!==false?d.purchasable!==false:false)};\n}\nfunction v2312UnitPrice(entry){\n  const data=entry.skus.map(s=>PRODUCT_DATA_CACHE[s]);if(data.some(d=>!d||d.priceMinor==null))return null;const sum=data.reduce((n,d)=>n+Number(d.priceMinor||0),0);return {minor:sum,prices:data[0].prices||null};\n}\nfunction v2312Image(entry){for(const sku of entry.skus){const d=PRODUCT_DATA_CACHE[sku];if(d?d.image:false)return d.image;}return '';}\nfunction v2312ProductName(entry){if(entry.skus.length===1){const d=PRODUCT_DATA_CACHE[entry.skus[0]];if(d?d.name:false)return d.name;}return entry.label;}\nfunction v2312StaticIds(entry){const ids=entry.skus.map(s=>SKU_TO_PRODUCT_ID[s]).filter(Boolean);return ids.length===entry.skus.length?ids.map(String):[];}\nfunction v2312Render(){\n  const panel=document.getElementById('vb-v2312-parts-panel');if(!panel)return;const T=v2312T();panel.hidden=!VB_V2312.open;if(!VB_V2312.open)return;\n  const agg=v2312Aggregate();\n  if(VB_V2312.loading){panel.innerHTML=`<div class=\"vb-v2312-loading\">${esc(T.loading)}<\/div>`;return;}\n  if(!agg.entries.length){panel.innerHTML=`<div class=\"vb-v2312-parts-head\"><div><h4>${esc(T.title)}<\/h4><p>${esc(T.intro.replace('{count}',agg.totalContainers))}<\/p><\/div><span class=\"vb-v2312-scope\">${esc(agg.selected?T.selectedScope:T.allScope)}<\/span><\/div><div class=\"vb-v2312-empty\">${esc(T.empty)}<\/div>`;return;}\n  const rows=agg.entries.map(entry=>{\n    const st=VB_V2312.state.get(entry.key),stock=v2312EntryStock(entry),ids=v2312EntryIds(entry),ready=stock.ready?ids.length===entry.skus.length:false,disabled=!ready||!stock.ok;\n    if(disabled)st.checked=false;\n    const img=v2312Image(entry),unit=v2312UnitPrice(entry),linePrice=unit?formatStorePriceMinor(unit.minor*st.qty,unit.prices):'';\n    const warning=!stock.ready||!ids.length?T.liveUnavailable:(!stock.ok?T.outOfStock:'');\n    const staticIds=v2312StaticIds(entry);\n    return `<div class=\"vb-v2312-part-row${disabled?' vb-v2312-unavailable':''}\" data-v2312-key=\"${esc(entry.key)}\" data-skus=\"${esc(entry.skus.join(','))}\" data-product-ids=\"${esc(staticIds.join(','))}\">\n      <label class=\"vb-v2312-check\"><input type=\"checkbox\" class=\"vb-part-checkbox vb-v2312-checkbox\" data-vb-action=\"bulk-part-check\" data-v2312-key=\"${esc(entry.key)}\" ${(st.checked?!disabled:false)?'checked':''} ${disabled?'disabled':''}><\/label>\n      <div class=\"vb-v2312-thumb${img?'':' vb-v2312-thumb-empty'}\">${img?`<img decoding=\"async\" src=\"${esc(img)}\" alt=\"\">`:''}<\/div>\n      <div class=\"vb-v2312-part-copy\"><span class=\"vb-v2312-part-role\">${esc(v2312RoleLabel(entry.role))}<\/span><span class=\"vb-v2312-part-name\">${esc(v2312ProductName(entry))}<\/span><span class=\"vb-v2312-part-fit\">${esc(T.fits.replace('{count}',entry.containerCount))}<\/span>${warning?`<span class=\"vb-v2312-part-warning\">${esc(warning)}<\/span>`:''}<\/div>\n      <div class=\"vb-v2312-part-side\"><div class=\"vb-v2312-qty-wrap\"><div class=\"vb-v2312-qty\"><button type=\"button\" class=\"vb-part-qty-btn\" data-vb-action=\"bulk-part-qty\" data-v2312-key=\"${esc(entry.key)}\" data-delta=\"-1\" ${disabled?'disabled':''}>\u2212<\/button><span class=\"vb-v2312-qty-val\">${st.qty}<\/span><button type=\"button\" class=\"vb-part-qty-btn\" data-vb-action=\"bulk-part-qty\" data-v2312-key=\"${esc(entry.key)}\" data-delta=\"1\" ${disabled?'disabled':''}>+<\/button><\/div><button type=\"button\" class=\"vb-v2312-one-per\" data-vb-action=\"bulk-part-auto\" data-v2312-key=\"${esc(entry.key)}\" data-active=\"${st.auto?'true':'false'}\" ${disabled?'disabled':''}>${esc(T.onePer)}<\/button><\/div><span class=\"vb-v2312-price\">${esc(linePrice||'')}<\/span><\/div>\n    <\/div>`;\n  }).join('');\n  panel.innerHTML=`<div class=\"vb-v2312-parts-head\"><div><h4>${esc(T.title)}<\/h4><p>${esc(T.intro.replace('{count}',agg.totalContainers))}<\/p><\/div><span class=\"vb-v2312-scope\">${esc(agg.selected?T.selectedScope:T.allScope)}<\/span><\/div><div class=\"vb-v2312-parts-list\">${rows}<\/div><div class=\"vb-v2312-footer\"><span id=\"vb-v2312-total\" class=\"vb-v2312-total\"><\/span><button type=\"button\" id=\"vb-v2312-add\" class=\"vb-cta-btn vb-v2312-add\" data-vb-action=\"bulk-parts-add\">${esc(T.add)}<\/button><div id=\"vb-v2312-status\" class=\"vb-email-status vb-v2312-status\" role=\"status\" aria-live=\"polite\"><\/div><\/div>`;\n  v2312UpdateTotal();\n}\nfunction v2312UpdateTotal(){\n  const el=document.getElementById('vb-v2312-total');const add=document.getElementById('vb-v2312-add');if(!el)return;const T=v2312T();let total=0,prices=null,count=0;\n  VB_V2312.entries.forEach(entry=>{const st=VB_V2312.state.get(entry.key);if(!st||!st.checked)return;const unit=v2312UnitPrice(entry);if(unit){total+=unit.minor*st.qty;prices=prices||unit.prices;}count++;});\n  el.textContent=(total>0?prices:false)?`${T.total}: ${formatStorePriceMinor(total,prices)}`:'';if(add)add.disabled=count===0;\n}\nasync function v2312Open(){\n  const panel=document.getElementById('vb-v2312-parts-panel');if(!panel)return;VB_V2312.open=!VB_V2312.open;const btn=document.querySelector('[data-vb-action=\"bulk-parts-open\"]');if(btn)btn.setAttribute('aria-expanded',String(VB_V2312.open));if(!VB_V2312.open){panel.hidden=true;return;}\n  const agg=v2312Aggregate();panel.hidden=false;VB_V2312.loading=true;v2312Render();const skus=[...new Set(agg.entries.flatMap(e=>e.skus))];try{await fetchProductData(skus);}finally{VB_V2312.loading=false;v2312Render();}\n}\nasync function v2312RefreshIfOpen(){if(!VB_V2312.open)return;const agg=v2312Aggregate();const skus=[...new Set(agg.entries.flatMap(e=>e.skus))];const missing=skus.filter(s=>!PRODUCT_DATA_CACHE[s]?!isProductDataMissingFresh(s):false);if(missing.length){VB_V2312.loading=true;v2312Render();try{await fetchProductData(missing);}finally{VB_V2312.loading=false;}}v2312Render();}\nfunction v2312Adjust(key,delta){const entry=VB_V2312.entries.find(e=>e.key===key),st=VB_V2312.state.get(key);if(!entry||!st)return;st.auto=false;st.qty=normalizePartQty(st.qty+Number(delta||0));v2312Render();}\nfunction v2312SetAuto(key){const entry=VB_V2312.entries.find(e=>e.key===key),st=VB_V2312.state.get(key);if(!entry||!st)return;st.auto=true;st.qty=entry.containerCount;v2312Render();}\nfunction v2312SetChecked(key,checked){const st=VB_V2312.state.get(key);if(!st)return;st.checked=!!checked;v2312UpdateTotal();}\nasync function v2312AddToCart(){\n  const T=v2312T(),S=STRINGS[CURRENT_LANG]||STRINGS.en,status=document.getElementById('vb-v2312-status'),btn=document.getElementById('vb-v2312-add');if(!status||!btn)return;const items=[],rows=[];\n  VB_V2312.entries.forEach(entry=>{const st=VB_V2312.state.get(entry.key);if(!st||!st.checked)return;const ids=v2312EntryIds(entry);if(ids.length!==entry.skus.length)return;ids.forEach(id=>items.push({productId:id,quantity:st.qty}));const row=[...document.querySelectorAll('.vb-v2312-part-row')].find(node=>node.dataset.v2312Key===entry.key);if(row)rows.push(row);});\n  if(!items.length){status.className='vb-email-status vb-v2312-status vb-email-status-error';status.textContent=S.partsNoneSelected;return;}\n  await addProductIdsToCart(items,status,btn,S,rows,CURRENT_LANG);\n  rows.forEach(row=>{const key=row.dataset.v2312Key,cb=row.querySelector('.vb-v2312-checkbox'),st=VB_V2312.state.get(key);if(st?cb:false)st.checked=cb.checked;});v2312UpdateTotal();\n}\nfunction v2312InstallCommandUi(){\n  const command=document.getElementById('vb-v21-command');if(!command)return;const foot=command.querySelector('.vb-v21-command-foot');if(!foot)return;\n  const hasParts=v2312SuccessfulPartGroups().length>0;let btn=document.getElementById('vb-v2312-parts-btn');let panel=document.getElementById('vb-v2312-parts-panel');\n  if(!hasParts){if(btn)btn.remove();if(panel)panel.remove();VB_V2312.open=false;return;}\n  if(!btn){btn=document.createElement('button');btn.type='button';btn.id='vb-v2312-parts-btn';btn.className='vb-app-tool vb-v2312-parts-btn';btn.dataset.vbAction='bulk-parts-open';btn.setAttribute('aria-expanded','false');const compare=foot.querySelector('[data-vb-action=\"compare-selected\"]');if(compare)foot.insertBefore(btn,compare);else foot.appendChild(btn);}\n  const selectedCount=VB_V21.bulkSelectedCodes.size;btn.textContent=selectedCount?`${v2312T().button} \u00b7 ${selectedCount}`:v2312T().button;\n  if(!panel){panel=document.createElement('div');panel.id='vb-v2312-parts-panel';panel.className='vb-v2312-parts-panel';panel.hidden=true;foot.insertAdjacentElement('afterend',panel);}\n  if(VB_V2312.open){btn.setAttribute('aria-expanded','true');v2312RefreshIfOpen();}\n}\nfunction v2312SuccessfulPartGroups(){return LAST_RENDERED_GROUPS.filter(g=>g?(g.result?(!g.result.error?getAvailablePartsForResult(g.result).some(i=>i.skus?i.skus.length:false):false):false):false);}\nconst V2312_BASE_ENHANCE_RESULTS=enhanceV21Results;\nenhanceV21Results=function(results,groups,lang){const r=V2312_BASE_ENHANCE_RESULTS(results,groups,lang);VB_V2312.open=false;VB_V2312.entries=[];VB_V2312.state.clear();v2312InstallCommandUi();return r;};\nconst V2312_BASE_RENDER_ROWS=renderV21CommandRows;\nrenderV21CommandRows=function(){const r=V2312_BASE_RENDER_ROWS();v2312InstallCommandUi();return r;};\nconst V2312_BASE_BULK_SELECTION=toggleV21BulkSelection;\ntoggleV21BulkSelection=function(code,checked){const r=V2312_BASE_BULK_SELECTION(code,checked);v2312InstallCommandUi();v2312RefreshIfOpen();return r;};\nconst V2312_BASE_SELECT_ALL=v21SelectAllBulk;\nv21SelectAllBulk=function(){const r=V2312_BASE_SELECT_ALL();v2312RefreshIfOpen();return r;};\nconst V2312_BASE_APPLY_V21_STRINGS=applyV21Strings;\napplyV21Strings=function(){const r=V2312_BASE_APPLY_V21_STRINGS();v2312InstallCommandUi();return r;};\nfunction v2312InstallEvents(){const root=document.querySelector('.vb-check');if(!root)return;root.addEventListener('click',event=>{const t=event.target.closest('[data-vb-action]');if(!t)return;const a=t.dataset.vbAction;if(a==='bulk-parts-open')v2312Open();else if(a==='bulk-part-qty')v2312Adjust(t.dataset.v2312Key,Number(t.dataset.delta));else if(a==='bulk-part-auto')v2312SetAuto(t.dataset.v2312Key);else if(a==='bulk-parts-add')v2312AddToCart();});root.addEventListener('change',event=>{const t=event.target;if(t?t.matches('.vb-v2312-checkbox'):false)v2312SetChecked(t.dataset.v2312Key,t.checked);});}\nconst V2312_BASE_INIT_V21=initV21App;\ninitV21App=function(){V2312_BASE_INIT_V21();v2312InstallEvents();};\n\/\/ Voert een zoekactie uit met zichtbare laadstatus op de knop (relevant\n\/\/ omdat een serienummer-lookup een externe fetch kan triggeren, die anders\n\/\/ onzichtbaar even blijft \"hangen\"). Wordt door alle drie de manieren om een\n\/\/ zoekactie te starten gebruikt (knop, Ctrl\/Cmd+Enter, voorbeeld-knop).\n\/\/ Onthoudt de laatst succesvol gedecodeerde artikel-\/serienummers binnen de sessie (max. 5,\n\/\/ nieuwste eerst, duplicaten verwijderd) en toont ze als klikbare snelkoppelingen boven het\n\/\/ resultaat -- handig bij het vergelijken van een paar varianten zonder steeds opnieuw te typen.\nconst RECENT_CODES_STORAGE_KEY = 'vb_recent_codes';\nconst RECENT_CODES_MAX = 5;\nfunction updateRecentCodes(){}\nfunction renderRecentChips(){}\nfunction fillAndSearch(code){\n  const codeEl = document.getElementById('vb-code');\n  if(codeEl){\n    codeEl.value = code;\n    updateClearBtnVisibility();\n  }\n  runSearch(code, 'recent');\n}\nlet SEARCH_SEQUENCE = 0;\nasync function runSearch(rawValue, source){\n  const searchId = ++SEARCH_SEQUENCE;\n  const searchLang = CURRENT_LANG;\n  const metricSource = source || 'unknown';\n  const metricDescriptor = vbMetricLookupDescriptor(rawValue);\n  const metricStartedAt = (typeof performance !== 'undefined' ? !!performance.now : false) ? performance.now() : Date.now();\n  vbMetric('lookup_started', { ...metricDescriptor, source:metricSource, language:searchLang });\n  const submitBtn = document.getElementById('vb-submit');\n  const codeWrap = document.getElementById('vb-code-wrap');\n  const resultEl = document.getElementById('vb-result');\n  submitBtn.classList.add('vb-loading');\n  submitBtn.disabled = true;\n  if(resultEl) resultEl.setAttribute('aria-busy', 'true');\n  if(codeWrap) codeWrap.classList.add('vb-scanning');\n  const skeletonTimer = setTimeout(() => {\n    if(searchId === SEARCH_SEQUENCE){ if(resultEl) resultEl.innerHTML = buildSkeletonHtml(); }\n  }, 180);\n  try{\n    const results = await parseAndResolveAll(rawValue, searchLang);\n    if(searchId !== SEARCH_SEQUENCE) return;\n    clearTimeout(skeletonTimer);\n    render(results, searchLang);\n    const metricEndedAt = (typeof performance !== 'undefined' ? !!performance.now : false) ? performance.now() : Date.now();\n    vbMetric('lookup_completed', { ...metricDescriptor, ...vbMetricResultSummary(results), source:metricSource, language:searchLang, duration_ms:metricEndedAt - metricStartedAt });\n      const root = document.querySelector('.vb-check');\n      let rootHasSuccess = false;\n      if(root){\n        if(results.some(r => !r.error)) rootHasSuccess = true;\n      }\n      if(rootHasSuccess){\n        root.classList.remove('vb-search-success');\n        void root.offsetWidth;\n        root.classList.add('vb-search-success');\n        setTimeout(() => root.classList.remove('vb-search-success'), 850);\n      }\n    updateRecentCodes(results);\n    if(typeof v21AfterSearch === 'function') v21AfterSearch(rawValue, results, metricSource, searchLang);\n    scrollResultIntoView();\n  } catch(err){\n    if(searchId === SEARCH_SEQUENCE){\n      console.error('[VARIBOX Checker] Onverwachte fout tijdens zoeken:', err);\n      const metricEndedAt = (typeof performance !== 'undefined' ? !!performance.now : false) ? performance.now() : Date.now();\n      vbMetric('lookup_exception', { ...metricDescriptor, source:metricSource, language:searchLang, duration_ms:metricEndedAt - metricStartedAt, error_type:'exception', outcome:'failure' });\n      const S = STRINGS[searchLang];\n      if(resultEl) resultEl.innerHTML = `<div class=\"vb-error\">${rowIcon('warning')}<span>${esc(S.quoteFormMissingForm)}<\/span><\/div>`;\n    }\n  } finally {\n    clearTimeout(skeletonTimer);\n    if(searchId === SEARCH_SEQUENCE){\n      submitBtn.classList.remove('vb-loading');\n      submitBtn.disabled = false;\n      if(resultEl) resultEl.setAttribute('aria-busy', 'false');\n      if(codeWrap) codeWrap.classList.remove('vb-scanning');\n    }\n  }\n}\n\n\/\/ Bouwt een subtiele skelet-placeholder (kaartvorm + shimmer) die alleen\n\/\/ verschijnt als een zoekactie langer dan 180ms duurt \u2014 relevant bij een\n\/\/ serienummer-lookup (externe fetch), niet bij een gewoon artikelnummer\n\/\/ (decodeert vrijwel instant, dus geen onnodig geflikker).\nfunction buildSkeletonHtml(){\n  return `<div class=\"vb-skeleton\">\n    <div class=\"vb-skeleton-head\"><\/div>\n    <div class=\"vb-skeleton-row\"><\/div>\n    <div class=\"vb-skeleton-row\"><\/div>\n    <div class=\"vb-skeleton-row\"><\/div>\n  <\/div>`;\n}\n\n\/\/ Scrollt het resultaat zacht in beeld als het (deels) buiten het zichtbare\n\/\/ gebied valt \u2014 vooral op mobiel verdwijnt het resultaat anders onder de\n\/\/ vouw na het zoeken. Doet niets als het al zichtbaar is, en respecteert de\n\/\/ reduced-motion-instelling van de bezoeker.\nfunction scrollResultIntoView(){\n  const el = document.getElementById('vb-result');\n  if(!el || !el.getBoundingClientRect || !el.firstChild) return;\n  const rect = el.getBoundingClientRect();\n  const viewportHeight = window.innerHeight || document.documentElement.clientHeight;\n  if(rect.top >= 0){\n    if(rect.top < viewportHeight * 0.5) return;\n  }\n  const mq = window.matchMedia ? window.matchMedia('(prefers-reduced-motion: reduce)') : null;\n  const prefersReducedMotion = mq ? mq.matches : false;\n  el.scrollIntoView({ behavior: prefersReducedMotion ? 'auto' : 'smooth', block: 'start' });\n}\n\nfunction updateInputMeta(){\n  const el = document.getElementById('vb-input-meta');\n  const codeEl = document.getElementById('vb-code');\n  const wrap = document.getElementById('vb-code-wrap');\n  if(!el || !codeEl) return;\n  const U = UX_STRINGS[CURRENT_LANG] || UX_STRINGS.en;\n  const raw = codeEl.value || '';\n  const entries = raw.split(\/[\\n,;]+\/).map(v=>v.trim()).filter(Boolean);\n  \/\/ Contextual help: once the user has started entering\/scanning a code, the\n  \/\/ example and bulk hint have already done their job. Bring them back only\n  \/\/ when the input is empty again.\n  const hasInput = raw.trim().length > 0;\n  const exampleEl = document.getElementById('vb-example');\n  const bulkHintEl = document.getElementById('vb-bulk-hint');\n  if(exampleEl) exampleEl.hidden = hasInput;\n  if(bulkHintEl) bulkHintEl.hidden = hasInput;\n  el.className = 'vb-input-meta';\n  if(wrap) wrap.classList.remove('vb-input-ready','vb-input-bulk');\n  if(entries.length === 0){ el.textContent=''; return; }\n  let text='';\n  if(entries.length > 1){\n    text = U.bulkDetected.replace('{count}', Math.min(entries.length, MAX_BULK_CODES));\n    if(typeof classifyV21Entries === 'function'){\n      const C = classifyV21Entries(raw); const T = typeof v21T === 'function' ? v21T() : null;\n      if(T){ const parts=[]; if(C.serials) parts.push(C.serials + ' ' + T.serials); if(C.articles) parts.push(C.articles + ' ' + T.articles); if(C.invalid) parts.push(C.invalid + ' ' + T.invalid); if(parts.length) text += ' \u00b7 ' + parts.join(' \u00b7 '); }\n    }\n    el.classList.add('vb-input-meta-bulk');\n    if(wrap) wrap.classList.add('vb-input-bulk');\n  } else {\n    const value = entries[0].toUpperCase().replace(\/\\s+\/g,'');\n    const articlePrefix = \/^(VB|VC|VI|VK|DT)\/.test(value);\n    const max = articlePrefix || value.length > 8 ? 12 : 8;\n    const kind = max === 12 ? U.articleNumber : U.serialNumber;\n    const n = value.length;\n    text = (n === max ? U.ready : U.progress).replace('{kind}',kind).replace('{n}',n).replace('{max}',max);\n    if(n === max){ el.classList.add('vb-input-meta-ready'); if(wrap) wrap.classList.add('vb-input-ready'); }\n  }\n  el.innerHTML = `<span class=\"vb-input-meta-text\">${esc(text)}<\/span><span class=\"vb-input-shortcut\">${esc(U.enterHint)}<\/span>`;\n}\n\ndocument.getElementById('vb-submit').addEventListener('click', () => {\n  runSearch(document.getElementById('vb-code').value, 'button');\n});\ndocument.getElementById('vb-code').addEventListener('keydown', (e) => {\n  if(e.key !== 'Enter') return;\n  const codeEl = document.getElementById('vb-code');\n  const raw = codeEl.value || '';\n  const alreadyBulk = \/[\\n,;]\/.test(raw);\n  let shouldSearch = false;\n  if(e.ctrlKey){ shouldSearch = true; }\n  else if(e.metaKey){ shouldSearch = true; }\n  else if(!e.shiftKey){ if(!alreadyBulk) shouldSearch = true; }\n  if(shouldSearch){\n    e.preventDefault();\n    runSearch(raw, 'keyboard');\n  }\n});\ndocument.getElementById('vb-fill-example').addEventListener('click', (e) => {\n  e.preventDefault();\n  document.getElementById('vb-code').value = 'VB1001AED709';\n  updateClearBtnVisibility();\n  updateInputMeta();\n  vbMetric('example_used', { source:'example', language:CURRENT_LANG, interaction:'submit' });\n  runSearch('VB1001AED709', 'example');\n});\ndocument.getElementById('vb-lang').addEventListener('change', (e) => {\n  const currentInput = document.getElementById('vb-code').value;\n  initLang(e.target.value);\n  vbMetric('language_changed', { source:'language_change', language:CURRENT_LANG, interaction:'change' });\n  updateInputMeta();\n  if(currentInput.trim()) runSearch(currentInput, 'language_change');\n});\n\nfunction updateClearBtnVisibility(){\n  const codeEl = document.getElementById('vb-code');\n  const clearBtn = document.getElementById('vb-code-clear');\n  if(!codeEl || !clearBtn) return;\n  clearBtn.classList.toggle('vb-visible', codeEl.value.length > 0);\n}\ndocument.getElementById('vb-code').addEventListener('input', () => { updateClearBtnVisibility(); updateInputMeta(); });\ndocument.getElementById('vb-code-clear').addEventListener('click', () => {\n  const codeEl = document.getElementById('vb-code');\n  const descriptorBeforeClear = vbMetricLookupDescriptor(codeEl.value);\n  codeEl.value = '';\n  ++SEARCH_SEQUENCE; \/\/ voorkomt dat een nog lopende serienummerlookup later alsnog het oude resultaat terugzet\n  const resultEl = document.getElementById('vb-result');\n  if(resultEl){ resultEl.innerHTML = ''; resultEl.setAttribute('aria-busy', 'false'); }\n  LAST_RENDERED_RESULTS = [];\n  LAST_RENDERED_GROUPS = [];\n  if(typeof resetV21ResultState === 'function') resetV21ResultState(true);\n  const submitBtn = document.getElementById('vb-submit');\n  if(submitBtn){ submitBtn.classList.remove('vb-loading'); submitBtn.disabled = false; }\n  const codeWrap = document.getElementById('vb-code-wrap');\n  if(codeWrap) codeWrap.classList.remove('vb-scanning');\n  updateClearBtnVisibility();\n  updateInputMeta();\n  vbMetric('input_cleared', { ...descriptorBeforeClear, source:'auto', language:CURRENT_LANG, interaction:'clear' });\n  codeEl.focus();\n});\n\nlet initialLang = detectLang();\nlet initialSharedCode = null;\ntry{\n  const initialParams = new URLSearchParams(window.location.search);\n  const sharedLang = (initialParams.get('vblang') || '').toLowerCase();\n  if(STRINGS[sharedLang]) initialLang = sharedLang;\n  initialSharedCode = initialParams.get('vbcode');\n} catch(e){ \/* URLSearchParams niet beschikbaar -- terugvallen op detectLang() *\/ }\ninitLang(initialLang);\nif(typeof initV21App === 'function') initV21App();\nupdateInputMeta();\nrenderRecentChips();\nlet initialRestore = null;\nif(!initialSharedCode){ if(typeof v21SessionRead === 'function') initialRestore = v21SessionRead(); }\nif(initialRestore){ if(STRINGS[initialRestore.lang]){ CURRENT_LANG = initialRestore.lang; document.getElementById('vb-lang').value = CURRENT_LANG; applyStrings(CURRENT_LANG); if(typeof applyV21Strings === 'function') applyV21Strings(); } }\nvbMetric('checker_ready', { source:initialSharedCode ? 'shared_link' : (initialRestore ? 'restore' : 'auto'), language:CURRENT_LANG, mode:(initialSharedCode || initialRestore) ? 'single' : 'empty' });\n\/\/ Shared links win over session restore. Otherwise restore the previous standalone session locally.\nconst bootCode = initialSharedCode || (initialRestore ? initialRestore.raw : initialRestore);\nif(bootCode){\n  const codeEl = document.getElementById('vb-code');\n  if(codeEl){\n    codeEl.value = bootCode;\n    updateClearBtnVisibility();\n    updateInputMeta();\n    runSearch(bootCode, initialSharedCode ? 'shared_link' : 'restore');\n    if(initialRestore){ if(typeof showFormFeedbackToast === 'function'){ if(typeof v21T === 'function') setTimeout(() => showFormFeedbackToast(v21T().restored, true), 250); } }\n  }\n}\nif(typeof window !== 'undefined') window.addEventListener('popstate', event => {\n  try{\n    const state = (event.state ? event.state.varibox : false) ? event.state : null; const params = new URLSearchParams(window.location.search);\n    const raw = state ? state.raw : (params.get('vbcode') || ''); const lang = (state ? STRINGS[state.lang] : false) ? state.lang : ((params.get('vblang') || '').toLowerCase());\n    if(lang ? STRINGS[lang] : false){ CURRENT_LANG=lang; document.getElementById('vb-lang').value=lang; applyStrings(lang); if(typeof applyV21Strings==='function') applyV21Strings(); }\n    const codeEl=document.getElementById('vb-code'); if(codeEl){codeEl.value=raw;updateClearBtnVisibility();updateInputMeta();}\n    if(raw){ if(typeof VB_V21!=='undefined') VB_V21.suppressUrlUpdate=true; Promise.resolve(runSearch(raw,'history')).finally(()=>{if(typeof VB_V21!=='undefined')VB_V21.suppressUrlUpdate=false;}); }\n    else{ const result=document.getElementById('vb-result'); if(result) result.innerHTML=''; LAST_RENDERED_RESULTS=[]; LAST_RENDERED_GROUPS=[]; if(typeof resetV21ResultState==='function')resetV21ResultState(false); else if(typeof updateV21ToolbarState==='function')updateV21ToolbarState(); }\n  }catch(e){}\n});\ndocument.addEventListener('keydown', e => {\n  if(typeof trapV21ModalFocus==='function'){ if(trapV21ModalFocus(e)) return; }\n  const tag=((e.target?e.target.tagName:e.target)||'').toLowerCase(); const typing=['input','textarea','select'].includes(tag);\n  if(e.key==='\/' ? !typing : false){e.preventDefault();const input=document.getElementById('vb-code');if(input){input.focus();input.select();}}\n  if(e.key==='Escape' ? typeof closeV21Modal==='function' : false){closeV21Modal('vb-v21-compare-modal');closeV21Modal('vb-v21-scan-modal');}\n  if(!typing ? (e.altKey ? ((e.key==='c'||e.key==='C') ? typeof openV21Compare==='function' : false) : false) : false){e.preventDefault();openV21Compare();}\n  if(!typing ? (e.altKey ? ((e.key==='e'||e.key==='E') ? typeof exportV21Csv==='function' : false) : false) : false){e.preventDefault();exportV21Csv(false);}\n});\nconst checkerRoot = document.querySelector('.vb-check');\nif(checkerRoot){\n  checkerRoot.addEventListener('click', event => {\n    const target = event.target.closest('[data-vb-action]');\n    if(!target || !checkerRoot.contains(target)) return;\n    const action = target.dataset.vbAction;\n    const idx = Number(target.dataset.idx);\n    const itemIdx = Number(target.dataset.itemIdx);\n    const delta = Number(target.dataset.delta);\n    if(action === 'part-qty') adjustPartQty(idx, itemIdx, delta);\n    else if(action === 'qty') adjustQty(idx, delta);\n    else if(action === 'toggle-parts') togglePartsPopup(idx);\n    else if(action === 'add-parts') addSelectedPartsToCart(idx);\n    else if(action === 'add-all-parts') addAllSelectedPartsToCart();\n    else if(action === 'copy') copyCode(target.dataset.copyValue || '', target);\n    else if(action === 'fill-search') fillAndSearch(target.dataset.code || '');\n    else if(action === 'toggle-next-step') toggleNextStepForm(target.dataset.formId, target.dataset.otherFormId);\n    else if(action === 'close-form') closeNextStepForm(target.dataset.formId);\n    else if(action === 'toggle-info') toggleInfoPanel(target.dataset.infoId, target);\n    else if(action === 'filter-results') filterResultCards(target.dataset.filter || 'all', target);\n    else if(action === 'toggle-compact') toggleCompactResults(target);\n    else if(action === 'open-scanner') openV21Scanner();\n    else if(action === 'export-all') exportV21Csv(false);\n    else if(action === 'export-selected') exportV21Csv(true);\n    else if(action === 'print-results') printV21();\n    else if(action === 'previous-search') v21PreviousSearch();\n    else if(action === 'toggle-compare') toggleV21Compare(target.dataset.code || '');\n    else if(action === 'open-compare') openV21Compare();\n    else if(action === 'clear-compare') clearV21Compare();\n    else if(action === 'close-modal') closeV21Modal(target.dataset.modalId || '');\n    else if(action === 'bulk-select-all') v21SelectAllBulk();\n    else if(action === 'compare-selected') v21CompareSelected();\n    else if(action === 'view-result'){ const item=document.querySelectorAll('.vb-result-item')[Number(target.dataset.resultIndex)]; if(item){item.classList.remove('vb-filter-hidden');item.scrollIntoView({behavior:(window.matchMedia?window.matchMedia('(prefers-reduced-motion: reduce)').matches:false)?'auto':'smooth',block:'center'});} }\n    else if(action === 'focus-search'){\n      const codeEl = document.getElementById('vb-code');\n      if(codeEl){\n        codeEl.focus(); codeEl.select();\n        let reduced = false;\n        if(window.matchMedia){ reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches; }\n        codeEl.scrollIntoView({behavior:reduced ? 'auto' : 'smooth',block:'center'});\n      }\n    }\n  });\n  checkerRoot.addEventListener('change', event => {\n    const target = event.target;\n    if(target.matches('.vb-part-checkbox[data-vb-action=\"part-checkbox\"]')){\n      onPartCheckboxChange(Number(target.dataset.idx), Number(target.dataset.itemIdx));\n    } else if(target.matches('.vb-qty-input[data-vb-qty-index]')){\n      normalizeQtyInput(Number(target.dataset.vbQtyIndex));\n    } else if(target.matches('.vb-v21-bulk-check[data-vb-action=\"bulk-select\"]')){\n      toggleV21BulkSelection(target.dataset.code || '', target.checked);\n    } else if(target.id === 'vb-v21-command-sort'){\n      VB_V21.bulkSort = target.value || 'status'; renderV21CommandRows();\n    }\n  });\n  checkerRoot.addEventListener('input', event => {\n    const target=event.target; if(target ? target.id==='vb-v21-command-search' : false){ VB_V21.bulkSearch=target.value||''; renderV21CommandRows(); }\n  });\n  checkerRoot.addEventListener('submit', event => {\n    const form = event.target.closest('form[data-vb-form]');\n    if(!form || !checkerRoot.contains(form)) return;\n    event.preventDefault();\n    if(form.dataset.vbForm === 'quote') submitCombinedQuote();\n    else if(form.dataset.vbForm === 'email') submitCombinedEmail();\n  });\n}\n})();\n<\/script>\n\n\n<\/div><\/div><\/div><\/div><\/div><\/div>\n\n\n<p><script>\nvar gform;gform||(document.addEventListener(\"gform_main_scripts_loaded\",function(){gform.scriptsLoaded=!0}),document.addEventListener(\"gform\/theme\/scripts_loaded\",function(){gform.themeScriptsLoaded=!0}),window.addEventListener(\"DOMContentLoaded\",function(){gform.domLoaded=!0}),gform={domLoaded:!1,scriptsLoaded:!1,themeScriptsLoaded:!1,isFormEditor:()=>\"function\"==typeof InitializeEditor,callIfLoaded:function(o){return!(!gform.domLoaded||!gform.scriptsLoaded||!gform.themeScriptsLoaded&&!gform.isFormEditor()||(gform.isFormEditor()&&console.warn(\"The use of gform.initializeOnLoaded() is deprecated in the form editor context and will be removed in Gravity Forms 3.1.\"),o(),0))},initializeOnLoaded:function(o){gform.callIfLoaded(o)||(document.addEventListener(\"gform_main_scripts_loaded\",()=>{gform.scriptsLoaded=!0,gform.callIfLoaded(o)}),document.addEventListener(\"gform\/theme\/scripts_loaded\",()=>{gform.themeScriptsLoaded=!0,gform.callIfLoaded(o)}),window.addEventListener(\"DOMContentLoaded\",()=>{gform.domLoaded=!0,gform.callIfLoaded(o)}))},hooks:{action:{},filter:{}},addAction:function(o,r,e,t){gform.addHook(\"action\",o,r,e,t)},addFilter:function(o,r,e,t){gform.addHook(\"filter\",o,r,e,t)},doAction:function(o){gform.doHook(\"action\",o,arguments)},applyFilters:function(o){return gform.doHook(\"filter\",o,arguments)},removeAction:function(o,r){gform.removeHook(\"action\",o,r)},removeFilter:function(o,r,e){gform.removeHook(\"filter\",o,r,e)},addHook:function(o,r,e,t,n){null==gform.hooks[o][r]&&(gform.hooks[o][r]=[]);var d=gform.hooks[o][r];null==n&&(n=r+\"_\"+d.length),gform.hooks[o][r].push({tag:n,callable:e,priority:t=null==t?10:t})},doHook:function(r,o,e){var t;if(e=Array.prototype.slice.call(e,1),null!=gform.hooks[r][o]&&((o=gform.hooks[r][o]).sort(function(o,r){return o.priority-r.priority}),o.forEach(function(o){\"function\"!=typeof(t=o.callable)&&(t=window[t]),\"action\"==r?t.apply(null,e):e[0]=t.apply(null,e)})),\"filter\"==r)return e[0]},removeHook:function(o,r,t,n){var e;null!=gform.hooks[o][r]&&(e=(e=gform.hooks[o][r]).filter(function(o,r,e){return!!(null!=n&&n!=o.tag||null!=t&&t!=o.priority)}),gform.hooks[o][r]=e)}});\n<\/script>\n\n                <div class='gf_browser_gecko gform_wrapper gravity-theme gform-theme--no-framework' data-form-theme='gravity-theme' data-form-index='0' id='gform_wrapper_15' ><div id='gf_15' class='gform_anchor' tabindex='-1'><\/div><form method='post' enctype='multipart\/form-data' target='gform_ajax_frame_15' id='gform_15'  action='\/es\/wp-json\/wp\/v2\/pages\/73603#gf_15' data-formid='15' novalidate>\n                        <div class='gform-body gform_body'><div id='gform_fields_15' class='gform_fields top_label form_sublabel_above description_above validation_above'><div id=\"field_15_9\" class=\"gfield gfield--type-honeypot gform_validation_container field_sublabel_above gfield--has-description field_description_above field_validation_above gfield_visibility_visible\"  ><label class='gfield_label gform-field-label' for='input_15_9'><span class='gform-field-label__text'>Facebook<\/span><\/label><div class='gfield_description' id='gfield_description_15_9'>Este campo es un campo de validaci\u00f3n y debe quedar sin cambios.<\/div><div class='ginput_container'><input name='input_9' id='input_15_9' type='text' value='' autocomplete='new-password'\/><\/div><\/div><fieldset id=\"field_15_1\" class=\"gfield gfield--type-name gfield--input-type-name gfield--width-full gfield_contains_required field_sublabel_above gfield--no-description field_description_above field_validation_above gfield_visibility_visible\"  ><legend class='gfield_label gform-field-label gfield_label_before_complex' ><span class='gform-field-label__text'>Nombre:<\/span><span class=\"gfield_required\"><span class=\"gfield_required gfield_required_text\">(Obligatorio)<\/span><\/span><\/legend><div class='ginput_complex ginput_container ginput_container--name no_prefix no_first_name no_middle_name no_last_name no_suffix gf_name_has_0 ginput_container_name gform-grid-row' id='input_15_1'>\n                            \n                            \n                            \n                            \n                            \n                        <\/div><\/fieldset><div id=\"field_15_6\" class=\"gfield gfield--type-text gfield--input-type-text gfield--width-full gfield_contains_required field_sublabel_above gfield--no-description field_description_above field_validation_above gfield_visibility_visible\"  ><label class='gfield_label gform-field-label' for='input_15_6'><span class='gform-field-label__text'>Nombre de la empresa:<\/span><span class=\"gfield_required\"><span class=\"gfield_required gfield_required_text\">(Obligatorio)<\/span><\/span><\/label><div class='ginput_container ginput_container_text'><input name='input_6' id='input_15_6' type='text' value='' class='large'     aria-required=\"true\" aria-invalid=\"false\"   \/><\/div><\/div><div id=\"field_15_4\" class=\"gfield gfield--type-phone gfield--input-type-phone gfield--phone-format-international gfield--width-full gfield_contains_required field_sublabel_above gfield--no-description field_description_above field_validation_above gfield_visibility_visible\"  ><label class='gfield_label gform-field-label' for='input_15_4'><span class='gform-field-label__text'>Tel\u00e9fono<\/span><span class=\"gfield_required\"><span class=\"gfield_required gfield_required_text\">(Obligatorio)<\/span><\/span><\/label><div class='ginput_container ginput_container_phone'><input name='input_4' id='input_15_4' type='tel' value='' class='large'   aria-required=\"true\" aria-invalid=\"false\"    \/><\/div><\/div><div id=\"field_15_3\" class=\"gfield gfield--type-email gfield--input-type-email gfield--width-full gfield_contains_required field_sublabel_above gfield--no-description field_description_above field_validation_above gfield_visibility_visible\"  ><label class='gfield_label gform-field-label' for='input_15_3'><span class='gform-field-label__text'>Correo electr\u00f3nico<\/span><span class=\"gfield_required\"><span class=\"gfield_required gfield_required_text\">(Obligatorio)<\/span><\/span><\/label><div class='ginput_container ginput_container_email'>\n                            <input name='input_3' id='input_15_3' type='email' value='' class='large'    aria-required=\"true\" aria-invalid=\"false\"  \/>\n                        <\/div><\/div><div id=\"field_15_7\" class=\"gfield gfield--type-textarea gfield--input-type-textarea gfield--width-full field_sublabel_above gfield--no-description field_description_above field_validation_above gfield_visibility_visible\"  ><label class='gfield_label gform-field-label' for='input_15_7'><span class='gform-field-label__text'>Detalles del resultado<\/span><\/label><div class='ginput_container ginput_container_textarea'><textarea name='input_7' id='input_15_7' class='textarea large'      aria-invalid=\"false\"   rows='10' cols='50'><\/textarea><\/div><\/div><div id=\"field_15_8\" class=\"gfield gfield--type-hidden gfield--input-type-hidden gfield--width-full gform_hidden field_sublabel_above gfield--no-description field_description_above field_validation_above gfield_visibility_visible\"  ><div class='ginput_container ginput_container_text'><input name='input_8' id='input_15_8' type='hidden' class='gform_hidden'  aria-invalid=\"false\" value='' \/><\/div><\/div><\/div><\/div>\n        <div class='gform-footer gform_footer top_label'> <button type='submit' id='gform_submit_button_15' class='gform_button button' onclick='gform.submission.handleButtonClick(this);' data-submission-type='submit' >Enviar<\/button> <input type='hidden' name='gform_ajax' value='form_id=15&amp;title=&amp;description=&amp;tabindex=0&amp;theme=gravity-theme&amp;styles=[]&amp;hash=3dea58a8f394417b8d3c8cecd8a17b3f' \/>\n            <input type='hidden' class='gform_hidden' name='gform_submission_method' data-js='gform_submission_method_15' value='iframe' \/>\n            <input type='hidden' class='gform_hidden' name='gform_theme' data-js='gform_theme_15' id='gform_theme_15' value='gravity-theme' \/>\n            <input type='hidden' class='gform_hidden' name='gform_style_settings' data-js='gform_style_settings_15' id='gform_style_settings_15' value='[]' \/>\n            <input type='hidden' class='gform_hidden' name='is_submit_15' value='1' \/>\n            <input type='hidden' class='gform_hidden' name='gform_submit' value='15' \/>\n            \n            <input type='hidden' class='gform_hidden' name='gform_currency' data-currency='EUR' value='YTJrcVgevDvtuWeqylDWwFdC96RdYcsGJ4oI47mV6GXS1vYZMrRy5xBbgLGG+IUP5vHYx7UEz7JfU55BpFjIBJpLWrdgavpmGj7Ez8lCBKVZGHg=' \/>\n            <input type='hidden' class='gform_hidden' name='gform_unique_id' value='' \/>\n            <input type='hidden' class='gform_hidden' name='state_15' value='WyJ7XCI4XCI6XCIxNzYzMmQ5ZDY5NDQ2YjliN2VmMzBlMzAwZDRhOWMwMFwiLFwiZ2Zvcm1fc3VibWlzc2lvbl9tZXRob2RcIjpbXCJhYTBhNmU0ZDFhNWZhMGYyNTY1NDNhMmNkMTQ3YjlmNlwiLFwiMjA2MmQ1MjZhYWJkM2E0MzQ1YWFkN2E5ZTRlYWViYjRcIixcIjJkNzIzNDNmYTNhYmY1NDg1MGUyNGUxYzRjMTA3M2M1XCJdLFwiZ2Zvcm1fdGhlbWVcIjpcIjY0ODUxZWM5MDFhZDQ2ZGFmMTE5MTc3NzQ5OTJmZmIwXCIsXCJnZm9ybV9zdHlsZV9zZXR0aW5nc1wiOlwiYzc2ODk2ZDIxY2U0MmQxYjgzZGUwOTg5ZmMxYWI0NzRcIixcImZvcm1faWRcIjpcImU5OTgwZGRmODM3NzlhODFiY2NmYjBlNjRkMDU1ZGE0XCIsXCJ1cmxcIjpcIjBhMTgyNzU4NTdlMjhhM2I0ZWFmOTAyMDVkOWU2ZWQ1XCIsXCJzdGF0ZV90aW1lc3RhbXBcIjpcIjcxMjgxNjI1NjAwOWY4ZmQ4OTdlNGJkOTVhY2Y5MDYyXCJ9IiwiZTE2NjgzMzhlZGQyNTdmZjMwN2JlYmJkMmNmMzE2ZTUiLDE3OTEwODUxMTFd' \/>\n            <input type='hidden' autocomplete='off' class='gform_hidden' name='gform_target_page_number_15' id='gform_target_page_number_15' value='0' \/>\n            <input type='hidden' autocomplete='off' class='gform_hidden' name='gform_source_page_number_15' id='gform_source_page_number_15' value='1' \/>\n            <input type='hidden' name='gform_field_values' value='' \/>\n            \n        <\/div>\n                        <\/form>\n                        <\/div>\n\t\t                <iframe style='display:none;width:0px;height:0px;' src='about:blank' name='gform_ajax_frame_15' id='gform_ajax_frame_15' title='Este iframe contiene la l\u00f3gica necesaria para gestionar formularios con ajax activado.'><\/iframe>\n\t\t                <script>\ngform.initializeOnLoaded( function() {jQuery('#gform_ajax_frame_15').on('load',function(){var contents = jQuery(this).contents().find('*').html();var is_postback = contents.indexOf('GF_AJAX_POSTBACK') >= 0;if(!is_postback){return;}var form_content = jQuery(this).contents().find('#gform_wrapper_15');var is_confirmation = jQuery(this).contents().find('#gform_confirmation_wrapper_15').length > 0;var is_redirect = contents.indexOf('gformRedirect(){') >= 0;var is_form = form_content.length > 0 && ! is_redirect && ! is_confirmation;var mt = parseInt(jQuery('html').css('margin-top'), 10) + parseInt(jQuery('body').css('margin-top'), 10) + 100;if(is_form){jQuery('#gform_wrapper_15').html(form_content.html());if(form_content.hasClass('gform_validation_error')){jQuery('#gform_wrapper_15').addClass('gform_validation_error');} else {jQuery('#gform_wrapper_15').removeClass('gform_validation_error');}setTimeout( function() { \/* delay the scroll by 50 milliseconds to fix a bug in chrome *\/ jQuery(document).scrollTop(jQuery('#gform_wrapper_15').offset().top - mt); }, 50 );var current_page = jQuery('#gform_source_page_number_15').val();jQuery(document).trigger('gform_page_loaded', [15, current_page]);window['gf_submitting_15'] = false;}else if(!is_redirect){var confirmation_content = jQuery(this).contents().find('.GF_AJAX_POSTBACK').html();if(!confirmation_content){confirmation_content = contents;}jQuery('#gform_wrapper_15').replaceWith(confirmation_content);jQuery(document).scrollTop(jQuery('#gf_15').offset().top - mt);jQuery(document).trigger('gform_confirmation_loaded', [15]);window['gf_submitting_15'] = false;wp.a11y.speak(jQuery('#gform_confirmation_message_15').text());}else{jQuery('#gform_15').append(contents);if(window['gformRedirect']) {gformRedirect();}}jQuery(document).trigger(\"gform_pre_post_render\", [{ formId: \"15\", currentPage: \"current_page\", abort: function() { this.preventDefault(); } }]);        if (event && event.defaultPrevented) {                return;        }        const gformWrapperDiv = document.getElementById( \"gform_wrapper_15\" );        if ( gformWrapperDiv ) {            const visibilitySpan = document.createElement( \"span\" );            visibilitySpan.id = \"gform_visibility_test_15\";            gformWrapperDiv.insertAdjacentElement( \"afterend\", visibilitySpan );        }        const visibilityTestDiv = document.getElementById( \"gform_visibility_test_15\" );        let postRenderFired = false;        function triggerPostRender() {            if ( postRenderFired ) {                return;            }            postRenderFired = true;            gform.core.triggerPostRenderEvents( 15, current_page );            if ( visibilityTestDiv ) {                visibilityTestDiv.parentNode.removeChild( visibilityTestDiv );            }        }        function debounce( func, wait, immediate ) {            var timeout;            return function() {                var context = this, args = arguments;                var later = function() {                    timeout = null;                    if ( !immediate ) func.apply( context, args );                };                var callNow = immediate && !timeout;                clearTimeout( timeout );                timeout = setTimeout( later, wait );                if ( callNow ) func.apply( context, args );            };        }        const debouncedTriggerPostRender = debounce( function() {            triggerPostRender();        }, 200 );        if ( visibilityTestDiv && visibilityTestDiv.offsetParent === null ) {            const observer = new MutationObserver( ( mutations ) => {                mutations.forEach( ( mutation ) => {                    if ( mutation.type === 'attributes' && visibilityTestDiv.offsetParent !== null ) {                        debouncedTriggerPostRender();                        observer.disconnect();                    }                });            });            observer.observe( document.body, {                attributes: true,                childList: false,                subtree: true,                attributeFilter: [ 'style', 'class' ],            });        } else {            triggerPostRender();        }    } );} );\n<\/script>\n<br \/>\n\n                <div class='gf_browser_gecko gform_wrapper gravity-theme gform-theme--no-framework' data-form-theme='gravity-theme' data-form-index='0' id='gform_wrapper_13' ><div id='gf_13' class='gform_anchor' tabindex='-1'><\/div><form method='post' enctype='multipart\/form-data' target='gform_ajax_frame_13' id='gform_13'  action='\/es\/wp-json\/wp\/v2\/pages\/73603#gf_13' data-formid='13' novalidate>\n                        <div class='gform-body gform_body'><div id='gform_fields_13' class='gform_fields top_label form_sublabel_below description_below validation_below'><div id=\"field_13_16\" class=\"gfield gfield--type-honeypot gform_validation_container field_sublabel_below gfield--has-description field_description_below field_validation_below gfield_visibility_visible\"  ><label class='gfield_label gform-field-label' for='input_13_16'><span class='gform-field-label__text'>Email<\/span><\/label><div class='ginput_container'><input name='input_16' id='input_13_16' type='text' value='' autocomplete='new-password'\/><\/div><div class='gfield_description' id='gfield_description_13_16'>Este campo es un campo de validaci\u00f3n y debe quedar sin cambios.<\/div><\/div><div id=\"field_13_12\" class=\"gfield gfield--type-text gfield--input-type-text gfield--width-full gfield_contains_required field_sublabel_below gfield--no-description field_description_below field_validation_below gfield_visibility_visible\"  ><label class='gfield_label gform-field-label' for='input_13_12'><span class='gform-field-label__text'>Name:<\/span><span class=\"gfield_required\"><span class=\"gfield_required gfield_required_text\">(Obligatorio)<\/span><\/span><\/label><div class='ginput_container ginput_container_text'><input name='input_12' id='input_13_12' type='text' value='' class='large'     aria-required=\"true\" aria-invalid=\"false\"   \/><\/div><\/div><div id=\"field_13_3\" class=\"gfield gfield--type-text gfield--input-type-text gfield--width-full gfield_contains_required field_sublabel_below gfield--no-description field_description_below field_validation_below gfield_visibility_visible\"  ><label class='gfield_label gform-field-label' for='input_13_3'><span class='gform-field-label__text'>Company<\/span><span class=\"gfield_required\"><span class=\"gfield_required gfield_required_text\">(Obligatorio)<\/span><\/span><\/label><div class='ginput_container ginput_container_text'><input name='input_3' id='input_13_3' type='text' value='' class='large'     aria-required=\"true\" aria-invalid=\"false\"   \/><\/div><\/div><div id=\"field_13_4\" class=\"gfield gfield--type-phone gfield--input-type-phone gfield--phone-format-international gfield--width-full gfield_contains_required field_sublabel_below gfield--no-description field_description_below field_validation_below gfield_visibility_visible\"  ><label class='gfield_label gform-field-label' for='input_13_4'><span class='gform-field-label__text'>Telephone<\/span><span class=\"gfield_required\"><span class=\"gfield_required gfield_required_text\">(Obligatorio)<\/span><\/span><\/label><div class='ginput_container ginput_container_phone'><input name='input_4' id='input_13_4' type='tel' value='' class='large'   aria-required=\"true\" aria-invalid=\"false\"    \/><\/div><\/div><div id=\"field_13_5\" class=\"gfield gfield--type-email gfield--input-type-email gfield--width-full gfield_contains_required field_sublabel_below gfield--no-description field_description_below field_validation_below gfield_visibility_visible\"  ><label class='gfield_label gform-field-label' for='input_13_5'><span class='gform-field-label__text'>Email<\/span><span class=\"gfield_required\"><span class=\"gfield_required gfield_required_text\">(Obligatorio)<\/span><\/span><\/label><div class='ginput_container ginput_container_email'>\n                            <input name='input_5' id='input_13_5' type='email' value='' class='large'    aria-required=\"true\" aria-invalid=\"false\"  \/>\n                        <\/div><\/div><div id=\"field_13_14\" class=\"gfield gfield--type-number gfield--input-type-number gfield--width-full field_sublabel_below gfield--no-description field_description_below field_validation_below gfield_visibility_visible\"  ><label class='gfield_label gform-field-label' for='input_13_14'><span class='gform-field-label__text'>Quantity:<\/span><\/label><div class='ginput_container ginput_container_number'><input name='input_14' id='input_13_14' type='text' step='any'   value='' class='large'      aria-invalid=\"false\"  \/><\/div><\/div><div id=\"field_13_13\" class=\"gfield gfield--type-textarea gfield--input-type-textarea gfield--width-full field_sublabel_below gfield--no-description field_description_below field_validation_below gfield_visibility_visible\"  ><label class='gfield_label gform-field-label' for='input_13_13'><span class='gform-field-label__text'>Message:<\/span><\/label><div class='ginput_container ginput_container_textarea'><textarea name='input_13' id='input_13_13' class='textarea large'      aria-invalid=\"false\"   rows='10' cols='50'><\/textarea><\/div><\/div><div id=\"field_13_15\" class=\"gfield gfield--type-hidden gfield--input-type-hidden gfield--width-full gform_hidden field_sublabel_below gfield--no-description field_description_below field_validation_below gfield_visibility_visible\"  ><div class='ginput_container ginput_container_text'><input name='input_15' id='input_13_15' type='hidden' class='gform_hidden'  aria-invalid=\"false\" value='' \/><\/div><\/div><\/div><\/div>\n        <div class='gform-footer gform_footer top_label'> <button type='submit' id='gform_submit_button_13' class='gform_button button' onclick='gform.submission.handleButtonClick(this);' data-submission-type='submit' >Request quote<\/button> <input type='hidden' name='gform_ajax' value='form_id=13&amp;title=&amp;description=&amp;tabindex=0&amp;theme=gravity-theme&amp;styles=[]&amp;hash=5963588e91f677ffce39cba42079fde9' \/>\n            <input type='hidden' class='gform_hidden' name='gform_submission_method' data-js='gform_submission_method_13' value='iframe' \/>\n            <input type='hidden' class='gform_hidden' name='gform_theme' data-js='gform_theme_13' id='gform_theme_13' value='gravity-theme' \/>\n            <input type='hidden' class='gform_hidden' name='gform_style_settings' data-js='gform_style_settings_13' id='gform_style_settings_13' value='[]' \/>\n            <input type='hidden' class='gform_hidden' name='is_submit_13' value='1' \/>\n            <input type='hidden' class='gform_hidden' name='gform_submit' value='13' \/>\n            \n            <input type='hidden' class='gform_hidden' name='gform_currency' data-currency='EUR' value='cgcSF6zJvnr3uMV5pqPfQY\/oCl5ZwIe1w+U+DU2HdX40nwxqz068DBNJC+ShTYGHUACGwtKKzqHcsNpFhYAM2d86RxM3Y9RqgsNqZHcoe9p2sks=' \/>\n            <input type='hidden' class='gform_hidden' name='gform_unique_id' value='' \/>\n            <input type='hidden' class='gform_hidden' name='state_13' value='WyJ7XCIxNVwiOlwiMTc2MzJkOWQ2OTQ0NmI5YjdlZjMwZTMwMGQ0YTljMDBcIixcImdmb3JtX3N1Ym1pc3Npb25fbWV0aG9kXCI6W1wiYWEwYTZlNGQxYTVmYTBmMjU2NTQzYTJjZDE0N2I5ZjZcIixcIjIwNjJkNTI2YWFiZDNhNDM0NWFhZDdhOWU0ZWFlYmI0XCIsXCIyZDcyMzQzZmEzYWJmNTQ4NTBlMjRlMWM0YzEwNzNjNVwiXSxcImdmb3JtX3RoZW1lXCI6XCI2NDg1MWVjOTAxYWQ0NmRhZjExOTE3Nzc0OTkyZmZiMFwiLFwiZ2Zvcm1fc3R5bGVfc2V0dGluZ3NcIjpcImM3Njg5NmQyMWNlNDJkMWI4M2RlMDk4OWZjMWFiNDc0XCIsXCJmb3JtX2lkXCI6XCI4OTM3MDUwMTA4ZTM4YzFjOWQ0MDY1ZGRjZDIzMDE5MFwiLFwidXJsXCI6XCIwYTE4Mjc1ODU3ZTI4YTNiNGVhZjkwMjA1ZDllNmVkNVwiLFwic3RhdGVfdGltZXN0YW1wXCI6XCI3MTI4MTYyNTYwMDlmOGZkODk3ZTRiZDk1YWNmOTA2MlwifSIsImE3ZmU5NjhhYWNiNDRhMDYxNDgzNDhhYTEzYTYxNzVlIiwxNzkxMDg1MTExXQ==' \/>\n            <input type='hidden' autocomplete='off' class='gform_hidden' name='gform_target_page_number_13' id='gform_target_page_number_13' value='0' \/>\n            <input type='hidden' autocomplete='off' class='gform_hidden' name='gform_source_page_number_13' id='gform_source_page_number_13' value='1' \/>\n            <input type='hidden' name='gform_field_values' value='' \/>\n            \n        <\/div>\n                        <\/form>\n                        <\/div>\n\t\t                <iframe style='display:none;width:0px;height:0px;' src='about:blank' name='gform_ajax_frame_13' id='gform_ajax_frame_13' title='Este iframe contiene la l\u00f3gica necesaria para gestionar formularios con ajax activado.'><\/iframe>\n\t\t                <script>\ngform.initializeOnLoaded( function() {jQuery('#gform_ajax_frame_13').on('load',function(){var contents = jQuery(this).contents().find('*').html();var is_postback = contents.indexOf('GF_AJAX_POSTBACK') >= 0;if(!is_postback){return;}var form_content = jQuery(this).contents().find('#gform_wrapper_13');var is_confirmation = jQuery(this).contents().find('#gform_confirmation_wrapper_13').length > 0;var is_redirect = contents.indexOf('gformRedirect(){') >= 0;var is_form = form_content.length > 0 && ! is_redirect && ! is_confirmation;var mt = parseInt(jQuery('html').css('margin-top'), 10) + parseInt(jQuery('body').css('margin-top'), 10) + 100;if(is_form){jQuery('#gform_wrapper_13').html(form_content.html());if(form_content.hasClass('gform_validation_error')){jQuery('#gform_wrapper_13').addClass('gform_validation_error');} else {jQuery('#gform_wrapper_13').removeClass('gform_validation_error');}setTimeout( function() { \/* delay the scroll by 50 milliseconds to fix a bug in chrome *\/ jQuery(document).scrollTop(jQuery('#gform_wrapper_13').offset().top - mt); }, 50 );var current_page = jQuery('#gform_source_page_number_13').val();jQuery(document).trigger('gform_page_loaded', [13, current_page]);window['gf_submitting_13'] = false;}else if(!is_redirect){var confirmation_content = jQuery(this).contents().find('.GF_AJAX_POSTBACK').html();if(!confirmation_content){confirmation_content = contents;}jQuery('#gform_wrapper_13').replaceWith(confirmation_content);jQuery(document).scrollTop(jQuery('#gf_13').offset().top - mt);jQuery(document).trigger('gform_confirmation_loaded', [13]);window['gf_submitting_13'] = false;wp.a11y.speak(jQuery('#gform_confirmation_message_13').text());}else{jQuery('#gform_13').append(contents);if(window['gformRedirect']) {gformRedirect();}}jQuery(document).trigger(\"gform_pre_post_render\", [{ formId: \"13\", currentPage: \"current_page\", abort: function() { this.preventDefault(); } }]);        if (event && event.defaultPrevented) {                return;        }        const gformWrapperDiv = document.getElementById( \"gform_wrapper_13\" );        if ( gformWrapperDiv ) {            const visibilitySpan = document.createElement( \"span\" );            visibilitySpan.id = \"gform_visibility_test_13\";            gformWrapperDiv.insertAdjacentElement( \"afterend\", visibilitySpan );        }        const visibilityTestDiv = document.getElementById( \"gform_visibility_test_13\" );        let postRenderFired = false;        function triggerPostRender() {            if ( postRenderFired ) {                return;            }            postRenderFired = true;            gform.core.triggerPostRenderEvents( 13, current_page );            if ( visibilityTestDiv ) {                visibilityTestDiv.parentNode.removeChild( visibilityTestDiv );            }        }        function debounce( func, wait, immediate ) {            var timeout;            return function() {                var context = this, args = arguments;                var later = function() {                    timeout = null;                    if ( !immediate ) func.apply( context, args );                };                var callNow = immediate && !timeout;                clearTimeout( timeout );                timeout = setTimeout( later, wait );                if ( callNow ) func.apply( context, args );            };        }        const debouncedTriggerPostRender = debounce( function() {            triggerPostRender();        }, 200 );        if ( visibilityTestDiv && visibilityTestDiv.offsetParent === null ) {            const observer = new MutationObserver( ( mutations ) => {                mutations.forEach( ( mutation ) => {                    if ( mutation.type === 'attributes' && visibilityTestDiv.offsetParent !== null ) {                        debouncedTriggerPostRender();                        observer.disconnect();                    }                });            });            observer.observe( document.body, {                attributes: true,                childList: false,                subtree: true,                attributeFilter: [ 'style', 'class' ],            });        } else {            triggerPostRender();        }    } );} );\n<\/script>\n<\/p>\n\n\n\n<div class=\"wp-block-ugb-heading ugb-heading wow animate__animated animate__fadeIn ugb-3c8eb5b ugb-main-block\"><style>.ugb-3c8eb5b .ugb-heading__title{text-align:left;margin-bottom:24px !important}.ugb-3c8eb5b .ugb-heading__subtitle{margin-bottom:24px !important}.ugb-3c8eb5b .ugb-inner-block{text-align:left}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><h2 class=\"ugb-heading__title\">Preguntas frecuentes<\/h2><p class=\"ugb-heading__subtitle\">Estas son algunas de las preguntas que recibimos con m\u00e1s frecuencia sobre la herramienta de verificaci\u00f3n \u2014 despliegue cualquier tema para obtener m\u00e1s detalles.<\/p><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-accordion ugb-accordion wow animate__animated animate__fadeIn ugb-b682575 ugb-accordion--v2 ugb-accordion--design-basic ugb-main-block\" aria-expanded=\"false\"><style>.ugb-b682575 .ugb-accordion__heading{border-radius:8px !important}.ugb-b682575 .ugb-accordion__arrow{width:17px !important;height:17px !important}@media screen and (min-width:768px){.ugb-b682575.ugb-accordion{margin-bottom:12px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-accordion__item\"><div class=\"ugb-accordion__heading\" role=\"button\" tabindex=\"0\"><h6 class=\"ugb-accordion__title\">\u00bfQu\u00e9 productos VARIBOX cubre esta herramienta de verificaci\u00f3n?<\/h6><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 20 20\" class=\"ugb-accordion__arrow\" width=\"20\" height=\"20\"><path d=\"M16.7 3.3L10 10 3.3 3.4 0 6.7l10 10v-.1l10-9.9z\"><\/path><\/svg><\/div><div class=\"ugb-accordion__content\" role=\"region\"><div class=\"ugb-accordion__content-inner\">\n<p class=\"wp-block-paragraph\">Esta herramienta decodifica los n\u00fameros de art\u00edculo de VARIBOX FC 1000, FC 800, CC 250 y Drumtainer. Para otros productos de nuestra gama (como Single Containment), p\u00f3ngase en contacto con el Servicio de Atenci\u00f3n al Cliente \u2014 estaremos encantados de ayudarle.<\/p>\n<\/div><\/div><\/div><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-accordion ugb-accordion wow animate__animated animate__fadeIn ugb-ec87a17 ugb-accordion--v2 ugb-accordion--design-basic ugb-main-block\" aria-expanded=\"false\"><style>.ugb-ec87a17 .ugb-accordion__heading{border-radius:8px !important}.ugb-ec87a17 .ugb-accordion__arrow{width:17px !important;height:17px !important}@media screen and (min-width:768px){.ugb-ec87a17.ugb-accordion{margin-bottom:12px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-accordion__item\"><div class=\"ugb-accordion__heading\" role=\"button\" tabindex=\"0\"><h6 class=\"ugb-accordion__title\">Mi n\u00famero de art\u00edculo no se reconoce, \u00bfqu\u00e9 hago ahora?<\/h6><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 20 20\" class=\"ugb-accordion__arrow\" width=\"20\" height=\"20\"><path d=\"M16.7 3.3L10 10 3.3 3.4 0 6.7l10 10v-.1l10-9.9z\"><\/path><\/svg><\/div><div class=\"ugb-accordion__content\" role=\"region\"><div class=\"ugb-accordion__content-inner\">\n<p class=\"wp-block-paragraph\">Compruebe primero que ha introducido los 12 caracteres completos, sin espacios. \u00bfSigue sin reconocerse? P\u00f3ngase en contacto con el Servicio de Atenci\u00f3n al Cliente de VARIBOX y le ayudaremos.<\/p>\n<\/div><\/div><\/div><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-accordion ugb-accordion wow animate__animated animate__fadeIn ugb-1ac826a ugb-accordion--v2 ugb-accordion--design-basic ugb-main-block\" aria-expanded=\"false\"><style>.ugb-1ac826a .ugb-accordion__heading{border-radius:8px !important}.ugb-1ac826a .ugb-accordion__arrow{width:17px !important;height:17px !important}@media screen and (min-width:768px){.ugb-1ac826a.ugb-accordion{margin-bottom:12px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-accordion__item\"><div class=\"ugb-accordion__heading\" role=\"button\" tabindex=\"0\"><h6 class=\"ugb-accordion__title\">\u00bfQu\u00e9 significa \u00abConnect+\u00bb en mi resultado?<\/h6><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 20 20\" class=\"ugb-accordion__arrow\" width=\"20\" height=\"20\"><path d=\"M16.7 3.3L10 10 3.3 3.4 0 6.7l10 10v-.1l10-9.9z\"><\/path><\/svg><\/div><div class=\"ugb-accordion__content\" role=\"region\"><div class=\"ugb-accordion__content-inner\">\n<p class=\"wp-block-paragraph\">Connect+ significa que su VARIBOX est\u00e1 equipado con el sensor Pack AI, que permite controlar de forma remota el nivel de llenado y la ubicaci\u00f3n.<\/p>\n<\/div><\/div><\/div><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-accordion ugb-accordion wow animate__animated animate__fadeIn ugb-6fce484 ugb-accordion--v2 ugb-accordion--design-basic ugb-main-block\" aria-expanded=\"false\"><style>.ugb-6fce484 .ugb-accordion__heading{border-radius:8px !important}.ugb-6fce484 .ugb-accordion__arrow{width:17px !important;height:17px !important}@media screen and (min-width:768px){.ugb-6fce484.ugb-accordion{margin-bottom:12px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-accordion__item\"><div class=\"ugb-accordion__heading\" role=\"button\" tabindex=\"0\"><h6 class=\"ugb-accordion__title\">Se muestran dos posibles resultados, \u00bfqu\u00e9 significa esto?<\/h6><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 20 20\" class=\"ugb-accordion__arrow\" width=\"20\" height=\"20\"><path d=\"M16.7 3.3L10 10 3.3 3.4 0 6.7l10 10v-.1l10-9.9z\"><\/path><\/svg><\/div><div class=\"ugb-accordion__content\" role=\"region\"><div class=\"ugb-accordion__content-inner\">\n<p class=\"wp-block-paragraph\">Para un n\u00famero reducido de configuraciones (por ejemplo, sin tubo de aspiraci\u00f3n instalado), el material de la junta no puede determinarse con total certeza solo a partir del n\u00famero de art\u00edculo. En ese caso, compruebe la placa de identificaci\u00f3n o la Declaration of Compliance, o p\u00f3ngase en contacto con nosotros.<\/p>\n<\/div><\/div><\/div><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-accordion ugb-accordion wow animate__animated animate__fadeIn ugb-f244f58 ugb-accordion--v2 ugb-accordion--design-basic ugb-main-block\" aria-expanded=\"false\"><style>.ugb-f244f58 .ugb-accordion__heading{border-radius:8px !important}.ugb-f244f58 .ugb-accordion__arrow{width:17px !important;height:17px !important}@media screen and (min-width:768px){.ugb-f244f58.ugb-accordion{margin-bottom:12px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-accordion__item\"><div class=\"ugb-accordion__heading\" role=\"button\" tabindex=\"0\"><h6 class=\"ugb-accordion__title\">\u00bfCu\u00e1l es la diferencia entre VARIBOX FC y CC?<\/h6><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 20 20\" class=\"ugb-accordion__arrow\" width=\"20\" height=\"20\"><path d=\"M16.7 3.3L10 10 3.3 3.4 0 6.7l10 10v-.1l10-9.9z\"><\/path><\/svg><\/div><div class=\"ugb-accordion__content\" role=\"region\"><div class=\"ugb-accordion__content-inner\">\n<p class=\"wp-block-paragraph\">FC 1000 y FC 800 son unidades Full Containment, mientras que CC 250 es una unidad Compact Containment. La herramienta de verificaci\u00f3n le muestra cu\u00e1l tiene, junto con el resto de los detalles de la configuraci\u00f3n.<\/p>\n<\/div><\/div><\/div><\/div><\/div><\/div>\n\n\n\n<div class=\"alignfull wp-block-ugb-container ugb-container ugb-78dcb74 ugb-container--v2 ugb-container--design-plain ugb-main-block ugb-main-block--inner-center ugb--has-block-background\"><style>.ugb-78dcb74.ugb-container{background-color:#0078BF}.ugb-78dcb74.ugb-container:before{background-color:#0078BF}@media screen and (max-width:768px){.ugb-78dcb74.ugb-container{padding-top:0px !important;padding-bottom:0px !important}}@media screen and (min-width:768px){.ugb-78dcb74 > .ugb-inner-block > .ugb-block-content > *{padding-top:64px !important;padding-bottom:64px !important}}<\/style><div class=\"ugb-inner-block ugb-inner-block--center\"><div class=\"ugb-block-content\"><div class=\"ugb-container__wrapper ugb-78dcb74-wrapper\"><div class=\"ugb-container__side\"><div class=\"ugb-container__content-wrapper ugb-78dcb74-content-wrapper\">\n<div class=\"wp-block-ugb-heading ugb-heading wow animate__animated animate__fadeIn ugb-f21345d ugb-main-block\"><style>.ugb-f21345d .ugb-heading__title{text-align:center;margin-bottom:24px !important;color:#ffffff !important}.ugb-f21345d .ugb-heading__subtitle{margin-bottom:24px !important;color:#ffffff !important}.ugb-f21345d .ugb-inner-block{text-align:center}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><h2 class=\"ugb-heading__title\">\u00bfTodav\u00eda tiene preguntas sobre su VARIBOX?<\/h2><p class=\"ugb-heading__subtitle\">\u00bfNo est\u00e1 seguro del resultado, o una combinaci\u00f3n le resulta desconocida? Nuestro equipo de Atenci\u00f3n al Cliente estar\u00e1 encantado de ayudarle.<\/p><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-button ugb-button-wrapper green-button wow animate__animated animate__fadeIn ugb-2cce803 ugb-button--mobile-aligned ugb-main-block\"><style>.ugb-2cce803 .ugb-block-content{justify-content:center !important}.ugb-2cce803 .ugb-button1 .ugb-button--inner{font-weight:bold !important}.ugb-2cce803 .ugb-button1:hover{opacity:1}.ugb-2cce803 .ugb-inner-block{text-align:center}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-button-container\"><a class=\"ugb-button1 ugb-button ugb-button--size-normal\" href=\"https:\/\/varibox.best4u.dev\/es\/contacto\/\" rel=\"\" title=\"\"><span class=\"ugb-button--inner\">P\u00f3ngase en contacto<\/span><\/a><\/div><\/div><\/div><\/div>\n<\/div><\/div><\/div><\/div><\/div><\/div>\n\n\n\n<div class=\"alignfull wp-block-ugb-container ugb-container ugb-9ddd86e ugb-container--v2 ugb-container--design-plain ugb-main-block ugb-main-block--inner-center ugb--has-block-background ugb--has-background-overlay\"><style>.ugb-9ddd86e.ugb-container{background-color:var(--theme-palette-color-8,#f8fafc)}.ugb-9ddd86e.ugb-container:before{background-image:linear-gradient(180deg,var(--theme-palette-color-8,#f8fafc) 0%,#f8fafc 100%)}@media screen and (min-width:768px){.ugb-9ddd86e.ugb-container{margin-bottom:0px !important;padding-top:0px !important;padding-right:35px !important;padding-bottom:0px !important;padding-left:35px !important}}@media screen and (max-width:768px){.ugb-9ddd86e.ugb-container{padding-top:20px !important;padding-right:18px !important;padding-bottom:0px !important;padding-left:18px !important}}@media screen and (min-width:768px){.ugb-9ddd86e > .ugb-inner-block > .ugb-block-content > *{padding-top:64px !important;padding-bottom:64px !important}}<\/style><div class=\"ugb-inner-block ugb-inner-block--center\"><div class=\"ugb-block-content\"><div class=\"ugb-container__wrapper ugb-9ddd86e-wrapper\"><div class=\"ugb-container__side\"><div class=\"ugb-container__content-wrapper ugb-9ddd86e-content-wrapper\">\n<div class=\"wp-block-ugb-heading ugb-heading wow animate__animated animate__fadeIn ugb-a38e962 ugb-main-block\"><style>.ugb-a38e962 .ugb-heading__title{text-align:center;margin-bottom:16px !important}.ugb-a38e962 .ugb-heading__subtitle{margin-bottom:0px !important}.ugb-a38e962 .ugb-inner-block{text-align:center}@media screen and (min-width:768px){.ugb-a38e962.ugb-heading{margin-bottom:64px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><h2 class=\"ugb-heading__title\">Nuestros contenedores intermedios a granel<\/h2><p class=\"ugb-heading__subtitle\">Proporcionamos envases para la distribuci\u00f3n de productos qu\u00edmicos que destacan por su seguridad, reutilizaci\u00f3n y sostenibilidad.<\/p><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-columns ugb-columns wow animate__animated animate__fadeIn ugb-9965351 ugb-columns--design-plain ugb-columns--columns-3 ugb-main-block\"><style>.ugb-9965351-content-wrapper{grid-column-gap:35px !important}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-columns__item ugb-9965351-content-wrapper\">\n<div class=\"wp-block-ugb-column ugb-column ugb-8f900dd ugb-column--design-plain ugb-main-block\"><style>.ugb-8f900dd-column-wrapper .ugb-column__content-wrapper{width:270px !important}.ugb-8f900dd-column-wrapper{align-items:center !important}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-column__item ugb-8f900dd-column-wrapper\"><div class=\"ugb-column__content-wrapper\">\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" src=\"https:\/\/varibox.best4u.dev\/wp-content\/uploads\/2024\/10\/VARIBOX-Full-Containment-4.png\" alt=\"VARIBOX Full Containment\" class=\"wp-image-10758\"\/><\/figure>\n\n\n\n<div class=\"wp-block-ugb-heading ugb-heading ugb-82ad5d5 ugb-main-block\"><style>.ugb-82ad5d5 .ugb-heading__title{color:var(--theme-palette-color-4,#64748b);font-weight:400 !important}@media screen and (min-width:768px){.ugb-82ad5d5.ugb-heading{margin-top:24px !important;margin-bottom:0px !important}}@media screen and (max-width:768px){.ugb-82ad5d5.ugb-heading{margin-bottom:10px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><h4 class=\"ugb-heading__title\">VARIBOX<\/h4><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-heading ugb-heading ugb-616c0aa ugb-main-block\"><style>@media screen and (min-width:768px){.ugb-616c0aa.ugb-heading{margin-top:0px !important;margin-bottom:16px !important}}@media screen and (max-width:768px){.ugb-616c0aa.ugb-heading{margin-bottom:10px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><h5 class=\"ugb-heading__title\">Full Containment<\/h5><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-icon-list ugb-icon-list ugb-1ba5f66 ugb-icon-list--v2 ugb-main-block\"><style>.ugb-1ba5f66 li{font-size:13px !important;font-weight:bold !important;color:var(--theme-palette-color-4,#64748b)}.ugb-1ba5f66 li::before{background-image:url('data:image\/svg+xml;base64,PHN2ZyBjbGFzcz0idWdiLWN1c3RvbS1pY29uIiB3aWR0aD0iMjAiIGhlaWdodD0iMTEiIHZpZXdCb3g9IjAgMCAyMCAxMSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBzdHlsZT0iZmlsbDogIzViYzIzNyAhaW1wb3J0YW50OyBjb2xvcjogIzViYzIzNyAhaW1wb3J0YW50Ij4KPHBhdGggZD0iTTE1LjQzNzUgMC4wMzEyNUMxNC4yNSAwLjAzMTI1IDEzLjA5MzggMC41IDEyLjI1IDEuMzQzNzVMMTAgMy41OTM3NUw3LjcxODc1IDEuMzQzNzVDNi44NzUgMC41IDUuNzE4NzUgMCA0LjUzMTI1IDBDMi4wMzEyNSAwLjAzMTI1IDAgMi4wNjI1IDAgNC41NjI1VjUuNDY4NzVDMCA3Ljk2ODc1IDIuMDMxMjUgMTAgNC41MzEyNSAxMEM1LjcxODc1IDEwIDYuODc1IDkuNTMxMjUgNy43MTg3NSA4LjY4NzVMMTAgNi40Mzc1TDEyLjI1IDguNjg3NUMxMy4wOTM4IDkuNTMxMjUgMTQuMjUgMTAuMDMxMiAxNS40Mzc1IDEwLjAzMTJDMTcuOTM3NSAxMCAyMCA3Ljk2ODc1IDIwIDUuNDY4NzVWNC41NjI1QzIwIDIuMDYyNSAxNy45Mzc1IDAuMDMxMjUgMTUuNDM3NSAwLjAzMTI1Wk02LjMxMjUgNy4yODEyNUM1Ljg0Mzc1IDcuNzUgNS4xODc1IDguMDMxMjUgNC41MzEyNSA4LjAzMTI1QzMuMTI1IDggMiA2Ljg3NSAyIDUuNDY4NzVWNC41NjI1QzIgMy4xNTYyNSAzLjEyNSAyLjAzMTI1IDQuNTMxMjUgMi4wMzEyNUM1LjE4NzUgMi4wMzEyNSA1Ljg0Mzc1IDIuMjgxMjUgNi4zMTI1IDIuNzVMOC41NjI1IDUuMDMxMjVMNi4zMTI1IDcuMjgxMjVaTTE4IDUuNDY4NzVDMTggNi44NzUgMTYuODQzOCA4LjAzMTI1IDE1LjQzNzUgOC4wMzEyNUMxNC43ODEyIDguMDMxMjUgMTQuMTI1IDcuNzUgMTMuNjU2MiA3LjI4MTI1TDExLjQwNjIgNS4wMzEyNUwxMy42NTYyIDIuNzVDMTQuMTI1IDIuMjgxMjUgMTQuNzgxMiAyLjAzMTI1IDE1LjQzNzUgMi4wMzEyNUMxNi44NDM4IDIgMTggMy4xNTYyNSAxOCA0LjU2MjVWNS40Njg3NVoiIGZpbGw9IiM1YmMyMzciIHN0cm9rZT0iIzViYzIzNyIgc3R5bGU9ImZpbGw6IHJnYig5MSwgMTk0LCA1NSk7IHN0cm9rZTogcmdiKDkxLCAxOTQsIDU1KTsiLz4KPC9zdmc+')}.ugb-1ba5f66.ugb-icon-list ul{columns:1}@media screen and (min-width:768px){.ugb-1ba5f66.ugb-icon-list{margin-top:16px !important;margin-bottom:9px !important}}@media screen and (max-width:768px){.ugb-1ba5f66.ugb-icon-list{margin-bottom:10px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><ul><li> Retenci\u00f3n integrada 110%<\/li><\/ul><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-icon-list ugb-icon-list ugb-d688550 ugb-icon-list--v2 ugb-main-block\"><style>.ugb-d688550 li{font-size:13px !important;font-weight:bold !important;color:var(--theme-palette-color-4,#64748b)}.ugb-d688550 li::before{background-image:url('data:image\/svg+xml;base64,PHN2ZyBjbGFzcz0idWdiLWN1c3RvbS1pY29uIiB3aWR0aD0iMTciIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNyAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBzdHlsZT0iZmlsbDogIzViYzIzNyAhaW1wb3J0YW50OyBjb2xvcjogIzViYzIzNyAhaW1wb3J0YW50Ij4KPHBhdGggZD0iTTYuNjI1IDcuNjI1QzYuNzgxMjUgOC4yNSA2LjA2MjUgOC43ODEyNSA1LjUgOC40MDYyNUw0LjcxODc1IDcuOTM3NUwzLjEyNSAxMC41QzIuNzE4NzUgMTEuMTU2MiAzLjE4NzUgMTIuMDMxMiA0IDEyLjAzMTJINUM1LjUzMTI1IDEyLjAzMTIgNiAxMi40Njg4IDYgMTNDNiAxMy41NjI1IDUuNTMxMjUgMTQuMDMxMiA1IDE0LjAzMTJINEMxLjYyNSAxNC4wMzEyIDAuMTg3NSAxMS40Mzc1IDEuNDM3NSA5LjQzNzVMMy4wMzEyNSA2Ljg3NUwyLjI4MTI1IDYuNDA2MjVDMS43MTg3NSA2LjA2MjUgMS44NDM3NSA1LjE4NzUgMi41IDUuMDMxMjVMNS4zNDM3NSA0LjM3NUM1LjYyNSA0LjMxMjUgNS45MDYyNSA0LjQ2ODc1IDUuOTY4NzUgNC43NUw2LjYyNSA3LjYyNVpNOS44NDM3NSAyLjQ2ODc1TDExLjEyNSA0LjU2MjVMMTAuMzc1IDUuMDMxMjVDOS43ODEyNSA1LjM3NSA5LjkzNzUgNi4yNSAxMC41OTM4IDYuMzc1TDEzLjQzNzUgNy4wNjI1QzEzLjcxODggNy4xMjUgMTQgNi45Mzc1IDE0LjAzMTIgNi42ODc1TDE0LjcxODggMy44MTI1QzE0Ljg0MzggMy4xNTYyNSAxNC4xNTYyIDIuNjU2MjUgMTMuNTYyNSAzTDEyLjgxMjUgMy41TDExLjUzMTIgMS40Mzc1QzEwLjM0MzggLTAuNDY4NzUgNy42MjUgLTAuNDY4NzUgNi40Mzc1IDEuNDM3NUw2LjIxODc1IDEuNzgxMjVDNS45MDYyNSAyLjI1IDYuMDYyNSAyLjg3NSA2LjUzMTI1IDMuMTU2MjVDNyAzLjQ2ODc1IDcuNjI1IDMuMzEyNSA3LjkwNjI1IDIuODQzNzVMOC4xMjUgMi40Njg3NUM4LjUzMTI1IDEuODQzNzUgOS40Mzc1IDEuODc1IDkuODQzNzUgMi40Njg3NVpNMTYuNTMxMiA5LjQzNzVMMTYgOC41OTM3NUMxNS42ODc1IDguMTI1IDE1LjA5MzggNy45Njg3NSAxNC42MjUgOC4yNUMxNC4xNTYyIDguNTYyNSAxNCA5LjE1NjI1IDE0LjMxMjUgOS42MjVMMTQuODQzOCAxMC41QzE1LjI1IDExLjE1NjIgMTQuNzgxMiAxMi4wMzEyIDEzLjk2ODggMTIuMDMxMkgxMC45Njg4VjExLjEyNUMxMC45Njg4IDEwLjQzNzUgMTAuMTg3NSAxMC4xMjUgOS43MTg3NSAxMC41OTM4TDcuNjI1IDEyLjY1NjJDNy40Mzc1IDEyLjg3NSA3LjQzNzUgMTMuMTg3NSA3LjYyNSAxMy4zNzVMOS43MTg3NSAxNS40Mzc1QzEwLjE4NzUgMTUuOTA2MiAxMC45Njg4IDE1LjU5MzggMTAuOTY4OCAxNC45MDYyVjE0LjAzMTJIMTMuOTY4OEMxNi4zNDM4IDE0LjAzMTIgMTcuNzgxMiAxMS40Mzc1IDE2LjUzMTIgOS40Mzc1WiIgZmlsbD0iIzViYzIzNyIgc3Ryb2tlPSIjNWJjMjM3IiBzdHlsZT0iZmlsbDogcmdiKDkxLCAxOTQsIDU1KTsgc3Ryb2tlOiByZ2IoOTEsIDE5NCwgNTUpOyIvPgo8L3N2Zz4=')}.ugb-d688550.ugb-icon-list ul{columns:1}@media screen and (min-width:768px){.ugb-d688550.ugb-icon-list{margin-top:0px !important;margin-bottom:9px !important}}@media screen and (max-width:768px){.ugb-d688550.ugb-icon-list{margin-bottom:10px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><ul><li><strong>Vida \u00fatil 10 veces m\u00e1s larga<\/strong><\/li><\/ul><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-icon-list ugb-icon-list ugb-2623abd ugb-icon-list--v2 ugb-main-block\"><style>.ugb-2623abd li{font-size:13px !important;font-weight:bold !important;color:var(--theme-palette-color-4,#64748b)}.ugb-2623abd li::before{background-image:url('data:image\/svg+xml;base64,PHN2ZyBjbGFzcz0idWdiLWN1c3RvbS1pY29uIiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBzdHlsZT0iZmlsbDogIzViYzIzNyAhaW1wb3J0YW50OyBjb2xvcjogIzViYzIzNyAhaW1wb3J0YW50Ij4KPHBhdGggZD0iTTEwLjEyNSAzLjI1TDEyIDRMMTIuNzUgNS44NzVDMTIuODEyNSA1Ljk2ODc1IDEyLjkwNjIgNiAxMyA2QzEzLjA5MzggNiAxMy4xNTYyIDUuOTY4NzUgMTMuMjE4OCA1Ljg3NUwxNCA0TDE1Ljg0MzggMy4yNUMxNS45Mzc1IDMuMTg3NSAxNiAzLjA5Mzc1IDE2IDNDMTYgMi45MDYyNSAxNS45Mzc1IDIuODQzNzUgMTUuODQzOCAyLjc4MTI1TDE0IDJMMTMuMjE4OCAwLjE1NjI1QzEzLjE1NjIgMC4wNjI1IDEzLjA5MzggMCAxMyAwQzEyLjkwNjIgMCAxMi44MTI1IDAuMDYyNSAxMi43NSAwLjE1NjI1TDEyIDJMMTAuMTI1IDIuNzgxMjVDMTAuMDMxMiAyLjg0Mzc1IDEwIDIuOTA2MjUgMTAgM0MxMCAzLjA5Mzc1IDEwLjAzMTIgMy4xODc1IDEwLjEyNSAzLjI1Wk0xNS44NDM4IDEyLjc4MTJMMTQgMTJMMTMuMjE4OCAxMC4xNTYyQzEzLjE1NjIgMTAuMDYyNSAxMy4wOTM4IDEwIDEzIDEwQzEyLjkwNjIgMTAgMTIuODEyNSAxMC4wNjI1IDEyLjc1IDEwLjE1NjJMMTIgMTJMMTAuMTI1IDEyLjc4MTJDMTAuMDMxMiAxMi44NDM4IDEwIDEyLjkwNjIgMTAgMTNDMTAgMTMuMDkzOCAxMC4wMzEyIDEzLjE4NzUgMTAuMTI1IDEzLjI1TDEyIDE0TDEyLjc1IDE1Ljg3NUMxMi44MTI1IDE1Ljk2ODggMTIuOTA2MiAxNiAxMyAxNkMxMy4wOTM4IDE2IDEzLjE1NjIgMTUuOTY4OCAxMy4yMTg4IDE1Ljg3NUwxNCAxNEwxNS44NDM4IDEzLjI1QzE1LjkzNzUgMTMuMTg3NSAxNiAxMy4wOTM4IDE2IDEzQzE2IDEyLjkwNjIgMTUuOTM3NSAxMi44NDM4IDE1Ljg0MzggMTIuNzgxMlpNMTIgOEMxMiA3LjgxMjUgMTEuODc1IDcuNjI1IDExLjcxODggNy41NjI1TDguMTg3NSA1Ljc4MTI1TDYuNDM3NSAyLjI4MTI1QzYuMjUgMS45Mzc1IDUuNzE4NzUgMS45Mzc1IDUuNTMxMjUgMi4yODEyNUwzLjc4MTI1IDUuNzgxMjVMMC4yNSA3LjU2MjVDMC4wOTM3NSA3LjYyNSAwIDcuODEyNSAwIDhDMCA4LjE4NzUgMC4wOTM3NSA4LjM3NSAwLjI1IDguNDM3NUwzLjc4MTI1IDEwLjIxODhMNS41MzEyNSAxMy43NUM1LjYyNSAxMy45MDYyIDUuNzgxMjUgMTQgNiAxNEM2LjE1NjI1IDE0IDYuMzQzNzUgMTMuOTA2MiA2LjQzNzUgMTMuNzVMOC4xODc1IDEwLjIxODhMMTEuNzE4OCA4LjQzNzVDMTEuODc1IDguMzc1IDEyIDguMTg3NSAxMiA4WiIgZmlsbD0iIzViYzIzNyIgc3Ryb2tlPSIjNWJjMjM3IiBzdHlsZT0iZmlsbDogcmdiKDkxLCAxOTQsIDU1KTsgc3Ryb2tlOiByZ2IoOTEsIDE5NCwgNTUpOyIvPgo8L3N2Zz4=')}.ugb-2623abd.ugb-icon-list ul{columns:1}@media screen and (min-width:768px){.ugb-2623abd.ugb-icon-list{margin-top:0px !important;margin-bottom:35px !important}}@media screen and (max-width:768px){.ugb-2623abd.ugb-icon-list{margin-bottom:10px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><ul><li>0,5 litros de residuos<\/li><\/ul><\/div><\/div><\/div>\n\n\n\n<div class=\"aligncenter wp-block-ugb-button ugb-button-wrapper blue-button ugb-4ac0229 ugb-main-block\"><style>.ugb-4ac0229 .ugb-block-content{justify-content:center !important}.ugb-4ac0229 .ugb-button1 .ugb-button--inner{font-size:16px !important;font-weight:bold !important}.ugb-4ac0229 .ugb-button1{padding-top:10px;padding-right:50px;padding-bottom:10px;padding-left:50px;opacity:1;border-radius:5px !important}.ugb-4ac0229 .ugb-button1:hover{background-color:;opacity:1}.ugb-4ac0229 .ugb-button1:before{content:\"\";background-image:linear-gradient(90deg,,);border-radius:5px !important}.ugb-4ac0229 .ugb-inner-block{text-align:center}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-button-container\"><a class=\"ugb-button1 ugb-button ugb-button--size-large ugb-button--ghost-to-normal-effect ugb-button--design-ghost\" href=\"https:\/\/varibox.best4u.dev\/es\/varibox_product\/varibox-full-containment\/\" rel=\"\" title=\"\"><span class=\"ugb-button--inner\">M\u00e1s informaci\u00f3n<\/span><\/a><\/div><\/div><\/div><\/div>\n<\/div><\/div><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-column ugb-column ugb-c4cf8a7 ugb-column--design-plain ugb-main-block\"><style>.ugb-c4cf8a7-column-wrapper .ugb-column__content-wrapper{width:270px !important}.ugb-c4cf8a7-column-wrapper{align-items:center !important}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-column__item ugb-c4cf8a7-column-wrapper\"><div class=\"ugb-column__content-wrapper\">\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" src=\"https:\/\/varibox.best4u.dev\/wp-content\/uploads\/2024\/10\/VARIBOX-Compact-Containment-4.png\" alt=\"VARIBOX Compact Containment\" class=\"wp-image-10773\"\/><\/figure>\n\n\n\n<div class=\"wp-block-ugb-heading ugb-heading ugb-9511c2f ugb-main-block\"><style>.ugb-9511c2f .ugb-heading__title{color:var(--theme-palette-color-4,#64748b);font-weight:400 !important}@media screen and (min-width:768px){.ugb-9511c2f.ugb-heading{margin-top:24px !important;margin-bottom:0px !important}}@media screen and (max-width:768px){.ugb-9511c2f.ugb-heading{margin-bottom:10px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><h4 class=\"ugb-heading__title\">VARIBOX<\/h4><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-heading ugb-heading ugb-922f1f6 ugb-main-block\"><style>@media screen and (min-width:768px){.ugb-922f1f6.ugb-heading{margin-top:0px !important;margin-bottom:16px !important}}@media screen and (max-width:768px){.ugb-922f1f6.ugb-heading{margin-bottom:10px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><h5 class=\"ugb-heading__title\">Compact Containment<\/h5><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-icon-list ugb-icon-list ugb-8d36e6a ugb-icon-list--v2 ugb-main-block\"><style>.ugb-8d36e6a li{font-size:13px !important;font-weight:bold !important;color:var(--theme-palette-color-4,#64748b)}.ugb-8d36e6a li::before{background-image:url('data:image\/svg+xml;base64,PHN2ZyBjbGFzcz0idWdiLWN1c3RvbS1pY29uIiB3aWR0aD0iMjAiIGhlaWdodD0iMTEiIHZpZXdCb3g9IjAgMCAyMCAxMSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBzdHlsZT0iZmlsbDogIzViYzIzNyAhaW1wb3J0YW50OyBjb2xvcjogIzViYzIzNyAhaW1wb3J0YW50Ij4KPHBhdGggZD0iTTE1LjQzNzUgMC4wMzEyNUMxNC4yNSAwLjAzMTI1IDEzLjA5MzggMC41IDEyLjI1IDEuMzQzNzVMMTAgMy41OTM3NUw3LjcxODc1IDEuMzQzNzVDNi44NzUgMC41IDUuNzE4NzUgMCA0LjUzMTI1IDBDMi4wMzEyNSAwLjAzMTI1IDAgMi4wNjI1IDAgNC41NjI1VjUuNDY4NzVDMCA3Ljk2ODc1IDIuMDMxMjUgMTAgNC41MzEyNSAxMEM1LjcxODc1IDEwIDYuODc1IDkuNTMxMjUgNy43MTg3NSA4LjY4NzVMMTAgNi40Mzc1TDEyLjI1IDguNjg3NUMxMy4wOTM4IDkuNTMxMjUgMTQuMjUgMTAuMDMxMiAxNS40Mzc1IDEwLjAzMTJDMTcuOTM3NSAxMCAyMCA3Ljk2ODc1IDIwIDUuNDY4NzVWNC41NjI1QzIwIDIuMDYyNSAxNy45Mzc1IDAuMDMxMjUgMTUuNDM3NSAwLjAzMTI1Wk02LjMxMjUgNy4yODEyNUM1Ljg0Mzc1IDcuNzUgNS4xODc1IDguMDMxMjUgNC41MzEyNSA4LjAzMTI1QzMuMTI1IDggMiA2Ljg3NSAyIDUuNDY4NzVWNC41NjI1QzIgMy4xNTYyNSAzLjEyNSAyLjAzMTI1IDQuNTMxMjUgMi4wMzEyNUM1LjE4NzUgMi4wMzEyNSA1Ljg0Mzc1IDIuMjgxMjUgNi4zMTI1IDIuNzVMOC41NjI1IDUuMDMxMjVMNi4zMTI1IDcuMjgxMjVaTTE4IDUuNDY4NzVDMTggNi44NzUgMTYuODQzOCA4LjAzMTI1IDE1LjQzNzUgOC4wMzEyNUMxNC43ODEyIDguMDMxMjUgMTQuMTI1IDcuNzUgMTMuNjU2MiA3LjI4MTI1TDExLjQwNjIgNS4wMzEyNUwxMy42NTYyIDIuNzVDMTQuMTI1IDIuMjgxMjUgMTQuNzgxMiAyLjAzMTI1IDE1LjQzNzUgMi4wMzEyNUMxNi44NDM4IDIgMTggMy4xNTYyNSAxOCA0LjU2MjVWNS40Njg3NVoiIGZpbGw9IiM1YmMyMzciIHN0cm9rZT0iIzViYzIzNyIgc3R5bGU9ImZpbGw6IHJnYig5MSwgMTk0LCA1NSk7IHN0cm9rZTogcmdiKDkxLCAxOTQsIDU1KTsiLz4KPC9zdmc+')}.ugb-8d36e6a.ugb-icon-list ul{columns:1}@media screen and (min-width:768px){.ugb-8d36e6a.ugb-icon-list{margin-top:16px !important;margin-bottom:9px !important}}@media screen and (max-width:768px){.ugb-8d36e6a.ugb-icon-list{margin-bottom:10px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><ul><li>Elimina el levantamiento f\u00edsico<\/li><\/ul><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-icon-list ugb-icon-list ugb-5fbc0e1 ugb-icon-list--v2 ugb-main-block\"><style>.ugb-5fbc0e1 li{font-size:13px !important;font-weight:bold !important;color:var(--theme-palette-color-4,#64748b)}.ugb-5fbc0e1 li::before{background-image:url('data:image\/svg+xml;base64,PHN2ZyBjbGFzcz0idWdiLWN1c3RvbS1pY29uIiB3aWR0aD0iMTciIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNyAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBzdHlsZT0iZmlsbDogIzViYzIzNyAhaW1wb3J0YW50OyBjb2xvcjogIzViYzIzNyAhaW1wb3J0YW50Ij4KPHBhdGggZD0iTTYuNjI1IDcuNjI1QzYuNzgxMjUgOC4yNSA2LjA2MjUgOC43ODEyNSA1LjUgOC40MDYyNUw0LjcxODc1IDcuOTM3NUwzLjEyNSAxMC41QzIuNzE4NzUgMTEuMTU2MiAzLjE4NzUgMTIuMDMxMiA0IDEyLjAzMTJINUM1LjUzMTI1IDEyLjAzMTIgNiAxMi40Njg4IDYgMTNDNiAxMy41NjI1IDUuNTMxMjUgMTQuMDMxMiA1IDE0LjAzMTJINEMxLjYyNSAxNC4wMzEyIDAuMTg3NSAxMS40Mzc1IDEuNDM3NSA5LjQzNzVMMy4wMzEyNSA2Ljg3NUwyLjI4MTI1IDYuNDA2MjVDMS43MTg3NSA2LjA2MjUgMS44NDM3NSA1LjE4NzUgMi41IDUuMDMxMjVMNS4zNDM3NSA0LjM3NUM1LjYyNSA0LjMxMjUgNS45MDYyNSA0LjQ2ODc1IDUuOTY4NzUgNC43NUw2LjYyNSA3LjYyNVpNOS44NDM3NSAyLjQ2ODc1TDExLjEyNSA0LjU2MjVMMTAuMzc1IDUuMDMxMjVDOS43ODEyNSA1LjM3NSA5LjkzNzUgNi4yNSAxMC41OTM4IDYuMzc1TDEzLjQzNzUgNy4wNjI1QzEzLjcxODggNy4xMjUgMTQgNi45Mzc1IDE0LjAzMTIgNi42ODc1TDE0LjcxODggMy44MTI1QzE0Ljg0MzggMy4xNTYyNSAxNC4xNTYyIDIuNjU2MjUgMTMuNTYyNSAzTDEyLjgxMjUgMy41TDExLjUzMTIgMS40Mzc1QzEwLjM0MzggLTAuNDY4NzUgNy42MjUgLTAuNDY4NzUgNi40Mzc1IDEuNDM3NUw2LjIxODc1IDEuNzgxMjVDNS45MDYyNSAyLjI1IDYuMDYyNSAyLjg3NSA2LjUzMTI1IDMuMTU2MjVDNyAzLjQ2ODc1IDcuNjI1IDMuMzEyNSA3LjkwNjI1IDIuODQzNzVMOC4xMjUgMi40Njg3NUM4LjUzMTI1IDEuODQzNzUgOS40Mzc1IDEuODc1IDkuODQzNzUgMi40Njg3NVpNMTYuNTMxMiA5LjQzNzVMMTYgOC41OTM3NUMxNS42ODc1IDguMTI1IDE1LjA5MzggNy45Njg3NSAxNC42MjUgOC4yNUMxNC4xNTYyIDguNTYyNSAxNCA5LjE1NjI1IDE0LjMxMjUgOS42MjVMMTQuODQzOCAxMC41QzE1LjI1IDExLjE1NjIgMTQuNzgxMiAxMi4wMzEyIDEzLjk2ODggMTIuMDMxMkgxMC45Njg4VjExLjEyNUMxMC45Njg4IDEwLjQzNzUgMTAuMTg3NSAxMC4xMjUgOS43MTg3NSAxMC41OTM4TDcuNjI1IDEyLjY1NjJDNy40Mzc1IDEyLjg3NSA3LjQzNzUgMTMuMTg3NSA3LjYyNSAxMy4zNzVMOS43MTg3NSAxNS40Mzc1QzEwLjE4NzUgMTUuOTA2MiAxMC45Njg4IDE1LjU5MzggMTAuOTY4OCAxNC45MDYyVjE0LjAzMTJIMTMuOTY4OEMxNi4zNDM4IDE0LjAzMTIgMTcuNzgxMiAxMS40Mzc1IDE2LjUzMTIgOS40Mzc1WiIgZmlsbD0iIzViYzIzNyIgc3Ryb2tlPSIjNWJjMjM3IiBzdHlsZT0iZmlsbDogcmdiKDkxLCAxOTQsIDU1KTsgc3Ryb2tlOiByZ2IoOTEsIDE5NCwgNTUpOyIvPgo8L3N2Zz4=')}.ugb-5fbc0e1.ugb-icon-list ul{columns:1}@media screen and (min-width:768px){.ugb-5fbc0e1.ugb-icon-list{margin-top:0px !important;margin-bottom:9px !important}}@media screen and (max-width:768px){.ugb-5fbc0e1.ugb-icon-list{margin-bottom:10px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><ul><li>No se necesitan cubeta de retenci\u00f3n <\/li><\/ul><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-icon-list ugb-icon-list ugb-b29613a ugb-icon-list--v2 ugb-main-block\"><style>.ugb-b29613a li{font-size:13px !important;font-weight:bold !important;color:var(--theme-palette-color-4,#64748b)}.ugb-b29613a li::before{background-image:url('data:image\/svg+xml;base64,PHN2ZyBjbGFzcz0idWdiLWN1c3RvbS1pY29uIiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBzdHlsZT0iZmlsbDogIzViYzIzNyAhaW1wb3J0YW50OyBjb2xvcjogIzViYzIzNyAhaW1wb3J0YW50Ij4KPHBhdGggZD0iTTEwLjEyNSAzLjI1TDEyIDRMMTIuNzUgNS44NzVDMTIuODEyNSA1Ljk2ODc1IDEyLjkwNjIgNiAxMyA2QzEzLjA5MzggNiAxMy4xNTYyIDUuOTY4NzUgMTMuMjE4OCA1Ljg3NUwxNCA0TDE1Ljg0MzggMy4yNUMxNS45Mzc1IDMuMTg3NSAxNiAzLjA5Mzc1IDE2IDNDMTYgMi45MDYyNSAxNS45Mzc1IDIuODQzNzUgMTUuODQzOCAyLjc4MTI1TDE0IDJMMTMuMjE4OCAwLjE1NjI1QzEzLjE1NjIgMC4wNjI1IDEzLjA5MzggMCAxMyAwQzEyLjkwNjIgMCAxMi44MTI1IDAuMDYyNSAxMi43NSAwLjE1NjI1TDEyIDJMMTAuMTI1IDIuNzgxMjVDMTAuMDMxMiAyLjg0Mzc1IDEwIDIuOTA2MjUgMTAgM0MxMCAzLjA5Mzc1IDEwLjAzMTIgMy4xODc1IDEwLjEyNSAzLjI1Wk0xNS44NDM4IDEyLjc4MTJMMTQgMTJMMTMuMjE4OCAxMC4xNTYyQzEzLjE1NjIgMTAuMDYyNSAxMy4wOTM4IDEwIDEzIDEwQzEyLjkwNjIgMTAgMTIuODEyNSAxMC4wNjI1IDEyLjc1IDEwLjE1NjJMMTIgMTJMMTAuMTI1IDEyLjc4MTJDMTAuMDMxMiAxMi44NDM4IDEwIDEyLjkwNjIgMTAgMTNDMTAgMTMuMDkzOCAxMC4wMzEyIDEzLjE4NzUgMTAuMTI1IDEzLjI1TDEyIDE0TDEyLjc1IDE1Ljg3NUMxMi44MTI1IDE1Ljk2ODggMTIuOTA2MiAxNiAxMyAxNkMxMy4wOTM4IDE2IDEzLjE1NjIgMTUuOTY4OCAxMy4yMTg4IDE1Ljg3NUwxNCAxNEwxNS44NDM4IDEzLjI1QzE1LjkzNzUgMTMuMTg3NSAxNiAxMy4wOTM4IDE2IDEzQzE2IDEyLjkwNjIgMTUuOTM3NSAxMi44NDM4IDE1Ljg0MzggMTIuNzgxMlpNMTIgOEMxMiA3LjgxMjUgMTEuODc1IDcuNjI1IDExLjcxODggNy41NjI1TDguMTg3NSA1Ljc4MTI1TDYuNDM3NSAyLjI4MTI1QzYuMjUgMS45Mzc1IDUuNzE4NzUgMS45Mzc1IDUuNTMxMjUgMi4yODEyNUwzLjc4MTI1IDUuNzgxMjVMMC4yNSA3LjU2MjVDMC4wOTM3NSA3LjYyNSAwIDcuODEyNSAwIDhDMCA4LjE4NzUgMC4wOTM3NSA4LjM3NSAwLjI1IDguNDM3NUwzLjc4MTI1IDEwLjIxODhMNS41MzEyNSAxMy43NUM1LjYyNSAxMy45MDYyIDUuNzgxMjUgMTQgNiAxNEM2LjE1NjI1IDE0IDYuMzQzNzUgMTMuOTA2MiA2LjQzNzUgMTMuNzVMOC4xODc1IDEwLjIxODhMMTEuNzE4OCA4LjQzNzVDMTEuODc1IDguMzc1IDEyIDguMTg3NSAxMiA4WiIgZmlsbD0iIzViYzIzNyIgc3Ryb2tlPSIjNWJjMjM3IiBzdHlsZT0iZmlsbDogcmdiKDkxLCAxOTQsIDU1KTsgc3Ryb2tlOiByZ2IoOTEsIDE5NCwgNTUpOyIvPgo8L3N2Zz4=')}.ugb-b29613a.ugb-icon-list ul{columns:1}@media screen and (min-width:768px){.ugb-b29613a.ugb-icon-list{margin-top:0px !important;margin-bottom:35px !important}}@media screen and (max-width:768px){.ugb-b29613a.ugb-icon-list{margin-bottom:10px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><ul><li>Sistema 100% circuito cerrado<\/li><\/ul><\/div><\/div><\/div>\n\n\n\n<div class=\"aligncenter wp-block-ugb-button ugb-button-wrapper blue-button ugb-f282528 ugb-main-block\"><style>.ugb-f282528 .ugb-block-content{justify-content:center !important}.ugb-f282528 .ugb-button1 .ugb-button--inner{font-size:16px !important;font-weight:bold !important}.ugb-f282528 .ugb-button1{padding-top:10px;padding-right:50px;padding-bottom:10px;padding-left:50px;opacity:1;border-radius:5px !important}.ugb-f282528 .ugb-button1:hover{background-color:;opacity:1}.ugb-f282528 .ugb-button1:before{content:\"\";background-image:linear-gradient(90deg,,);border-radius:5px !important}.ugb-f282528 .ugb-inner-block{text-align:center}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-button-container\"><a class=\"ugb-button1 ugb-button ugb-button--size-large ugb-button--ghost-to-normal-effect ugb-button--design-ghost\" href=\"\/es\/varibox_product\/varibox-compacto-de-doble-pared\/\" rel=\"\" title=\"\"><span class=\"ugb-button--inner\">M\u00e1s informaci\u00f3n<\/span><\/a><\/div><\/div><\/div><\/div>\n<\/div><\/div><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-column ugb-column ugb-8152187 ugb-column--design-plain ugb-main-block\"><style>.ugb-8152187-column-wrapper .ugb-column__content-wrapper{width:270px !important}.ugb-8152187-column-wrapper{align-items:center !important}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-column__item ugb-8152187-column-wrapper\"><div class=\"ugb-column__content-wrapper\">\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" src=\"https:\/\/varibox.best4u.dev\/wp-content\/uploads\/2024\/10\/VARIBOX-Drumtainer-4.png\" alt=\"VARIBOX Drumtainer\" class=\"wp-image-10784\"\/><\/figure>\n\n\n\n<div class=\"wp-block-ugb-heading ugb-heading ugb-0ea1912 ugb-main-block\"><style>.ugb-0ea1912 .ugb-heading__title{color:var(--theme-palette-color-4,#64748b);font-weight:400 !important}@media screen and (min-width:768px){.ugb-0ea1912.ugb-heading{margin-top:24px !important;margin-bottom:0px !important}}@media screen and (max-width:768px){.ugb-0ea1912.ugb-heading{margin-bottom:10px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><h4 class=\"ugb-heading__title\">VARIBOX<\/h4><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-heading ugb-heading ugb-0829459 ugb-main-block\"><style>@media screen and (min-width:768px){.ugb-0829459.ugb-heading{margin-top:0px !important;margin-bottom:16px !important}}@media screen and (max-width:768px){.ugb-0829459.ugb-heading{margin-bottom:10px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><h5 class=\"ugb-heading__title\">Drumtainer<\/h5><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-icon-list ugb-icon-list ugb-ba43b9f ugb-icon-list--v2 ugb-main-block\"><style>.ugb-ba43b9f li{font-size:13px !important;font-weight:bold !important;color:var(--theme-palette-color-4,#64748b)}.ugb-ba43b9f li::before{background-image:url('data:image\/svg+xml;base64,PHN2ZyBjbGFzcz0idWdiLWN1c3RvbS1pY29uIiB3aWR0aD0iMjAiIGhlaWdodD0iMTEiIHZpZXdCb3g9IjAgMCAyMCAxMSIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBzdHlsZT0iZmlsbDogIzViYzIzNyAhaW1wb3J0YW50OyBjb2xvcjogIzViYzIzNyAhaW1wb3J0YW50Ij4KPHBhdGggZD0iTTE1LjQzNzUgMC4wMzEyNUMxNC4yNSAwLjAzMTI1IDEzLjA5MzggMC41IDEyLjI1IDEuMzQzNzVMMTAgMy41OTM3NUw3LjcxODc1IDEuMzQzNzVDNi44NzUgMC41IDUuNzE4NzUgMCA0LjUzMTI1IDBDMi4wMzEyNSAwLjAzMTI1IDAgMi4wNjI1IDAgNC41NjI1VjUuNDY4NzVDMCA3Ljk2ODc1IDIuMDMxMjUgMTAgNC41MzEyNSAxMEM1LjcxODc1IDEwIDYuODc1IDkuNTMxMjUgNy43MTg3NSA4LjY4NzVMMTAgNi40Mzc1TDEyLjI1IDguNjg3NUMxMy4wOTM4IDkuNTMxMjUgMTQuMjUgMTAuMDMxMiAxNS40Mzc1IDEwLjAzMTJDMTcuOTM3NSAxMCAyMCA3Ljk2ODc1IDIwIDUuNDY4NzVWNC41NjI1QzIwIDIuMDYyNSAxNy45Mzc1IDAuMDMxMjUgMTUuNDM3NSAwLjAzMTI1Wk02LjMxMjUgNy4yODEyNUM1Ljg0Mzc1IDcuNzUgNS4xODc1IDguMDMxMjUgNC41MzEyNSA4LjAzMTI1QzMuMTI1IDggMiA2Ljg3NSAyIDUuNDY4NzVWNC41NjI1QzIgMy4xNTYyNSAzLjEyNSAyLjAzMTI1IDQuNTMxMjUgMi4wMzEyNUM1LjE4NzUgMi4wMzEyNSA1Ljg0Mzc1IDIuMjgxMjUgNi4zMTI1IDIuNzVMOC41NjI1IDUuMDMxMjVMNi4zMTI1IDcuMjgxMjVaTTE4IDUuNDY4NzVDMTggNi44NzUgMTYuODQzOCA4LjAzMTI1IDE1LjQzNzUgOC4wMzEyNUMxNC43ODEyIDguMDMxMjUgMTQuMTI1IDcuNzUgMTMuNjU2MiA3LjI4MTI1TDExLjQwNjIgNS4wMzEyNUwxMy42NTYyIDIuNzVDMTQuMTI1IDIuMjgxMjUgMTQuNzgxMiAyLjAzMTI1IDE1LjQzNzUgMi4wMzEyNUMxNi44NDM4IDIgMTggMy4xNTYyNSAxOCA0LjU2MjVWNS40Njg3NVoiIGZpbGw9IiM1YmMyMzciIHN0cm9rZT0iIzViYzIzNyIgc3R5bGU9ImZpbGw6IHJnYig5MSwgMTk0LCA1NSk7IHN0cm9rZTogcmdiKDkxLCAxOTQsIDU1KTsiLz4KPC9zdmc+')}.ugb-ba43b9f.ugb-icon-list ul{columns:1}@media screen and (min-width:768px){.ugb-ba43b9f.ugb-icon-list{margin-top:16px !important;margin-bottom:9px !important}}@media screen and (max-width:768px){.ugb-ba43b9f.ugb-icon-list{margin-bottom:10px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><ul><li>Sobreembalaje m\u00f3vil para bidones<\/li><\/ul><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-icon-list ugb-icon-list ugb-ac3a5a9 ugb-icon-list--v2 ugb-main-block\"><style>.ugb-ac3a5a9 li{font-size:13px !important;font-weight:bold !important;color:var(--theme-palette-color-4,#64748b)}.ugb-ac3a5a9 li::before{background-image:url('data:image\/svg+xml;base64,PHN2ZyBjbGFzcz0idWdiLWN1c3RvbS1pY29uIiB3aWR0aD0iMTciIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNyAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBzdHlsZT0iZmlsbDogIzViYzIzNyAhaW1wb3J0YW50OyBjb2xvcjogIzViYzIzNyAhaW1wb3J0YW50Ij4KPHBhdGggZD0iTTYuNjI1IDcuNjI1QzYuNzgxMjUgOC4yNSA2LjA2MjUgOC43ODEyNSA1LjUgOC40MDYyNUw0LjcxODc1IDcuOTM3NUwzLjEyNSAxMC41QzIuNzE4NzUgMTEuMTU2MiAzLjE4NzUgMTIuMDMxMiA0IDEyLjAzMTJINUM1LjUzMTI1IDEyLjAzMTIgNiAxMi40Njg4IDYgMTNDNiAxMy41NjI1IDUuNTMxMjUgMTQuMDMxMiA1IDE0LjAzMTJINEMxLjYyNSAxNC4wMzEyIDAuMTg3NSAxMS40Mzc1IDEuNDM3NSA5LjQzNzVMMy4wMzEyNSA2Ljg3NUwyLjI4MTI1IDYuNDA2MjVDMS43MTg3NSA2LjA2MjUgMS44NDM3NSA1LjE4NzUgMi41IDUuMDMxMjVMNS4zNDM3NSA0LjM3NUM1LjYyNSA0LjMxMjUgNS45MDYyNSA0LjQ2ODc1IDUuOTY4NzUgNC43NUw2LjYyNSA3LjYyNVpNOS44NDM3NSAyLjQ2ODc1TDExLjEyNSA0LjU2MjVMMTAuMzc1IDUuMDMxMjVDOS43ODEyNSA1LjM3NSA5LjkzNzUgNi4yNSAxMC41OTM4IDYuMzc1TDEzLjQzNzUgNy4wNjI1QzEzLjcxODggNy4xMjUgMTQgNi45Mzc1IDE0LjAzMTIgNi42ODc1TDE0LjcxODggMy44MTI1QzE0Ljg0MzggMy4xNTYyNSAxNC4xNTYyIDIuNjU2MjUgMTMuNTYyNSAzTDEyLjgxMjUgMy41TDExLjUzMTIgMS40Mzc1QzEwLjM0MzggLTAuNDY4NzUgNy42MjUgLTAuNDY4NzUgNi40Mzc1IDEuNDM3NUw2LjIxODc1IDEuNzgxMjVDNS45MDYyNSAyLjI1IDYuMDYyNSAyLjg3NSA2LjUzMTI1IDMuMTU2MjVDNyAzLjQ2ODc1IDcuNjI1IDMuMzEyNSA3LjkwNjI1IDIuODQzNzVMOC4xMjUgMi40Njg3NUM4LjUzMTI1IDEuODQzNzUgOS40Mzc1IDEuODc1IDkuODQzNzUgMi40Njg3NVpNMTYuNTMxMiA5LjQzNzVMMTYgOC41OTM3NUMxNS42ODc1IDguMTI1IDE1LjA5MzggNy45Njg3NSAxNC42MjUgOC4yNUMxNC4xNTYyIDguNTYyNSAxNCA5LjE1NjI1IDE0LjMxMjUgOS42MjVMMTQuODQzOCAxMC41QzE1LjI1IDExLjE1NjIgMTQuNzgxMiAxMi4wMzEyIDEzLjk2ODggMTIuMDMxMkgxMC45Njg4VjExLjEyNUMxMC45Njg4IDEwLjQzNzUgMTAuMTg3NSAxMC4xMjUgOS43MTg3NSAxMC41OTM4TDcuNjI1IDEyLjY1NjJDNy40Mzc1IDEyLjg3NSA3LjQzNzUgMTMuMTg3NSA3LjYyNSAxMy4zNzVMOS43MTg3NSAxNS40Mzc1QzEwLjE4NzUgMTUuOTA2MiAxMC45Njg4IDE1LjU5MzggMTAuOTY4OCAxNC45MDYyVjE0LjAzMTJIMTMuOTY4OEMxNi4zNDM4IDE0LjAzMTIgMTcuNzgxMiAxMS40Mzc1IDE2LjUzMTIgOS40Mzc1WiIgZmlsbD0iIzViYzIzNyIgc3Ryb2tlPSIjNWJjMjM3IiBzdHlsZT0iZmlsbDogcmdiKDkxLCAxOTQsIDU1KTsgc3Ryb2tlOiByZ2IoOTEsIDE5NCwgNTUpOyIvPgo8L3N2Zz4=')}.ugb-ac3a5a9.ugb-icon-list ul{columns:1}@media screen and (min-width:768px){.ugb-ac3a5a9.ugb-icon-list{margin-top:0px !important;margin-bottom:9px !important}}@media screen and (max-width:768px){.ugb-ac3a5a9.ugb-icon-list{margin-bottom:10px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><ul><li>Retenci\u00f3n integrada 110%<\/li><\/ul><\/div><\/div><\/div>\n\n\n\n<div class=\"wp-block-ugb-icon-list ugb-icon-list ugb-e2459a9 ugb-icon-list--v2 ugb-main-block\"><style>.ugb-e2459a9 li{font-size:13px !important;font-weight:bold !important;color:var(--theme-palette-color-4,#64748b)}.ugb-e2459a9 li::before{background-image:url('data:image\/svg+xml;base64,PHN2ZyBjbGFzcz0idWdiLWN1c3RvbS1pY29uIiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBzdHlsZT0iZmlsbDogIzViYzIzNyAhaW1wb3J0YW50OyBjb2xvcjogIzViYzIzNyAhaW1wb3J0YW50Ij4KPHBhdGggZD0iTTEwLjEyNSAzLjI1TDEyIDRMMTIuNzUgNS44NzVDMTIuODEyNSA1Ljk2ODc1IDEyLjkwNjIgNiAxMyA2QzEzLjA5MzggNiAxMy4xNTYyIDUuOTY4NzUgMTMuMjE4OCA1Ljg3NUwxNCA0TDE1Ljg0MzggMy4yNUMxNS45Mzc1IDMuMTg3NSAxNiAzLjA5Mzc1IDE2IDNDMTYgMi45MDYyNSAxNS45Mzc1IDIuODQzNzUgMTUuODQzOCAyLjc4MTI1TDE0IDJMMTMuMjE4OCAwLjE1NjI1QzEzLjE1NjIgMC4wNjI1IDEzLjA5MzggMCAxMyAwQzEyLjkwNjIgMCAxMi44MTI1IDAuMDYyNSAxMi43NSAwLjE1NjI1TDEyIDJMMTAuMTI1IDIuNzgxMjVDMTAuMDMxMiAyLjg0Mzc1IDEwIDIuOTA2MjUgMTAgM0MxMCAzLjA5Mzc1IDEwLjAzMTIgMy4xODc1IDEwLjEyNSAzLjI1Wk0xNS44NDM4IDEyLjc4MTJMMTQgMTJMMTMuMjE4OCAxMC4xNTYyQzEzLjE1NjIgMTAuMDYyNSAxMy4wOTM4IDEwIDEzIDEwQzEyLjkwNjIgMTAgMTIuODEyNSAxMC4wNjI1IDEyLjc1IDEwLjE1NjJMMTIgMTJMMTAuMTI1IDEyLjc4MTJDMTAuMDMxMiAxMi44NDM4IDEwIDEyLjkwNjIgMTAgMTNDMTAgMTMuMDkzOCAxMC4wMzEyIDEzLjE4NzUgMTAuMTI1IDEzLjI1TDEyIDE0TDEyLjc1IDE1Ljg3NUMxMi44MTI1IDE1Ljk2ODggMTIuOTA2MiAxNiAxMyAxNkMxMy4wOTM4IDE2IDEzLjE1NjIgMTUuOTY4OCAxMy4yMTg4IDE1Ljg3NUwxNCAxNEwxNS44NDM4IDEzLjI1QzE1LjkzNzUgMTMuMTg3NSAxNiAxMy4wOTM4IDE2IDEzQzE2IDEyLjkwNjIgMTUuOTM3NSAxMi44NDM4IDE1Ljg0MzggMTIuNzgxMlpNMTIgOEMxMiA3LjgxMjUgMTEuODc1IDcuNjI1IDExLjcxODggNy41NjI1TDguMTg3NSA1Ljc4MTI1TDYuNDM3NSAyLjI4MTI1QzYuMjUgMS45Mzc1IDUuNzE4NzUgMS45Mzc1IDUuNTMxMjUgMi4yODEyNUwzLjc4MTI1IDUuNzgxMjVMMC4yNSA3LjU2MjVDMC4wOTM3NSA3LjYyNSAwIDcuODEyNSAwIDhDMCA4LjE4NzUgMC4wOTM3NSA4LjM3NSAwLjI1IDguNDM3NUwzLjc4MTI1IDEwLjIxODhMNS41MzEyNSAxMy43NUM1LjYyNSAxMy45MDYyIDUuNzgxMjUgMTQgNiAxNEM2LjE1NjI1IDE0IDYuMzQzNzUgMTMuOTA2MiA2LjQzNzUgMTMuNzVMOC4xODc1IDEwLjIxODhMMTEuNzE4OCA4LjQzNzVDMTEuODc1IDguMzc1IDEyIDguMTg3NSAxMiA4WiIgZmlsbD0iIzViYzIzNyIgc3Ryb2tlPSIjNWJjMjM3IiBzdHlsZT0iZmlsbDogcmdiKDkxLCAxOTQsIDU1KTsgc3Ryb2tlOiByZ2IoOTEsIDE5NCwgNTUpOyIvPgo8L3N2Zz4=')}.ugb-e2459a9.ugb-icon-list ul{columns:1}@media screen and (min-width:768px){.ugb-e2459a9.ugb-icon-list{margin-top:0px !important;margin-bottom:35px !important}}@media screen and (max-width:768px){.ugb-e2459a9.ugb-icon-list{margin-bottom:10px !important}}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><ul><li>No se necesitan cubeta de retenci\u00f3n<\/li><\/ul><\/div><\/div><\/div>\n\n\n\n<div class=\"aligncenter wp-block-ugb-button ugb-button-wrapper blue-button ugb-9bb2d95 ugb-main-block\"><style>.ugb-9bb2d95 .ugb-block-content{justify-content:center !important}.ugb-9bb2d95 .ugb-button1 .ugb-button--inner{font-size:16px !important;font-weight:bold !important}.ugb-9bb2d95 .ugb-button1{padding-top:10px;padding-right:50px;padding-bottom:10px;padding-left:50px;opacity:1;border-radius:5px !important}.ugb-9bb2d95 .ugb-button1:hover{background-color:;opacity:1}.ugb-9bb2d95 .ugb-button1:before{content:\"\";background-image:linear-gradient(90deg,,);border-radius:5px !important}.ugb-9bb2d95 .ugb-inner-block{text-align:center}<\/style><div class=\"ugb-inner-block\"><div class=\"ugb-block-content\"><div class=\"ugb-button-container\"><a class=\"ugb-button1 ugb-button ugb-button--size-large ugb-button--ghost-to-normal-effect ugb-button--design-ghost\" href=\"https:\/\/varibox.best4u.dev\/es\/varibox_product\/varibox-drumtainer\/\" rel=\"\" title=\"\"><span class=\"ugb-button--inner\">M\u00e1s informaci\u00f3n<\/span><\/a><\/div><\/div><\/div><\/div>\n<\/div><\/div><\/div><\/div><\/div>\n<\/div><\/div><\/div><\/div>\n<\/div><\/div><\/div><\/div><\/div><\/div>\n\n","protected":false},"excerpt":{"rendered":"<p>VARIBOX Checker El n\u00famero de art\u00edculo completo consta de 12 caracteres (por ejemplo, VB1001AED709) y se encuentra en la confirmaci\u00f3n de pedido, en la factura o en la placa de identificaci\u00f3n del propio VARIBOX. Introd\u00fazcalo a continuaci\u00f3n para ver el material de la junta, la configuraci\u00f3n del tubo de aspiraci\u00f3n\/respiradero, el sensor de nivel y [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"footnotes":"","_yoast_wpseo_title":"","_yoast_wpseo_metadesc":"","_yoast_wpseo_focuskw":"","rank_math_title":"VARIBOX Checker | VARIBOX IBCs","rank_math_description":"Utiliza el VARIBOX Checker para obtener m\u00e1s informaci\u00f3n sobre el tipo de contenedor que pediste inicialmente a la f\u00e1brica de Deventer.","rank_math_focus_keyword":"VARIBOX Checker","_aioseop_title":"","_aioseop_description":""},"class_list":["post-73603","page","type-page","status-publish","hentry"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":8}},"featured_image_urls_v2":{"full":"","thumbnail":"","medium":"","medium_large":"","large":"","1536x1536":"","2048x2048":"","woocommerce_archive_thumbnail":"","gform-image-choice-sm":"","gform-image-choice-md":"","gform-image-choice-lg":"","woocommerce_thumbnail":"","woocommerce_single":"","woocommerce_gallery_thumbnail":"","variation_swatches_image_size":"","variation_swatches_tooltip_size":""},"post_excerpt_stackable_v2":"<p>VARIBOX CheckerEl n\u00famero de art\u00edculo completo consta de 12 caracteres (por ejemplo, VB1001AED709) y se encuentra en la confirmaci\u00f3n de pedido, en la factura o en la placa de identificaci\u00f3n del propio VARIBOX. Introd\u00fazcalo a continuaci\u00f3n para ver el material de la junta, la configuraci\u00f3n del tubo de aspiraci\u00f3n\/respiradero, el sensor de nivel y el color de su unidad. Esta herramienta cubre VARIBOX FC 1000, FC 800, CC 250 y Drumtainer \u2014 para otros productos VARIBOX (como Single Containment), p\u00f3ngase en contacto con el Servicio de Atenci\u00f3n al Cliente. P\u00f3ngase en contacto M\u00e1s seguro Reutilizable Sostenible Welke VARIBOX-variant heb ik?&hellip;<\/p>\n","category_list_v2":"","author_info_v2":{"name":"Jeffrey","url":"https:\/\/varibox.best4u.dev\/es\/author\/variwebshop\/"},"comments_num_v2":"0 comments","acf":[],"_links":{"self":[{"href":"https:\/\/varibox.best4u.dev\/es\/wp-json\/wp\/v2\/pages\/73603","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/varibox.best4u.dev\/es\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/varibox.best4u.dev\/es\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/varibox.best4u.dev\/es\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/varibox.best4u.dev\/es\/wp-json\/wp\/v2\/comments?post=73603"}],"version-history":[{"count":0,"href":"https:\/\/varibox.best4u.dev\/es\/wp-json\/wp\/v2\/pages\/73603\/revisions"}],"wp:attachment":[{"href":"https:\/\/varibox.best4u.dev\/es\/wp-json\/wp\/v2\/media?parent=73603"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}