{"id":18902,"date":"2026-05-28T14:16:33","date_gmt":"2026-05-28T07:16:33","guid":{"rendered":"https:\/\/staging.vietnamdetox.com\/dat-cho\/"},"modified":"2026-09-03T09:49:34","modified_gmt":"2026-09-03T02:49:34","slug":"dat-cho","status":"publish","type":"page","link":"https:\/\/staging.vietnamdetox.com\/vi\/dat-cho\/","title":{"rendered":"\u0110\u1eb7t ch\u1ed7"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"18902\" class=\"elementor elementor-18902 elementor-18130\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-d7b5290 e-con e-atomic-element e-flexbox-base e-330c203 \" data-id=\"d7b5290\" data-element_type=\"e-flexbox\" data-e-type=\"e-flexbox\" data-interaction-id=\"d7b5290\" data-e-type=\"e-flexbox\" data-id=\"d7b5290\">\n    \t\t<div class=\"elementor-element elementor-element-ee7c941 elementor-widget elementor-widget-html\" data-id=\"ee7c941\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" \/>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" \/>\n    <title>Vietnam Detox Booking<\/title>\n    <script src=\"https:\/\/cdn.tailwindcss.com\/3.4.17\"><\/script>\n    <script>\n      tailwind.config = {\n        theme: {\n          extend: {\n            colors: {\n              brand: {\n                ivory: '#fefaf2',\n                panna: '#f5e8d0',\n                ember: '#e06420',\n                gold: '#f5a030',\n                forest: '#1e3d20',\n                ink: '#1c1c18',\n                muted: '#8a8070',\n              },\n              emerald: {\n                50: '#fff6ed',\n                100: '#fce5d3',\n                200: '#f6c8a5',\n                300: '#efa06c',\n                400: '#e97b3f',\n                500: '#e06420',\n                600: '#e06420',\n                700: '#d45318',\n                800: '#e06420',\n                900: '#c43010',\n                950: '#8c2a0c',\n              },\n              stone: {\n                50: '#fdf9f1',\n                100: '#f5e8d0',\n                200: '#e5d5ba',\n                300: '#cbbba3',\n                400: '#a89d89',\n                500: '#8a8070',\n                600: '#655f54',\n                700: '#2c2820',\n                800: '#1e3d20',\n                900: '#1c1c18',\n                950: '#12120f',\n              },\n              amber: {\n                50: '#fff8e8',\n                100: '#fceed0',\n                200: '#fbd99b',\n                300: '#f8bd60',\n                400: '#f5a030',\n                500: '#f5a030',\n                600: '#d78b25',\n                700: '#a9671c',\n                800: '#7f4c19',\n                900: '#663e18',\n                950: '#3b200a',\n              },\n              rose: {\n                50: '#fff3ed',\n                100: '#fbded0',\n                200: '#f4bca4',\n                300: '#ea8f6d',\n                400: '#e06420',\n                500: '#d45318',\n                600: '#c43010',\n                700: '#a42b0d',\n                800: '#85250f',\n                900: '#6d2210',\n                950: '#3b0e06',\n              },\n            },\n            fontFamily: {\n              sans: ['\"Be Vietnam Pro\"', 'system-ui', 'sans-serif'],\n              display: ['\"Cormorant Garamond\"', 'Georgia', 'serif'],\n            },\n          }\n        }\n      }\n    <\/script>\n    <script crossorigin src=\"https:\/\/unpkg.com\/react@18.3.1\/umd\/react.production.min.js\"><\/script>\n    <script crossorigin src=\"https:\/\/unpkg.com\/react-dom@18.3.1\/umd\/react-dom.production.min.js\"><\/script>\n    <script src=\"https:\/\/unpkg.com\/@babel\/standalone@7.26.2\/babel.min.js\"><\/script>\n    <link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\" \/>\n    <link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin \/>\n    <link href=\"https:\/\/fonts.googleapis.com\/css2?family=Be+Vietnam+Pro:wght@300;400;500;600&family=Cormorant+Garamond:ital,wght@0,300;0,400;0,500;1,300;1,400&display=swap\" rel=\"stylesheet\" \/>\n    <style>\n      :root {\n        --vdx-ivory: #fefaf2;\n        --vdx-panna: #f5e8d0;\n        --vdx-warm: #edd5a8;\n        --vdx-white: #fffdf8;\n        --vdx-ember: #e06420;\n        --vdx-flame: #c43010;\n        --vdx-gold: #f5a030;\n        --vdx-forest: #1e3d20;\n        --vdx-ink: #1c1c18;\n        --vdx-body: #2c2820;\n        --vdx-muted: #8a8070;\n        --vdx-border: rgba(30, 61, 32, 0.13);\n        --vdx-display: \"Cormorant Garamond\", Georgia, serif;\n        --vdx-sans: \"Be Vietnam Pro\", system-ui, sans-serif;\n      }\n\n      body {\n        margin: 0;\n        background: var(--vdx-ivory);\n        color: var(--vdx-body);\n        font-family: var(--vdx-sans);\n      }\n\n      \/*\n       * Elementor embeds the site header above this file with negative template\n       * margins and an overlaid header. Remove the manual page offset and reserve\n       * the real header height instead. These rules are inactive when this file\n       * is opened as a standalone page.\n       *\/\n      body.vdx-elementor-embed .elementor-location-header {\n        margin: 0 !important;\n      }\n\n      body.vdx-elementor-embed\n      .elementor[data-elementor-type=\"wp-page\"]\n      > .elementor-element:first-child {\n        margin-block-start: 0 !important;\n      }\n\n      body.vdx-elementor-embed #booking-app-wrapper {\n        padding-top: 110px !important;\n      }\n\n      @media (max-width: 1199px) {\n        body.vdx-elementor-embed #booking-app-wrapper {\n          padding-top: 92px !important;\n        }\n      }\n\n      .hide-scrollbar::-webkit-scrollbar {\n        display: none;\n      }\n      .hide-scrollbar {\n        -ms-overflow-style: none;\n        scrollbar-width: none;\n      }\n      \/* Prevent iOS Safari auto-zoom on input focus *\/\n      @media screen and (max-width: 768px) {\n        #booking-app-wrapper input,\n        #booking-app-wrapper select,\n        #booking-app-wrapper textarea {\n          font-size: 16px !important;\n        }\n      }\n      \/* Prevent blue browser outlines, use the brand ember accent instead *\/\n      #booking-app-wrapper *:focus-visible {\n        outline: 2px solid #e06420 !important;\n        outline-offset: 2px;\n      }\n\n      \/* ---------------------------------------------------------------\n         VIETNAM DETOX 2026 DESIGN SYSTEM\n         Shared visual foundation for every step of the booking flow.\n         --------------------------------------------------------------- *\/\n\n      #root,\n      #booking-app-wrapper,\n      #booking-app-wrapper *,\n      #booking-app-wrapper *::before,\n      #booking-app-wrapper *::after {\n        box-sizing: border-box;\n      }\n\n      #booking-app-wrapper {\n        min-height: 100vh;\n        overflow-x: clip;\n        background:\n          radial-gradient(circle at 8% 4%, rgba(245, 160, 48, 0.09), transparent 28rem),\n          radial-gradient(circle at 94% 28%, rgba(30, 61, 32, 0.055), transparent 34rem),\n          var(--vdx-ivory) !important;\n        color: var(--vdx-body) !important;\n        font-family: var(--vdx-sans) !important;\n        font-weight: 400;\n        line-height: 1.7;\n      }\n\n      #booking-app-wrapper button,\n      #booking-app-wrapper input,\n      #booking-app-wrapper select,\n      #booking-app-wrapper textarea {\n        font-family: var(--vdx-sans) !important;\n      }\n\n      #booking-app-wrapper > div > main {\n        padding-top: clamp(48px, 6vw, 76px) !important;\n        padding-bottom: clamp(88px, 9vw, 124px) !important;\n      }\n\n      \/* Editorial step introductions used throughout Home and Y\u00ean Retreat. *\/\n      #booking-app-wrapper header {\n        position: relative;\n        max-width: 760px;\n        padding-left: 22px;\n      }\n\n      #booking-app-wrapper header::before {\n        position: absolute;\n        top: 4px;\n        bottom: 4px;\n        left: 0;\n        width: 2px;\n        background: linear-gradient(180deg, var(--vdx-ember), rgba(224, 100, 32, 0.12));\n        content: \"\";\n      }\n\n      #booking-app-wrapper header > p:first-child,\n      #booking-app-wrapper section > p:first-child[class*=\"uppercase\"],\n      #booking-app-wrapper section > div:first-child > p:first-child[class*=\"uppercase\"] {\n        color: var(--vdx-ember) !important;\n        font-family: var(--vdx-sans) !important;\n        font-size: 10px !important;\n        font-weight: 600 !important;\n        letter-spacing: 0.2em !important;\n        line-height: 1.5;\n      }\n\n      #booking-app-wrapper h1 {\n        margin: 0;\n        color: var(--vdx-forest) !important;\n        font-family: var(--vdx-display) !important;\n        font-size: clamp(44px, 5vw, 62px) !important;\n        font-weight: 300 !important;\n        letter-spacing: -0.025em;\n        line-height: 1.02;\n        text-wrap: balance;\n      }\n\n      #booking-app-wrapper h2,\n      #booking-app-wrapper h3 {\n        color: var(--vdx-forest) !important;\n        font-family: var(--vdx-display) !important;\n        font-weight: 400 !important;\n        letter-spacing: -0.012em;\n        line-height: 1.12;\n      }\n\n      #booking-app-wrapper h2 {\n        font-size: clamp(26px, 3vw, 34px) !important;\n      }\n\n      #booking-app-wrapper header h1 + p {\n        max-width: 66ch;\n        color: var(--vdx-muted) !important;\n        font-size: 15px;\n        font-weight: 300;\n        line-height: 1.8;\n      }\n\n      \/* Softer cards and restrained radii from the current site. *\/\n      #booking-app-wrapper .rounded-3xl {\n        border-radius: 20px !important;\n      }\n\n      #booking-app-wrapper .rounded-2xl {\n        border-radius: 14px !important;\n      }\n\n      #booking-app-wrapper .bg-white {\n        background-color: rgba(255, 253, 248, 0.96) !important;\n      }\n\n      #booking-app-wrapper .bg-stone-50 {\n        background-color: rgba(245, 232, 208, 0.28) !important;\n      }\n\n      #booking-app-wrapper .border-stone-100,\n      #booking-app-wrapper .border-stone-200 {\n        border-color: var(--vdx-border) !important;\n      }\n\n      #booking-app-wrapper .shadow-sm {\n        box-shadow: 0 10px 28px rgba(30, 61, 32, 0.065) !important;\n      }\n\n      #booking-app-wrapper .shadow-md,\n      #booking-app-wrapper .shadow-lg {\n        box-shadow: 0 18px 42px rgba(30, 61, 32, 0.1) !important;\n      }\n\n      #booking-app-wrapper .shadow-xl,\n      #booking-app-wrapper .shadow-2xl {\n        box-shadow: 0 24px 60px rgba(28, 28, 24, 0.14) !important;\n      }\n\n      #booking-app-wrapper .bg-emerald-50 {\n        background-color: rgba(224, 100, 32, 0.065) !important;\n      }\n\n      #booking-app-wrapper .border-emerald-100,\n      #booking-app-wrapper .border-emerald-200 {\n        border-color: rgba(224, 100, 32, 0.2) !important;\n      }\n\n      \/* Fields use the same quiet white surface and ember focus treatment. *\/\n      #booking-app-wrapper input:not([type=\"checkbox\"]):not([type=\"radio\"]),\n      #booking-app-wrapper select,\n      #booking-app-wrapper textarea {\n        min-height: 52px;\n        border: 1px solid rgba(30, 61, 32, 0.18) !important;\n        border-radius: 8px !important;\n        background: var(--vdx-white) !important;\n        color: var(--vdx-ink) !important;\n        box-shadow: none !important;\n        transition: border-color 180ms ease, box-shadow 180ms ease;\n      }\n\n      #booking-app-wrapper textarea {\n        min-height: 126px;\n        resize: vertical;\n      }\n\n      #booking-app-wrapper input::placeholder,\n      #booking-app-wrapper textarea::placeholder {\n        color: rgba(44, 40, 32, 0.42) !important;\n        opacity: 1;\n      }\n\n      #booking-app-wrapper input:not([type=\"checkbox\"]):not([type=\"radio\"]):focus,\n      #booking-app-wrapper select:focus,\n      #booking-app-wrapper textarea:focus {\n        border-color: var(--vdx-ember) !important;\n        outline: none !important;\n        box-shadow: 0 0 0 3px rgba(224, 100, 32, 0.13) !important;\n      }\n\n      #booking-app-wrapper input[type=\"checkbox\"],\n      #booking-app-wrapper input[type=\"radio\"] {\n        accent-color: var(--vdx-ember);\n      }\n\n      \/*\n       * Use one shape for every text\/action button. Icon-only controls remain\n       * circular so their compact hit areas and familiar affordances are kept.\n       *\/\n      #booking-app-wrapper button:not(.vdx-icon-button):not(.vdx-date-arrow):not(.vdx-date-button),\n      #booking-app-wrapper a.vdx-action-button {\n        border-radius: 8px !important;\n      }\n\n      #booking-app-wrapper .vdx-date-button {\n        border-radius: 9999px !important;\n      }\n\n      \/* Primary navigation actions: compact, uppercase and ember\u2014not pills. *\/\n      #booking-app-wrapper button.bg-emerald-800.px-6,\n      #booking-app-wrapper button.bg-emerald-800.px-8,\n      #booking-app-wrapper button.bg-emerald-800.w-full,\n      #booking-app-wrapper a.bg-emerald-800,\n      #booking-app-wrapper button.bg-stone-900.px-8,\n      #booking-app-wrapper button.bg-stone-200.px-6 {\n        min-height: 48px;\n        border: 1px solid transparent !important;\n        border-radius: 8px !important;\n        font-size: 11px !important;\n        font-weight: 600 !important;\n        letter-spacing: 0.14em;\n        line-height: 1.3;\n        text-transform: uppercase;\n        box-shadow: none !important;\n        transition: background 180ms ease, border-color 180ms ease, color 180ms ease, transform 180ms ease;\n      }\n\n      #booking-app-wrapper button.bg-emerald-800.px-6,\n      #booking-app-wrapper button.bg-emerald-800.px-8,\n      #booking-app-wrapper button.bg-emerald-800.w-full,\n      #booking-app-wrapper a.bg-emerald-800 {\n        border-color: var(--vdx-ember) !important;\n        background: var(--vdx-ember) !important;\n        color: var(--vdx-ivory) !important;\n      }\n\n      #booking-app-wrapper button.bg-emerald-800.px-6:hover,\n      #booking-app-wrapper button.bg-emerald-800.px-8:hover,\n      #booking-app-wrapper button.bg-emerald-800.w-full:hover,\n      #booking-app-wrapper a.bg-emerald-800:hover {\n        border-color: var(--vdx-flame) !important;\n        background: var(--vdx-flame) !important;\n        color: var(--vdx-ivory) !important;\n        transform: translateY(-1px);\n      }\n\n      #booking-app-wrapper button.bg-stone-900.px-8 {\n        border-color: var(--vdx-forest) !important;\n        background: var(--vdx-forest) !important;\n        color: var(--vdx-ivory) !important;\n      }\n\n      #booking-app-wrapper button.bg-stone-900.px-8:hover {\n        background: #29552b !important;\n      }\n\n      #booking-app-wrapper button:disabled {\n        transform: none !important;\n      }\n\n      #booking-app-wrapper #payment-actions {\n        border: 1px solid rgba(30, 61, 32, 0.09);\n        background: rgba(245, 232, 208, 0.32) !important;\n      }\n\n      #booking-app-wrapper .font-mono {\n        color: var(--vdx-forest) !important;\n        font-family: var(--vdx-sans) !important;\n        letter-spacing: 0.06em;\n      }\n\n      @media (max-width: 767px) {\n        #booking-app-wrapper {\n          padding-bottom: 72px !important;\n          background:\n            radial-gradient(circle at 12% 3%, rgba(245, 160, 48, 0.08), transparent 20rem),\n            var(--vdx-ivory) !important;\n        }\n\n        #booking-app-wrapper > div > main {\n          padding: 38px 18px 72px !important;\n        }\n\n        #booking-app-wrapper header {\n          padding-left: 17px;\n        }\n\n        #booking-app-wrapper h1 {\n          font-size: clamp(39px, 12vw, 50px) !important;\n        }\n\n        #booking-app-wrapper .rounded-3xl {\n          border-radius: 16px !important;\n        }\n\n        #booking-app-wrapper button.bg-emerald-800.px-6,\n        #booking-app-wrapper button.bg-emerald-800.px-8,\n        #booking-app-wrapper button.bg-emerald-800.w-full,\n        #booking-app-wrapper a.bg-emerald-800,\n        #booking-app-wrapper button.bg-stone-900.px-8 {\n          width: 100%;\n          justify-content: center;\n        }\n\n        \/* Keep paired step actions compact beside Back. Their enabled\n           bg-emerald class otherwise triggers the full-width mobile primary-\n           button rule above. *\/\n        #booking-app-wrapper button.vdx-paired-step-action {\n          flex: 0 0 auto;\n          width: auto !important;\n          min-height: 44px;\n          padding: 10px 16px !important;\n        }\n      }\n\n      @media (prefers-reduced-motion: reduce) {\n        #booking-app-wrapper *,\n        #booking-app-wrapper *::before,\n        #booking-app-wrapper *::after {\n          scroll-behavior: auto !important;\n          transition-duration: 0.01ms !important;\n        }\n      }\n      \/* Keep selected\/action colors from being replaced by Hello Elementor's button:focus rule. *\/\n      #booking-app-wrapper button.bg-emerald-50:hover,\n      #booking-app-wrapper button.bg-emerald-50:focus,\n      #booking-app-wrapper button.bg-emerald-50:active {\n        color: #1c1c18 !important;\n        background-color: #fff6ed !important;\n        border-color: #e06420 !important;\n      }\n      #booking-app-wrapper button.bg-emerald-800:focus,\n      #booking-app-wrapper button.bg-emerald-800:active {\n        color: #fff !important;\n        background-color: #e06420 !important;\n        border-color: #e06420 !important;\n      }\n      #booking-app-wrapper button.bg-emerald-800:hover {\n        color: #fff !important;\n        background-color: #c43010 !important;\n        border-color: #c43010 !important;\n      }\n      #booking-app-wrapper .vdx-date-arrow,\n      #booking-app-wrapper .vdx-date-arrow:active {\n        width: 28px !important;\n        min-width: 28px !important;\n        height: 28px !important;\n        padding: 0 !important;\n        color: #1e3d20 !important;\n        background-color: #fefaf2 !important;\n        border-color: #e5d5ba !important;\n      }\n      #booking-app-wrapper .vdx-date-arrow svg {\n        display: block !important;\n        width: 16px !important;\n        height: 16px !important;\n        flex: 0 0 16px !important;\n        fill: none !important;\n        stroke: #1e3d20 !important;\n        stroke-width: 2.5 !important;\n      }\n      #booking-app-wrapper .vdx-date-arrow:hover,\n      #booking-app-wrapper .vdx-date-arrow:focus-visible {\n        color: #fff !important;\n        background-color: #e06420 !important;\n        border-color: #e06420 !important;\n      }\n      #booking-app-wrapper .vdx-date-arrow:hover svg,\n      #booking-app-wrapper .vdx-date-arrow:focus-visible svg {\n        stroke: #fff !important;\n      }\n    <\/style>\n  <\/head>\n  <body class=\"bg-brand-ivory\">\n    <script>\n      if (document.querySelector(\".elementor-location-header\")) {\n        document.body.classList.add(\"vdx-elementor-embed\");\n      }\n    <\/script>\n    <div id=\"root\"><\/div>\n\n    <script type=\"text\/babel\" data-presets=\"react\">\n      \/** @jsxRuntime classic *\/\n      const FALLBACK_IMAGE = \"\/wp-content\/uploads\/2024\/11\/retreat-placeholder.webp\";\n      let bookingRoot = null;\n\n      const getInitialLang = () => {\n        const docLang = document.documentElement.lang?.toLowerCase() || \"\";\n        if (docLang.startsWith(\"vi\")) return \"vn\";\n        if (docLang.startsWith(\"de\")) return \"de\";\n        \n        const path = window.location.pathname.toLowerCase();\n        if (path.includes(\"dang-ky\")) return \"vn\";\n        if (path.includes(\"\/de\/\")) return \"de\";\n        \n        return \"en\";\n      };\n\n      const normalizeLang = (value) => {\n        const normalized = String(value || \"\").toLowerCase();\n        if (normalized === \"vi\") return \"vn\";\n        return [\"en\", \"vn\", \"de\"].includes(normalized) ? normalized : getInitialLang();\n      };\n\n      const normalizeBookingReturnPath = (value) => {\n        if (!value) return \"\";\n        try {\n          const path = new URL(value, window.location.origin).pathname;\n          const normalizedPath = `\/${path.replace(\/^\\\/+|\\\/+$\/g, \"\")}\/`;\n          return [\"\/booking\/\", \"\/vi\/dat-cho\/\", \"\/de\/booking-flow\/\"].includes(normalizedPath)\n            ? normalizedPath\n            : \"\";\n        } catch (error) {\n          return \"\";\n        }\n      };\n\n      const getDefaultBookingReturnPath = (lang) => {\n        const normalizedLang = normalizeLang(lang);\n        if (normalizedLang === \"vn\") return \"\/vi\/dat-cho\/\";\n        if (normalizedLang === \"de\") return \"\/de\/booking-flow\/\";\n        return \"\/booking\/\";\n      };\n\n      const getBookingReturnPath = (lang = getInitialLang()) => {\n        const fallbackPath = getDefaultBookingReturnPath(lang);\n\n        \/\/ Elementor normally runs the app inline. If it is placed in a\n        \/\/ same-origin frame, use the parent page rather than the frame URL.\n        if (window.top === window) {\n          return normalizeBookingReturnPath(window.location.href) || fallbackPath;\n        }\n\n        const candidates = [];\n        try {\n          candidates.push(window.top.location.href);\n        } catch (error) {\n          \/\/ A cross-origin parent cannot be inspected; document.referrer is\n          \/\/ the safe fallback in that case.\n        }\n        candidates.push(document.referrer, window.location.href);\n\n        for (const candidate of candidates) {\n          const path = normalizeBookingReturnPath(candidate);\n          if (path) return path;\n        }\n\n        return fallbackPath;\n      };\n\n      const showInlineError = (message, options = {}) => {\n        const { retry = false } = options;\n        const container = document.getElementById(\"root\");\n        if (!container) return;\n        container.innerHTML = \"\";\n        const wrapper = document.createElement(\"div\");\n        wrapper.id = \"booking-app-wrapper\";\n        wrapper.style.padding = \"48px 24px\";\n        wrapper.style.fontFamily = '\"Be Vietnam Pro\", system-ui, sans-serif';\n        wrapper.style.maxWidth = \"560px\";\n        wrapper.style.margin = \"64px auto\";\n        wrapper.style.textAlign = \"center\";\n        const heading = document.createElement(\"h2\");\n        heading.textContent = \"We hit a snag\";\n        heading.style.marginBottom = \"12px\";\n        heading.style.color = \"#1c1c18\";\n        const body = document.createElement(\"p\");\n        body.textContent = message || \"Please try again in a moment.\";\n        body.style.color = \"#8a8070\";\n        body.style.marginBottom = retry ? \"20px\" : \"0\";\n        wrapper.appendChild(heading);\n        wrapper.appendChild(body);\n        if (retry) {\n          const button = document.createElement(\"button\");\n          button.type = \"button\";\n          button.textContent = \"Try again\";\n          button.style.background = \"#e06420\";\n          button.style.color = \"#fff\";\n          button.style.border = \"none\";\n          button.style.padding = \"12px 24px\";\n          button.style.borderRadius = \"8px\";\n          button.style.fontWeight = \"600\";\n          button.style.letterSpacing = \"0.12em\";\n          button.style.textTransform = \"uppercase\";\n          button.style.cursor = \"pointer\";\n          button.addEventListener(\"click\", () => {\n            button.disabled = true;\n            button.textContent = \"Reconnecting\u2026\";\n            bootBookingApp();\n          });\n          wrapper.appendChild(button);\n        }\n        container.appendChild(wrapper);\n      };\n\n      const handleImageError = (event) => {\n        const target = event?.target;\n        if (!target || target.dataset?.fallbackApplied === \"true\") return;\n        target.src = FALLBACK_IMAGE;\n        target.setAttribute(\"data-fallback-applied\", \"true\");\n        target.alt = target.alt ? `${target.alt} unavailable` : \"Image unavailable\";\n      };\n\n      let RETREATS = [];\n      let TRANSPORT_BY_RETREAT = {};\n      let ROOMS_BY_RETREAT = [];\n\n      const fetchRetreats = async (overrideLang = null) => {\n        try {\n          const params = new URLSearchParams(window.location.search || \"\");\n          const langParam = normalizeLang(\n            overrideLang || params.get(\"booking_lang\") || params.get(\"lang\") || getInitialLang()\n          );\n          const response = await fetch(`\/wp-json\/retreats\/v1\/all?lang=${langParam}`);\n          if (!response.ok) throw new Error(`HTTP ${response.status}`);\n          const rawRetreats = await response.json();\n          if (!Array.isArray(rawRetreats) || rawRetreats.length === 0) {\n            throw new Error(\"Empty retreat response\");\n          }\n\n          const buildRoomBenefit = (pkg) => {\n            if (pkg.roomType) return pkg.roomType;\n            if (pkg.type) return pkg.type;\n            if (pkg.person) return pkg.person > 1 ? `Shared for ${pkg.person}` : \"Solo retreat\";\n            return \"Retreat package\";\n          };\n\n          RETREATS = rawRetreats.map((retreat) => {\n            const packages = Array.isArray(retreat.packages) ? retreat.packages : [];\n            const transportations = Array.isArray(retreat.transportations) ? retreat.transportations : [];\n            const normalizedPackages = packages.map((pkg, index) => {\n              const sku = pkg.sku || null;\n              return {\n                ...pkg,\n                id: sku || `pkg-${retreat.id}-${index}`,\n                sku,\n                images: Array.isArray(pkg.images) && pkg.images.length > 0 ? pkg.images : [FALLBACK_IMAGE],\n                benefit: buildRoomBenefit(pkg),\n              };\n            });\n\n            TRANSPORT_BY_RETREAT[retreat.id] = transportations;\n            ROOMS_BY_RETREAT[retreat.id] = normalizedPackages;\n            return retreat;\n          });\n\n          return RETREATS.length > 0;\n        } catch (error) {\n          console.error(\"Failed to fetch retreats:\", error);\n          return false;\n        }\n      };\n\n      window.__fetchRetreats = fetchRetreats;\n\n      const TRANSLATIONS = {\n        en: {\n          step: \"Step\",\n          plan_journey: \"Plan your journey\",\n          plan_description: \"Select the start date, number of guests, and residence. Every price line item updates before we request personal details.\",\n          upcoming_retreats: \"Upcoming retreats\",\n          retreats_description: \"Choose the experience and date that resonates most with your well-being goals.\",\n          available_dates: \"Available dates\",\n          early_bird_label: \"Early Bird \u2013{{discount}}\",\n          limited_spots: \"Limited spots available\",\n          guests: \"Guests\",\n          one_guest: \"One guest\",\n          two_guests: \"Two guests\",\n          save_together: \"Save {{discount}} together\",\n          private_journey: \"Fully private journey\",\n          guest_one: \"Guest One\",\n          guest_two: \"Guest Two\",\n          accommodation: \"Accommodation\",\n          health_prep_first: \"Health preparation first\",\n          health_prep_description: \"Every guest completes their own health & lifestyle questionnaire during booking and enjoys a personal preparation call with the Vietnam Detox team after payment.\",\n          no_accommodation: \"Accommodation options will appear here for this retreat.\",\n          no_upcoming_dates: \"No upcoming retreat dates are currently available.\",\n          per_guest: \"Per guest\",\n          selected: \"Selected\",\n          tap_to_select: \"Tap to select\",\n          view_photos: \"View photos\",\n          airport_transfer: \"Airport transfer (optional)\",\n          continue_to_details: \"Continue to details\",\n          continue: \"Continue\",\n          details: \"Details\",\n          details_description: \"Used for booking confirmation and invoicing only. These contacts also receive each guest\u2019s health questionnaire and preparation call details.\",\n          primary_guest: \"Primary guest\",\n          primary_description: \"This information appears on your booking confirmation and invoice.\",\n          first_name: \"First name\",\n          last_name: \"Last name\",\n          email_address: \"Email address\",\n          phone_number: \"Phone number\",\n          phone_helper: \"Helpful in case we need to reach you shortly before arrival.\",\n          invoice_helper: \"We use this information only to issue your booking confirmation and invoice if required.\",\n          street_house: \"Street & house number\",\n          city: \"City\",\n          postal_code: \"Postal code\",\n          country_residence: \"Country of residence\",\n          need_company_invoice: \"I need an invoice issued to a company\",\n          company_name: \"Company name\",\n          tax_id: \"VAT \/ Tax ID\",\n          second_guest: \"Second guest\",\n          second_description: \"Used to send their questionnaire and schedule their personal preparation call.\",\n          back: \"Back\",\n          review: \"Review\",\n          review_description: \"Confirm dates, residence, guests, and transfers before the deposit step.\",\n          retreat: \"Retreat\",\n          retreat_dates: \"Retreat dates\",\n          edit: \"Edit\",\n          no_transfer: \"No airport transfer\",\n          deposit_health_review: \"Deposit & health review\",\n          deposit_secures: \"A 30% deposit secures your booking.\",\n          health_info: \"After your deposit, each guest receives their own health questionnaire and we schedule a personal preparation call.\",\n          health_prep: \"Health preparation\",\n          health_prep_desc: \"To support your well-being, every guest completes a short questionnaire followed by a personal preparation call with our team. This ensures the retreat is tailored and safe for you.\",\n          medical_confidentiality: \"Medical Confidentiality\",\n          medical_confidentiality_desc: \"Your health information is treated with strict medical confidentiality and is only accessible by our senior medical team.\",\n          after_deposit: \"After deposit\",\n          questionnaire: \"Questionnaire\",\n          questionnaire_desc: \"Each guest receives their own health & lifestyle questionnaire to complete at their own pace.\",\n          before_arrival: \"Before arrival\",\n          prep_call: \"Preparation Call\",\n          prep_call_desc: \"A mandatory 30-minute private call to review your answers and answer any questions you may have.\",\n          refund_policy: \"100% refund of your deposit if participating is not recommended after the health review.\",\n          continue_to_payment: \"Continue to payment\",\n          payment: \"Payment\",\n          payment_desc: \"Secure your booking with a 30% deposit.\",\n          payment_method: \"Payment method\",\n          zero_extra_fees: \"Zero extra fees\",\n          card_processing_fee: \"Card processing fee (3.6%)\",\n          onepay_domestic: \"OnePay \u00b7 Domestic QR\",\n          onepay_international: \"OnePay \u00b7 International Cards\",\n          onepay_domestic_desc: \"Pay via local bank apps with QR. No extra fees.\",\n          onepay_intl_desc: \"Pay via Visa, Mastercard, JCB, Amex. Secured by OnePay.\",\n          stripe_desc: \"Secure card payment in USD. A 3.6% processing fee is automatically added to the total.\",\n          bank_transfer_desc: \"Pay in VND via local bank transfer. No extra processing fees.\",\n          processing_payment: \"Processing payment...\",\n          confirm_bank_transfer: \"Confirm bank transfer\",\n          pay_securely_msg: \"Pay {{amount}} securely\",\n          booking_secured: \"Booking secured!\",\n          proceeding_next: \"Proceeding to next step...\",\n          almost_done: \"You\u2019re almost done.\",\n          health_prep_screening_desc: \"Each guest completes a personal health questionnaire and a mandatory preparation call with the Vietnam Detox team. This is how we tailor the experience and make sure you feel confident before arrival.\",\n          what_happens_next: \"What happens next\",\n          timeline_item_1: \"Each guest receives their own health & lifestyle questionnaire.\",\n          timeline_item_2: \"The Vietnam Detox team reviews every response personally.\",\n          timeline_item_3: \"A mandatory 30-minute preparation call is scheduled after each questionnaire.\",\n          timeline_item_4: \"Status after payment: Reserved \u2013 preparation pending.\",\n          timeline_item_5: \"Status after calls: Booking confirmed.\",\n          quick_precheck: \"Quick pre-check\",\n          quick_precheck_desc: \"If you answer \u201cYes\u201d to any of these, our team will follow up personally.\",\n          safety_question_1: \"Are you currently pregnant or breastfeeding?\",\n          safety_question_2: \"Do you have Type 1 diabetes?\",\n          safety_question_3: \"Do you have a diagnosed eating disorder?\",\n          safety_question_4: \"Are you under active treatment that may affect fasting?\",\n          yes: \"Yes\",\n          no: \"No\",\n          continue_begin_health_prep: \"Continue \u2013 Begin Health Preparation\",\n          back_to_booking: \"Back to booking\",\n          prep_timeline: \"Health preparation timeline\",\n          prep_timeline_desc: \"Track questionnaires, preparation calls, and final confirmation.\",\n          deposit_received: \"Deposit received\",\n          status_reserved_pending: \"Status: Reserved \u2013 preparation pending\",\n          awaiting_payment: \"Awaiting payment\",\n          guest_1_health_prep: \"Guest 1 health preparation\",\n          guest_2_health_prep: \"Guest 2 health preparation\",\n          prep_complete: \"Questionnaire + call complete\",\n          awaiting_prep: \"Awaiting questionnaire and call\",\n          team_confirmation: \"Vietnam Detox team confirmation\",\n          status_confirmed: \"Status: Booking confirmed\",\n          begins_after_calls: \"Begins after preparation calls\",\n          guest: \"Guest\",\n          confirmation_note: \"We confirm once both questionnaires and preparation calls are complete.\",\n          questionnaire_call_complete: \"Questionnaire + call complete\",\n          awaiting_questionnaire_call: \"Awaiting questionnaire and call\",\n          open_health_questionnaire: \"Open health questionnaire\",\n          link_copied: \"Link copied\",\n          copy_this_link: \"Copy this link\",\n          copy_link: \"Copy link\",\n          share_link_description: \"You can share this link if the questionnaire should be completed on another device or by your travel partner.\",\n          included_personal_health_review_call: \"Included personal health review call\",\n          included_personal_health_review_call_desc: \"After submitting the health questionnaire, the Vietnam Detox team offers a complimentary 30-minute 1-on-1 call to review your answers, answer questions, and make sure the program is well suited for you. This call is included in your retreat and will be scheduled after the health preparation steps are submitted.\",\n          request_health_review_call_alert: \"Thank you. We will contact you to schedule your personal health review call.\",\n          request_my_health_review_call: \"Request my health review call\",\n          back_to_health_preparation_hub: \"Back to health preparation hub\",\n          move_to_confirmation: \"Move to confirmation\",\n          booking_confirmed: \"Booking confirmed\",\n          booking_confirmed_desc: \"Your journey to health is now officially scheduled. We look forward to welcoming you at the retreat.\",\n          booking_ref: \"Booking Reference\",\n          return_home: \"Return to home page\",\n          investment_summary: \"Investment summary\",\n          real_time_update: \"Line items update in real-time.\",\n          subtotal: \"Subtotal\",\n          early_bird_discount: \"Early Bird \u2013{{discount}}\",\n          friend_discount: \"Shared room discount\",\n          retreat_total: \"Retreat total\",\n          deposit_label: \"Deposit\",\n          deposit_due_label: \"Deposit due today\",\n          quick_pre_check: \"Quick Pre-Check\",\n          quick_pre_check_desc: \"Before we finalize your reservation, we need to ask a few health & safety questions.\",\n          remaining_balance: \"Remaining balance\",\n          card_fee: \"Card processing fee\",\n          due_today: \"Due today\",\n          deposit_received_msg: \"Deposit received.\",\n          refund_note: \"100% refund if participation is declined after the health review.\",\n          something_went_wrong: \"Something went wrong\",\n          error_desc: \"We encountered an error while processing your booking. Please refresh the page.\",\n          refresh_page: \"Refresh page\",\n          language: \"Language\",\n          booking_progress: \"Booking progress\",\n          underweight_title: \"Severe underweight \/ eating disorder\",\n          underweight_desc: \"Do you currently suffer from severe underweight (for example a BMI below 18) or from a diagnosed eating disorder such as anorexia?\",\n          liverKidney_title: \"Advanced liver or kidney condition\",\n          liverKidney_desc: \"Have you been diagnosed with advanced liver or kidney disease (reduced liver or kidney function)?\",\n          pregnancy_title: \"Pregnancy or breastfeeding\",\n          pregnancy_desc: \"Are you currently pregnant or breastfeeding a child?\",\n          cardio_title: \"Severe heart or cardiovascular condition\",\n          cardio_desc: \"Have you been diagnosed with a severe heart or cardiovascular condition (for example heart failure or advanced coronary heart disease)?\",\n          honest_answer_thanks: \"Thank you very much for your honest answer.\",\n          safety_guideline_1: \"Based on established fasting safety guidelines, the condition you have indicated is considered a situation where fasting should only be undertaken, if at all, under close specialist supervision in a clinical setting.\",\n          safety_guideline_2: \"Our fasting retreats are designed for preventive and restorative purposes and cannot provide the level of continuous monitoring required in this case.\",\n          safety_guideline_3: \"Out of responsibility for your safety and well-being, we are therefore unfortunately unable to offer participation in this retreat at this time. If you wish, you are very welcome to contact Vietnam Detox so we can share information about alternative, gentler lifestyle and nutrition programs that may be more appropriate for you right now.\",\n          contact_email: \"hello@vietnamdetox.com\",\n          contact_vd: \"Contact Vietnam Detox\",\n          return_overview: \"Return to retreat overview\",\n          read_more: \"Read more\",\n          payment_failed: \"Payment failed\",\n          payment_failed_desc: \"Something went wrong with your transaction. Please check your details or try a different payment method.\",\n          try_again: \"Try again\"\n        },\n        vn: {\n          step: \"B\u01b0\u1edbc\",\n          plan_journey: \"L\u00ean k\u1ebf ho\u1ea1ch h\u00e0nh tr\u00ecnh\",\n          plan_description: \"Ch\u1ecdn ng\u00e0y b\u1eaft \u0111\u1ea7u, s\u1ed1 kh\u00e1ch v\u00e0 ch\u1ed7 \u1edf. M\u1ecdi chi ph\u00ed s\u1ebd \u0111\u01b0\u1ee3c c\u1eadp nh\u1eadt tr\u01b0\u1edbc khi b\u1ea1n \u0111i\u1ec1n th\u00f4ng tin c\u00e1 nh\u00e2n.\",\n          upcoming_retreats: \"C\u00e1c kh\u00f3a thanh l\u1ecdc s\u1eafp t\u1edbi\",\n          retreats_description: \"Ch\u1ecdn tr\u1ea3i nghi\u1ec7m v\u00e0 ng\u00e0y ph\u00f9 h\u1ee3p nh\u1ea5t v\u1edbi m\u1ee5c ti\u00eau s\u1ee9c kh\u1ecfe c\u1ee7a b\u1ea1n.\",\n          available_dates: \"Ng\u00e0y c\u00f2n tr\u1ed1ng\",\n          early_bird_label: \"\u01afu \u0111\u00e3i \u0111\u1eb7t s\u1edbm \u2013{{discount}}\",\n          limited_spots: \"S\u1ed1 l\u01b0\u1ee3ng ch\u1ed7 c\u00f3 h\u1ea1n\",\n          guests: \"Kh\u00e1ch\",\n          one_guest: \"M\u1ed9t kh\u00e1ch\",\n          two_guests: \"Hai kh\u00e1ch\",\n          save_together: \"Ti\u1ebft ki\u1ec7m {{discount}} khi \u0111i c\u00f9ng nhau\",\n          private_journey: \"H\u00e0nh tr\u00ecnh ri\u00eang t\u01b0\",\n          guest_one: \"Kh\u00e1ch th\u1ee9 nh\u1ea5t\",\n          guest_two: \"Kh\u00e1ch th\u1ee9 hai\",\n          accommodation: \"Ch\u1ed7 \u1edf\",\n          health_prep_first: \"Chu\u1ea9n b\u1ecb s\u1ee9c kh\u1ecfe tr\u01b0\u1edbc\",\n          health_prep_description: \"M\u1ed7i kh\u00e1ch s\u1ebd ho\u00e0n th\u00e0nh b\u1ea3ng h\u1ecfi s\u1ee9c kh\u1ecfe & l\u1ed1i s\u1ed1ng trong khi \u0111\u1eb7t ch\u1ed7 v\u00e0 c\u00f3 cu\u1ed9c g\u1ecdi chu\u1ea9n b\u1ecb c\u00e1 nh\u00e2n v\u1edbi Vietnam Detox sau khi thanh to\u00e1n.\",\n          no_accommodation: \"C\u00e1c l\u1ef1a ch\u1ecdn ch\u1ed7 \u1edf s\u1ebd xu\u1ea5t hi\u1ec7n \u1edf \u0111\u00e2y cho kh\u00f3a n\u00e0y.\",\n          no_upcoming_dates: \"Hi\u1ec7n ch\u01b0a c\u00f3 ng\u00e0y retreat s\u1eafp t\u1edbi.\",\n          per_guest: \"M\u1ed7i kh\u00e1ch\",\n          selected: \"\u0110\u00e3 ch\u1ecdn\",\n          tap_to_select: \"Nh\u1ea5n \u0111\u1ec3 ch\u1ecdn\",\n          view_photos: \"Xem \u1ea3nh\",\n          airport_transfer: \"\u0110\u01b0a \u0111\u00f3n s\u00e2n bay (t\u00f9y ch\u1ecdn)\",\n          continue_to_details: \"Ti\u1ebfp t\u1ee5c \u0111\u1ebfn th\u00f4ng tin\",\n          continue: \"Ti\u1ebfp t\u1ee5c\",\n          details: \"Th\u00f4ng tin chi ti\u1ebft\",\n          details_description: \"Ch\u1ec9 s\u1eed d\u1ee5ng \u0111\u1ec3 x\u00e1c nh\u1eadn \u0111\u1eb7t ch\u1ed7 v\u00e0 xu\u1ea5t h\u00f3a \u0111\u01a1n. C\u00e1c li\u00ean h\u1ec7 n\u00e0y c\u0169ng s\u1ebd nh\u1eadn \u0111\u01b0\u1ee3c b\u1ea3ng h\u1ecfi s\u1ee9c kh\u1ecfe v\u00e0 th\u00f4ng tin cu\u1ed9c g\u1ecdi chu\u1ea9n b\u1ecb.\",\n          primary_guest: \"Kh\u00e1ch ch\u00ednh\",\n          primary_description: \"Th\u00f4ng tin n\u00e0y s\u1ebd xu\u1ea5t hi\u1ec7n tr\u00ean x\u00e1c nh\u1eadn \u0111\u1eb7t ch\u1ed7 v\u00e0 h\u00f3a \u0111\u01a1n.\",\n          first_name: \"T\u00ean\",\n          last_name: \"H\u1ecd\",\n          email_address: \"\u0110\u1ecba ch\u1ec9 email\",\n          phone_number: \"S\u1ed1 \u0111i\u1ec7n tho\u1ea1i\",\n          phone_helper: \"Gi\u00fap ch\u00fang t\u00f4i li\u00ean h\u1ec7 v\u1edbi b\u1ea1n tr\u01b0\u1edbc khi \u0111\u1ebfn.\",\n          invoice_helper: \"Ch\u00fang t\u00f4i ch\u1ec9 s\u1eed d\u1ee5ng th\u00f4ng tin n\u00e0y \u0111\u1ec3 xu\u1ea5t x\u00e1c nh\u1eadn \u0111\u1eb7t ch\u1ed7 v\u00e0 h\u00f3a \u0111\u01a1n n\u1ebfu c\u1ea7n.\",\n          street_house: \"S\u1ed1 nh\u00e0 & t\u00ean \u0111\u01b0\u1eddng\",\n          city: \"Th\u00e0nh ph\u1ed1\",\n          postal_code: \"M\u00e3 b\u01b0u \u0111i\u1ec7n\",\n          country_residence: \"Qu\u1ed1c gia c\u01b0 tr\u00fa\",\n          need_company_invoice: \"T\u00f4i c\u1ea7n xu\u1ea5t h\u00f3a \u0111\u01a1n cho c\u00f4ng ty\",\n          company_name: \"T\u00ean c\u00f4ng ty\",\n          tax_id: \"M\u00e3 s\u1ed1 thu\u1ebf\",\n          second_guest: \"Kh\u00e1ch th\u1ee9 hai\",\n          second_description: \"D\u00f9ng \u0111\u1ec3 g\u1eedi b\u1ea3ng h\u1ecfi v\u00e0 s\u1eafp x\u1ebfp cu\u1ed9c g\u1ecdi chu\u1ea9n b\u1ecb s\u1ee9c kh\u1ecfe.\",\n          back: \"Quay l\u1ea1i\",\n          review: \"Xem l\u1ea1i\",\n          review_description: \"X\u00e1c nh\u1eadn ng\u00e0y, n\u01a1i \u1edf, kh\u00e1ch v\u00e0 \u0111\u01b0a \u0111\u00f3n tr\u01b0\u1edbc khi \u0111\u1eb7t c\u1ecdc.\",\n          retreat: \"Kh\u00f3a thanh l\u1ecdc\",\n          retreat_dates: \"Ng\u00e0y th\u1ef1c hi\u1ec7n\",\n          edit: \"S\u1eeda\",\n          no_transfer: \"Kh\u00f4ng c\u00f3 \u0111\u01b0a \u0111\u00f3n s\u00e2n bay\",\n          deposit_health_review: \"\u0110\u1eb7t c\u1ecdc & Ki\u1ec3m tra s\u1ee9c kh\u1ecfe\",\n          deposit_secures: \"\u0110\u1eb7t c\u1ecdc 30% \u0111\u1ec3 gi\u1eef ch\u1ed7.\",\n          health_info: \"Sau khi \u0111\u1eb7t c\u1ecdc, m\u1ed7i kh\u00e1ch s\u1ebd nh\u1eadn \u0111\u01b0\u1ee3c b\u1ea3ng h\u1ecfi s\u1ee9c kh\u1ecfe v\u00e0 l\u1ecbch h\u1eb9n cu\u1ed9c g\u1ecdi chu\u1ea9n b\u1ecb.\",\n          health_prep: \"Chu\u1ea9n b\u1ecb s\u1ee9c kh\u1ecfe\",\n          health_prep_desc: \"\u0110\u1ec3 h\u1ed7 tr\u1ee3 s\u1ee9c kh\u1ecfe c\u1ee7a b\u1ea1n, m\u1ed7i kh\u00e1ch ho\u00e0n th\u00e0nh m\u1ed9t b\u1ea3ng h\u1ecfi ng\u1eafn k\u00e8m cu\u1ed9c g\u1ecdi chu\u1ea9n b\u1ecb v\u1edbi \u0111\u1ed9i ng\u0169 c\u1ee7a ch\u00fang t\u00f4i. \u0110i\u1ec1u n\u00e0y \u0111\u1ea3m b\u1ea3o kh\u00f3a thanh l\u1ecdc an to\u00e0n cho b\u1ea1n.\",\n          medical_confidentiality: \"B\u1ea3o m\u1eadt y t\u1ebf\",\n          medical_confidentiality_desc: \"Th\u00f4ng tin s\u1ee9c kh\u1ecfe c\u1ee7a b\u1ea1n \u0111\u01b0\u1ee3c b\u1ea3o m\u1eadt tuy\u1ec7t \u0111\u1ed1i v\u00e0 ch\u1ec9 \u0111\u1ed9i ng\u0169 y t\u1ebf c\u1ea5p cao c\u1ee7a ch\u00fang t\u00f4i m\u1edbi c\u00f3 quy\u1ec1n truy c\u1eadp.\",\n          after_deposit: \"Sau khi \u0111\u1eb7t c\u1ecdc\",\n          questionnaire: \"B\u1ea3ng h\u1ecfi s\u1ee9c kh\u1ecfe\",\n          questionnaire_desc: \"M\u1ed7i kh\u00e1ch nh\u1eadn \u0111\u01b0\u1ee3c b\u1ea3ng h\u1ecfi s\u1ee9c kh\u1ecfe & l\u1ed1i s\u1ed1ng ri\u00eang \u0111\u1ec3 ho\u00e0n th\u00e0nh theo th\u1eddi gian c\u1ee7a m\u00ecnh.\",\n          before_arrival: \"Tr\u01b0\u1edbc khi \u0111\u1ebfn\",\n          prep_call: \"Cu\u1ed9c g\u1ecdi chu\u1ea9n b\u1ecb\",\n          prep_call_desc: \"Cu\u1ed9c g\u1ecdi ri\u00eang t\u01b0 30 ph\u00fat b\u1eaft bu\u1ed9c \u0111\u1ec3 xem x\u00e9t c\u00e1c c\u00e2u tr\u1ea3 l\u1eddi v\u00e0 gi\u1ea3i \u0111\u00e1p th\u1eafc m\u1eafc c\u1ee7a b\u1ea1n.\",\n          refund_policy: \"Ho\u00e0n ti\u1ec1n 100% ti\u1ec1n c\u1ecdc n\u1ebfu b\u1ea1n kh\u00f4ng \u0111\u01b0\u1ee3c khuy\u00ean tham gia sau khi ki\u1ec3m tra s\u1ee9c kh\u1ecfe.\",\n          continue_to_payment: \"Ti\u1ebfp t\u1ee5c thanh to\u00e1n\",\n          payment: \"Thanh to\u00e1n\",\n          payment_desc: \"\u0110\u1ea3m b\u1ea3o ch\u1ed7 c\u1ee7a b\u1ea1n v\u1edbi 30% ti\u1ec1n \u0111\u1eb7t c\u1ecdc.\",\n          payment_method: \"Ph\u01b0\u01a1ng th\u1ee9c thanh to\u00e1n\",\n          zero_extra_fees: \"Kh\u00f4ng ph\u00e1t sinh ph\u00ed\",\n          card_processing_fee: \"Ph\u00ed x\u1eed l\u00fd th\u1ebb (3.6%)\",\n          onepay_domestic: \"OnePay \u00b7 Qu\u00e9t QR\",\n          onepay_international: \"OnePay \u00b7 Th\u1ebb qu\u1ed1c t\u1ebf\",\n          onepay_domestic_desc: \"Thanh to\u00e1n qua \u1ee9ng d\u1ee5ng ng\u00e2n h\u00e0ng b\u1eb1ng c\u00e1ch qu\u00e9t QR. Kh\u00f4ng m\u1ea5t ph\u00ed.\",\n          onepay_intl_desc: \"Thanh to\u00e1n qua Visa, Mastercard, JCB, Amex. B\u1ea3o m\u1eadt b\u1edfi OnePay.\",\n          stripe_desc: \"Thanh to\u00e1n b\u1eb1ng th\u1ebb qua Stripe (USD). Ph\u00ed 3.6% s\u1ebd \u0111\u01b0\u1ee3c t\u1ef1 \u0111\u1ed9ng c\u1ed9ng v\u00e0o t\u1ed5ng ti\u1ec1n.\",\n          bank_transfer_desc: \"Thanh to\u00e1n b\u1eb1ng VND qua chuy\u1ec3n kho\u1ea3n ng\u00e2n h\u00e0ng n\u1ed9i \u0111\u1ecba. Kh\u00f4ng m\u1ea5t ph\u00ed x\u1eed l\u00fd.\",\n          processing_payment: \"\u0110ang x\u1eed l\u00fd thanh to\u00e1n...\",\n          confirm_bank_transfer: \"X\u00e1c nh\u1eadn chuy\u1ec3n kho\u1ea3n\",\n          pay_securely_msg: \"Thanh to\u00e1n {{amount}}\",\n          booking_secured: \"\u0110\u00e3 gi\u1eef ch\u1ed7 th\u00e0nh c\u00f4ng!\",\n          proceeding_next: \"\u0110ang chuy\u1ec3n sang b\u01b0\u1edbc ti\u1ebfp theo...\",\n          almost_done: \"B\u1ea1n s\u1eafp ho\u00e0n t\u1ea5t.\",\n          health_prep_screening_desc: \"M\u1ed7i kh\u00e1ch ho\u00e0n th\u00e0nh b\u1ea3ng h\u1ecfi s\u1ee9c kh\u1ecfe c\u00e1 nh\u00e2n v\u00e0 cu\u1ed9c g\u1ecdi chu\u1ea9n b\u1ecb b\u1eaft bu\u1ed9c v\u1edbi \u0111\u1ed9i ng\u0169 Vietnam Detox. \u0110\u00e2y l\u00e0 c\u00e1ch ch\u00fang t\u00f4i \u0111i\u1ec1u ch\u1ec9nh tr\u1ea3i nghi\u1ec7m cho b\u1ea1n.\",\n          what_happens_next: \"\u0110i\u1ec1u g\u00ec x\u1ea3y ra ti\u1ebfp theo\",\n          timeline_item_1: \"M\u1ed7i kh\u00e1ch nh\u1eadn b\u1ea3ng h\u1ecfi s\u1ee9c kh\u1ecfe & l\u1ed1i s\u1ed1ng ri\u00eang.\",\n          timeline_item_2: \"\u0110\u1ed9i ng\u0169 Vietnam Detox xem x\u00e9t t\u1eebng c\u00e2u tr\u1ea3 l\u1eddi.\",\n          timeline_item_3: \"L\u1ecbch h\u1eb9n cu\u1ed9c g\u1ecdi chu\u1ea9n b\u1ecb 30 ph\u00fat sau khi g\u1eedi b\u1ea3ng h\u1ecfi.\",\n          timeline_item_4: \"Tr\u1ea1ng th\u00e1i sau thanh to\u00e1n: \u0110\u00e3 gi\u1eef ch\u1ed7 \u2013 \u0111ang ch\u1edd chu\u1ea9n b\u1ecb.\",\n          timeline_item_5: \"Tr\u1ea1ng th\u00e1i sau cu\u1ed9c g\u1ecdi: \u0110\u00e3 x\u00e1c nh\u1eadn \u0111\u1eb7t ch\u1ed7.\",\n          quick_precheck: \"Ki\u1ec3m tra nhanh\",\n          quick_precheck_desc: \"N\u1ebfu b\u1ea1n tr\u1ea3 l\u1eddi \u201cC\u00f3\u201d cho b\u1ea5t k\u1ef3 c\u00e2u n\u00e0o, \u0111\u1ed9i ng\u0169 c\u1ee7a ch\u00fang t\u00f4i s\u1ebd li\u00ean h\u1ec7 ri\u00eang.\",\n          safety_question_1: \"B\u1ea1n hi\u1ec7n \u0111ang mang thai ho\u1eb7c cho con b\u00fa?\",\n          safety_question_2: \"B\u1ea1n c\u00f3 b\u1ec7nh ti\u1ec3u \u0111\u01b0\u1eddng lo\u1ea1i 1?\",\n          safety_question_3: \"B\u1ea1n c\u00f3 r\u1ed1i lo\u1ea1n \u0103n u\u1ed1ng \u0111\u01b0\u1ee3c ch\u1ea9n \u0111o\u00e1n?\",\n          safety_question_4: \"B\u1ea1n \u0111ang \u0111i\u1ec1u tr\u1ecb b\u1ec7nh c\u00f3 th\u1ec3 \u1ea3nh h\u01b0\u1edfng \u0111\u1ebfn vi\u1ec7c nh\u1ecbn \u0103n?\",\n          yes: \"C\u00f3\",\n          no: \"Kh\u00f4ng\",\n          continue_begin_health_prep: \"Ti\u1ebfp t\u1ee5c \u2013 B\u1eaft \u0111\u1ea7u chu\u1ea9n b\u1ecb s\u1ee9c kh\u1ecfe\",\n          back_to_booking: \"Quay l\u1ea1i \u0111\u1eb7t ch\u1ed7\",\n          prep_timeline: \"Ti\u1ebfn tr\u00ecnh chu\u1ea9n b\u1ecb s\u1ee9c kh\u1ecfe\",\n          prep_timeline_desc: \"Theo d\u00f5i b\u1ea3ng h\u1ecfi, cu\u1ed9c g\u1ecdi chu\u1ea9n b\u1ecb v\u00e0 x\u00e1c nh\u1eadn cu\u1ed1i c\u00f9ng.\",\n          deposit_received: \"\u0110\u00e3 nh\u1eadn ti\u1ec1n c\u1ecdc\",\n          status_reserved_pending: \"Tr\u1ea1ng th\u00e1i: \u0110\u00e3 gi\u1eef ch\u1ed7 \u2013 \u0111ang ch\u1edd chu\u1ea9n b\u1ecb\",\n          awaiting_payment: \"\u0110ang ch\u1edd thanh to\u00e1n\",\n          guest_1_health_prep: \"Chu\u1ea9n b\u1ecb s\u1ee9c kh\u1ecfe Kh\u00e1ch 1\",\n          guest_2_health_prep: \"Chu\u1ea9n b\u1ecb s\u1ee9c kh\u1ecfe Kh\u00e1ch 2\",\n          prep_complete: \"B\u1ea3ng h\u1ecfi + Cu\u1ed9c g\u1ecdi ho\u00e0n t\u1ea5t\",\n          awaiting_prep: \"\u0110ang ch\u1edd b\u1ea3ng h\u1ecfi v\u00e0 cu\u1ed9c g\u1ecdi\",\n          team_confirmation: \"X\u00e1c nh\u1eadn t\u1eeb \u0111\u1ed9i ng\u0169 Vietnam Detox\",\n          status_confirmed: \"Tr\u1ea1ng th\u00e1i: \u0110\u00e3 x\u00e1c nh\u1eadn \u0111\u1eb7t ch\u1ed7\",\n          begins_after_calls: \"B\u1eaft \u0111\u1ea7u sau c\u00e1c cu\u1ed9c g\u1ecdi chu\u1ea9n b\u1ecb\",\n          guest: \"Kh\u00e1ch\",\n          confirmation_note: \"Ch\u00fang t\u00f4i x\u00e1c nh\u1eadn sau khi c\u1ea3 b\u1ea3ng h\u1ecfi v\u00e0 cu\u1ed9c g\u1ecdi chu\u1ea9n b\u1ecb ho\u00e0n t\u1ea5t.\",\n          questionnaire_call_complete: \"B\u1ea3ng h\u1ecfi + Cu\u1ed9c g\u1ecdi ho\u00e0n t\u1ea5t\",\n          awaiting_questionnaire_call: \"\u0110ang ch\u1edd b\u1ea3ng h\u1ecfi v\u00e0 cu\u1ed9c g\u1ecdi\",\n          open_health_questionnaire: \"M\u1edf b\u1ea3ng h\u1ecfi s\u1ee9c kh\u1ecfe\",\n          link_copied: \"\u0110\u00e3 sao ch\u00e9p li\u00ean k\u1ebft\",\n          copy_this_link: \"Sao ch\u00e9p li\u00ean k\u1ebft n\u00e0y\",\n          copy_link: \"Sao ch\u00e9p li\u00ean k\u1ebft\",\n          share_link_description: \"B\u1ea1n c\u00f3 th\u1ec3 chia s\u1ebb li\u00ean k\u1ebft n\u00e0y n\u1ebfu kh\u00e1ch \u0111\u1ed3ng h\u00e0nh c\u1ea7n ho\u00e0n th\u00e0nh tr\u00ean thi\u1ebft b\u1ecb kh\u00e1c.\",\n          included_personal_health_review_call: \"Bao g\u1ed3m cu\u1ed9c g\u1ecdi t\u01b0 v\u1ea5n s\u1ee9c kh\u1ecfe\",\n          included_personal_health_review_call_desc: \"Sau khi g\u1eedi b\u1ea3ng h\u1ecfi s\u1ee9c kh\u1ecfe, Vietnam Detox t\u1eb7ng b\u1ea1n m\u1ed9t cu\u1ed9c g\u1ecdi 1-1 mi\u1ec5n ph\u00ed 30 ph\u00fat \u0111\u1ec3 xem x\u00e9t c\u00e1c c\u00e2u tr\u1ea3 l\u1eddi. Cu\u1ed9c g\u1ecdi n\u00e0y \u0111\u00e3 bao g\u1ed3m trong kh\u00f3a h\u1ecdc.\",\n          request_health_review_call_alert: \"C\u1ea3m \u01a1n b\u1ea1n. Ch\u00fang t\u00f4i s\u1ebd li\u00ean h\u1ec7 s\u1edbm nh\u1ea5t.\",\n          request_my_health_review_call: \"Y\u00eau c\u1ea7u cu\u1ed9c g\u1ecdi t\u01b0 v\u1ea5n s\u1ee9c kh\u1ecfe\",\n          back_to_health_preparation_hub: \"Quay l\u1ea1i trung t\u00e2m chu\u1ea9n b\u1ecb\",\n          move_to_confirmation: \"Chuy\u1ec3n sang x\u00e1c nh\u1eadn\",\n          booking_confirmed: \"\u0110\u00e3 x\u00e1c nh\u1eadn \u0111\u1eb7t ch\u1ed7\",\n          booking_confirmed_desc: \"H\u00e0nh tr\u00ecnh s\u1ee9c kh\u1ecfe c\u1ee7a b\u1ea1n \u0111\u00e3 \u0111\u01b0\u1ee3c l\u1ecbch ch\u00ednh th\u1ee9c. Ch\u00fang t\u00f4i r\u1ea5t mong \u0111\u01b0\u1ee3c \u0111\u00f3n ti\u1ebfp b\u1ea1n.\",\n          booking_ref: \"M\u00e3 \u0111\u1eb7t ch\u1ed7\",\n          return_home: \"Quay l\u1ea1i trang ch\u1ee7\",\n          investment_summary: \"Th\u00f4ng tin thanh to\u00e1n\",\n          real_time_update: \"C\u00e1c m\u1ee5c chi ph\u00ed c\u1eadp nh\u1eadt theo th\u1eddi gian th\u1ef1c.\",\n          subtotal: \"T\u1ea1m t\u00ednh\",\n          early_bird_discount: \"\u01afu \u0111\u00e3i \u0111\u1eb7t s\u1edbm \u2013{{discount}}\",\n          friend_discount: \"Gi\u1ea3m gi\u00e1 ph\u00f2ng chung\",\n          retreat_total: \"T\u1ed5ng c\u1ed9ng kh\u00f3a thanh l\u1ecdc\",\n          deposit_label: \"\u0110\u1eb7t c\u1ecdc\",\n          deposit_due_label: \"S\u1ed1 ti\u1ec1n c\u1ecdc c\u1ea7n thanh to\u00e1n\",\n          quick_pre_check: \"Ki\u1ec3m tra s\u01a1 b\u1ed9\",\n          quick_pre_check_desc: \"Tr\u01b0\u1edbc khi ho\u00e0n t\u1ea5t \u0111\u1eb7t ch\u1ed7, ch\u00fang t\u00f4i c\u1ea7n h\u1ecfi m\u1ed9t v\u00e0i c\u00e2u h\u1ecfi v\u1ec1 s\u1ee9c kh\u1ecfe & an to\u00e0n.\",\n          remaining_balance: \"S\u1ed1 d\u01b0 c\u00f2n l\u1ea1i\",\n          card_fee: \"Ph\u00ed x\u1eed l\u00fd th\u1ebb\",\n          due_today: \"Thanh to\u00e1n h\u00f4m nay\",\n          deposit_received_msg: \"\u0110\u00e3 nh\u1eadn ti\u1ec1n c\u1ecdc.\",\n          refund_note: \"Ho\u00e0n ti\u1ec1n 100% n\u1ebfu b\u1ea1n kh\u00f4ng \u0111\u01b0\u1ee3c khuy\u00ean tham gia sau khi ki\u1ec3m tra s\u1ee9c kh\u1ecfe.\",\n          something_went_wrong: \"\u0110\u00e3 x\u1ea3y ra l\u1ed7i\",\n          error_desc: \"\u0110\u00e3 x\u1ea3y ra l\u1ed7i khi x\u1eed l\u00fd \u0111\u1eb7t ch\u1ed7 c\u1ee7a b\u1ea1n. Vui l\u00f2ng t\u1ea3i l\u1ea1i trang.\",\n          refresh_page: \"T\u1ea3i l\u1ea1i trang\",\n          language: \"Ng\u00f4n ng\u1eef\",\n          booking_progress: \"Ti\u1ebfn tr\u00ecnh \u0111\u1eb7t ch\u1ed7\",\n          underweight_title: \"Thi\u1ebfu c\u00e2n nghi\u00eam tr\u1ecdng \/ R\u1ed1i lo\u1ea1n \u0103n u\u1ed1ng\",\n          underweight_desc: \"B\u1ea1n hi\u1ec7n c\u00f3 \u0111ang b\u1ecb thi\u1ebfu c\u00e2n nghi\u00eam tr\u1ecdng (v\u00ed d\u1ee5: BMI d\u01b0\u1edbi 18) ho\u1eb7c m\u1eafc ch\u1ee9ng r\u1ed1i lo\u1ea1n \u0103n u\u1ed1ng \u0111\u00e3 \u0111\u01b0\u1ee3c ch\u1ea9n \u0111o\u00e1n nh\u01b0 ch\u00e1n \u0103n kh\u00f4ng?\",\n          liverKidney_title: \"B\u1ec7nh gan ho\u1eb7c th\u1eadn giai \u0111o\u1ea1n ti\u1ebfn tri\u1ec3n\",\n          liverKidney_desc: \"B\u1ea1n c\u00f3 \u0111\u01b0\u1ee3c ch\u1ea9n \u0111o\u00e1n m\u1eafc b\u1ec7nh gan ho\u1eb7c th\u1eadn giai \u0111o\u1ea1n ti\u1ebfn tri\u1ec3n (suy gi\u1ea3m ch\u1ee9c n\u0103ng gan ho\u1eb7c th\u1eadn) kh\u00f4ng?\",\n          pregnancy_title: \"\u0110ang mang thai ho\u1eb7c cho con b\u00fa\",\n          pregnancy_desc: \"B\u1ea1n hi\u1ec7n c\u00f3 \u0111ang mang thai ho\u1eb7c cho con b\u00fa kh\u00f4ng?\",\n          cardio_title: \"B\u1ec7nh tim m\u1ea1ch nghi\u00eam tr\u1ecdng\",\n          cardio_desc: \"B\u1ea1n c\u00f3 \u0111\u01b0\u1ee3c ch\u1ea9n \u0111o\u00e1n m\u1eafc b\u1ec7nh tim ho\u1eb7c tim m\u1ea1ch nghi\u00eam tr\u1ecdng (v\u00ed d\u1ee5: suy tim ho\u1eb7c b\u1ec7nh m\u1ea1ch v\u00e0nh ti\u1ebfn tri\u1ec3n) kh\u00f4ng?\",\n          honest_answer_thanks: \"C\u1ea3m \u01a1n b\u1ea1n r\u1ea5t nhi\u1ec1u v\u00ec c\u00e2u tr\u1ea3 l\u1eddi trung th\u1ef1c.\",\n          safety_guideline_1: \"D\u1ef1a tr\u00ean c\u00e1c h\u01b0\u1edbng d\u1eabn an to\u00e0n nh\u1ecbn \u0103n, t\u00ecnh tr\u1ea1ng b\u1ea1n v\u1eeba cung c\u1ea5p \u0111\u01b0\u1ee3c xem l\u00e0 tr\u01b0\u1eddng h\u1ee3p ch\u1ec9 n\u00ean nh\u1ecbn \u0103n (n\u1ebfu c\u00f3) d\u01b0\u1edbi s\u1ef1 theo d\u00f5i ch\u1eb7t ch\u1ebd c\u1ee7a chuy\u00ean gia t\u1ea1i c\u01a1 s\u1edf y t\u1ebf.\",\n          safety_guideline_2: \"C\u00e1c kh\u00f3a thanh l\u1ecdc c\u1ee7a ch\u00fang t\u00f4i \u0111\u01b0\u1ee3c thi\u1ebft k\u1ebf cho m\u1ee5c \u0111\u00edch ph\u00f2ng ng\u1eeba v\u00e0 ph\u1ee5c h\u1ed3i, do \u0111\u00f3 kh\u00f4ng th\u1ec3 cung c\u1ea5p m\u1ee9c \u0111\u1ed9 theo d\u00f5i li\u00ean t\u1ee5c nh\u01b0 y\u00eau c\u1ea7u trong tr\u01b0\u1eddng h\u1ee3p n\u00e0y.\",\n          safety_guideline_3: \"V\u00ec tr\u00e1ch nhi\u1ec7m v\u1edbi s\u1ef1 an to\u00e0n v\u00e0 s\u1ee9c kh\u1ecfe c\u1ee7a b\u1ea1n, ch\u00fang t\u00f4i r\u1ea5t ti\u1ebfc kh\u00f4ng th\u1ec3 ti\u1ebfp nh\u1eadn b\u1ea1n tham gia kh\u00f3a thanh l\u1ecdc l\u1ea7n n\u00e0y. Vui l\u00f2ng li\u00ean h\u1ec7 v\u1edbi Vietnam Detox \u0111\u1ec3 ch\u00fang t\u00f4i chia s\u1ebb c\u00e1c l\u1ef1a ch\u1ecdn l\u1ed1i s\u1ed1ng v\u00e0 ch\u01b0\u01a1ng tr\u00ecnh dinh d\u01b0\u1ee1ng nh\u1eb9 nh\u00e0ng, ph\u00f9 h\u1ee3p h\u01a1n v\u1edbi b\u1ea1n v\u00e0o l\u00fac n\u00e0y.\",\n          contact_email: \"hello@vietnamdetox.com\",\n          contact_vd: \"Li\u00ean h\u1ec7 Vietnam Detox\",\n          return_overview: \"Tr\u1edf l\u1ea1i trang t\u1ed5ng quan\",\n          read_more: \"Xem th\u00eam\",\n          payment_failed: \"Thanh to\u00e1n kh\u00f4ng th\u00e0nh c\u00f4ng\",\n          payment_failed_desc: \"\u0110\u00e3 x\u1ea3y ra l\u1ed7i trong qu\u00e1 tr\u00ecnh giao d\u1ecbch. Vui l\u00f2ng ki\u1ec3m tra l\u1ea1i th\u00f4ng tin ho\u1eb7c th\u1eed ph\u01b0\u01a1ng th\u1ee9c thanh to\u00e1n kh\u00e1c.\",\n          try_again: \"Th\u1eed l\u1ea1i\"\n        },\n        de: {\n          step: \"Schritt\",\n          plan_journey: \"Planen Sie Ihre Reise\",\n          plan_description: \"W\u00e4hlen Sie Startdatum, G\u00e4steanzahl und Unterkunft. Die Preise aktualisieren sich in Echtzeit bei jeder Auswahl.\",\n          upcoming_retreats: \"Kommende Retreats\",\n          retreats_description: \"W\u00e4hlen Sie das Erlebnis, das am besten zu Ihren Wellness-Zielen passt.\",\n          available_dates: \"Verf\u00fcgbare Termine\",\n          early_bird_label: \"Fr\u00fchbucher \u2013{{discount}}\",\n          limited_spots: \"Begrenzte Pl\u00e4tze\",\n          guests: \"G\u00e4ste\",\n          one_guest: \"Ein Gast\",\n          two_guests: \"Zwei G\u00e4ste\",\n          save_together: \"{{discount}} gemeinsam sparen\",\n          private_journey: \"Exklusive Reise\",\n          guest_one: \"Erster Gast\",\n          guest_two: \"Zweiter Gast\",\n          accommodation: \"Unterkunft\",\n          health_prep_first: \"Gesundheitsvorbereitung\",\n          health_prep_description: \"Jeder Gast f\u00fcllt einen Fragebogen aus und f\u00fchrt nach der Zahlung ein pers\u00f6nliches Gespr\u00e4ch mit dem Vietnam Detox Team.\",\n          no_accommodation: \"Unterkunftsoptionen werden hier angezeigt.\",\n          no_upcoming_dates: \"Derzeit sind keine zuk\u00fcnftigen Retreat-Termine verf\u00fcgbar.\",\n          per_guest: \"Pro Gast\",\n          selected: \"Ausgew\u00e4hlt\",\n          tap_to_select: \"Ausw\u00e4hlen\",\n          view_photos: \"Fotos ansehen\",\n          airport_transfer: \"Flughafentransfer (optional)\",\n          continue_to_details: \"Weiter zu den Details\",\n          continue: \"Weiter\",\n          details: \"Details\",\n          details_description: \"Wird f\u00fcr Buchungsbest\u00e4tigung und Rechnung verwendet. Kontakte erhalten Gesundheitsfragebogen und Gespr\u00e4chsdetails.\",\n          primary_guest: \"Hauptgast\",\n          primary_description: \"Diese Informationen erscheinen auf Ihrer Buchungsbest\u00e4tigung.\",\n          first_name: \"Vorname\",\n          last_name: \"Nachname\",\n          email_address: \"E-Mail-Adresse\",\n          phone_number: \"Telefonnummer\",\n          phone_helper: \"Hilfreich f\u00fcr kurzfristige Erreichbarkeit.\",\n          invoice_helper: \"Nur f\u00fcr Buchungsbest\u00e4tigung und Rechnung verwendet.\",\n          street_house: \"Stra\u00dfe & Hausnummer\",\n          city: \"Stadt\",\n          postal_code: \"Postleitzahl\",\n          country_residence: \"Land\",\n          need_company_invoice: \"Ich ben\u00f6tige eine Firmenrechnung\",\n          company_name: \"Firmenname\",\n          tax_id: \"Steuernummer\",\n          second_guest: \"Zweiter Gast\",\n          second_description: \"F\u00fcr Fragebogen und Vorbereitungsgespr\u00e4ch.\",\n          back: \"Zur\u00fcck\",\n          review: \"\u00dcberpr\u00fcfung\",\n          review_description: \"Best\u00e4tigen Sie alle Details vor der Anzahlung.\",\n          retreat: \"Retreat\",\n          retreat_dates: \"Termine\",\n          edit: \"Bearbeiten\",\n          no_transfer: \"Kein Transfer\",\n          deposit_health_review: \"Anzahlung & Gesundheit\",\n          deposit_secures: \"30% Anzahlung sichert Ihre Buchung.\",\n          health_info: \"Nach Anzahlung erh\u00e4lt jeder Gast einen Fragebogen und ein pers\u00f6nliches Gespr\u00e4ch wird geplant.\",\n          health_prep: \"Gesundheitsvorbereitung\",\n          health_prep_desc: \"Um Sie bestm\u00f6glich zu unterst\u00fctzen, f\u00fcllt jeder Gast einen Fragebogen aus, gefolgt von einem Gespr\u00e4ch mit unserem Team.\",\n          medical_confidentiality: \"Medizinische Vertraulichkeit\",\n          medical_confidentiality_desc: \"Ihre Daten werden streng vertraulich behandelt und sind nur f\u00fcr unser medizinisches Team zug\u00e4nglich.\",\n          after_deposit: \"Nach Anzahlung\",\n          questionnaire: \"Fragebogen\",\n          questionnaire_desc: \"Jeder Gast erh\u00e4lt einen Gesundheits- & Lebensstil-Fragebogen.\",\n          before_arrival: \"Vor der Anreise\",\n          prep_call: \"Vorbereitungsgespr\u00e4ch\",\n          prep_call_desc: \"Ein obligatorisches 30-min\u00fctiges Gespr\u00e4ch zur Kl\u00e4rung aller Fragen.\",\n          refund_policy: \"100% R\u00fcckerstattung der Anzahlung, falls die Teilnahme gesundheitlich nicht empfohlen wird.\",\n          continue_to_payment: \"Weiter zur Zahlung\",\n          payment: \"Zahlung\",\n          payment_desc: \"Sichern Sie Ihre Buchung mit 30% Anzahlung.\",\n          payment_method: \"Zahlungsmethode\",\n          zero_extra_fees: \"Keine Extrageb\u00fchren\",\n          card_processing_fee: \"Kartengeb\u00fchr (3,6%)\",\n          onepay_domestic: \"OnePay \u00b7 Inland ATM \/ QR\",\n          onepay_international: \"OnePay \u00b7 Internationale Karten\",\n          onepay_domestic_desc: \"Zahlung \u00fcber lokale Bank-Apps, ATM-Karten oder QR. Keine Extrageb\u00fchren.\",\n          onepay_intl_desc: \"Zahlung \u00fcber Visa, Mastercard, JCB, Amex. Gesichert durch OnePay.\",\n          stripe_desc: \"Sichere Kartenzahlung in USD. 3,6% Geb\u00fchr werden automatisch hinzugef\u00fcgt.\",\n          bank_transfer_desc: \"Zahlung in VND per Bank\u00fcberweisung. Keine Extrageb\u00fchren.\",\n          processing_payment: \"Verarbeitung...\",\n          confirm_bank_transfer: \"\u00dcberweisung best\u00e4tigen\",\n          pay_securely_msg: \"{{amount}} sicher bezahlen\",\n          booking_secured: \"Buchung gesichert!\",\n          proceeding_next: \"Weiter zum n\u00e4chsten Schritt...\",\n          almost_done: \"Fast geschafft.\",\n          health_prep_screening_desc: \"Jeder Gast f\u00fcllt einen Fragebogen aus und f\u00fchrt ein Gespr\u00e4ch mit uns. So bereiten wir alles optimal vor.\",\n          what_happens_next: \"Was als N\u00e4chstes passiert\",\n          timeline_item_1: \"Fragebogen zu Gesundheit & Lebensstil f\u00fcr jeden Gast.\",\n          timeline_item_2: \"Pers\u00f6nliche Pr\u00fcfung durch das Vietnam Detox Team.\",\n          timeline_item_3: \"Vorbereitungsgespr\u00e4ch nach dem Fragebogen.\",\n          timeline_item_4: \"Status nach Zahlung: Reserviert \u2013 Vorbereitung l\u00e4uft.\",\n          timeline_item_5: \"Status nach Gespr\u00e4chen: Buchung best\u00e4tigt.\",\n          quick_precheck: \"Vorabcheck\",\n          quick_precheck_desc: \"Bei Antworten mit \u201eJa\u201c meldet sich unser Team pers\u00f6nlich.\",\n          safety_question_1: \"Sind Sie aktuell schwanger oder stillend?\",\n          safety_question_2: \"Haben Sie Typ-1-Diabetes?\",\n          safety_question_3: \"Haben Sie eine diagnostizierte Essst\u00f6rung?\",\n          safety_question_4: \"Sind Sie in Behandlung, die das Fasten beeinflusst?\",\n          yes: \"Ja\",\n          no: \"Nein\",\n          continue_begin_health_prep: \"Weiter \u2013 Vorbereitung beginnen\",\n          back_to_booking: \"Zur\u00fcck zur Buchung\",\n          prep_timeline: \"Zeitplan der Vorbereitung\",\n          prep_timeline_desc: \"Status von Frageb\u00f6gen, Gespr\u00e4chen und Best\u00e4tigung.\",\n          deposit_received: \"Anzahlung erhalten\",\n          status_reserved_pending: \"Status: Reserviert \u2013 Vorbereitung l\u00e4uft\",\n          awaiting_payment: \"Warten auf Zahlung\",\n          guest_1_health_prep: \"Vorbereitung Gast 1\",\n          guest_2_health_prep: \"Vorbereitung Gast 2\",\n          prep_complete: \"Fragebogen + Gespr\u00e4ch erledigt\",\n          awaiting_prep: \"Warten auf Fragebogen\/Gespr\u00e4ch\",\n          team_confirmation: \"Best\u00e4tigung durch Vietnam Detox Team\",\n          status_confirmed: \"Status: Buchung best\u00e4tigt\",\n          begins_after_calls: \"Nach den Gespr\u00e4chen\",\n          guest: \"Gast\",\n          confirmation_note: \"Best\u00e4tigung erfolgt nach Abschluss aller Vorbereitungen.\",\n          questionnaire_call_complete: \"Fragebogen + Gespr\u00e4ch erledigt\",\n          awaiting_questionnaire_call: \"Warten auf Fragebogen\/Gespr\u00e4ch\",\n          open_health_questionnaire: \"Fragebogen \u00f6ffnen\",\n          link_copied: \"Kopiert\",\n          copy_this_link: \"Link kopieren\",\n          copy_link: \"Link kopieren\",\n          share_link_description: \"Link f\u00fcr Mitreisende zum Ausf\u00fcllen auf anderen Ger\u00e4ten.\",\n          included_personal_health_review_call: \"Inklusive Gesundheitsgespr\u00e4ch\",\n          included_personal_health_review_call_desc: \"Ein kostenloses 30-min\u00fctiges Gespr\u00e4ch zur Abstimmung des Programms ist inbegriffen.\",\n          request_health_review_call_alert: \"Vielen Dank. Wir melden uns in K\u00fcrze.\",\n          request_my_health_review_call: \"Gesundheitsgespr\u00e4ch anfordern\",\n          back_to_health_preparation_hub: \"Zur\u00fcck zur Vorbereitung\",\n          move_to_confirmation: \"Weiter zur Best\u00e4tigung\",\n          booking_confirmed: \"Buchung best\u00e4tigt\",\n          booking_confirmed_desc: \"Ihre Reise ist offiziell geplant. Wir freuen uns auf Sie!\",\n          booking_ref: \"Buchungscode\",\n          return_home: \"Zur\u00fcck zur Startseite\",\n          investment_summary: \"Zusammenfassung\",\n          real_time_update: \"Preise aktualisieren sich live.\",\n          subtotal: \"Zwischensumme\",\n          early_bird_discount: \"Fr\u00fchbucher \u2013{{discount}}\",\n          friend_discount: \"Mehrbettzimmer-Rabatt\",\n          retreat_total: \"Gesamtbetrag\",\n          deposit_label: \"Anzahlung\",\n          deposit_due_label: \"Heute f\u00e4llige Anzahlung\",\n          quick_pre_check: \"Kurzer Vorab-Check\",\n          quick_pre_check_desc: \"Bevor wir Ihre Reservierung abschlie\u00dfen, m\u00fcssen wir einige Gesundheits- und Sicherheitsfragen stellen.\",\n          remaining_balance: \"Restbetrag\",\n          card_fee: \"Kartengeb\u00fchr\",\n          due_today: \"Heute f\u00e4llig\",\n          deposit_received_msg: \"Anzahlung erhalten.\",\n          refund_note: \"100% R\u00fcckerstattung bei Ablehnung nach Gesundheitspr\u00fcfung.\",\n          something_went_wrong: \"Fehler aufgetreten\",\n          error_desc: \"Ein Fehler ist aufgetreten. Bitte Seite neu laden.\",\n          refresh_page: \"Seite neu laden\",\n          language: \"Sprache\",\n          booking_progress: \"Buchungsfortschritt\",\n          underweight_title: \"Starkes Untergewicht \/ Essst\u00f6rung\",\n          underweight_desc: \"Leiden Sie derzeit unter starkem Untergewicht (z. B. BMI unter 18) oder einer diagnostizierten Essst\u00f6rung wie Magersucht?\",\n          liverKidney_title: \"Fortgeschrittene Leber- oder Nierenerkrankung\",\n          liverKidney_desc: \"Wurde bei Ihnen eine fortgeschrittene Leber- oder Nierenerkrankung (eingeschr\u00e4nkte Leber- oder Nierenfunktion) diagnostiziert?\",\n          pregnancy_title: \"Schwangerschaft oder Stillzeit\",\n          pregnancy_desc: \"Sind Sie derzeit schwanger oder stillen Sie ein Kind?\",\n          cardio_title: \"Schwere Herz- oder Herz-Kreislauf-Erkrankung\",\n          cardio_desc: \"Wurde bei Ihnen eine schwere Herz- oder Herz-Kreislauf-Erkrankung diagnostiziert (z. B. Herzinsuffizienz oder fortgeschrittene koronare Herzkrankheit)?\",\n          honest_answer_thanks: \"Vielen Dank f\u00fcr Ihre ehrliche Antwort.\",\n          safety_guideline_1: \"Basierend auf den etablierten Sicherheitsrichtlinien f\u00fcr das Fasten gilt die von Ihnen angegebene Bedingung als eine Situation, in der das Fasten \u2013 wenn \u00fcberhaupt \u2013 nur unter engmaschiger fach\u00e4rztlicher Aufsicht in einer klinischen Einrichtung durchgef\u00fchrt werden sollte.\",\n          safety_guideline_2: \"Unsere Fasten-Retreats sind f\u00fcr pr\u00e4ventive und regenerative Zwecke konzipiert und k\u00f6nnen die in diesem Fall erforderliche kontinuierliche \u00dcberwachung nicht leisten.\",\n          safety_guideline_3: \"Aus Verantwortung f\u00fcr Ihre Sicherheit und Ihr Wohlbefinden k\u00f6nnen wir Ihnen daher zu diesem Zeitpunkt leider keine Teilnahme an diesem Retreat anbieten. Wenn Sie m\u00f6chten, k\u00f6nnen Sie sich gerne an Vietnam Detox wenden, damit wir Informationen \u00fcber alternative, sanftere Lebensstil- und Ern\u00e4hrungsprogramme teilen k\u00f6nnen, die im Moment besser f\u00fcr Sie geeignet sein k\u00f6nnten.\",\n          contact_email: \"hello@vietnamdetox.com\",\n          contact_vd: \"Vietnam Detox kontaktieren\",\n          return_overview: \"Zur\u00fcck zur Retreat-\u00dcbersicht\",\n          read_more: \"Weiterlesen\",\n          payment_failed: \"Zahlung fehlgeschlagen\",\n          payment_failed_desc: \"Bei Ihrer Transaktion ist etwas schiefgelaufen. Bitte \u00fcberpr\u00fcfen Sie Ihre Angaben oder versuchen Sie eine andere Zahlungsmethode.\",\n          try_again: \"Erneut versuchen\"\n        }\n      };\n\n\n\n      const startBookingApp = () => {\n        if (!window.React || !window.ReactDOM) {\n          showInlineError(\"Required files did not load. Please check your connection and try again.\", { retry: true });\n          return;\n        }\n        const rootNode = document.getElementById(\"root\");\n        if (!rootNode) {\n          showInlineError(\"Unable to initialize the booking experience.\");\n          return;\n        }\n\n        const { useState, useMemo, useEffect, useRef } = React;\n\n        const CURRENCY_RATE = 25400;\n        const STRIPE_FEE_RATE = 0.03;\n        const STEPS = [\"config\", \"details\", \"review\", \"health_check\", \"payment\", \"screening\", \"review_state\", \"confirmed\"];\n        const PRETTY_PATHS = false;\n        const BOOKING_API_ENDPOINT = \"\/wp-json\/retreats\/v1\/bookings\";\n\n        const formatVND = (value, l = null) => {\n          const localeLang = l || parseRouteFromLocation().lang || getInitialLang();\n          const locale = localeLang === \"vn\" ? \"vi-VN\" : localeLang === \"de\" ? \"de-DE\" : \"en-US\";\n          return new Intl.NumberFormat(locale, { \n            style: \"currency\", \n            currency: \"VND\",\n            minimumFractionDigits: 0,\n            maximumFractionDigits: 0\n          }).format(Math.round(value));\n        };\n        const formatUSD = (value, l = null) => {\n          const localeLang = l || parseRouteFromLocation().lang || getInitialLang();\n          const locale = localeLang === \"de\" ? \"de-DE\" : \"en-US\";\n          const formatted = Math.round(value \/ CURRENCY_RATE).toLocaleString(locale);\n          return `~ $${formatted} USD`;\n        };\n\n        const calculateConfiguredDiscount = (baseAmount, config, units = 1) => {\n          const value = Number(config?.value) || 0;\n          if (value <= 0) return 0;\n          if (config?.type === \"percentage\") {\n            return baseAmount * value \/ 100;\n          }\n          return value * units;\n        };\n\n        const formatConfiguredDiscount = (config, lang) => {\n          const value = Number(config?.value) || 0;\n          return config?.type === \"percentage\" ? `${value}%` : formatVND(value, lang);\n        };\n\n\n\n\n        const HEALTHCHECK_URLS = {\n          vn: \"\/healthcheck-2\/\",\n          en: \"\/healthcheck\/\",\n          de: \"\/de\/healthcheck\/\",\n        };\n\n        const Icons = {\n          Building: () => (\n            <svg\n              width=\"24\"\n              height=\"24\"\n              viewBox=\"0 0 24 24\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              strokeWidth=\"2\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n            >\n              <rect x=\"4\" y=\"2\" width=\"16\" height=\"20\" rx=\"2\" ry=\"2\" \/>\n              <path d=\"M9 22v-4h6v4\" \/>\n              <path d=\"M8 6h.01\" \/>\n              <path d=\"M16 6h.01\" \/>\n              <path d=\"M12 6h.01\" \/>\n              <path d=\"M12 10h.01\" \/>\n              <path d=\"M12 14h.01\" \/>\n              <path d=\"M16 10h.01\" \/>\n              <path d=\"M16 14h.01\" \/>\n              <path d=\"M8 10h.01\" \/>\n              <path d=\"M8 14h.01\" \/>\n            <\/svg>\n          ),\n          CreditCard: () => (\n            <svg\n              width=\"24\"\n              height=\"24\"\n              viewBox=\"0 0 24 24\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              strokeWidth=\"2\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n            >\n              <rect x=\"1\" y=\"4\" width=\"22\" height=\"16\" rx=\"2\" ry=\"2\" \/>\n              <line x1=\"1\" y1=\"10\" x2=\"23\" y2=\"10\" \/>\n            <\/svg>\n          ),\n\n          ShieldCheck: () => (\n            <svg\n              width=\"24\"\n              height=\"24\"\n              viewBox=\"0 0 24 24\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              strokeWidth=\"2\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n            >\n              <path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10\" \/>\n              <path d=\"m9 12 2 2 4-4\" \/>\n            <\/svg>\n          ),\n\n          ChevronRight: () => (\n            <svg\n              width=\"20\"\n              height=\"20\"\n              viewBox=\"0 0 24 24\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              strokeWidth=\"2\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n            >\n              <path d=\"m9 18 6-6-6-6\" \/>\n            <\/svg>\n          ),\n          ChevronLeft: () => (\n            <svg\n              width=\"20\"\n              height=\"20\"\n              viewBox=\"0 0 24 24\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              strokeWidth=\"2\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n            >\n              <path d=\"m15 18-6-6 6-6\" \/>\n            <\/svg>\n          ),\n          Users: () => (\n            <svg\n              width=\"20\"\n              height=\"20\"\n              viewBox=\"0 0 24 24\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              strokeWidth=\"2\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n            >\n              <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" \/>\n              <circle cx=\"9\" cy=\"7\" r=\"4\" \/>\n              <path d=\"M22 21v-2a4 4 0 0 0-3-3.87\" \/>\n              <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" \/>\n            <\/svg>\n          ),\n          User: () => (\n            <svg\n              width=\"20\"\n              height=\"20\"\n              viewBox=\"0 0 24 24\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              strokeWidth=\"2\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n            >\n              <path d=\"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\" \/>\n              <circle cx=\"12\" cy=\"7\" r=\"4\" \/>\n            <\/svg>\n          ),\n          Check: () => (\n            <svg\n              width=\"20\"\n              height=\"20\"\n              viewBox=\"0 0 24 24\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              strokeWidth=\"2\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n            >\n              <path d=\"M20 6 9 17l-5-5\" \/>\n            <\/svg>\n          ),\n          Info: () => (\n            <svg\n              width=\"16\"\n              height=\"16\"\n              viewBox=\"0 0 24 24\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              strokeWidth=\"2\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n            >\n              <circle cx=\"12\" cy=\"12\" r=\"10\" \/>\n              <path d=\"M12 16v-4\" \/>\n              <path d=\"M12 8h.01\" \/>\n            <\/svg>\n          ),\n        };\n\n        const COUNTRY_DIAL_CODES = {\n          vietnam: \"+84\",\n          \"united states\": \"+1\",\n          usa: \"+1\",\n          canada: \"+1\",\n          singapore: \"+65\",\n          australia: \"+61\",\n          germany: \"+49\",\n          france: \"+33\",\n          \"united kingdom\": \"+44\",\n          uk: \"+44\",\n          thailand: \"+66\",\n          japan: \"+81\",\n        };\n        const PHONE_CODE_OPTIONS = Array.from(new Set(Object.values(COUNTRY_DIAL_CODES)));\n\n        const SAFETY_QUESTIONS = [\n          {\n            id: \"underweight\",\n            title: \"Severe underweight \/ eating disorder\",\n            description:\n              \"Do you currently suffer from severe underweight (for example a BMI below 18) or from a diagnosed eating disorder such as anorexia?\",\n          },\n          {\n            id: \"liverKidney\",\n            title: \"Advanced liver or kidney condition\",\n            description: \"Have you been diagnosed with advanced liver or kidney disease (reduced liver or kidney function)?\",\n          },\n          {\n            id: \"pregnancy\",\n            title: \"Pregnancy or breastfeeding\",\n            description: \"Are you currently pregnant or breastfeeding a child?\",\n          },\n          {\n            id: \"cardio\",\n            title: \"Severe heart or cardiovascular condition\",\n            description:\n              \"Have you been diagnosed with a severe heart or cardiovascular condition (for example heart failure or advanced coronary heart disease)?\",\n          },\n        ];\n\n        const parseRouteFromLocation = () => {\n          const params = new URLSearchParams(window.location.search || \"\");\n          const wantsScreening = params.get(\"view\") === \"screening\" || params.get(\"screening\") === \"true\";\n          const wantsPayment = params.get(\"view\") === \"payment\";\n          const recoveryId = params.get(\"recovery_id\");\n          const recoveryToken = params.get(\"token\");\n          let stepParam = params.get(\"step\");\n          if (wantsScreening) {\n            stepParam = \"screening\";\n          } else if (wantsPayment) {\n            stepParam = \"payment\";\n          }\n          if (!STEPS.includes(stepParam)) {\n            stepParam = \"config\";\n          }\n          const langParam = normalizeLang(\n            params.get(\"booking_lang\") || params.get(\"lang\") || getInitialLang()\n          );\n          return { step: stepParam, lang: langParam, recoveryId, recoveryToken };\n        };\n\n\n\n\n        const getRoomsForRetreat = (retreatId) => ROOMS_BY_RETREAT[retreatId] || [];\n        const getTransportOptionsForRetreat = (retreatId) => TRANSPORT_BY_RETREAT[retreatId] || [];\n\n        const getDialCodeForCountry = (countryName) => {\n          if (!countryName) return null;\n          const normalized = countryName.trim().toLowerCase();\n          return COUNTRY_DIAL_CODES[normalized] || null;\n        };\n\n          const PriceSummary = ({ context = \"default\", pricing, paymentMethod, stripeFee, paymentDueNow, lang, roomName, guestsCount, retreatName, retreatDate }) => {\n            const t = (key) => TRANSLATIONS[lang]?.[key] || TRANSLATIONS.en[key] || key;\n\n\n            const showEarlyBird = pricing.earlyBird > 0;\n            const showFriend = pricing.friend > 0;\n            const showDepositLine = context === \"review\" || context === \"payment\";\n            const showReviewNote = context === \"review\";\n            const depositLabel = context === \"payment\" ? t(\"deposit_due_label\") : t(\"deposit_label\");\n            return (\n              <div className=\"bg-white border border-stone-100 rounded-3xl p-6 shadow-sm space-y-4\">\n                <div>\n                  <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400 font-semibold mb-4\">{t(\"investment_summary\")}<\/p>\n                  \n                  <div className=\"space-y-4 mb-4\">\n                    {retreatName && (\n                      <div>\n                        <p className=\"text-[10px] uppercase tracking-[0.2em] text-stone-400 mb-1\">{t(\"retreat\")}<\/p>\n                        <p className=\"text-base font-semibold text-stone-900 leading-tight\" title={retreatName}>{retreatName}<\/p>\n                      <\/div>\n                    )}\n                    {retreatDate && (\n                      <div>\n                        <p className=\"text-[10px] uppercase tracking-[0.2em] text-stone-400 mb-1\">{t(\"retreat_dates\")}<\/p>\n                        <p className=\"text-sm font-medium text-stone-700 leading-tight\" title={retreatDate}>{retreatDate}<\/p>\n                      <\/div>\n                    )}\n                  <\/div>\n                  \n                  <p className=\"text-sm text-stone-500 pt-3 border-t border-stone-100\">{t(\"real_time_update\")}<\/p>\n                <\/div>\n                <div className=\"space-y-2 text-sm\">\n                  <div className=\"flex items-start justify-between gap-3\">\n                    <div>\n                      <p className=\"font-semibold text-stone-900\">{roomName || t(\"accommodation\")}<\/p>\n                      <p className=\"text-xs text-stone-500\">{guestsCount === 2 ? t(\"two_guests\") : t(\"one_guest\")}<\/p>\n                    <\/div>\n                    <span className=\"font-semibold whitespace-nowrap\">{formatVND(pricing.subtotal, lang)}<\/span>\n                  <\/div>\n                  {showEarlyBird && (\n                    <div className=\"flex justify-between text-emerald-700\">\n                      <span>{t(\"early_bird_discount\").replace(\"{{discount}}\", formatConfiguredDiscount(pricing.earlyBirdConfig, lang))}<\/span>\n                      <span>-{formatVND(pricing.earlyBird, lang)}<\/span>\n                    <\/div>\n                  )}\n                  {showFriend && (\n                    <div className=\"flex justify-between text-emerald-700\">\n                      <span>{t(\"save_together\").replace(\"{{discount}}\", formatConfiguredDiscount(pricing.friendConfig, lang))}<\/span>\n                      <span>-{formatVND(pricing.friend, lang)}<\/span>\n                    <\/div>\n                  )}\n                  <div className=\"flex justify-between text-stone-500\">\n                    <span>{t(\"airport_transfer\").replace(\" (optional)\", \"\")}<\/span>\n                    <span>{formatVND(pricing.transport, lang)}<\/span>\n                  <\/div>\n                <\/div>\n                <div className=\"flex justify-between pt-2 border-t border-stone-100\">\n                  <span className=\"text-stone-500\">{t(\"retreat_total\")}<\/span>\n                  <span className=\"text-2xl font-bold\">{formatVND(pricing.total, lang)}<\/span>\n                <\/div>\n                {showDepositLine && (\n                  <>\n                    <div className=\"flex justify-between\">\n                      <span className=\"text-stone-500\">{depositLabel}<\/span>\n                      <span className=\"font-semibold\">{formatVND(pricing.deposit, lang)}<\/span>\n                    <\/div>\n                    <div className=\"flex justify-between text-sm text-stone-500\">\n                      <span>{t(\"remaining_balance\")}<\/span>\n                      <span className=\"font-semibold\">{formatVND(pricing.remaining, lang)}<\/span>\n                    <\/div>\n                  <\/>\n                )}\n                <p className=\"text-sm text-stone-500\">{formatUSD(pricing.total, lang)}<\/p>\n                {showReviewNote && (\n                  <p className=\"text-sm text-stone-600\">\n                    {t(\"refund_note\")}\n                  <\/p>\n                )}\n                {context === \"payment\" && (\n                  <div className=\"pt-2 border-t border-stone-100 space-y-2\">\n                    {paymentMethod === \"stripe\" && stripeFee > 0 && (\n                      <div className=\"flex justify-between text-amber-700\">\n                        <span>{t(\"card_fee\")}<\/span>\n                        <span>{formatVND(stripeFee, lang)}<\/span>\n                      <\/div>\n                    )}\n                    <div className=\"flex justify-between\">\n                      <span className=\"text-stone-500\">{t(\"due_today\")}<\/span>\n                      <span className=\"text-xl font-bold\">{formatVND(paymentDueNow, lang)}<\/span>\n                    <\/div>\n                    <p className=\"text-sm text-stone-500\">{formatUSD(paymentDueNow, lang)}<\/p>\n                  <\/div>\n                )}\n                {context === \"confirmed\" && <p className=\"text-sm text-emerald-700\">{t(\"deposit_received_msg\")}<\/p>}\n              <\/div>\n            );\n          };\n\n\n        \/\/ Constants will be defined inside App to ensure RETREATS is loaded\n\n        const buildHealthCheckUrl = (bookingId, customerId, lang = \"en\") => {\n          if (!bookingId || !customerId) return \"\";\n          const params = new URLSearchParams({\n            reg_id: bookingId,\n            cus_id: customerId,\n          });\n          const baseUrl = HEALTHCHECK_URLS[lang] || HEALTHCHECK_URLS.en;\n          return `${baseUrl}?${params.toString()}`;\n        };\n\n        const parseRetreatStartDate = (value) => {\n          if (!value) return null;\n          const dateOnlyMatch = String(value).match(\/^(\\d{4})-(\\d{2})-(\\d{2})\/);\n          const parsed = dateOnlyMatch\n            ? new Date(Number(dateOnlyMatch[1]), Number(dateOnlyMatch[2]) - 1, Number(dateOnlyMatch[3]))\n            : new Date(value);\n          if (Number.isNaN(parsed.getTime())) return null;\n          parsed.setHours(0, 0, 0, 0);\n          return parsed;\n        };\n\n        const isRetreatDateAvailable = (date) => {\n          const startDate = parseRetreatStartDate(date?.start);\n          if (!startDate) return false;\n          const today = new Date();\n          today.setHours(0, 0, 0, 0);\n          return startDate >= today;\n        };\n\n        const App = () => {\n          const DEFAULT_RETREAT = RETREATS.find((retreat) =>\n            (Array.isArray(retreat.dates) ? retreat.dates : []).some(isRetreatDateAvailable)\n          ) || { id: 0, dates: [], image: FALLBACK_IMAGE };\n          const DEFAULT_DATE = DEFAULT_RETREAT.dates?.find(isRetreatDateAvailable) || { label: \"\" };\n          const DEFAULT_ROOMS = getRoomsForRetreat(DEFAULT_RETREAT.id);\n          const DEFAULT_ROOM_ID = DEFAULT_ROOMS[0]?.id || null;\n          const DEFAULT_TRANSPORT = getTransportOptionsForRetreat(DEFAULT_RETREAT.id)?.[0]?.id ?? null;\n          const DEFAULT_PHONE_CODE = getDialCodeForCountry(\"Vietnam\") || \"+84\";\n\n          const [route, setRoute] = useState(parseRouteFromLocation);\n          const [isTransitioning, setIsTransitioning] = useState(false);\n\n          useEffect(() => {\n            const rootNode = document.getElementById(\"root\");\n            if (rootNode) {\n              rootNode.querySelectorAll('button').forEach(btn => {\n                if (!btn.getAttribute('type')) {\n                  btn.setAttribute('type', 'button');\n                }\n              });\n            }\n          });\n\n          const [savedState] = useState(() => {\n            const params = new URLSearchParams(window.location.search || \"\");\n            const paymentStatus = params.get(\"payment\");\n            if (paymentStatus === \"success\" || paymentStatus === \"failed\") {\n              try {\n                const raw = sessionStorage.getItem(\"vdx_booking_state\");\n                if (raw) return JSON.parse(raw);\n              } catch(e) {}\n            }\n            return null;\n          });\n\n          const [selection, setSelection] = useState(() => savedState?.selection || ({\n            retreatId: DEFAULT_RETREAT.id,\n            retreatName: DEFAULT_RETREAT.name,\n            retreatLocation: DEFAULT_RETREAT.location,\n            retreatEarlyBirdNote: DEFAULT_RETREAT.earlyBirdNote,\n            retreatImage: DEFAULT_RETREAT.image,\n            date: DEFAULT_DATE.label,\n            guests: 1,\n            roomType: DEFAULT_ROOM_ID,\n            transfer: DEFAULT_TRANSPORT,\n          }));\n          const [guestDetails, setGuestDetails] = useState(() => savedState?.guestDetails || ({\n            guest1: {\n              firstName: \"\",\n              lastName: \"\",\n              email: \"\",\n              phone: \"\",\n              phoneCountryCode: DEFAULT_PHONE_CODE,\n              phoneCodeManuallySet: false,\n              street: \"\",\n              city: \"\",\n              postalCode: \"\",\n              country: \"\",\n              needsCompanyInvoice: false,\n              companyName: \"\",\n              taxId: \"\",\n            },\n            guest2: { firstName: \"\", lastName: \"\", email: \"\", phone: \"\" },\n          }));\n          const [paymentMethod, setPaymentMethod] = useState(() => savedState?.paymentMethod || \"onepay_domestic\");\n          const [paymentSubmitting, setPaymentSubmitting] = useState(false);\n          const [paymentError, setPaymentError] = useState(\"\");\n          const [paymentSuccess, setPaymentSuccess] = useState(false);\n          const [galleryRoom, setGalleryRoom] = useState(null);\n          const [galleryIndex, setGalleryIndex] = useState(0);\n          const [depositPaid, setDepositPaid] = useState(() => {\n            const params = new URLSearchParams(window.location.search || \"\");\n            if (params.get(\"payment\") === \"success\") return true; \n            if (params.get(\"payment\") === \"failed\") return false;\n            return savedState ? true : false;\n          });\n\n          const [bookingMeta, setBookingMeta] = useState(() => {\n            if (savedState?.bookingMeta) return savedState.bookingMeta;\n            const params = new URLSearchParams(window.location.search || \"\");\n            const bId = params.get(\"booking_id\");\n            if (bId) return { bookingId: parseInt(bId), customerIds: [] };\n            return { bookingId: null, customerIds: [] };\n          });\n          const [bookingStatus, setBookingStatus] = useState(\"\");\n          const [screeningStatus, setScreeningStatus] = useState(() => savedState?.screeningStatus || { guest1: \"pending\", guest2: (savedState?.selection?.guests || 1) === 2 ? \"pending\" : \"not_required\" });\n          const [safetyAnswers, setSafetyAnswers] = useState({\n            underweight: \"\",\n            liverKidney: \"\",\n            pregnancy: \"\",\n            cardio: \"\",\n          });\n          const modalRef = useRef(null);\n          const closeButtonRef = useRef(null);\n          const scrollLockRef = useRef({ top: 0, previousFocus: null });\n          const initialRouteRef = useRef(route);\n\n          const routeStep = route?.step;\n          const flowStep = STEPS.includes(routeStep) ? routeStep : \"config\";\n          const lang = route?.lang || getInitialLang();\n\n          const [recoveryLoading, setRecoveryLoading] = useState(!!route.recoveryId);\n\n          useEffect(() => {\n            if (route.recoveryId && route.recoveryToken) {\n              const fetchRecovery = async () => {\n                try {\n                  const response = await fetch(`\/wp-json\/retreats\/v1\/registration-recovery\/${route.recoveryId}?token=${route.recoveryToken}`);\n                  if (response.ok) {\n                    const data = await response.json();\n                    if (data.selection) {\n                      const r = RETREATS.find(ret => ret.id === data.selection.retreatId);\n                      const rooms = r ? (ROOMS_BY_RETREAT[r.id] || []) : [];\n                      \n                      \/\/ Better room matching logic\n                      let recoveredRoomId = data.selection.roomType;\n                      if (recoveredRoomId) {\n                        const directMatch = rooms.find(rm => rm.id === recoveredRoomId);\n                        if (!directMatch) {\n                          \/\/ Fallback: match by SKU if the ID was a legacy \"SKU-index\" format\n                          const recoveredSku = recoveredRoomId.split(\/[-_]\/)[0];\n                          const skuMatch = rooms.find(rm => rm.sku === recoveredSku || rm.id === recoveredSku);\n                          if (skuMatch) {\n                            recoveredRoomId = skuMatch.id;\n                          }\n                        }\n                      }\n\n                      setSelection(prev => ({ \n                        ...prev, \n                        ...data.selection,\n                        roomType: recoveredRoomId || data.selection.roomType,\n                        retreatImage: r?.image || prev.retreatImage,\n                        retreatEarlyBirdNote: r?.earlyBirdNote || prev.retreatEarlyBirdNote\n                      }));\n                    }\n                    if (data.guestDetails) {\n                      setGuestDetails(prev => ({\n                        guest1: { ...prev.guest1, ...data.guestDetails.guest1 },\n                        guest2: { ...prev.guest2, ...data.guestDetails.guest2 },\n                      }));\n                    }\n                    if (data.bookingMeta) {\n                      setBookingMeta(data.bookingMeta);\n                    }\n                    \/\/ Jump to Review\/Payment step\n                    setRoute(prev => ({ ...prev, step: \"payment\", recoveryId: null, recoveryToken: null }));\n                  }\n                } catch (err) {\n                  console.error(\"Recovery failed\", err);\n                } finally {\n                  setRecoveryLoading(false);\n                }\n              };\n              fetchRecovery();\n            }\n          }, [route.recoveryId, route.recoveryToken]);\n\n          useEffect(() => {\n            if (!bookingMeta.bookingId) return;\n            \n            const fetchStatus = async () => {\n              try {\n                const response = await fetch(`\/wp-json\/retreats\/v1\/registration-status\/${bookingMeta.bookingId}`);\n                if (response.ok) {\n                  const data = await response.json();\n                  setBookingStatus(data.status);\n                  \n                  const isPaid = data.status === \"Deposit received\" || data.status === \"Payment received\";\n                  if (isPaid) setDepositPaid(true);\n\n                  setBookingMeta(prev => ({\n                    ...prev,\n                    customerIds: data.customer_ids || []\n                  }));\n\n                  const isDone = (hc) => hc === \"yes\" || hc === \"Yes\" || hc === true || hc === \"1\" || hc === 1 || String(hc).toLowerCase().trim() === \"yes\";\n\n                  setScreeningStatus(prev => ({\n                    guest1: isDone(data.guest1_hc) ? \"complete\" : \"pending\",\n                    guest2: data.total_guests === 2 ? (isDone(data.guest2_hc) ? \"complete\" : \"pending\") : \"not_required\"\n                  }));\n                }\n              } catch (err) {\n                console.error(\"Status fetch failed\", err);\n              }\n            };\n            \n            fetchStatus();\n            \n            const pollInterval = setInterval(fetchStatus, 5000);\n            return () => clearInterval(pollInterval);\n          }, [bookingMeta.bookingId]);\n\n\n\n          const t = (key, data = {}) => {\n            let text = TRANSLATIONS[lang]?.[key] || TRANSLATIONS.en[key] || key;\n            Object.keys(data).forEach((placeholder) => {\n              text = text.replace(`{${placeholder}}`, data[placeholder]);\n            });\n            return text;\n          };\n\n          const [isSwitchingLang, setIsSwitchingLang] = useState(false);\n\n          const switchLanguage = async (newLang) => {\n            if (newLang === route.lang) return;\n            setIsSwitchingLang(true);\n            try {\n              if (window.__fetchRetreats) {\n                await window.__fetchRetreats(newLang);\n              }\n              \n              if (RETREATS.length > 0) {\n                const newDefaultRetreat = RETREATS.find((retreat) =>\n                  (Array.isArray(retreat.dates) ? retreat.dates : []).some(isRetreatDateAvailable)\n                );\n                if (!newDefaultRetreat) {\n                  setRoute({ step: \"config\", lang: newLang });\n                  return;\n                }\n                const newDefaultDate = newDefaultRetreat.dates.find(isRetreatDateAvailable);\n                const newRoomsForRetreat = getRoomsForRetreat(newDefaultRetreat.id);\n                const newDefaultRoomId = newRoomsForRetreat[0]?.id || null;\n                const newTransport = getTransportOptionsForRetreat(newDefaultRetreat.id)[0]?.id ?? null;\n\n                setSelection((prev) => ({\n                  ...prev,\n                  retreatId: newDefaultRetreat.id,\n                  retreatName: newDefaultRetreat.name,\n                  retreatLocation: newDefaultRetreat.location,\n                  retreatEarlyBirdNote: newDefaultRetreat.earlyBirdNote,\n                  retreatImage: newDefaultRetreat.image,\n                  date: newDefaultDate?.label || null,\n                  roomType: newDefaultRoomId,\n                  transfer: newTransport,\n                }));\n              }\n\n              const safeStep = STEPS.includes(route.step) ? route.step : \"config\";\n              setRoute({ step: safeStep, lang: newLang });\n            } catch (e) {\n              console.error(\"Language switch failed\", e);\n            } finally {\n              setIsSwitchingLang(false);\n            }\n          };\n\n          const syncRoute = (nextRoute) => {\n            const safeStep = STEPS.includes(nextRoute.step) ? nextRoute.step : \"config\";\n            setIsTransitioning(true);\n            window.scrollTo({ top: 0, behavior: \"smooth\" });\n            setTimeout(() => {\n              setRoute({ step: safeStep, lang: nextRoute.lang || getInitialLang() });\n              setIsTransitioning(false);\n            }, 400);\n          };\n\n          useEffect(() => {\n            window.scrollTo({ top: 0, behavior: \"smooth\" });\n          }, [route]);\n\n          useEffect(() => {\n            setScreeningStatus((prev) => {\n              if (selection.guests === 1 && prev.guest2 !== \"not_required\") {\n                return { ...prev, guest2: \"not_required\" };\n              }\n              if (selection.guests === 2 && prev.guest2 === \"not_required\") {\n                return { ...prev, guest2: \"pending\" };\n              }\n              return prev;\n            });\n          }, [selection.guests]);\n\n          const goToStep = (nextStep, replace = false) => {\n            let targetStep = STEPS.includes(nextStep) ? nextStep : \"config\";\n            \n            \/\/ If we have a recovery bookingId, don't allow going back to pre-payment steps\n            if (bookingMeta.bookingId) {\n                const prePaymentSteps = [\"config\", \"details\", \"review\", \"health_check\"];\n                if (prePaymentSteps.includes(targetStep)) {\n                    targetStep = \"payment\";\n                }\n            }\n\n            if (targetStep === \"payment\" && !safetyCleared && !bookingMeta.bookingId) {\n              targetStep = \"health_check\";\n            }\n            const postPaymentSteps = [\"screening\", \"review_state\", \"confirmed\"];\n            if (postPaymentSteps.includes(targetStep) && !depositPaid) {\n              targetStep = \"payment\";\n            }\n            syncRoute({ ...route, step: targetStep }, replace);\n          };\n\n          useEffect(() => {\n            const postPaymentSteps = [\"screening\", \"review_state\", \"confirmed\"];\n            if (postPaymentSteps.includes(flowStep) && !depositPaid) {\n              goToStep(\"payment\", true);\n            }\n          }, [flowStep, depositPaid]);\n\n\n\n          const dateOptions = useMemo(() => {\n            const rawDates = RETREATS.flatMap((retreat) =>\n              (Array.isArray(retreat.dates) ? retreat.dates : []).map((date) => ({\n                ...date,\n                retreatId: retreat.id,\n                retreatName: retreat.name,\n                location: retreat.location,\n                image: retreat.image,\n                earlyBirdNote: retreat.earlyBirdNote,\n                promotion: retreat.promotion,\n              })),\n            );\n\n            const now = new Date();\n            now.setHours(0, 0, 0, 0);\n            return rawDates\n              .map((date) => {\n                const startDate = parseRetreatStartDate(date.start);\n                const earlyBirdDeadline = date.earlyBirdDeadline ? parseRetreatStartDate(date.earlyBirdDeadline) : null;\n                const isEarlyBirdActive = earlyBirdDeadline ? now <= earlyBirdDeadline : false;\n                return {\n                  ...date,\n                  startDate,\n                  isEarlyBirdActive,\n                };\n              })\n              .filter((date) => date.startDate && date.startDate >= now)\n              .sort((a, b) => a.startDate - b.startDate);\n          }, [route.lang]);\n\n          const hasValidDateSelection = dateOptions.some(\n            (date) => date.retreatId === selection.retreatId && date.label === selection.date,\n          );\n\n          useEffect(() => {\n            if (recoveryLoading || bookingMeta.bookingId || hasValidDateSelection) return;\n            const fallbackDate =\n              dateOptions.find((date) => date.retreatId === selection.retreatId) || dateOptions[0];\n            if (!fallbackDate) {\n              setSelection((prev) => ({\n                ...prev,\n                retreatId: 0,\n                retreatName: \"\",\n                retreatLocation: \"\",\n                retreatEarlyBirdNote: \"\",\n                retreatImage: FALLBACK_IMAGE,\n                date: \"\",\n                roomType: null,\n                transfer: null,\n              }));\n              return;\n            }\n            const fallbackRetreat = RETREATS.find((retreat) => retreat.id === fallbackDate.retreatId);\n            const roomsForFallback = getRoomsForRetreat(fallbackDate.retreatId);\n            setSelection((prev) => ({\n              ...prev,\n              retreatId: fallbackDate.retreatId,\n              retreatName: fallbackDate.retreatName,\n              retreatLocation: fallbackDate.location,\n              retreatEarlyBirdNote: fallbackDate.earlyBirdNote,\n              retreatImage: fallbackDate.image || fallbackRetreat?.image || FALLBACK_IMAGE,\n              date: fallbackDate.label,\n              roomType: prev.retreatId === fallbackDate.retreatId ? prev.roomType : roomsForFallback[0]?.id || null,\n              transfer:\n                prev.retreatId === fallbackDate.retreatId\n                  ? prev.transfer\n                  : (getTransportOptionsForRetreat(fallbackDate.retreatId)[0]?.id ?? null),\n            }));\n          }, [dateOptions, hasValidDateSelection, recoveryLoading, bookingMeta.bookingId, selection.retreatId]);\n\n          const roomsForCurrentRetreat = useMemo(() => getRoomsForRetreat(selection.retreatId), [selection.retreatId, route.lang]);\n          const filteredRoomsForCurrentRetreat = useMemo(() => {\n            if (!Array.isArray(roomsForCurrentRetreat) || roomsForCurrentRetreat.length === 0) return [];\n            const desired = selection.guests === 1 ? \"single\" : \"shared\";\n            return roomsForCurrentRetreat.filter((room) => {\n              const roomPerson = Number(room.person);\n              if (Number.isFinite(roomPerson) && roomPerson > 0) {\n                return roomPerson === selection.guests;\n              }\n              const typeHint = `${room.type || \"\"} ${room.name || \"\"}`.toLowerCase();\n              if (desired === \"single\") return typeHint.includes(\"single\");\n              if (desired === \"shared\") return typeHint.includes(\"shared\");\n              return true;\n            });\n          }, [roomsForCurrentRetreat, selection.guests]);\n          const transportOptionsForCurrentRetreat = useMemo(() => getTransportOptionsForRetreat(selection.retreatId), [selection.retreatId]);\n\n          const pricing = useMemo(() => {\n            const roomOptions = filteredRoomsForCurrentRetreat.length ? filteredRoomsForCurrentRetreat : roomsForCurrentRetreat;\n            const room = roomOptions.find((r) => r.id === selection.roomType) || roomOptions[0];\n            const roomPrice = room ? room.price : 0;\n            const transportOption =\n              transportOptionsForCurrentRetreat.find((option) => option.id === selection.transfer) || transportOptionsForCurrentRetreat[0];\n            const subtotal = roomPrice;\n            const selectedDate = dateOptions.find(\n              (date) => date.retreatId === selection.retreatId && date.label === selection.date,\n            );\n            const promotion = selectedDate?.promotion || {};\n            const guestCount = Number(selection.guests) || 0;\n            const isEarlyBirdEligible = !!selectedDate?.isEarlyBirdActive;\n            const isFriendPromotionEligible = guestCount === 2 && Number(promotion.friend?.value) > 0;\n            const rawEarlyBird = isEarlyBirdEligible\n              ? calculateConfiguredDiscount(subtotal, promotion.earlyBird, guestCount)\n              : 0;\n            const earlyBird = rawEarlyBird;\n            const friendBase = subtotal - earlyBird;\n            const rawFriend = isFriendPromotionEligible\n              ? calculateConfiguredDiscount(friendBase, promotion.friend)\n              : 0;\n            const friend = rawFriend;\n            const promotionTotal = earlyBird + friend;\n            const transport = transportOption?.price || 0;\n            const total = subtotal - promotionTotal + transport;\n            const deposit = Math.round(total * 0.3);\n            const remaining = total - deposit;\n            return {\n              subtotal,\n              earlyBird,\n              friend,\n              promotionTotal,\n              transport,\n              total,\n              deposit,\n              remaining,\n              earlyBirdConfig: promotion.earlyBird,\n              friendConfig: promotion.friend,\n            };\n          }, [selection, dateOptions, roomsForCurrentRetreat, filteredRoomsForCurrentRetreat, transportOptionsForCurrentRetreat]);\n\n          const stripeFee = paymentMethod === \"stripe\" ? Math.round(pricing.deposit * STRIPE_FEE_RATE) : 0;\n          const paymentDueNow = pricing.deposit + stripeFee;\n          const screeningsComplete = screeningStatus.guest1 === \"complete\" && \n                                     (selection.guests === 1 || screeningStatus.guest2 === \"complete\") &&\n                                     (bookingStatus === \"Payment received\" || bookingStatus === \"Deposit received\");\n          const safetyAllAnswered = Object.values(safetyAnswers).every((value) => value === \"yes\" || value === \"no\");\n          const safetyHasConcern = Object.values(safetyAnswers).some((value) => value === \"yes\");\n          const safetyCleared = safetyAllAnswered && !safetyHasConcern;\n\n          const updateSelection = (updates) => setSelection((prev) => ({ ...prev, ...updates }));\n\n          const roomOptionsForSummary = filteredRoomsForCurrentRetreat.length ? filteredRoomsForCurrentRetreat : roomsForCurrentRetreat;\n          const selectedRoomForSummary = roomOptionsForSummary.find((r) => r.id === selection.roomType) || roomOptionsForSummary[0];\n          const selectedRoomName = selectedRoomForSummary?.name || selectedRoomForSummary?.type || \"\";\n\n          useEffect(() => {\n            if (recoveryLoading) return;\n            if (filteredRoomsForCurrentRetreat.length === 0) return;\n            const hasSelected = filteredRoomsForCurrentRetreat.some((room) => room.id === selection.roomType);\n            if (!hasSelected) {\n              setSelection((prev) => ({ ...prev, roomType: filteredRoomsForCurrentRetreat[0].id }));\n            }\n          }, [filteredRoomsForCurrentRetreat, selection.roomType, recoveryLoading]);\n\n          const updateGuest = (guestKey, field, value) => {\n            setGuestDetails((prev) => ({\n              ...prev,\n              [guestKey]: { ...prev[guestKey], [field]: value },\n            }));\n          };\n\n          const updateSafetyAnswer = (questionId, value) => {\n            setSafetyAnswers((prev) => ({ ...prev, [questionId]: value }));\n          };\n\n          const handlePrimaryCountryChange = (value) => {\n            setGuestDetails((prev) => {\n              const nextGuest1 = { ...prev.guest1, country: value };\n              if (!nextGuest1.phoneCodeManuallySet) {\n                const dial = getDialCodeForCountry(value);\n                if (dial) {\n                  nextGuest1.phoneCountryCode = dial;\n                }\n              }\n              return { ...prev, guest1: nextGuest1 };\n            });\n          };\n\n          const handlePrimaryPhoneCodeChange = (value) => {\n            setGuestDetails((prev) => ({\n              ...prev,\n              guest1: { ...prev.guest1, phoneCountryCode: value, phoneCodeManuallySet: true },\n            }));\n          };\n\n          const handleRetreatSelection = (dateOption) => {\n            if (!dateOption) return;\n            setSelection((prev) => {\n              const isSameRetreat = prev.retreatId === dateOption.retreatId;\n              const roomsForSelectedRetreat = getRoomsForRetreat(dateOption.retreatId);\n              return {\n                ...prev,\n                retreatId: dateOption.retreatId,\n                retreatName: dateOption.retreatName,\n                retreatLocation: dateOption.location,\n                retreatEarlyBirdNote: dateOption.earlyBirdNote,\n                retreatImage: dateOption.image,\n                date: dateOption.label,\n                roomType: isSameRetreat ? prev.roomType : roomsForSelectedRetreat[0]?.id || null,\n                transfer: isSameRetreat ? prev.transfer : (getTransportOptionsForRetreat(dateOption.retreatId)[0]?.id ?? null),\n              };\n            });\n          };\n\n          const openGallery = (room) => {\n            setGalleryRoom(room);\n            setGalleryIndex(0);\n          };\n\n          const closeGallery = () => {\n            setGalleryRoom(null);\n            setGalleryIndex(0);\n          };\n\n          const showNextImage = () => {\n            if (!galleryRoom) return;\n            setGalleryIndex((index) => (index + 1) % galleryRoom.images.length);\n          };\n\n          const showPrevImage = () => {\n            if (!galleryRoom) return;\n            setGalleryIndex((index) => (index - 1 + galleryRoom.images.length) % galleryRoom.images.length);\n          };\n\n          useEffect(() => {\n            if (!galleryRoom) return undefined;\n            const previousFocus = document.activeElement;\n            const body = document.body;\n            const originalOverflow = body.style.overflow;\n            const originalPaddingRight = body.style.paddingRight;\n\n            \/\/ To prevent layout shift when scrollbar disappears\n            const scrollBarWidth = window.innerWidth - document.documentElement.clientWidth;\n\n            body.style.overflow = \"hidden\";\n            if (scrollBarWidth > 0) {\n              body.style.paddingRight = `${scrollBarWidth}px`;\n            }\n\n            const handleKeyDown = (event) => {\n              if (event.key === \"Escape\") {\n                event.preventDefault();\n                closeGallery();\n                return;\n              }\n              if (event.key === \"Tab\") {\n                const focusableSelectors = 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n                const nodes = modalRef.current?.querySelectorAll(focusableSelectors);\n                const focusable = nodes ? Array.from(nodes).filter((node) => !node.hasAttribute(\"disabled\")) : [];\n                if (focusable.length === 0) return;\n                const first = focusable[0];\n                const last = focusable[focusable.length - 1];\n                if (event.shiftKey) {\n                  if (document.activeElement === first) {\n                    event.preventDefault();\n                    last.focus();\n                  }\n                } else if (document.activeElement === last) {\n                  event.preventDefault();\n                  first.focus();\n                }\n              }\n            };\n\n            document.addEventListener(\"keydown\", handleKeyDown);\n            requestAnimationFrame(() => closeButtonRef.current?.focus());\n\n            return () => {\n              document.removeEventListener(\"keydown\", handleKeyDown);\n              body.style.overflow = originalOverflow;\n              body.style.paddingRight = originalPaddingRight;\n              previousFocus?.focus?.();\n            };\n          }, [galleryRoom]);\n\n          const guestDetailsValid = () => {\n            const emailPattern = \/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$\/;\n            const g1 = guestDetails.guest1;\n            const primaryFieldsFilled =\n              g1.firstName.trim() &&\n              g1.lastName.trim() &&\n              g1.email.trim() &&\n              emailPattern.test(g1.email.trim()) &&\n              g1.phone.trim() &&\n              g1.street.trim() &&\n              g1.city.trim() &&\n              g1.postalCode.trim() &&\n              g1.country.trim();\n            const companyValid = !g1.needsCompanyInvoice || (g1.companyName.trim() && g1.taxId.trim());\n            if (!primaryFieldsFilled || !companyValid) return false;\n            if (selection.guests === 1) return true;\n\n            const g2 = guestDetails.guest2;\n            const g2Valid =\n              g2.firstName.trim() &&\n              g2.lastName.trim() &&\n              g2.email.trim() &&\n              emailPattern.test(g2.email.trim()) &&\n              g2.phone.trim();\n            return g2Valid;\n          };\n\n          const buildBookingPayload = () => {\n            const selectedDate = dateOptions.find(\n              (date) => date.retreatId === selection.retreatId && date.label === selection.date,\n            );\n            const selectedRoom = roomsForCurrentRetreat.find((room) => room.id === selection.roomType) || roomsForCurrentRetreat[0] || null;\n            const selectedTransport =\n              transportOptionsForCurrentRetreat.find((option) => option.id === selection.transfer) || transportOptionsForCurrentRetreat[0] || null;\n            const purchaseFirstName = guestDetails.guest1.firstName?.trim() || \"\";\n            const purchaseLastName = guestDetails.guest1.lastName?.trim() || \"\";\n            const purchaseEmail = guestDetails.guest1.email?.trim() || \"\";\n            const purchasePhone = guestDetails.guest1.phone?.trim() || \"\";\n            const packageType = selectedRoom?.type || selectedRoom?.roomType || \"\";\n            const transportType = selectedTransport?.label ?? selectedTransport?.id ?? \"\";\n            return {\n              lang: lang,\n              retreat_id: selection.retreatId,\n              retreat_name: selection.retreatName,\n              location: selection.retreatLocation,\n              total_persons: selection.guests,\n              purchase_first_name: purchaseFirstName,\n              purchase_last_name: purchaseLastName,\n              purchase_email: purchaseEmail,\n              purchase_phone: purchasePhone,\n              start_date: selectedDate?.start || \"\",\n              end_date: selectedDate?.end || \"\",\n              package_sku: selectedRoom?.sku || \"\",\n              package_type: packageType,\n              package_price: selectedRoom?.price || 0,\n              transportation_type: transportType,\n              transportation_fee: selectedTransport?.price || 0,\n              total: pricing.total,\n              join_with_a_friend: selection.guests === 2 ? \"yes\" : \"\",\n              retreat: {\n                id: selection.retreatId,\n                name: selection.retreatName,\n                location: selection.retreatLocation,\n                earlyBirdNote: selection.retreatEarlyBirdNote,\n                image: selection.retreatImage,\n              },\n              date: selectedDate\n                ? {\n                    label: selectedDate.label,\n                    start: selectedDate.start,\n                    end: selectedDate.end,\n                    earlyBirdDeadline: selectedDate.earlyBirdDeadline || null,\n                    limited: !!selectedDate.limited,\n                    isEarlyBirdActive: !!selectedDate.isEarlyBirdActive,\n                  }\n                : null,\n              guests: selection.guests,\n              room: selectedRoom\n                ? {\n                    id: selectedRoom.id,\n                    sku: selectedRoom.sku || null,\n                    name: selectedRoom.name,\n                    type: selectedRoom.type || null,\n                    person: selectedRoom.person || null,\n                    price: selectedRoom.price || 0,\n                    roomType: selectedRoom.roomType || null,\n                  }\n                : null,\n              transport: selectedTransport ? { id: selectedTransport.id, label: selectedTransport.label, price: selectedTransport.price || 0 } : null,\n              guestDetails,\n              pricing: {\n                subtotal: pricing.subtotal,\n                earlyBird: pricing.earlyBird,\n                friend: pricing.friend,\n                transport: pricing.transport,\n                total: pricing.total,\n                deposit: pricing.deposit,\n                remaining: pricing.remaining,\n                stripeFee,\n                paymentDueNow,\n              },\n              paymentMethod,\n              screeningStatus,\n              safetyAnswers,\n              submittedAt: new Date().toISOString(),\n            };\n          };\n\n          const handlePayment = async () => {\n            if (paymentSubmitting) return;\n            setPaymentError(\"\");\n            setPaymentSubmitting(true);\n            try {\n              let bookingId = bookingMeta.bookingId;\n              let customerIds = bookingMeta.customerIds;\n\n              if (!bookingId) {\n                const payload = buildBookingPayload();\n                const response = await fetch(BOOKING_API_ENDPOINT, {\n                  method: \"POST\",\n                  headers: { \"Content-Type\": \"application\/json\" },\n                  body: JSON.stringify(payload),\n                });\n                if (!response.ok) {\n                  throw new Error(`HTTP ${response.status}`);\n                }\n                const responseBody = await response.json();\n                bookingId = responseBody?.booking_id;\n                customerIds = Array.isArray(responseBody?.customer_ids) ? responseBody.customer_ids : [];\n                \n                setBookingMeta({\n                  bookingId: bookingId ?? null,\n                  customerIds: customerIds,\n                });\n              }\n\n              \/\/ If OnePay, redirect to OnePay URL generator\n              if (paymentMethod === \"onepay_domestic\" || paymentMethod === \"onepay_intl\") {\n                const returnPath = getBookingReturnPath(lang);\n                const urlResponse = await fetch(\"\/wp-json\/retreats\/v1\/onepay-url\", {\n                  method: \"POST\",\n                  headers: { \"Content-Type\": \"application\/json\" },\n                  body: JSON.stringify({ \n                    booking_id: bookingId, \n                    payment_type: paymentMethod,\n                    lang: lang,\n                    return_base: returnPath\n                  }),\n                });\n                if (!urlResponse.ok) throw new Error(\"Failed to generate OnePay URL\");\n                const urlData = await urlResponse.json();\n                if (urlData.return_path !== returnPath) {\n                  throw new Error(\n                    `OnePay return path mismatch: expected ${returnPath}, received ${urlData.return_path || \"none\"}`\n                  );\n                }\n                if (urlData.payment_url) {\n                  try {\n                    sessionStorage.setItem(\"vdx_booking_state\", JSON.stringify({\n                      selection,\n                      guestDetails,\n                      paymentMethod,\n                      bookingMeta: {\n                        bookingId: bookingId ?? null,\n                        customerIds: customerIds,\n                      },\n                      screeningStatus\n                    }));\n                  } catch(e) {}\n                  window.location.href = urlData.payment_url;\n                  return;\n                }\n              }\n\n              setPaymentSuccess(true);\n              if (!depositPaid) {\n                setDepositPaid(true);\n                setScreeningStatus((prev) => ({\n                  guest1: prev.guest1 === \"complete\" ? \"complete\" : \"pending\",\n                  guest2: selection.guests === 2 ? (prev.guest2 === \"complete\" ? \"complete\" : \"pending\") : \"not_required\",\n                }));\n              }\n              setTimeout(() => goToStep(\"screening\"), 2000);\n            } catch (error) {\n              console.error(\"Failed to submit booking payload\", error);\n              setPaymentError(\"We could not secure your booking right now. Please try again.\");\n            } finally {\n              setPaymentSubmitting(false);\n            }\n          };\n\n          const renderConfigStep = () => (\n            <div className=\"space-y-12\">\n              <header className=\"space-y-3\">\n                <p className=\"text-[12px] uppercase tracking-[0.4em] text-stone-400\">{t(\"step\")} 1<\/p>\n                <h1 className=\"text-4xl font-bold\">{t(\"plan_journey\")}<\/h1>\n                <p className=\"text-stone-500\">\n                  {t(\"plan_description\")}\n                <\/p>\n              <\/header>\n\n              <section className=\"space-y-4\">\n                <div>\n                  <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400 font-semibold\">{t(\"upcoming_retreats\")}<\/p>\n                  <p className=\"text-sm text-stone-500\">{t(\"retreats_description\")}<\/p>\n                <\/div>\n                <div className=\"space-y-4\">\n                  {RETREATS.map((retreat) => {\n                    const retreatDates = dateOptions.filter((option) => option.retreatId === retreat.id);\n                    const isActiveRetreat = selection.retreatId === retreat.id;\n                    const preferredDate =\n                      retreatDates.find((date) => selection.retreatId === retreat.id && date.label === selection.date) || retreatDates[0];\n                    return (\n                      <div key={retreat.id} className={`space-y-3 border rounded-3xl p-4 md:p-6 transition-all duration-300 ${isActiveRetreat ? \"border-2 border-emerald-600 bg-emerald-50 shadow-md\" : \"border-stone-100 bg-white shadow-sm\"}`}>\n                        <div\n                          className={`flex flex-col md:flex-row md:items-center gap-4 ${preferredDate ? \"cursor-pointer\" : \"cursor-default\"}`}\n                          role=\"button\"\n                          aria-pressed={isActiveRetreat}\n                          aria-disabled={!preferredDate}\n                          tabIndex={preferredDate ? 0 : -1}\n                          onClick={() => preferredDate && handleRetreatSelection(preferredDate)}\n                          onKeyDown={(event) => {\n                            if (event.key === \"Enter\" || event.key === \" \") {\n                              event.preventDefault();\n                              preferredDate && handleRetreatSelection(preferredDate);\n                            }\n                          }}\n                        >\n                          <div className=\"flex-shrink-0 w-full md:w-52\">\n                            <div className=\"relative h-32 w-full overflow-hidden rounded-2xl\">\n                              <img\n                                src={retreat.image || FALLBACK_IMAGE}\n                                alt={retreat.name}\n                                className=\"w-full h-full object-cover\"\n                                onError={handleImageError}\n                              \/>\n                              <div className=\"absolute inset-0 bg-gradient-to-t from-stone-900\/20 to-transparent pointer-events-none\" \/>\n                            <\/div>\n                          <\/div>\n                          <div className=\"flex-1 min-w-0 space-y-2\">\n                            <p className=\"text-xs uppercase tracking-[0.2em] text-stone-400\">{retreat.location}<\/p>\n                            <div className=\"flex items-start justify-between gap-3\">\n                              <h3 className=\"text-base font-semibold text-stone-900 truncate\">{retreat.name}<\/h3>\n                              <span\n                                className={`mt-1 w-6 h-6 rounded-full border flex items-center justify-center text-[10px] font-semibold ${\n                                  isActiveRetreat ? \"border-emerald-600 bg-emerald-600 text-white\" : \"border-stone-200 text-stone-300\"\n                                }`}\n                              >\n                                {isActiveRetreat ? <Icons.Check \/> : null}\n                              <\/span>\n                            <\/div>\n                            <p className=\"text-sm text-stone-500 line-clamp-2 md:line-clamp-none\">{retreat.description}<\/p>\n                            <div className=\"flex items-center gap-2 pt-1\">\n                              <a \n                                href={retreat.url} \n                                target=\"_blank\" \n                                rel=\"noopener noreferrer\"\n                                onClick={(e) => e.stopPropagation()}\n                                className=\"text-xs font-semibold text-emerald-700 hover:text-emerald-800 underline underline-offset-4 flex items-center gap-1 group\"\n                              >\n                                {t(\"read_more\")}\n                                <svg className=\"w-3 h-3 transition-transform group-hover:translate-x-0.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n                                  <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M14 5l7 7m0 0l-7 7m7-7H3\" \/>\n                                <\/svg>\n                              <\/a>\n                            <\/div>\n                            <p className=\"text-xs text-stone-500\">{retreat.earlyBirdNote}<\/p>\n                          <\/div>\n                        <\/div>\n                        <div className=\"space-y-2\">\n                          <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400\">{t(\"available_dates\")}<\/p>\n                          <div className=\"flex items-center gap-2\">\n                            {retreatDates.length > 2 && (\n                              <button\n                                type=\"button\"\n                                aria-label=\"Show earlier retreat dates\"\n                                className=\"vdx-date-arrow hidden md:inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-full border\"\n                                onClick={(event) => {\n                                  event.stopPropagation();\n                                  const container = event.currentTarget.nextSibling;\n                                  container?.scrollBy({ left: -220, behavior: \"smooth\" });\n                                }}\n                              >\n                                <Icons.ChevronLeft \/>\n                              <\/button>\n                            )}\n                            <div className=\"flex gap-2 overflow-x-auto hide-scrollbar py-2 px-2 flex-1\" onWheel={(event) => event.stopPropagation()}>\n                              {retreatDates.length === 0 && (\n                                <p className=\"py-2 text-sm text-stone-500\">{t(\"no_upcoming_dates\")}<\/p>\n                              )}\n                              {retreatDates.map((dateOption) => {\n                                const activeDate = selection.date === dateOption.label;\n                                const showEarlyBird = dateOption.isEarlyBirdActive;\n                                const showLimited = dateOption.limited;\n                                return (\n                                  <button\n                                    key={dateOption.label}\n                                    type=\"button\"\n                                    aria-label={`Select ${dateOption.label}`}\n                                    aria-pressed={activeDate}\n                                    onClick={(event) => {\n                                      event.stopPropagation();\n                                      handleRetreatSelection(dateOption);\n                                    }}\n                                    className={`vdx-date-button flex-shrink-0 px-3 py-2 text-xs md:text-sm rounded-full border transition-all duration-200 ${\n                                      activeDate ? \"bg-emerald-800 text-white border-emerald-800 scale-[1.05] shadow-md\" : \"border-stone-200 text-stone-600 hover:border-emerald-200 bg-white\"\n                                    }`}\n                                  >\n                                    <span className={`font-semibold whitespace-nowrap ${activeDate ? \"text-white\" : \"text-stone-900\"}`}>{dateOption.label}<\/span>\n                                    {(showEarlyBird || showLimited) && (\n                                      <div className=\"flex flex-wrap gap-1 mt-1 justify-center\">\n                                        {showEarlyBird && (\n                                          <span className={`text-[10px] font-semibold uppercase tracking-[0.2em] ${activeDate ? \"text-emerald-100\" : \"text-emerald-700\"}`}>\n                                            {t(\"early_bird_label\").replace(\"{{discount}}\", formatConfiguredDiscount(dateOption.promotion?.earlyBird, lang))}\n                                          <\/span>\n                                        )}\n                                        {showLimited && (\n                                          <span className={`text-[10px] font-semibold uppercase tracking-[0.2em] ${activeDate ? \"text-amber-200\" : \"text-amber-700\"}`}>\n                                            {t(\"limited_spots\")}\n                                          <\/span>\n                                        )}\n                                      <\/div>\n                                    )}\n                                  <\/button>\n                                );\n                              })}\n                            <\/div>\n                            {retreatDates.length > 2 && (\n                              <button\n                                type=\"button\"\n                                aria-label=\"Show later retreat dates\"\n                                className=\"vdx-date-arrow hidden md:inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-full border\"\n                                onClick={(event) => {\n                                  event.stopPropagation();\n                                  const container = event.currentTarget.previousSibling;\n                                  container?.scrollBy({ left: 220, behavior: \"smooth\" });\n                                }}\n                              >\n                                <Icons.ChevronRight \/>\n                              <\/button>\n                            )}\n                          <\/div>\n                        <\/div>\n                      <\/div>\n                    );\n                  })}\n                <\/div>\n              <\/section>\n\n              <section className=\"space-y-4\">\n                <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400 font-semibold\">{t(\"guests\")}<\/p>\n                <div className=\"flex flex-col md:flex-row gap-4\">\n                  {[1, 2].map((count) => {\n                    const active = selection.guests === count;\n                    return (\n                      <button\n                        key={count}\n                        type=\"button\"\n                        aria-pressed={active}\n                        onClick={() => updateSelection({ guests: count })}\n                        className={`flex-1 border-2 rounded-2xl p-4 flex items-center justify-between transition-all duration-200 ${\n                          active ? \"border-2 border-emerald-600 bg-emerald-50 ring-4 ring-emerald-600\/10 shadow-lg\" : \"border-stone-100 hover:border-stone-200\"\n                        }`}\n                      >\n                        <div className=\"text-left\">\n                          <p className=\"font-semibold\">{count === 1 ? t(\"one_guest\") : t(\"two_guests\")}<\/p>\n                          <p className=\"text-sm text-stone-500\">\n                            {count === 2\n                              ? t(\"save_together\").replace(\n                                  \"{{discount}}\",\n                                  formatConfiguredDiscount(\n                                    RETREATS.find((retreat) => retreat.id === selection.retreatId)?.promotion?.friend,\n                                    lang,\n                                  ),\n                                )\n                              : t(\"private_journey\")}\n                          <\/p>\n                        <\/div>\n                        {count === 2 ? <Icons.Users \/> : <Icons.User \/>}\n                      <\/button>\n                    );\n                  })}\n                <\/div>\n              <\/section>\n\n              <section className=\"space-y-4\">\n                <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400 font-semibold\">{t(\"accommodation\")}<\/p>\n                <div className=\"bg-emerald-50 border border-emerald-100 rounded-3xl p-5 text-left\">\n                  <p className=\"text-xs uppercase tracking-[0.3em] text-emerald-700 font-semibold\">{t(\"health_prep_first\")}<\/p>\n                  <p className=\"text-sm text-stone-600\">\n                    {t(\"health_prep_description\")}\n                  <\/p>\n                <\/div>\n\n                <div className=\"space-y-6\">\n                  {filteredRoomsForCurrentRetreat.length === 0 && (\n                    <p className=\"text-sm text-stone-500\">{t(\"no_accommodation\")}<\/p>\n                  )}\n                  {filteredRoomsForCurrentRetreat.map((room) => {\n                    const active = selection.roomType === room.id;\n                    return (\n                      <div\n                        key={room.id}\n                        role=\"button\"\n                        aria-pressed={active}\n                        tabIndex={0}\n                        onClick={() => updateSelection({ roomType: room.id })}\n                        onKeyDown={(event) => {\n                          if (event.key === \"Enter\" || event.key === \" \") {\n                            event.preventDefault();\n                            updateSelection({ roomType: room.id });\n                          }\n                        }}\n                        className={`w-full text-left border-2 rounded-3xl overflow-hidden cursor-pointer transition-all duration-300 ${\n                          active ? \"border-2 border-emerald-600 bg-emerald-50\/50 shadow-lg shadow-emerald-100\/40\" : \"border-stone-100 hover:border-stone-200\"\n                        }`}\n                      >\n                        <div className=\"grid grid-cols-1 md:grid-cols-3\">\n                          <div className=\"md:col-span-1 h-48 overflow-hidden\">\n                            <img src={room.images[0]} alt={room.name} className=\"w-full h-full object-cover\" onError={handleImageError} \/>\n                          <\/div>\n                          <div className=\"md:col-span-2 p-6 space-y-4\">\n                            <div>\n                              <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400\">{room.benefit}<\/p>\n                              <div className=\"flex items-center justify-between mt-2\">\n                                <h3 className=\"text-2xl font-bold\">{room.name}<\/h3>\n                                <p className=\"text-sm text-stone-500\">\n                                  {selection.guests === 2 ? formatVND(room.price, lang) : `${t(\"per_guest\")} ${formatVND(room.price, lang)}`}\n                                <\/p>\n                              <\/div>\n                            <\/div>\n                            <div className=\"flex items-center justify-between pt-3 border-t border-stone-200\">\n                              <span className={`text-sm font-semibold ${active ? \"text-emerald-700\" : \"text-stone-500\"}`}>\n                                {active ? t(\"selected\") : t(\"tap_to_select\")}\n                              <\/span>\n                              <button\n                                type=\"button\"\n                                onClick={(e) => {\n                                  e.stopPropagation();\n                                  openGallery(room);\n                                }}\n                                className=\"text-sm font-semibold text-emerald-700 hover:text-emerald-800\"\n                              >\n                                {t(\"view_photos\")}\n                              <\/button>\n                            <\/div>\n                          <\/div>\n                        <\/div>\n                      <\/div>\n                    );\n                  })}\n                <\/div>\n              <\/section>\n\n              <section className=\"space-y-4\">\n                <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400 font-semibold\">{t(\"airport_transfer\")}<\/p>\n                <select\n                  className=\"w-full border border-stone-200 rounded-2xl p-4 bg-stone-50 focus:ring-2 focus:ring-emerald-100 outline-none\"\n                  value={selection.transfer}\n                  onChange={(e) => updateSelection({ transfer: Number(e.target.value) })}\n                >\n                  {transportOptionsForCurrentRetreat.map((option) => (\n                    <option key={option.id} value={option.id}>\n                      {option.label} {option.price > 0 ? `(+${formatVND(option.price, lang)})` : \"\"}\n                    <\/option>\n                  ))}\n                <\/select>\n              <\/section>\n\n              <div className=\"flex justify-end\">\n                <button\n                  type=\"button\"\n                  disabled={!hasValidDateSelection}\n                  onClick={() => goToStep(\"details\")}\n                  className={`inline-flex items-center px-6 py-3 rounded-full font-semibold transition ${\n                    hasValidDateSelection\n                      ? \"bg-emerald-800 text-white hover:bg-emerald-900\"\n                      : \"bg-stone-200 text-stone-500 cursor-not-allowed\"\n                  }`}\n                >\n                  {t(\"continue\")} <Icons.ChevronRight \/>\n                <\/button>\n              <\/div>\n            <\/div>\n          );\n\n\n          const renderGuestDetailsStep = () => {\n            const primary = guestDetails.guest1;\n            const secondary = guestDetails.guest2;\n\n            const renderInput = (label, value, onChange, type = \"text\", helper) => (\n              <div className=\"space-y-2\">\n                <label className=\"text-[11px] uppercase tracking-[0.2em] text-stone-500\">{label}<\/label>\n                <input\n                  type={type}\n                  className=\"w-full border border-stone-200 rounded-2xl p-4 bg-stone-50 focus:ring-2 focus:ring-emerald-100 outline-none\"\n                  value={value}\n                  onChange={onChange}\n                \/>\n                {helper && <p className=\"text-xs text-stone-500\">{helper}<\/p>}\n              <\/div>\n            );\n\n            return (\n              <div className=\"space-y-10\">\n                <header className=\"space-y-2\">\n                  <p className=\"text-[12px] uppercase tracking-[0.4em] text-stone-400\">{t(\"step\")} 2<\/p>\n                  <h1 className=\"text-4xl font-bold\">{t(\"details\")}<\/h1>\n                  <p className=\"text-sm text-stone-500\">\n                    {t(\"details_description\")}\n                  <\/p>\n                <\/header>\n\n                <section className=\"space-y-6\">\n                  <div className=\"space-y-1\">\n                    <h2 className=\"text-xl font-semibold text-stone-900\">{t(\"primary_guest\")}<\/h2>\n                    <p className=\"text-sm text-stone-500\">{t(\"primary_description\")}<\/p>\n                  <\/div>\n                  <div className=\"space-y-6\">\n                    <div className=\"space-y-4\">\n                      {renderInput(t(\"first_name\"), primary.firstName, (e) => updateGuest(\"guest1\", \"firstName\", e.target.value))}\n                      {renderInput(t(\"last_name\"), primary.lastName, (e) => updateGuest(\"guest1\", \"lastName\", e.target.value))}\n                      {renderInput(t(\"email_address\"), primary.email, (e) => updateGuest(\"guest1\", \"email\", e.target.value), \"email\")}\n                    <\/div>\n                    <div className=\"space-y-2\">\n                      <label className=\"text-[11px] uppercase tracking-[0.2em] text-stone-500\">{t(\"phone_number\")}<\/label>\n                      <div className=\"flex flex-col sm:flex-row gap-3\">\n                        <div className=\"sm:w-32\">\n                          <select\n                            className=\"w-full border border-stone-200 rounded-2xl p-4 bg-stone-50 focus:ring-2 focus:ring-emerald-100 outline-none\"\n                            value={primary.phoneCountryCode}\n                            onChange={(e) => handlePrimaryPhoneCodeChange(e.target.value)}\n                          >\n                            {[...PHONE_CODE_OPTIONS].sort().map((code) => (\n                              <option key={code} value={code}>\n                                {code}\n                              <\/option>\n                            ))}\n                          <\/select>\n                        <\/div>\n                        <input\n                          type=\"tel\"\n                          className=\"flex-1 border border-stone-200 rounded-2xl p-4 bg-stone-50 focus:ring-2 focus:ring-emerald-100 outline-none\"\n                          value={primary.phone}\n                          onChange={(e) => updateGuest(\"guest1\", \"phone\", e.target.value)}\n                        \/>\n                      <\/div>\n                      <p className=\"text-xs text-stone-500\">{t(\"phone_helper\")}<\/p>\n                    <\/div>\n                    <div className=\"space-y-2\">\n                      <p className=\"text-xs text-stone-500\">\n                        {t(\"invoice_helper\")}\n                      <\/p>\n                      {renderInput(t(\"street_house\"), primary.street, (e) => updateGuest(\"guest1\", \"street\", e.target.value))}\n                      {renderInput(t(\"city\"), primary.city, (e) => updateGuest(\"guest1\", \"city\", e.target.value))}\n                      {renderInput(t(\"postal_code\"), primary.postalCode, (e) => updateGuest(\"guest1\", \"postalCode\", e.target.value))}\n                      {renderInput(t(\"country_residence\"), primary.country, (e) => handlePrimaryCountryChange(e.target.value))}\n                    <\/div>\n                    <div className=\"space-y-2\">\n                      <label className=\"flex items-center gap-2 text-sm text-stone-700\">\n                        <input\n                          type=\"checkbox\"\n                          checked={primary.needsCompanyInvoice}\n                          onChange={(e) => updateGuest(\"guest1\", \"needsCompanyInvoice\", e.target.checked)}\n                        \/>\n                        {t(\"need_company_invoice\")}\n                      <\/label>\n                      {primary.needsCompanyInvoice && (\n                        <div className=\"space-y-4\">\n                          {renderInput(t(\"company_name\"), primary.companyName, (e) => updateGuest(\"guest1\", \"companyName\", e.target.value))}\n                          {renderInput(t(\"tax_id\"), primary.taxId, (e) => updateGuest(\"guest1\", \"taxId\", e.target.value))}\n                        <\/div>\n                      )}\n                    <\/div>\n                  <\/div>\n                <\/section>\n\n                {selection.guests === 2 && (\n                  <section className=\"space-y-6 pt-8 border-t border-stone-200\">\n                    <div className=\"space-y-1\">\n                      <h2 className=\"text-xl font-semibold text-stone-900\">{t(\"second_guest\")}<\/h2>\n                      <p className=\"text-sm text-stone-500\">{t(\"second_description\")}<\/p>\n                    <\/div>\n                    <div className=\"space-y-4\">\n                      {renderInput(t(\"first_name\"), secondary.firstName, (e) => updateGuest(\"guest2\", \"firstName\", e.target.value))}\n                      {renderInput(t(\"last_name\"), secondary.lastName, (e) => updateGuest(\"guest2\", \"lastName\", e.target.value))}\n                      {renderInput(t(\"email_address\"), secondary.email, (e) => updateGuest(\"guest2\", \"email\", e.target.value), \"email\")}\n                      {renderInput(t(\"phone_number\"), secondary.phone, (e) => updateGuest(\"guest2\", \"phone\", e.target.value), \"tel\")}\n                    <\/div>\n                  <\/section>\n                )}\n\n                <div className=\"flex justify-between items-center gap-4\">\n                  {!bookingMeta.bookingId ? (\n                    <button type=\"button\" onClick={() => goToStep(\"config\")} className=\"inline-flex items-center text-stone-500 font-semibold\">\n                      <Icons.ChevronLeft \/> {t(\"back\")}\n                    <\/button>\n                  ) : <div><\/div>}\n                  <button\n                    type=\"button\"\n                    disabled={!guestDetailsValid()}\n                    onClick={() => goToStep(\"review\")}\n                    className={`vdx-paired-step-action inline-flex items-center px-6 py-3 rounded-full font-semibold ${\n                      guestDetailsValid() ? \"bg-emerald-800 text-white hover:bg-emerald-900\" : \"bg-stone-200 text-stone-500 cursor-not-allowed\"\n                    }`}\n                  >\n                    {t(\"review\")} <Icons.ChevronRight \/>\n                  <\/button>\n                <\/div>\n              <\/div>\n            );\n          };\n\n\n          const renderReviewStep = () => {\n            const dateInfo = dateOptions.find(\n              (date) => date.retreatId === selection.retreatId && date.label === selection.date,\n            );\n            const room = roomsForCurrentRetreat.find((r) => r.id === selection.roomType) || roomsForCurrentRetreat[0];\n            const transferOption =\n              transportOptionsForCurrentRetreat.find((option) => option.id === selection.transfer) || transportOptionsForCurrentRetreat[0];\n            const guests = [\n              { label: t(\"guest_one\"), data: guestDetails.guest1 },\n              ...(selection.guests === 2 ? [{ label: t(\"guest_two\"), data: guestDetails.guest2 }] : []),\n            ];\n\n            return (\n              <div className=\"space-y-10\">\n                <header className=\"space-y-3\">\n                  <p className=\"text-[12px] uppercase tracking-[0.4em] text-stone-400\">{t(\"step\")} 3<\/p>\n                  <h1 className=\"text-4xl font-bold\">{t(\"review\")}<\/h1>\n                  <p className=\"text-stone-500\">{t(\"review_description\")}<\/p>\n                <\/header>\n\n                <div className=\"space-y-6\">\n                  <div className=\"flex items-center justify-between\">\n                    <div>\n                      <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400\">{t(\"retreat\")}<\/p>\n                      <p className=\"font-semibold\">{selection.retreatName}<\/p>\n                      <p className=\"text-sm text-stone-500\">{selection.retreatLocation}<\/p>\n                      {selection.retreatEarlyBirdNote && <p className=\"text-xs text-emerald-700 mt-1\">{selection.retreatEarlyBirdNote}<\/p>}\n                    <\/div>\n                  <\/div>\n                  <div className=\"flex items-center justify-between\">\n                    <div>\n                      <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400\">{t(\"retreat_dates\")}<\/p>\n                      <p className=\"font-semibold\">{dateInfo?.label}<\/p>\n                    <\/div>\n                    {!bookingMeta.bookingId && (\n                      <button type=\"button\" className=\"text-sm text-emerald-700 font-semibold\" onClick={() => goToStep(\"config\")}>\n                        {t(\"edit\")}\n                      <\/button>\n                    )}\n                  <\/div>\n                  <div className=\"flex items-center justify-between\">\n                    <div>\n                      <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400\">{t(\"accommodation\")}<\/p>\n                      <p className=\"font-semibold\">{room?.name}<\/p>\n                    <\/div>\n                    {!bookingMeta.bookingId && (\n                      <button type=\"button\" className=\"text-sm text-emerald-700 font-semibold\" onClick={() => goToStep(\"config\")}>\n                        {t(\"edit\")}\n                      <\/button>\n                    )}\n                  <\/div>\n                  <div className=\"flex items-center justify-between\">\n                    <div>\n                      <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400\">{t(\"airport_transfer\").replace(\" (optional)\", \"\")}<\/p>\n                      <p className=\"font-semibold\">{transferOption?.label || t(\"no_transfer\")}<\/p>\n                    <\/div>\n                    {!bookingMeta.bookingId && (\n                      <button type=\"button\" className=\"text-sm text-emerald-700 font-semibold\" onClick={() => goToStep(\"config\")}>\n                        {t(\"edit\")}\n                      <\/button>\n                    )}\n                  <\/div>\n                <\/div>\n\n                <div className=\"space-y-6\">\n                  <div className=\"flex items-center justify-between\">\n                    <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400\">{t(\"guests\")}<\/p>\n                    <button type=\"button\" className=\"text-sm text-emerald-700 font-semibold\" onClick={() => goToStep(\"details\")}>\n                      {t(\"edit\")}\n                    <\/button>\n                  <\/div>\n                  <div className=\"space-y-4\">\n                    {guests.map((guest, index) => (\n                      <div key={guest.label} className={`${index > 0 ? \"pt-4 border-t border-stone-200\" : \"\"}`}>\n                        <p className=\"font-semibold\">{guest.label}<\/p>\n                        <p className=\"text-sm text-stone-500\">\n                          {guest.data.firstName || t(\"first_name\")} {guest.data.lastName || \"\"}\n                        <\/p>\n                        <p className=\"text-sm text-stone-500\">{guest.data.email || \"Email pending\"}<\/p>\n                      <\/div>\n                    ))}\n                  <\/div>\n                <\/div>\n\n                <div className=\"bg-stone-50 border border-stone-100 rounded-3xl p-6 space-y-2\">\n                  <h3 className=\"text-sm font-semibold text-stone-700 uppercase tracking-[0.3em]\">{t(\"deposit_health_review\")}<\/h3>\n                  <ul className=\"space-y-1 text-sm text-stone-600 list-disc pl-4\">\n                    <li>{t(\"deposit_secures\")}<\/li>\n                    <li>{t(\"health_info\")}<\/li>\n                  <\/ul>\n                <\/div>\n\n                <div className=\"flex justify-between items-center gap-4\">\n                  <button type=\"button\" onClick={() => goToStep(\"details\")} className=\"inline-flex items-center text-stone-500 font-semibold\">\n                    <Icons.ChevronLeft \/> {t(\"back\")}\n                  <\/button>\n                  <button\n                    type=\"button\"\n                    onClick={() => goToStep(\"health_check\")}\n                    className=\"vdx-paired-step-action inline-flex items-center bg-emerald-800 text-white px-6 py-3 rounded-full font-semibold hover:bg-emerald-900\"\n                  >\n                    {t(\"continue\")} <Icons.ChevronRight \/>\n                  <\/button>\n                <\/div>\n              <\/div>\n            );\n          };\n\n\n          const renderHealthPreparationStep = () => (\n            <div className=\"space-y-8\">\n              <header className=\"space-y-3\">\n                <p className=\"text-[12px] uppercase tracking-[0.4em] text-stone-400\">{t(\"step\")} 4<\/p>\n                <h1 className=\"text-4xl font-bold\">{t(\"health_prep\")}<\/h1>\n                <p className=\"text-stone-500\">\n                  {t(\"health_prep_desc\")}\n                <\/p>\n              <\/header>\n\n              <div className=\"space-y-5\">\n                {SAFETY_QUESTIONS.map((question) => {\n                  const currentValue = safetyAnswers[question.id];\n                  return (\n                    <div key={question.id} className=\"border border-stone-100 rounded-3xl p-6 space-y-4\">\n                      <div className=\"space-y-1\">\n                        <p className=\"text-sm font-semibold text-stone-800\">{t(question.id + \"_title\") || question.title}<\/p>\n                        <p className=\"text-sm text-stone-600\">{t(question.id + \"_desc\") || question.description}<\/p>\n                      <\/div>\n                      <div className=\"flex flex-wrap gap-3\">\n                        {[\n                          { label: t(\"yes\") || \"Yes\", value: \"yes\" },\n                          { label: t(\"no\") || \"No\", value: \"no\" },\n                        ].map((option) => {\n                          const active = currentValue === option.value;\n                          return (\n                            <button\n                              key={option.value}\n                              type=\"button\"\n                              aria-pressed={active}\n                              onClick={() => updateSafetyAnswer(question.id, option.value)}\n                              className={`px-4 py-2 rounded-full font-semibold text-sm border ${\n                                active ? \"bg-emerald-800 text-white border-emerald-800\" : \"border-stone-200 text-stone-600 hover:border-emerald-200\"\n                              }`}\n                            >\n                              {option.label}\n                            <\/button>\n                          );\n                        })}\n                      <\/div>\n                    <\/div>\n                  );\n                })}\n              <\/div>\n\n              {safetyHasConcern && (\n                <div className=\"bg-rose-50 border border-rose-100 rounded-3xl p-6 space-y-4\">\n                  <p className=\"font-semibold text-rose-900\">{t(\"honest_answer_thanks\") || \"Thank you very much for your honest answer.\"}<\/p>\n                  <div className=\"space-y-3 text-sm text-stone-700 leading-relaxed\">\n                    <p>\n                      {t(\"safety_guideline_1\") || \"Based on established fasting safety guidelines, the condition you have indicated is considered a situation where fasting should only be undertaken, if at all, under close specialist supervision in a clinical setting.\"}\n                    <\/p>\n                    <p>\n                      {t(\"safety_guideline_2\") || \"Our fasting retreats are designed for preventive and restorative purposes and cannot provide the level of continuous monitoring required in this case.\"}\n                    <\/p>\n                    <p>\n                      {t(\"safety_guideline_3\") || \"Out of responsibility for your safety and well-being, we are therefore unfortunately unable to offer participation in this retreat at this time. If you wish, you are very welcome to contact Vietnam Detox so we can share information about alternative, gentler lifestyle and nutrition programs that may be more appropriate for you right now.\"}\n                    <\/p>\n                  <\/div>\n                  <div className=\"flex flex-wrap gap-3\">\n                    <a\n                      href={`mailto:${t(\"contact_email\") || \"hello@vietnamdetox.com\"}`}\n                      className=\"vdx-action-button inline-flex items-center justify-center px-4 py-2 rounded-full border border-stone-200 text-sm font-semibold text-stone-700 hover:border-emerald-200\"\n                    >\n                      {t(\"contact_vd\") || \"Contact Vietnam Detox\"}\n                    <\/a>\n                    <button\n                      type=\"button\"\n                      onClick={() => goToStep(\"config\")}\n                      className=\"inline-flex items-center justify-center px-4 py-2 rounded-full border border-stone-200 text-sm font-semibold text-stone-700 hover:border-emerald-200\"\n                    >\n                      {t(\"return_overview\") || \"Return to retreat overview\"}\n                    <\/button>\n                  <\/div>\n                <\/div>\n              )}\n\n              <div className=\"flex justify-between items-center gap-4\">\n                <button type=\"button\" onClick={() => goToStep(\"review\")} className=\"inline-flex items-center text-stone-500 font-semibold\">\n                  <Icons.ChevronLeft \/> {t(\"back\")}\n                <\/button>\n                {!safetyHasConcern && (\n                  <button\n                    type=\"button\"\n                    disabled={!safetyAllAnswered}\n                    onClick={() => goToStep(\"payment\")}\n                    className={`vdx-paired-step-action inline-flex items-center px-6 py-3 rounded-full font-semibold ${\n                      safetyAllAnswered ? \"bg-emerald-800 text-white hover:bg-emerald-900\" : \"bg-stone-200 text-stone-500 cursor-not-allowed\"\n                    }`}\n                  >\n                    {t(\"continue\")} <Icons.ChevronRight \/>\n                  <\/button>\n                )}\n              <\/div>\n            <\/div>\n          );\n\n          const PaymentLogos = () => (\n            <div className=\"flex flex-wrap gap-1.5 mt-1.5\">\n              <span className=\"px-1.5 py-0.5 bg-[#1434CB] text-white text-[9px] font-bold italic rounded-[3px] tracking-wider leading-tight shadow-sm\">VISA<\/span>\n              <div className=\"px-1.5 py-0.5 bg-gradient-to-r from-[#202020] to-[#1a1a1a] flex items-center gap-1 rounded-[3px] shadow-sm\">\n                <div className=\"flex items-center\">\n                  <div className=\"w-2.5 h-2.5 rounded-full bg-[#EB001B] opacity-90\"><\/div>\n                  <div className=\"w-2.5 h-2.5 rounded-full bg-[#F79E1B] -ml-1 opacity-90\"><\/div>\n                <\/div>\n                <span className=\"text-[8px] text-white font-medium leading-tight\">mastercard<\/span>\n              <\/div>\n              <span className=\"px-1.5 py-0.5 bg-white text-[#0039A6] border border-stone-200 text-[9px] font-black rounded-[3px] leading-tight shadow-sm\">JCB<\/span>\n              <span className=\"px-1.5 py-0.5 bg-[#2E77BC] text-white text-[9px] font-bold rounded-[3px] leading-tight shadow-sm\">AMEX<\/span>\n              <span className=\"px-1.5 py-0.5 bg-black text-white text-[9px] font-medium rounded-[3px] flex items-center gap-0.5 leading-tight shadow-sm\">\n                <span className=\"text-[10px] leading-none\">&#63743;<\/span> Pay\n              <\/span>\n              <span className=\"px-1.5 py-0.5 bg-white text-stone-700 border border-stone-200 text-[9px] font-semibold rounded-[3px] flex items-center gap-0.5 leading-tight shadow-sm\">\n                <span className=\"font-bold text-blue-500\">G<\/span> Pay\n              <\/span>\n              <span className=\"px-1.5 py-0.5 bg-[#1428A0] text-white text-[9px] font-bold rounded-[3px] leading-tight shadow-sm\">Samsung Pay<\/span>\n            <\/div>\n          );\n\n          const VietQRLogo = () => (\n            <div className=\"flex flex-wrap gap-1.5 mt-1.5\">\n              <div className=\"flex items-center bg-white border border-stone-200 px-2 py-0.5 rounded-[3px] shadow-sm\">\n                <span className=\"text-[11px] font-extrabold italic text-red-600 tracking-tight leading-tight\">Viet<\/span>\n                <span className=\"text-[11px] font-extrabold italic text-blue-700 tracking-tight leading-tight\">QR<\/span>\n              <\/div>\n              <div className=\"flex items-center bg-white border border-stone-200 px-2 py-0.5 rounded-[3px] shadow-sm\">\n                <span className=\"text-[10px] font-bold text-green-700 tracking-tight leading-tight\">NAPAS<\/span>\n              <\/div>\n            <\/div>\n          );\n\n          const renderPaymentStep = () => {\n            const params = new URLSearchParams(window.location.search);\n            const isFailed = params.get(\"payment\") === \"failed\";\n            const failureReason = params.get(\"reason\");\n\n            const handleTryAgain = () => {\n              const newUrl = window.location.pathname + \"?view=payment&lang=\" + lang;\n              window.history.replaceState({}, \"\", newUrl);\n              setRoute({ step: \"payment\", lang: lang });\n              \n              \/\/ Scroll to payment button after UI update\n              setTimeout(() => {\n                const el = document.getElementById(\"payment-actions\");\n                if (el) el.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n              }, 100);\n            };\n\n            return (\n              <div className=\"space-y-10\">\n                <header className=\"space-y-2\">\n                  <p className=\"text-[12px] uppercase tracking-[0.4em] text-stone-400\">{t(\"step\")} 5<\/p>\n                  <h1 className=\"text-4xl font-bold\">{t(\"payment\")}<\/h1>\n                  <p className=\"text-sm text-stone-500\">{t(\"payment_desc\")}<\/p>\n                <\/header>\n\n                {isFailed && (\n                  <div className=\"bg-rose-50 border border-rose-100 rounded-3xl p-6 space-y-3 mb-6\">\n                    <div className=\"flex items-center gap-3 text-rose-800 font-bold text-lg\">\n                      <div className=\"bg-rose-600 text-white p-1 rounded-full scale-75\">\n                         <Icons.Info \/>\n                      <\/div>\n                      <p>{t(\"payment_failed\")}<\/p>\n                    <\/div>\n                    <p className=\"text-sm text-stone-600 leading-relaxed pl-10\">\n                      {failureReason || t(\"payment_failed_desc\")}\n                    <\/p>\n                    <div className=\"pl-10 pt-2\">\n                       <button\n                         type=\"button\"\n                         onClick={handleTryAgain}\n                         className=\"inline-flex items-center justify-center bg-rose-100 text-rose-900 px-6 py-2 rounded-full font-bold text-sm hover:bg-rose-200 transition gap-2\"\n                       >\n                         {t(\"try_again\")} <Icons.ChevronRight \/>\n                       <\/button>\n                    <\/div>\n                  <\/div>\n                )}\n\n                <PriceSummary\n                  context=\"payment\"\n                  pricing={pricing}\n                  paymentMethod={paymentMethod}\n                  stripeFee={stripeFee}\n                  paymentDueNow={paymentDueNow}\n                  lang={lang}\n                  roomName={selectedRoomName}\n                  guestsCount={selection.guests}\n                  retreatName={selection.retreatName}\n                  retreatDate={selection.date}\n                \/>\n\n              <div className=\"space-y-6\">\n                <div>\n                  <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400 font-semibold mb-4\">{t(\"payment_method\")}<\/p>\n                  <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n                    <button\n                      type=\"button\"\n                      aria-pressed={paymentMethod === \"onepay_domestic\"}\n                      onClick={() => setPaymentMethod(\"onepay_domestic\")}\n                      className={`p-4 border-2 rounded-2xl flex items-center justify-between transition-all ${\n                        paymentMethod === \"onepay_domestic\" ? \"border-emerald-600 bg-emerald-50 ring-4 ring-emerald-600\/10 shadow-lg\" : \"border-stone-100\"\n                      }`}\n                    >\n                      <div className=\"text-left flex flex-col justify-center\">\n                        <p className=\"font-semibold leading-none\">{t(\"onepay_domestic\")}<\/p>\n                        <VietQRLogo \/>\n                      <\/div>\n                      <Icons.Building \/>\n                    <\/button>\n                    <button\n                      type=\"button\"\n                      aria-pressed={paymentMethod === \"onepay_intl\"}\n                      onClick={() => setPaymentMethod(\"onepay_intl\")}\n                      className={`p-4 border-2 rounded-2xl flex items-center justify-between transition-all ${\n                        paymentMethod === \"onepay_intl\" ? \"border-emerald-600 bg-emerald-50 ring-4 ring-emerald-600\/10 shadow-lg\" : \"border-stone-100\"\n                      }`}\n                    >\n                      <div className=\"text-left flex flex-col justify-center\">\n                        <p className=\"font-semibold leading-none\">{t(\"onepay_international\")}<\/p>\n                        <PaymentLogos \/>\n                      <\/div>\n                      <Icons.CreditCard \/>\n                    <\/button>\n                  <\/div>\n                <\/div>\n\n                <div id=\"payment-actions\" className=\"bg-stone-50 rounded-3xl p-6\">\n                  {paymentMethod === \"stripe\" ? (\n                    <div className=\"space-y-4\">\n                      <p className=\"text-sm text-stone-600 leading-relaxed\">\n                        {t(\"stripe_desc\")}\n                      <\/p>\n                      <button\n                        type=\"button\"\n                        onClick={handlePayment}\n                        disabled={paymentSubmitting}\n                        className=\"w-full bg-emerald-800 text-white py-4 rounded-full font-bold text-lg hover:bg-emerald-900 transition flex items-center justify-center gap-2\"\n                      >\n                        {paymentSubmitting ? t(\"processing_payment\") : t(\"pay_securely_msg\").replace(\"{{amount}}\", formatVND(paymentDueNow, lang))}\n                      <\/button>\n                    <\/div>\n                  ) : paymentMethod === \"bank_transfer\" ? (\n                    <div className=\"space-y-4\">\n                      <p className=\"text-sm text-stone-600 leading-relaxed\">\n                        {t(\"bank_transfer_desc\")}\n                      <\/p>\n                      <button\n                        type=\"button\"\n                        onClick={handlePayment}\n                        disabled={paymentSubmitting}\n                        className=\"w-full bg-emerald-800 text-white py-4 rounded-full font-bold text-lg hover:bg-emerald-900 transition flex items-center justify-center gap-2\"\n                      >\n                        {paymentSubmitting ? t(\"processing_payment\") : t(\"confirm_bank_transfer\")} <Icons.ChevronRight \/>\n                      <\/button>\n                    <\/div>\n                  ) : (\n                    <div className=\"space-y-4\">\n                      <button\n                        type=\"button\"\n                        onClick={handlePayment}\n                        disabled={paymentSubmitting}\n                        className=\"w-full bg-emerald-800 text-white py-4 rounded-full font-bold text-lg hover:bg-emerald-900 transition flex items-center justify-center gap-2\"\n                      >\n                        {paymentSubmitting ? t(\"processing_payment\") : t(\"pay_securely_msg\").replace(\"{{amount}}\", formatVND(paymentDueNow, lang))}\n                      <\/button>\n                      <div className=\"text-sm text-stone-600 leading-relaxed flex flex-col gap-2\">\n                        {paymentMethod === \"onepay_domestic\" ? <VietQRLogo \/> : <PaymentLogos \/>}\n                      <\/div>\n                    <\/div>\n                  )}\n                <\/div>\n              <\/div>\n\n              {!bookingMeta.bookingId && (\n                <div className=\"flex justify-start\">\n                  <button type=\"button\" onClick={() => goToStep(\"health_check\")} className=\"inline-flex items-center text-stone-500 font-semibold\">\n                    <Icons.ChevronLeft \/> {t(\"back\")}\n                  <\/button>\n                <\/div>\n              )}\n              {paymentError && <p className=\"text-sm text-rose-600 mt-4\">{paymentError}<\/p>}\n              {paymentSuccess && (\n                <div className=\"fixed bottom-24 md:bottom-32 right-4 left-4 md:right-10 md:left-auto bg-emerald-800 text-white p-6 rounded-2xl shadow-2xl shadow-emerald-900\/50 z-50 flex items-center gap-4 w-auto md:w-96 ring-4 ring-emerald-800 ring-opacity-50 transform transition-all duration-300\">\n                  <div className=\"bg-white\/20 p-3 rounded-full shadow-inner\">\n                    <Icons.Check \/>\n                  <\/div>\n                  <div>\n                    <p className=\"font-extrabold text-lg tracking-wide\">{t(\"booking_secured\")}<\/p>\n                    <p className=\"text-sm text-emerald-50 font-medium mt-0.5\">{t(\"proceeding_next\")}<\/p>\n                  <\/div>\n                <\/div>\n              )}\n              <\/div>\n            );\n          };\n\n\n          const renderScreeningStep = () => {\n            const handlePrimary = () => {\n              if (!depositPaid) {\n                goToStep(\"payment\");\n              } else {\n                goToStep(\"review_state\");\n              }\n            };\n\n            const questions = [\n              t(\"safety_question_1\"),\n              t(\"safety_question_2\"),\n              t(\"safety_question_3\"),\n              t(\"safety_question_4\"),\n            ];\n\n            return (\n              <div className=\"space-y-8 max-w-2xl\">\n                <header className=\"space-y-3\">\n                  <p className=\"text-[12px] uppercase tracking-[0.4em] text-stone-400\">{t(\"step\")} 6<\/p>\n                  <h1 className=\"text-4xl font-bold\">{t(\"health_prep\")}<\/h1>\n                  <p className=\"text-stone-500\">{t(\"almost_done\")}<\/p>\n                  <p className=\"text-sm text-stone-500\">{t(\"health_prep_screening_desc\")}<\/p>\n                <\/header>\n\n                {new URLSearchParams(window.location.search).get(\"payment\") === \"success\" && (\n                  <div className=\"bg-emerald-50 border border-emerald-100 rounded-3xl p-6 space-y-3 mb-8\">\n                    <div className=\"flex items-center gap-3 text-emerald-800 font-bold\">\n                      <div className=\"bg-emerald-600 text-white p-1 rounded-full scale-75\">\n                        <Icons.Check \/>\n                      <\/div>\n                      <p>\u2713 {t(\"deposit_received_msg\") || \"Deposit payment successful. Your booking is now reserved.\"}<\/p>\n                    <\/div>\n                    {(new URLSearchParams(window.location.search).get(\"txn_id\") || new URLSearchParams(window.location.search).get(\"amount\")) && (\n                      <div className=\"text-xs text-emerald-700\/80 items-center gap-6 pl-9 pt-2 border-t border-emerald-200\/50 flex flex-wrap\">\n                        {new URLSearchParams(window.location.search).get(\"txn_id\") && (\n                          <p>\n                            <span className=\"font-semibold uppercase tracking-wider opacity-60 mr-2\">Transaction ID<\/span>\n                            <span className=\"font-mono\">{new URLSearchParams(window.location.search).get(\"txn_id\")}<\/span>\n                          <\/p>\n                        )}\n                        {new URLSearchParams(window.location.search).get(\"amount\") && (\n                          <p>\n                            <span className=\"font-semibold uppercase tracking-wider opacity-60 mr-2\">Amount Paid<\/span>\n                            <span>{formatVND(parseInt(new URLSearchParams(window.location.search).get(\"amount\")) \/ 100, lang)}<\/span>\n                          <\/p>\n                        )}\n                      <\/div>\n                    )}\n                  <\/div>\n                )}\n\n                <div className=\"bg-stone-50 border border-stone-100 rounded-3xl p-6 space-y-3\">\n                  <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400\">{t(\"what_happens_next\")}<\/p>\n                  <ul className=\"space-y-2 text-sm text-stone-600 list-disc pl-4\">\n                    <li>{t(\"timeline_item_1\")}<\/li>\n                    <li>{t(\"timeline_item_2\")}<\/li>\n                    <li>{t(\"timeline_item_3\")}<\/li>\n                    <li>{t(\"timeline_item_4\")}<\/li>\n                    <li>{t(\"timeline_item_5\")}<\/li>\n                  <\/ul>\n                <\/div>\n\n                <div className=\"space-y-4 border border-stone-100 rounded-3xl p-6\">\n                  <p className=\"text-sm font-semibold text-stone-700\">{t(\"quick_pre_check\")}<\/p>\n                  <p className=\"text-sm text-stone-500\">{t(\"quick_pre_check_desc\")}<\/p>\n                  <div className=\"space-y-3\">\n                    {questions.map((question) => (\n                      <label key={question} className=\"flex flex-col text-sm text-stone-600 gap-1\">\n                        {question}\n                        <select className=\"border border-stone-200 rounded-2xl px-4 py-2 bg-white focus:outline-none focus:ring-2 focus:ring-emerald-100\">\n                          <option value=\"no\">{t(\"no\")}<\/option>\n                          <option value=\"yes\">{t(\"yes\")}<\/option>\n                        <\/select>\n                      <\/label>\n                    ))}\n                  <\/div>\n                <\/div>\n\n                <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n                  <button\n                    type=\"button\"\n                    onClick={handlePrimary}\n                    className=\"inline-flex items-center justify-center bg-emerald-800 text-white px-6 py-3 rounded-full font-semibold hover:bg-emerald-900\"\n                  >\n                    {t(\"continue_begin_health_prep\")} <Icons.ChevronRight \/>\n                  <\/button>\n                  <button type=\"button\" onClick={() => goToStep(\"review\")} className=\"text-sm font-semibold text-stone-500 hover:text-stone-700\">\n                    {t(\"back_to_booking\")}\n                  <\/button>\n                <\/div>\n              <\/div>\n            );\n          };\n\n          const renderReviewStateStep = () => {\n            const timeline = [\n              {\n                label: t(\"deposit_received\"),\n                status: depositPaid ? \"done\" : \"pending\",\n                description: depositPaid ? t(\"status_reserved_pending\") : t(\"awaiting_payment\"),\n              },\n              {\n                label: t(\"guest_1_health_prep\"),\n                status: screeningStatus.guest1 === \"complete\" ? \"done\" : \"pending\",\n                description: screeningStatus.guest1 === \"complete\" ? t(\"prep_complete\") : t(\"awaiting_prep\"),\n              },\n            ];\n\n            if (selection.guests === 2) {\n              timeline.push({\n                label: t(\"guest_2_health_prep\"),\n                status: screeningStatus.guest2 === \"complete\" ? \"done\" : \"pending\",\n                description: screeningStatus.guest2 === \"complete\" ? t(\"prep_complete\") : t(\"awaiting_prep\"),\n              });\n            }\n\n            timeline.push({\n              label: t(\"team_confirmation\"),\n              status: (bookingStatus === \"Payment received\" || bookingStatus === \"Deposit received\") ? \"done\" : \"waiting\",\n              description: (bookingStatus === \"Payment received\" || bookingStatus === \"Deposit received\") ? t(\"status_confirmed\") : t(\"begins_after_calls\"),\n            });\n\n            const statusStyles = {\n              done: \"bg-emerald-600 text-white\",\n              pending: \"bg-stone-100 text-stone-600\",\n              waiting: \"bg-stone-100 text-stone-400\",\n            };\n\n            const screeningGuests = [\n              {\n                label: t(\"guest_1_health_prep\"),\n                status: screeningStatus.guest1,\n                guestNumber: 1,\n                name: `${guestDetails.guest1.firstName || t(\"guest\")} ${guestDetails.guest1.lastName || \"\"}`.trim() || t(\"guest\") + \" 1\",\n              },\n              ...(selection.guests === 2\n                ? [\n                    {\n                      label: t(\"guest_2_health_prep\"),\n                      status: screeningStatus.guest2,\n                      guestNumber: 2,\n                      name: `${guestDetails.guest2.firstName || t(\"guest\")} ${guestDetails.guest2.lastName || \"\"}`.trim() || t(\"guest\") + \" 2\",\n                    },\n                  ]\n                : []),\n            ];\n\n            return (\n              <div className=\"space-y-10 max-w-2xl\">\n                <header className=\"space-y-3\">\n                  <p className=\"text-[12px] uppercase tracking-[0.4em] text-stone-400\">{t(\"step\")} 7<\/p>\n                  <h1 className=\"text-4xl font-bold\">{t(\"prep_timeline\")}<\/h1>\n                  <p className=\"text-stone-500\">{t(\"prep_timeline_desc\")}<\/p>\n                <\/header>\n\n                <div className=\"space-y-4\">\n                  {timeline.map((item) => (\n                    <div key={item.label} className=\"flex items-center gap-4\">\n                      <div className={`w-12 h-12 rounded-full flex items-center justify-center ${statusStyles[item.status]}`}>\n                        <Icons.Check \/>\n                      <\/div>\n                      <div>\n                        <p className=\"font-semibold\">{item.label}<\/p>\n                        <p className=\"text-sm text-stone-500\">{item.description}<\/p>\n                      <\/div>\n                    <\/div>\n                  ))}\n                <\/div>\n\n                <div className=\"bg-stone-50 border border-stone-100 rounded-3xl p-6 space-y-2\">\n                  <p className=\"text-sm text-stone-600\">{t(\"status_reserved_pending\")}<\/p>\n                  <p className=\"text-sm text-stone-600\">{t(\"confirmation_note\")}<\/p>\n                <\/div>\n\n\n                <div className=\"space-y-4\">\n                  {screeningGuests.map((guest) => {\n                    const encodedName = encodeURIComponent(guest.name || `Guest ${guest.guestNumber}`);\n                    const fallbackUrl = `?view=screening&guest=${guest.guestNumber}&booking_id=${bookingMeta.bookingId || \"\"}&name=${encodedName}`;\n                    const url = buildHealthCheckUrl(bookingMeta.bookingId, bookingMeta.customerIds[guest.guestNumber - 1], lang) || fallbackUrl;\n                    return (\n                      <div key={guest.guestNumber} className=\"border border-stone-200 rounded-3xl p-5 space-y-3\">\n                        <div className=\"flex items-center justify-between\">\n                          <div>\n                            <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400\">{guest.label}<\/p>\n                            <p className=\"text-sm text-stone-500\">\n                              {guest.status === \"complete\" ? t(\"questionnaire_call_complete\") : t(\"awaiting_questionnaire_call\")}\n                            <\/p>\n                          <\/div>\n                          <div\n                            className={`w-10 h-10 rounded-full flex items-center justify-center ${guest.status === \"complete\" ? \"bg-emerald-100 text-emerald-700\" : \"bg-stone-100 text-stone-400\"}`}\n                          >\n                            <Icons.Check \/>\n                          <\/div>\n                        <\/div>\n                        <div className=\"flex flex-col gap-2 sm:flex-row\">\n                          <a\n                            href={url}\n                            className=\"vdx-action-button inline-flex items-center justify-center bg-emerald-800 text-white px-4 py-2 rounded-full font-semibold text-sm hover:bg-emerald-900\"\n                            target=\"_blank\"\n                            rel=\"noopener noreferrer\"\n                          >\n                            {t(\"open_health_questionnaire\")}\n                          <\/a>\n                          <button\n                            type=\"button\"\n                            className=\"inline-flex items-center justify-center bg-white text-stone-600 border border-stone-200 px-4 py-2 rounded-full text-sm font-semibold hover:border-emerald-200\"\n                            onClick={() => {\n                              const absoluteUrl =\n                                url.startsWith(\"http\") || url.startsWith(\"https\")\n                                  ? url\n                                  : window.location.origin && window.location.origin !== \"null\"\n                                    ? `${window.location.origin}\/${url}`\n                                    : url;\n                              const clipboard = navigator?.clipboard?.writeText;\n                              if (typeof clipboard === \"function\") {\n                                clipboard\n                                  .call(navigator.clipboard, absoluteUrl)\n                                  .then(() => alert(t(\"link_copied\")))\n                                  .catch(() => alert(`${t(\"copy_this_link\")}:\\n${absoluteUrl}`));\n                              } else {\n                                alert(`${t(\"copy_this_link\")}:\\n${absoluteUrl}`);\n                              }\n                            }}\n                          >\n                            {t(\"copy_link\")}\n                          <\/button>\n                        <\/div>\n                        <p className=\"text-xs text-stone-500\">\n                          {t(\"share_link_description\")}\n                        <\/p>\n                      <\/div>\n                    );\n                  })}\n                <\/div>\n\n                <div className=\"border border-emerald-100 bg-emerald-50 rounded-3xl p-6 space-y-2 text-left\">\n                  <p className=\"text-sm font-semibold text-stone-800\">{t(\"included_personal_health_review_call\")}<\/p>\n                  <p className=\"text-sm text-stone-600\">\n                    {t(\"included_personal_health_review_call_desc\")}\n                  <\/p>\n                  <button\n                    type=\"button\"\n                    className=\"inline-flex items-center bg-emerald-800 text-white px-4 py-2 rounded-full text-sm font-semibold hover:bg-emerald-900\"\n                    onClick={() => alert(t(\"request_health_review_call_alert\"))}\n                  >\n                    {t(\"request_my_health_review_call\")}\n                  <\/button>\n                <\/div>\n\n                <div className=\"flex justify-between items-center\">\n                  <button type=\"button\" onClick={() => goToStep(\"screening\")} className=\"inline-flex items-center text-stone-500 font-semibold\">\n                    <Icons.ChevronLeft \/> {t(\"back_to_health_preparation_hub\")}\n                  <\/button>\n                  <button\n                    type=\"button\"\n                    disabled={!screeningsComplete}\n                    onClick={() => goToStep(\"confirmed\")}\n                    className={`inline-flex items-center px-6 py-3 rounded-full font-semibold ${\n                      screeningsComplete ? \"bg-emerald-800 text-white hover:bg-emerald-900\" : \"bg-stone-200 text-stone-500 cursor-not-allowed\"\n                    }`}\n                  >\n                    {t(\"move_to_confirmation\")} <Icons.ChevronRight \/>\n                  <\/button>\n                <\/div>\n              <\/div>\n            );\n          };\n\n          const renderConfirmedStep = () => (\n            <div className=\"flex flex-col items-center justify-center space-y-8 py-10 text-center\">\n              <div className=\"w-20 h-20 bg-emerald-100 rounded-3xl flex items-center justify-center text-emerald-700\">\n                <Icons.Check \/>\n              <\/div>\n              <div className=\"space-y-3\">\n                <h1 className=\"text-4xl font-bold\">{t(\"booking_confirmed\")}<\/h1>\n                <p className=\"text-stone-500 max-w-md mx-auto\">\n                  {t(\"booking_confirmed_desc\")}\n                <\/p>\n              <\/div>\n              {bookingMeta.bookingId && (\n                <div className=\"bg-stone-50 border border-stone-100 rounded-3xl p-6 w-full max-w-md\">\n                  <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400 mb-2\">{t(\"booking_ref\")}<\/p>\n                  <p className=\"text-2xl font-mono font-bold text-stone-800\">#{bookingMeta.bookingId}<\/p>\n                <\/div>\n              )}\n              <PriceSummary context=\"confirmed\" pricing={pricing} lang={lang} roomName={selectedRoomName} guestsCount={selection.guests} retreatName={selection.retreatName} retreatDate={selection.date} \/>\n              <button\n                type=\"button\"\n                onClick={() => (window.location.href = \"\/\")}\n                className=\"inline-flex items-center bg-stone-900 text-white px-8 py-4 rounded-full font-bold hover:bg-stone-800 transition\"\n              >\n                {t(\"return_home\")}\n              <\/button>\n            <\/div>\n          );\n          const stepConfig = {\n            config: { content: renderConfigStep(), summaryContext: \"default\" },\n            details: { content: renderGuestDetailsStep(), summaryContext: \"default\" },\n            review: { content: renderReviewStep(), summaryContext: \"review\" },\n            health_check: { content: renderHealthPreparationStep(), summaryContext: \"default\" },\n            payment: { content: renderPaymentStep(), summaryContext: \"payment\" },\n            screening: { content: renderScreeningStep(), summaryContext: \"default\" },\n            review_state: { content: renderReviewStateStep(), summaryContext: \"default\" },\n            confirmed: { content: renderConfirmedStep(), summaryContext: \"confirmed\" },\n          };\n\n          const stepEntry = stepConfig[flowStep] || stepConfig.config;\n          const { content, summaryContext } = stepEntry;\n\n          if (recoveryLoading) {\n            return (\n              <div id=\"booking-app-wrapper\" className=\"min-h-screen bg-stone-50 flex items-center justify-center p-6\">\n                <div className=\"text-center space-y-4\">\n                  <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-stone-800 mx-auto\"><\/div>\n                  <p className=\"text-stone-500 font-medium\">Restoring your booking session...<\/p>\n                <\/div>\n              <\/div>\n            );\n          }\n\n          return (\n            <div id=\"booking-app-wrapper\" className=\"min-h-screen bg-brand-ivory font-sans text-stone-900 selection:bg-emerald-100 relative\">\n\n              {(isTransitioning) && (\n                <div className=\"fixed inset-0 z-[100] flex items-center justify-center bg-white\/60 backdrop-blur-[2px] transition-all duration-300\">\n                  <div className=\"w-14 h-14 bg-white rounded-full shadow-2xl flex items-center justify-center border border-stone-100\">\n                    <div className=\"w-6 h-6 border-[3px] border-emerald-600 border-t-transparent animate-spin rounded-full\"><\/div>\n                  <\/div>\n                <\/div>\n              )}\n\n              <div className={`transition-opacity duration-500 ease-in-out ${isTransitioning ? \"opacity-30 pointer-events-none\" : \"opacity-100\"}`}>\n                <main className=\"max-w-6xl mx-auto px-6 py-12 space-y-8\">\n                <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-12\">\n                  <div className={`${[\"payment\", \"confirmed\"].includes(flowStep) ? \"lg:col-span-3 max-w-4xl mx-auto w-full\" : \"lg:col-span-2\"} space-y-10`}>\n                    {content}\n                  <\/div>\n                  {![\"payment\", \"confirmed\"].includes(flowStep) && (\n                    <div className=\"hidden lg:block lg:col-span-1\">\n                      <div className=\"sticky top-24\">\n                        <PriceSummary\n                          context={summaryContext}\n                          pricing={pricing}\n                          paymentMethod={paymentMethod}\n                          stripeFee={stripeFee}\n                          paymentDueNow={paymentDueNow}\n                          lang={lang}\n                          roomName={selectedRoomName}\n                          guestsCount={selection.guests}\n                          retreatName={selection.retreatName}\n                          retreatDate={selection.date}\n                        \/>\n                      <\/div>\n                    <\/div>\n                  )}\n                <\/div>\n                {![\"payment\", \"confirmed\"].includes(flowStep) && (\n                  <div className=\"lg:hidden\">\n                    <PriceSummary\n                      context={summaryContext}\n                      pricing={pricing}\n                      paymentMethod={paymentMethod}\n                      stripeFee={stripeFee}\n                      paymentDueNow={paymentDueNow}\n                      lang={lang}\n                      roomName={selectedRoomName}\n                      guestsCount={selection.guests}\n                      retreatName={selection.retreatName}\n                      retreatDate={selection.date}\n                    \/>\n                  <\/div>\n                )}\n              <\/main>\n            <\/div>\n              {galleryRoom && (\n                <div\n                  className=\"fixed inset-0 bg-black\/80 z-50 flex items-center justify-center px-4\"\n                  onClick={(event) => {\n                    if (event.target === event.currentTarget) {\n                      closeGallery();\n                    }\n                  }}\n                >\n                  <div\n                    ref={modalRef}\n                    role=\"dialog\"\n                    aria-modal=\"true\"\n                    aria-label={`${galleryRoom.name} gallery`}\n                    className=\"relative max-w-3xl w-full bg-white rounded-3xl overflow-hidden shadow-2xl outline-none\"\n                    onClick={(e) => e.stopPropagation()}\n                    tabIndex={-1}\n                  >\n                    <button\n                      type=\"button\"\n                      ref={closeButtonRef}\n                      aria-label=\"Close gallery\"\n                      className=\"vdx-icon-button absolute top-4 right-4 text-stone-900 bg-white\/70 hover:bg-white rounded-full w-10 h-10 flex items-center justify-center text-xl\"\n                      onClick={closeGallery}\n                    >\n                      <span aria-hidden=\"true\">&times;<\/span>\n                    <\/button>\n                    <div className=\"relative\">\n                      <img\n                        src={galleryRoom.images[galleryIndex]}\n                        alt={galleryRoom.name}\n                        className=\"w-full h-[420px] object-cover\"\n                        onError={handleImageError}\n                      \/>\n                      {galleryRoom.images.length > 1 && (\n                        <>\n                          <button\n                            type=\"button\"\n                            className=\"vdx-icon-button absolute left-4 top-1\/2 -translate-y-1\/2 bg-white\/80 hover:bg-white text-stone-900 rounded-full p-2\"\n                            onClick={showPrevImage}\n                            aria-label=\"Previous image\"\n                          >\n                            \u2039\n                          <\/button>\n                          <button\n                            type=\"button\"\n                            className=\"vdx-icon-button absolute right-4 top-1\/2 -translate-y-1\/2 bg-white\/80 hover:bg-white text-stone-900 rounded-full p-2\"\n                            onClick={showNextImage}\n                            aria-label=\"Next image\"\n                          >\n                            \u203a\n                          <\/button>\n                        <\/>\n                      )}\n                    <\/div>\n                    <div className=\"p-6 space-y-1\">\n                      <p className=\"text-xs uppercase tracking-[0.3em] text-stone-400\">Gallery<\/p>\n                      <h3 className=\"text-2xl font-bold\">{galleryRoom.name}<\/h3>\n                      <p className=\"text-sm text-stone-500\">{galleryRoom.benefit}<\/p>\n                    <\/div>\n                  <\/div>\n                <\/div>\n              )}\n            <\/div>\n          );\n        };\n\n        class AppErrorBoundary extends React.Component {\n          constructor(props) {\n            super(props);\n            this.state = { hasError: false };\n            this.handleReset = this.handleReset.bind(this);\n          }\n\n          static getDerivedStateFromError(error) {\n            return { hasError: true, error };\n          }\n\n          componentDidCatch(error, info) {\n            console.error(\"Booking UI error\", error, info);\n          }\n\n          handleReset() {\n            this.setState({ hasError: false, error: null });\n            if (typeof this.props.onReset === \"function\") {\n              this.props.onReset();\n            }\n          }\n\n          render() {\n            if (this.state.hasError) {\n              const lang = parseRouteFromLocation().lang || getInitialLang();\n              const t = (key) => TRANSLATIONS[lang]?.[key] || TRANSLATIONS.en[key] || key;\n              return (\n                <div id=\"booking-app-wrapper\" className=\"min-h-screen bg-brand-ivory font-sans text-stone-900 selection:bg-emerald-100 flex items-center justify-center px-6\">\n                  <div className=\"max-w-md text-center space-y-4\">\n                    <p className=\"text-[12px] uppercase tracking-[0.4em] text-stone-400\">{t(\"booking_progress\")}<\/p>\n                    <h1 className=\"text-3xl font-bold text-stone-900\">{t(\"something_went_wrong\")}<\/h1>\n                    <p className=\"text-stone-600\">{t(\"error_desc\")}<\/p>\n                    <button\n                      type=\"button\"\n                      onClick={this.handleReset}\n                      className=\"inline-flex items-center justify-center bg-emerald-800 text-white px-6 py-3 rounded-full font-semibold hover:bg-emerald-900\"\n                    >\n                      {t(\"refresh_page\")}\n                    <\/button>\n                  <\/div>\n                <\/div>\n              );\n\n            }\n            return this.props.children;\n          }\n\n        }\n\n        const RootApp = () => {\n          const [resetKey, setResetKey] = useState(0);\n          const handleReset = () => setResetKey((key) => key + 1);\n          return (\n            <AppErrorBoundary onReset={handleReset}>\n              <App key={resetKey} \/>\n            <\/AppErrorBoundary>\n          );\n        };\n\n        if (!bookingRoot) {\n          bookingRoot = ReactDOM.createRoot(rootNode);\n        }\n        bookingRoot.render(<RootApp \/>);\n      };\n\n      const bootBookingApp = async () => {\n        if (window.__bookingAppBooted) return;\n        window.__bookingAppBooted = true;\n        try {\n          const rootNode = document.getElementById(\"root\");\n          if (rootNode) {\n            rootNode.innerHTML = `\n              <div id=\"booking-app-wrapper\" class=\"min-h-[50vh] flex flex-col items-center justify-center space-y-4\">\n                <div class=\"w-8 h-8 border-[3px] border-emerald-600 border-t-transparent rounded-full animate-spin\"><\/div>\n                <p class=\"text-[10px] font-bold uppercase tracking-[0.25em] text-stone-400\">Loading Retreats<\/p>\n              <\/div>\n            `;\n          }\n          const retreatsLoaded = await fetchRetreats();\n          if (!retreatsLoaded) {\n            showInlineError(\"Unable to load retreat options. Please try again.\", { retry: true });\n            return;\n          }\n          startBookingApp();\n        } catch (error) {\n          console.error(\"Booking app failed during init\", error);\n          showInlineError(\"We were unable to load the booking experience. Please try again.\", { retry: true });\n        }\n      };\n\n      if (document.readyState === \"loading\") {\n        document.addEventListener(\"DOMContentLoaded\", bootBookingApp);\n      } else {\n        bootBookingApp();\n      }\n    <\/script>\n  <\/body>\n<\/html>\n\t\t\t\t<\/div>\n\t\t\n<\/div>\n\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Vietnam Detox Booking<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-18902","page","type-page","status-publish","hentry"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>\u0110\u1eb7t ch\u1ed7 - Staging Vietnamdetox<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/staging.vietnamdetox.com\/vi\/dat-cho\/\" \/>\n<meta property=\"og:locale\" content=\"vi_VN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"\u0110\u1eb7t ch\u1ed7 - Staging Vietnamdetox\" \/>\n<meta property=\"og:description\" content=\"Vietnam Detox Booking\" \/>\n<meta property=\"og:url\" content=\"https:\/\/staging.vietnamdetox.com\/vi\/dat-cho\/\" \/>\n<meta property=\"og:site_name\" content=\"Staging Vietnamdetox\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-03T02:49:34+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u01af\u1edbc t\u00ednh th\u1eddi gian \u0111\u1ecdc\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 ph\u00fat\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/staging.vietnamdetox.com\\\/vi\\\/dat-cho\\\/\",\"url\":\"https:\\\/\\\/staging.vietnamdetox.com\\\/vi\\\/dat-cho\\\/\",\"name\":\"\u0110\u1eb7t ch\u1ed7 - Staging Vietnamdetox\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/staging.vietnamdetox.com\\\/vi\\\/#website\"},\"datePublished\":\"2026-05-28T07:16:33+00:00\",\"dateModified\":\"2026-09-03T02:49:34+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/staging.vietnamdetox.com\\\/vi\\\/dat-cho\\\/#breadcrumb\"},\"inLanguage\":\"vi\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/staging.vietnamdetox.com\\\/vi\\\/dat-cho\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/staging.vietnamdetox.com\\\/vi\\\/dat-cho\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/staging.vietnamdetox.com\\\/vi\\\/trang-chu-2\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\u0110\u1eb7t ch\u1ed7\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/staging.vietnamdetox.com\\\/vi\\\/#website\",\"url\":\"https:\\\/\\\/staging.vietnamdetox.com\\\/vi\\\/\",\"name\":\"Staging Vietnamdetox\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/staging.vietnamdetox.com\\\/vi\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/staging.vietnamdetox.com\\\/vi\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"vi\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/staging.vietnamdetox.com\\\/vi\\\/#organization\",\"name\":\"Staging Vietnamdetox\",\"url\":\"https:\\\/\\\/staging.vietnamdetox.com\\\/vi\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"vi\",\"@id\":\"https:\\\/\\\/staging.vietnamdetox.com\\\/vi\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/staging.vietnamdetox.com\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/logo-icon-color_cutout.svg\",\"contentUrl\":\"https:\\\/\\\/staging.vietnamdetox.com\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/logo-icon-color_cutout.svg\",\"width\":314,\"height\":435,\"caption\":\"Staging Vietnamdetox\"},\"image\":{\"@id\":\"https:\\\/\\\/staging.vietnamdetox.com\\\/vi\\\/#\\\/schema\\\/logo\\\/image\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"\u0110\u1eb7t ch\u1ed7 - Staging Vietnamdetox","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/staging.vietnamdetox.com\/vi\/dat-cho\/","og_locale":"vi_VN","og_type":"article","og_title":"\u0110\u1eb7t ch\u1ed7 - Staging Vietnamdetox","og_description":"Vietnam Detox Booking","og_url":"https:\/\/staging.vietnamdetox.com\/vi\/dat-cho\/","og_site_name":"Staging Vietnamdetox","article_modified_time":"2026-09-03T02:49:34+00:00","twitter_card":"summary_large_image","twitter_misc":{"\u01af\u1edbc t\u00ednh th\u1eddi gian \u0111\u1ecdc":"1 ph\u00fat"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/staging.vietnamdetox.com\/vi\/dat-cho\/","url":"https:\/\/staging.vietnamdetox.com\/vi\/dat-cho\/","name":"\u0110\u1eb7t ch\u1ed7 - Staging Vietnamdetox","isPartOf":{"@id":"https:\/\/staging.vietnamdetox.com\/vi\/#website"},"datePublished":"2026-05-28T07:16:33+00:00","dateModified":"2026-09-03T02:49:34+00:00","breadcrumb":{"@id":"https:\/\/staging.vietnamdetox.com\/vi\/dat-cho\/#breadcrumb"},"inLanguage":"vi","potentialAction":[{"@type":"ReadAction","target":["https:\/\/staging.vietnamdetox.com\/vi\/dat-cho\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/staging.vietnamdetox.com\/vi\/dat-cho\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/staging.vietnamdetox.com\/vi\/trang-chu-2\/"},{"@type":"ListItem","position":2,"name":"\u0110\u1eb7t ch\u1ed7"}]},{"@type":"WebSite","@id":"https:\/\/staging.vietnamdetox.com\/vi\/#website","url":"https:\/\/staging.vietnamdetox.com\/vi\/","name":"Staging Vietnamdetox","description":"","publisher":{"@id":"https:\/\/staging.vietnamdetox.com\/vi\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/staging.vietnamdetox.com\/vi\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"vi"},{"@type":"Organization","@id":"https:\/\/staging.vietnamdetox.com\/vi\/#organization","name":"Staging Vietnamdetox","url":"https:\/\/staging.vietnamdetox.com\/vi\/","logo":{"@type":"ImageObject","inLanguage":"vi","@id":"https:\/\/staging.vietnamdetox.com\/vi\/#\/schema\/logo\/image\/","url":"https:\/\/staging.vietnamdetox.com\/wp-content\/uploads\/2026\/05\/logo-icon-color_cutout.svg","contentUrl":"https:\/\/staging.vietnamdetox.com\/wp-content\/uploads\/2026\/05\/logo-icon-color_cutout.svg","width":314,"height":435,"caption":"Staging Vietnamdetox"},"image":{"@id":"https:\/\/staging.vietnamdetox.com\/vi\/#\/schema\/logo\/image\/"}}]}},"_hostinger_reach_plugin_has_subscription_block":false,"_hostinger_reach_plugin_is_elementor":false,"_links":{"self":[{"href":"https:\/\/staging.vietnamdetox.com\/vi\/wp-json\/wp\/v2\/pages\/18902","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/staging.vietnamdetox.com\/vi\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/staging.vietnamdetox.com\/vi\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/staging.vietnamdetox.com\/vi\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/staging.vietnamdetox.com\/vi\/wp-json\/wp\/v2\/comments?post=18902"}],"version-history":[{"count":70,"href":"https:\/\/staging.vietnamdetox.com\/vi\/wp-json\/wp\/v2\/pages\/18902\/revisions"}],"predecessor-version":[{"id":20564,"href":"https:\/\/staging.vietnamdetox.com\/vi\/wp-json\/wp\/v2\/pages\/18902\/revisions\/20564"}],"wp:attachment":[{"href":"https:\/\/staging.vietnamdetox.com\/vi\/wp-json\/wp\/v2\/media?parent=18902"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}