{
    "id": 16183,
    "date": "2026-04-17T02:36:50",
    "date_gmt": "2026-04-17T02:36:50",
    "guid": {
        "rendered": "https:\/\/interpoolspa.com\/?page_id=16183"
    },
    "modified": "2026-07-21T10:35:10",
    "modified_gmt": "2026-07-21T10:35:10",
    "slug": "instant-estimate-en",
    "status": "publish",
    "type": "page",
    "link": "https:\/\/interpoolspa.com\/en\/instant-estimate-en\/",
    "title": {
        "rendered": "Instant Estimate"
    },
    "content": {
        "rendered": "<div data-elementor-type=\"wp-page\" data-elementor-id=\"16183\" class=\"elementor elementor-16183\">\n\t\t\t\t<div class=\"elementor-element elementor-element-957fbf1 e-con-full e-flex e-con e-parent\" data-id=\"957fbf1\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-70aaaee elementor-widget elementor-widget-html\" data-id=\"70aaaee\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t\n<!doctype html>\n<html class=\"ips-standalone\" lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1,viewport-fit=cover\">\n<title>Interpool Spa Estimator \u2014 English<\/title>\n<!-- Interpool Spa Estimator v28 \u2014 English mobile gallery refinements.\n     Mobile target: iPhone 16 CSS viewport (393 \u00d7 852).\n     Preserves the approved premium viewport-filling layout, restores\n     Fluent Forms submission, keeps LINE as an explicit handoff, and\n     uses real Interpool project imagery across the estimator journey. -->\n<style>\n\/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   Interpool Spa - Guided Estimator v28 English mobile gallery refinements\n   All styles scoped under `.ips-estimator` so the tool can be\n   dropped into an Elementor HTML widget without leaking CSS.\n   No html\/body resets \u2014 host page styles are untouched.\n   \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n\n\n.ips-estimator{\n  --ips-gold:#d0b476;\n  --ips-gold-2:#8b7b4d;\n  --ips-gold-soft:rgba(208,180,118,.16);\n  --ips-ink:#1c1208;\n  --ips-text:#211810;\n  --ips-muted:#6e5c4e;\n  --ips-line:rgba(60,42,28,.12);\n  --ips-card-bg:rgba(28,20,13,.52);\n  --ips-card-border:rgba(255,255,255,.10);\n  --ips-card-shadow:0 40px 120px rgba(0,0,0,.45),0 4px 16px rgba(0,0,0,.25);\n  --ips-pad:28px;\n  font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif !important;\n  color:#fff;\n  background:#120c08;\n  position:relative;\n  width:100%;\n  min-height:100svh;\n  overflow:visible;\n  isolation:isolate;\n  -webkit-font-smoothing:antialiased;\n  line-height:1.5;\n}\n.ips-estimator *,\n.ips-estimator *::before,\n.ips-estimator *::after{box-sizing:border-box}\n.ips-estimator img{display:block;max-width:100%}\n.ips-estimator button{background:none;border:0;padding:0;margin:0;cursor:pointer;font:inherit;color:inherit}\n.ips-estimator input,\n.ips-estimator textarea,\n.ips-estimator select{font:inherit !important;color:inherit !important}\n.ips-estimator a{color:inherit;text-decoration:none}\n\n\/* \u2500\u2500 Stage background \u2500\u2500 *\/\n.ips-stage{position:fixed;inset:0;z-index:0;pointer-events:none}\n.ips-stage-bg{\n  position:absolute;inset:0;\n  background-size:cover;\n  background-position:center center;\n}\n.ips-stage-bg-next{\n  position:absolute;inset:0;\n  background-size:cover;\n  background-position:center center;\n  opacity:0;\n  animation:none;\n}\n@keyframes ips-bg-in{\n  from{opacity:0}\n  to{opacity:1}\n}\n.ips-stage-mask{\n  position:absolute;inset:0;\n  background:linear-gradient(180deg,rgba(10,5,2,.25) 0%,rgba(10,5,2,.50) 45%,rgba(10,5,2,.80) 100%);\n}\n\n\/* \u2500\u2500 Top pills (brand + language + home) float above card \u2500\u2500 *\/\n.ips-topbar{\n  position:absolute;top:0;left:50%;transform:translateX(-50%);z-index:4;\n  width:min(1120px,calc(100% - 48px));\n  display:flex;justify-content:space-between;align-items:center;\n  padding:18px 0;gap:12px;pointer-events:none;\n}\n.ips-brand,\n.ips-language,\n.ips-return{\n  display:inline-flex;align-items:center;gap:8px;\n  padding:9px 14px;border-radius:999px;\n  background:rgba(20,13,8,.55);\n  border:1px solid rgba(255,255,255,.12);\n  backdrop-filter:blur(10px);\n  -webkit-backdrop-filter:blur(10px);\n  font-size:.82rem;font-weight:700;letter-spacing:.01em;\n  pointer-events:auto;\n  color:#fff;\n}\n.ips-top-actions{\n  display:flex;align-items:center;gap:8px;\n  pointer-events:auto;\n}\n.ips-brand{\n  padding:10px 16px 10px 14px;\n  gap:12px;\n}\n.ips-estimator .ips-brand-logo{\n  display:block !important;\n  height:42px !important;\n  width:auto !important;\n  max-width:none !important;\n  min-width:0 !important;\n  flex:0 0 auto !important;\n}\n.ips-brand-label{\n  display:inline-flex;align-items:center;\n  padding:8px 12px;border-radius:999px;\n  background:rgba(255,255,255,.06);\n  border:1px solid rgba(255,255,255,.10);\n  font-size:.82rem;font-weight:800;letter-spacing:.02em;\n  color:#fff;\n  white-space:nowrap;\n}\n.ips-language{gap:3px;padding:4px}\n.ips-lang{\n  display:inline-flex;align-items:center;justify-content:center;\n  min-width:38px;padding:6px 10px;border-radius:999px;\n  color:#fff;text-decoration:none;font-size:.78rem;font-weight:700;\n  transition:background .18s,color .18s;\n}\n.ips-lang:hover{background:rgba(255,255,255,.10)}\n.ips-lang.is-active{background:#fff;color:#20160f}\n.ips-return{font-weight:600;transition:background .18s;white-space:nowrap}\n.ips-return:hover{background:rgba(40,28,18,.75)}\n.ips-home-icon{\n  width:16px;height:16px;flex:0 0 auto;\n  fill:none;stroke:currentColor;stroke-width:2;\n  stroke-linecap:round;stroke-linejoin:round;\n}\n.ips-return-mobile{display:none}\n\n\/* The estimator has its own direct language links, so hide only the redundant\n   TranslatePress floating switcher on the two estimator pages. *\/\nbody.page-id-16183 .trp-floating-switcher,\nbody.page-id-17317 .trp-floating-switcher{display:none !important}\n\n\/* \u2500\u2500 Outer shell centres the glass card \u2500\u2500 *\/\n.ips-shell{\n  position:relative;z-index:2;\n  min-height:100svh;\n  display:flex;align-items:center;justify-content:center;\n  padding:96px 24px;\n}\n\n\/* \u2500\u2500 The glass card \u2500\u2500 *\/\n.ips-card{\n  width:100%;\n  max-width:1120px;\n  height:auto;min-height:0;\n  display:flex;flex-direction:column;\n  background:var(--ips-card-bg);\n  backdrop-filter:blur(24px) saturate(115%);\n  -webkit-backdrop-filter:blur(24px) saturate(115%);\n  border:1px solid var(--ips-card-border);\n  border-radius:28px;\n  box-shadow:var(--ips-card-shadow);\n  overflow:hidden;\n}\n\/* Intro step is short on content \u2014 shrink the card so it doesn't\n   leave a wide dead zone next to the 680px intro column on desktop.\n   Other steps keep the full 1120px for their 3-col grids\/galleries. *\/\n.ips-estimator.ips-at-intro .ips-card{max-width:760px}\n\/* Card head holds progress label + bar (matches reference screenshot 1) *\/\n.ips-card-head{\n  flex-shrink:0;\n  min-height:58px;\n  display:flex;align-items:center;justify-content:space-between;gap:20px;\n  padding:16px var(--ips-pad) 0;\n}\n.ips-prog-label strong{display:block;font-size:.95rem;font-weight:700;letter-spacing:.005em}\n.ips-prog-label span{display:block;font-size:.76rem;color:rgba(255,255,255,.58);margin-top:2px}\n.ips-prog-track{\n  flex:0 1 320px;max-width:320px;min-width:160px;\n  height:4px;border-radius:999px;\n  background:rgba(255,255,255,.14);overflow:hidden;\n}\n.ips-prog-fill{\n  height:100%;border-radius:999px;\n  background:linear-gradient(90deg,#e2c686,#a08855);\n  transition:width .4s ease;\n}\n\n\/* Slide viewport *\/\n.ips-viewport{flex:0 0 auto;min-height:0;overflow:visible;position:relative}\n.ips-view{\n  min-width:100%;height:auto;\n  padding:14px var(--ips-pad) 16px;\n  overflow:visible;display:flex;flex-direction:column;\n  scrollbar-width:none;\n}\n.ips-view::-webkit-scrollbar{display:none}\n\n\/* \u2500\u2500 Shared typography \u2500\u2500 *\/\n.ips-eyebrow{\n  font-size:.84rem;font-weight:800;letter-spacing:.16em;text-transform:uppercase;\n  color:var(--ips-gold);margin-bottom:12px;\n}\n.ips-title{\n  font-family:Georgia,\"Times New Roman\",serif !important;\n  font-size:clamp(2.1rem,3.5vw,2.7rem);line-height:1.08;\n  margin:0 0 10px !important;text-wrap:balance;\n  color:#fff !important;\n}\n.ips-lead{\n  font-size:1.12rem;color:rgba(255,255,255,.88);line-height:1.6;\n  max-width:58ch;margin:0;\n}\n.ips-step-head{margin-bottom:14px;flex-shrink:0}\n\n\/* \u2500\u2500 Action buttons \u2500\u2500 *\/\n.ips-actions{\n  display:flex;gap:16px;flex-wrap:wrap;flex-shrink:0;\n  margin-top:16px;padding-top:12px;align-items:center;\n  border-top:1px solid rgba(255,255,255,.08);\n}\n.ips-actions .ips-btn{min-width:180px}\n.ips-btn{\n  appearance:none;cursor:pointer;\n  min-height:58px;\n  padding:14px 34px;\n  border-radius:999px;\n  font-weight:800;font-size:1rem;letter-spacing:.005em;\n  display:inline-flex;align-items:center;justify-content:center;gap:10px;white-space:nowrap;\n  transition:transform .18s ease,box-shadow .18s ease,background .18s,opacity .18s,border-color .18s,color .18s;\n}\n.ips-btn:hover:not(:disabled){transform:translateY(-1px)}\n.ips-btn:active:not(:disabled){transform:translateY(0)}\n.ips-btn:disabled{opacity:.45;cursor:not-allowed}\n.ips-btn-primary{\n  background:#cfb36f;\n  color:#20150b;\n  border:1px solid rgba(231,213,165,.52);\n  box-shadow:0 14px 30px rgba(0,0,0,.20), inset 0 1px 0 rgba(255,255,255,.18);\n}\n.ips-btn-primary:hover:not(:disabled){background:#d5bb79;box-shadow:0 16px 34px rgba(0,0,0,.24)}\n.ips-btn-ghost{\n  background:rgba(255,255,255,.04);\n  color:#fff;\n  border:1.5px solid rgba(255,255,255,.18);\n  box-shadow:inset 0 1px 0 rgba(255,255,255,.04);\n}\n.ips-btn-ghost:hover{background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.26)}\n.ips-btn-line{background:#06C755;color:#fff;box-shadow:0 10px 24px rgba(6,199,85,.25);border:0;gap:8px}\n.ips-btn-line:hover:not(:disabled){background:#05b34d}\n.ips-btn-line svg{width:22px;height:22px;flex-shrink:0}\n.ips-result-actions .ips-btn-close-result{background:#b8a472;color:#fff;box-shadow:0 10px 24px rgba(138,122,76,.25);border:0;min-height:58px;padding:14px 34px;border-radius:999px;font-weight:800;font-size:1rem;display:inline-flex;align-items:center;justify-content:center}\n.ips-result-actions .ips-btn-close-result:hover:not(:disabled){background:#a8955f}\n\n\/* \u2500\u2500\u2500 Step: intro \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n.ips-intro{display:flex;flex-direction:column;justify-content:flex-start;max-width:680px}\n.ips-mobile-break{display:none}\n.ips-intro .ips-eyebrow{margin-bottom:16px}\n.ips-display{\n  font-family:Georgia,\"Times New Roman\",serif !important;\n  font-size:clamp(2.6rem,5vw,4rem);line-height:1.0;\n  margin-bottom:18px;text-wrap:balance;\n  color:#fff !important;\n}\n.ips-pills{display:flex;flex-wrap:wrap;gap:10px;margin:18px 0 26px}\n.ips-pill{\n  display:inline-flex;align-items:center;gap:9px;\n  padding:9px 14px;border-radius:999px;\n  background:rgba(20,13,8,.55);\n  border:1px solid rgba(255,255,255,.12);\n  font-size:.85rem;\n  backdrop-filter:blur(6px);\n  -webkit-backdrop-filter:blur(6px);\n}\n.ips-pill-dot{width:6px;height:6px;border-radius:50%;background:var(--ips-gold);flex-shrink:0}\n\n\/* \u2500\u2500\u2500 Step: setting (2 image cards) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n.ips-choice-grid{\n  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;\n  width:100%;flex:1;min-height:0;\n}\n.ips-choice{\n  position:relative;border-radius:22px;overflow:hidden;cursor:pointer;\n  min-height:0;height:clamp(270px,32vh,340px);\n  border:2px solid rgba(255,255,255,.10);\n  background:rgba(255,255,255,.04);\n  transition:transform .22s ease,border-color .22s,box-shadow .22s;\n  text-align:left;\n}\n.ips-choice:hover{transform:translateY(-3px);box-shadow:0 18px 40px rgba(0,0,0,.22)}\n.ips-choice.sel{\n  border-color:rgba(208,180,118,.85);\n  box-shadow:0 0 0 3px rgba(208,180,118,.15),0 18px 40px rgba(0,0,0,.25);\n}\n.ips-choice-bg{\n  position:absolute;inset:0;background-size:cover;background-position:center;\n  transform:scale(1.03);transition:transform .4s ease;\n}\n.ips-choice:hover .ips-choice-bg{transform:scale(1.07)}\n.ips-choice::after{\n  content:\"\";position:absolute;inset:0;\n  background:linear-gradient(180deg,rgba(10,5,2,.05) 40%,rgba(10,5,2,.78) 100%);\n}\n\/* Real DOM overlay \u2014 replaces ::after so Elementor can't reset it *\/\n.ips-choice-overlay{\n  position:absolute;inset:0;pointer-events:none;\n  background:linear-gradient(180deg,rgba(10,5,2,.05) 40%,rgba(10,5,2,.78) 100%);\n  z-index:0;\n}\n.ips-choice-body{\n  position:absolute;left:0;right:0;bottom:0;z-index:1;padding:16px 18px 18px;\n}\n.ips-choice-header{display:flex;justify-content:space-between;align-items:flex-start;gap:10px;margin-bottom:6px}\n.ips-choice-name{font-size:1.4rem;font-weight:800}\n.ips-choice-desc{font-size:1.08rem;color:rgba(255,255,255,.82);line-height:1.5}\n.ips-check{\n  width:26px;height:26px;border-radius:50%;\n  display:grid;place-items:center;\n  border:1.5px solid rgba(255,255,255,.22);background:rgba(255,255,255,.10);\n  font-size:.78rem;font-weight:900;color:transparent;flex-shrink:0;\n  transition:.18s;\n}\n.ips-choice.sel .ips-check{background:var(--ips-gold);border-color:var(--ips-gold);color:var(--ips-ink)}\n\n\/* \u2500\u2500\u2500 Step: build type \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n.ips-build-wrap{display:flex;flex-direction:column;gap:14px;flex:1;min-height:0}\n.ips-build-tabs{\n  display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:10px;\n  flex-shrink:0;\n}\n.ips-build-tab{\n  padding:15px 12px;border-radius:14px;\n  background:rgba(255,255,255,.08);\n  border:1.5px solid rgba(255,255,255,.16);\n  color:rgba(255,255,255,.78);\n  font-family:Georgia,\"Times New Roman\",serif !important;\n  font-weight:400;font-size:clamp(.95rem,1.2vw,1.12rem);letter-spacing:.02em;text-align:center;\n  transition:.18s;\n}\n.ips-build-tab:hover{background:rgba(255,255,255,.14);color:#fff}\n.ips-build-tab.sel{\n  background:var(--ips-gold-soft);\n  border-color:var(--ips-gold);\n  color:#fff;\n  box-shadow:0 6px 18px rgba(0,0,0,.18);\n}\n.ips-build-panel{\n  flex:1;min-height:260px;\n  display:grid;grid-template-columns:.92fr 1.08fr;gap:18px;\n  padding:18px;border-radius:22px;\n  background:rgba(255,255,255,.04);\n  border:1px solid rgba(255,255,255,.09);\n}\n.ips-build-info{display:flex;flex-direction:column;justify-content:center}\n.ips-build-info-eyebrow{\n  font-size:clamp(.72rem,1vw,.82rem);font-weight:800;letter-spacing:.16em;text-transform:uppercase;\n  color:var(--ips-gold);margin-bottom:10px;\n}\n.ips-build-info-name{\n  font-family:Georgia,serif !important;font-size:clamp(1.5rem,2.4vw,2.1rem);line-height:1.1;\n  margin-bottom:10px;\n}\n.ips-build-info-desc{\n  font-size:clamp(.9rem,1.2vw,1.06rem);color:rgba(255,255,255,.76);line-height:1.58;margin-bottom:16px;\n}\n.ips-build-info-action{\n  display:inline-flex;align-items:center;gap:8px;\n  padding:10px 14px;border-radius:999px;\n  background:rgba(255,255,255,.10);\n  border:1px solid rgba(255,255,255,.16);\n  color:#fff;font-size:clamp(.85rem,1vw,.96rem);font-weight:700;\n  width:fit-content;transition:.18s;\n}\n.ips-build-info-action:hover{background:rgba(255,255,255,.18)}\n.ips-gallery-icon{display:grid;grid-template-columns:1fr 1fr;gap:2px;width:14px;flex-shrink:0}\n.ips-gallery-icon span{display:block;height:6px;border-radius:2px;background:currentColor}\n\n.ips-build-gallery{\n  display:grid;\n  grid-template-columns:repeat(2,minmax(0,1fr));\n  grid-template-rows:repeat(2,minmax(118px,1fr));\n  gap:10px;min-height:0;height:100%;\n}\n.ips-gallery-tile{\n  border-radius:16px;overflow:hidden;\n  background-size:cover;background-position:center;\n  min-height:100px;\n  transition:transform .28s ease,box-shadow .28s ease;\n  cursor:pointer;\n  position:relative;\n}\n.ips-gallery-tile:hover{transform:scale(1.02);box-shadow:0 14px 30px rgba(0,0,0,.25)}\n.ips-gallery-tile.tall{grid-row:auto}\n.ips-gallery-more{\n  position:absolute;inset:0;\n  display:grid;place-items:center;\n  background:linear-gradient(180deg,rgba(10,5,2,.20),rgba(10,5,2,.72));\n  color:#fff;font-size:.9rem;font-weight:700;\n  opacity:0;transition:opacity .2s;\n}\n.ips-gallery-tile.more-overlay .ips-gallery-more{opacity:1}\n.ips-gallery-tile:hover .ips-gallery-more{opacity:1}\n\n\/* \u2500\u2500\u2500 Step: style (2 large cards) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n.ips-style-grid{\n  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px;\n  flex:1;min-height:0;\n}\n.ips-style-card{\n  position:relative;border-radius:24px;overflow:hidden;cursor:pointer;\n  border:2px solid rgba(255,255,255,.10);\n  transition:transform .22s,border-color .22s,box-shadow .22s;\n  min-height:210px;text-align:left;\n}\n.ips-style-card:hover{transform:translateY(-3px);box-shadow:0 18px 40px rgba(0,0,0,.2)}\n.ips-style-card.sel{\n  border-color:rgba(208,180,118,.85);\n  box-shadow:0 0 0 3px rgba(208,180,118,.15);\n}\n.ips-style-bg{\n  position:absolute;inset:0;background-size:cover;background-position:center;\n  transition:transform .4s ease;\n}\n.ips-style-card:hover .ips-style-bg{transform:scale(1.04)}\n.ips-style-card::after{\n  content:\"\";position:absolute;inset:0;\n  background:none;\n}\n.ips-style-check{\n  position:absolute;top:14px;right:14px;z-index:2;\n  width:28px;height:28px;border-radius:50%;\n  display:grid;place-items:center;\n  border:1.5px solid rgba(255,255,255,.22);background:rgba(255,255,255,.10);\n  font-weight:900;font-size:.84rem;color:transparent;transition:.18s;\n}\n.ips-style-card.sel .ips-style-check{background:var(--ips-gold);border-color:var(--ips-gold);color:var(--ips-ink)}\n\/* Real DOM overlay for style cards *\/\n.ips-style-overlay{\n  position:absolute;inset:0;pointer-events:none;\n  background:linear-gradient(180deg,rgba(8,4,2,0) 30%,rgba(8,4,2,.22) 58%,rgba(8,4,2,.84) 100%);\n  z-index:0;\n}\n.ips-style-body{position:absolute;left:0;right:0;bottom:0;z-index:1;padding:22px}\n.ips-style-name{font-family:Georgia,serif !important;font-size:1.45rem;margin-bottom:6px;text-shadow:0 2px 10px rgba(0,0,0,.78)}\n.ips-style-desc{font-size:.88rem;color:rgba(255,255,255,.78);line-height:1.5;text-shadow:0 2px 8px rgba(0,0,0,.78)}\n.ips-style-card:last-child{grid-column:auto}\n\n\/* \u2500\u2500\u2500 Step: scale (slider + photo) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n.ips-scale-grid{\n  display:grid;grid-template-columns:1fr 1fr;gap:16px;\n  flex:1;min-width:0;min-height:240px;align-items:stretch;\n}\n.ips-scale-panel{\n  border-radius:24px;\n  background:rgba(255,255,255,.06);\n  border:1px solid rgba(255,255,255,.10);\n  min-width:0;padding:20px 32px;display:flex;flex-direction:column;justify-content:flex-start;\n}\n.ips-scale-controls{min-width:0;flex:0 0 auto}\n.ips-scale-row{display:flex;flex-direction:column;align-items:flex-start;gap:4px;margin-bottom:8px}\n.ips-scale-row h3{font-size:clamp(.75rem,1vw,.88rem);font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:var(--ips-gold)}\n.ips-scale-val{font-family:Georgia,\"Times New Roman\",serif !important;font-size:clamp(1.6rem,2.8vw,2.4rem);font-weight:400;color:#fff;line-height:1.1;position:relative;display:block;width:100%;max-width:100%;min-height:1.2em}\n.ips-estimator input.ips-scale-slider{\n  --ips-scale-progress:0%;\n  display:block!important;width:100%!important;max-width:100%!important;\n  min-height:44px!important;height:44px!important;margin:0!important;padding:0!important;\n  border:0!important;border-radius:0!important;background:transparent!important;box-shadow:none!important;\n  -webkit-appearance:none!important;appearance:none!important;\n  cursor:pointer;touch-action:pan-y;position:relative;z-index:2;\n}\n.ips-estimator input.ips-scale-slider::-webkit-slider-runnable-track{\n  height:8px;border-radius:999px;border:1px solid rgba(255,255,255,.46);\n  background:linear-gradient(90deg,var(--ips-gold) 0,var(--ips-gold) var(--ips-scale-progress),rgba(255,255,255,.28) var(--ips-scale-progress),rgba(255,255,255,.28) 100%);\n}\n.ips-estimator input.ips-scale-slider::-webkit-slider-thumb{\n  -webkit-appearance:none!important;appearance:none!important;\n  width:32px;height:32px;margin-top:-13px;border:2px solid rgba(255,255,255,.78);border-radius:50%;\n  background:var(--ips-gold);box-shadow:0 3px 12px rgba(0,0,0,.34);cursor:grab;\n}\n.ips-estimator input.ips-scale-slider:active::-webkit-slider-thumb{cursor:grabbing;transform:scale(1.06)}\n.ips-estimator input.ips-scale-slider::-moz-range-track{height:8px;border-radius:999px;border:1px solid rgba(255,255,255,.46);background:rgba(255,255,255,.28)}\n.ips-estimator input.ips-scale-slider::-moz-range-progress{height:8px;border-radius:999px;background:var(--ips-gold)}\n.ips-estimator input.ips-scale-slider::-moz-range-thumb{width:32px;height:32px;border:2px solid rgba(255,255,255,.78);border-radius:50%;background:var(--ips-gold);box-shadow:0 3px 12px rgba(0,0,0,.34)}\n.ips-scale-ticks{\n  position:relative;height:auto;min-height:44px;\n  width:100%;max-width:100%;margin:0;\n  display:block;\n  color:rgba(255,255,255,.64);font-size:clamp(.78rem,.95vw,.96rem);line-height:1.16;\n}\n.ips-scale-ticks [data-scale-value]{\n  position:absolute;top:0;display:flex;min-width:0;width:clamp(52px,14vw,78px);min-height:44px;white-space:nowrap;\n  align-items:center;justify-content:center;text-align:center;overflow-wrap:normal;\n  font-family:inherit!important;font-size:inherit!important;font-weight:400!important;line-height:inherit;\n  transform:translateX(-50%);padding:7px 2px;cursor:pointer;user-select:none;border-radius:10px;\n}\n.ips-scale-ticks [data-scale-value]:nth-child(1){left:16px}\n.ips-scale-ticks [data-scale-value]:nth-child(2){left:calc(25% + 8px)}\n.ips-scale-ticks [data-scale-value]:nth-child(3){left:50%}\n.ips-scale-ticks [data-scale-value]:nth-child(4){left:calc(75% - 8px)}\n.ips-scale-ticks [data-scale-value]:nth-child(5){left:calc(100% - 16px)}\n.ips-scale-ticks [data-scale-value]:hover,\n.ips-scale-ticks [data-scale-value]:focus-visible{color:#fff;background:rgba(255,255,255,.08);outline:none}\n.ips-scale-ticks [data-scale-value].sel{color:var(--ips-gold);font-weight:700!important}\n@media (max-width:360px){\n  .ips-scale-ticks{font-size:.78rem}\n  .ips-scale-ticks [data-scale-value]{width:50px}\n}\n.ips-scale-desc{\n  margin-top:12px;padding-top:0;\n  font-size:clamp(.92rem,1.2vw,1.06rem);color:rgba(255,255,255,.74);line-height:1.5;\n  position:relative;\n}\n.ips-scale-copy-stack{min-height:4.5em}\n.ips-scale-copy-option{position:absolute;inset:0;display:block;width:100%;max-width:100%;visibility:hidden;opacity:0;pointer-events:none}\n.ips-scale-copy-option.is-active{visibility:visible;opacity:1}\nhtml.ips-estimator-contact-active,\nbody.ips-estimator-contact-active{overscroll-behavior-y:none}\n.ips-estimator.ips-at-contact{overscroll-behavior:none}\n.ips-scale-photo{\n  border-radius:24px;overflow:hidden;position:relative;min-width:0;min-height:220px;\n  background:rgba(255,255,255,.06);\n  border:1px solid rgba(255,255,255,.10);\n}\n.ips-scale-photo img{width:100%;height:100%;object-fit:cover;transition:opacity .28s}\n.ips-scale-photo::after{\n  content:\"\";position:absolute;inset:0;\n  background:linear-gradient(180deg,transparent 50%,rgba(8,4,2,.45));\n}\n\n\/* \u2500\u2500\u2500 Step: timing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n.ips-timing-view .ips-step-head{margin-bottom:8px}\n.ips-timing-view .ips-timing-grid{flex:0 0 auto}\n.ips-timing-view .ips-actions{margin-top:12px !important;padding-top:10px !important}\n.ips-timing-grid{\n  display:grid;grid-template-columns:1fr;gap:10px;padding:4px 0;\n  flex:0 0 auto;min-height:auto;align-content:start;\n}\n.ips-timing-card{\n  text-align:left;padding:0;border-radius:20px;overflow:hidden;\n  background:rgba(255,255,255,.10);\n  border:1.5px solid rgba(255,255,255,.18);\n  transition:transform .18s,border-color .18s,background .18s,box-shadow .18s;\n}\n.ips-timing-card-inner{\n  display:flex;align-items:center;justify-content:space-between;gap:20px;\n  padding:20px 24px;\n}\n.ips-timing-card:hover{transform:translateY(-2px);background:rgba(255,255,255,.14);box-shadow:0 10px 28px rgba(0,0,0,.18)}\n.ips-timing-card.sel{\n  border-color:rgba(208,180,118,.90);\n  background:rgba(208,180,118,.13);\n  box-shadow:0 0 0 2px rgba(208,180,118,.22),0 10px 28px rgba(0,0,0,.18);\n}\n.ips-timing-copy{display:flex;flex-direction:column;gap:5px;flex:1 1 auto}\n.ips-timing-label{\n  display:block;\n  font-family:Georgia,\"Times New Roman\",serif !important;\n  font-size:clamp(1.18rem,2.2vw,1.9rem);font-weight:700;line-height:1.1;\n  color:var(--ips-gold);\n}\n.ips-timing-copy span{display:block;font-size:clamp(.88rem,1.4vw,1.12rem);line-height:1.5;color:rgba(255,255,255,.80)}\n.ips-timing-radio{\n  width:28px;height:28px;border-radius:50%;flex-shrink:0;\n  border:2px solid rgba(255,255,255,.30);\n  background:transparent;\n  transition:border-color .18s,background .18s;\n}\n.ips-timing-card.sel .ips-timing-radio{\n  border-color:var(--ips-gold);\n  background:var(--ips-gold);\n  box-shadow:0 0 0 3px rgba(208,180,118,.20);\n}\n\n\/* \u2500\u2500\u2500 Step: contact \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n.ips-contact-grid{\n  display:grid;grid-template-columns:.85fr 1.15fr;gap:14px;\n  flex:1;min-height:0;align-items:start;\n}\n.ips-summary{\n  border-radius:18px;\n  background:rgba(255,255,255,.06);\n  border:1px solid rgba(255,255,255,.10);\n  padding:20px;position:sticky;top:0;\n}\n.ips-summary-title{\n  font-size:.68rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase;\n  color:rgba(255,255,255,.58);margin-bottom:10px;\n}\n.ips-form{\n  border-radius:18px;\n  background:rgba(255,255,255,.06);\n  border:1px solid rgba(255,255,255,.10);\n  padding:20px;\n}\n.ips-form-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:8px}\n.ips-field{display:grid;gap:4px}\n.ips-field.full{grid-column:1\/-1}\n.ips-field-label{font-size:clamp(.78rem,1vw,.9rem);font-weight:700;color:rgba(255,255,255,.82)}\n.ips-input,\n.ips-select,\n.ips-textarea{\n  width:100%;border-radius:10px;\n  border:1px solid rgba(255,255,255,.14);\n  background:rgba(255,255,255,.08);\n  color:#fff;padding:9px 12px;outline:none;\n  transition:border-color .16s,box-shadow .16s,background .16s;\n}\n.ips-input::placeholder,\n.ips-textarea::placeholder{color:rgba(255,255,255,.38)}\n.ips-input:focus,\n.ips-select:focus,\n.ips-textarea:focus{\n  border-color:rgba(208,180,118,.85);\n  box-shadow:0 0 0 3px rgba(208,180,118,.14);\n  background:rgba(255,255,255,.12);\n}\n.ips-select option{color:#111;background:#fff}\n.ips-textarea{min-height:86px;resize:vertical}\n\n.ips-contact-view{padding-top:10px}\n.ips-contact-view .ips-step-head{margin-bottom:8px}\n.ips-contact-view .ips-title{font-size:clamp(1.9rem,2.55vw,2.35rem);line-height:1.02;margin-bottom:6px}\n.ips-contact-view .ips-lead{font-size:.95rem;max-width:48ch;margin-bottom:0}\n.ips-contact-grid.compact{grid-template-columns:.76fr 1.24fr;gap:10px;align-items:stretch}\n.ips-summary-compact{display:grid;grid-template-columns:1fr 1fr;gap:10px}\n.ips-summary-chip{\n  padding:9px 11px;border-radius:14px;\n  background:rgba(255,255,255,.05);\n  border:1px solid rgba(255,255,255,.08);\n}\n.ips-summary-chip span{display:block}\n.ips-summary-chip span:first-child{font-size:clamp(.66rem,.9vw,.76rem);letter-spacing:.08em;text-transform:uppercase;color:rgba(255,255,255,.54);margin-bottom:4px}\n.ips-summary-chip span:last-child{font-size:clamp(.86rem,1.1vw,1rem);font-weight:700;line-height:1.28}\n.ips-form.compact{padding:12px}\n.ips-form.compact .ips-form-grid{gap:6px}\n.ips-form.compact .ips-input,\n.ips-form.compact .ips-select,\n.ips-form.compact .ips-textarea{padding:9px 12px}\n.ips-contact-actions{\n  display:flex;gap:10px;align-items:center;flex-wrap:nowrap;\n  margin-top:6px;padding-top:6px;\n}\n.ips-contact-actions .ips-btn{min-width:150px}\n.ips-contact-submit{\n  min-width:220px;\n  padding-left:26px;padding-right:26px;\n  box-shadow:0 18px 40px rgba(0,0,0,.24), inset 0 1px 0 rgba(255,255,255,.24);\n}\n.ips-privacy{margin-top:4px;font-size:.72rem;color:rgba(255,255,255,.50);line-height:1.3}\n\n\/* \u2500\u2500\u2500 Lightbox (expanded gallery) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n.ips-lightbox{\n  position:fixed;inset:0;z-index:9998;display:none;\n  background:rgba(8,4,2,.88);\n  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);\n  padding:24px;align-items:center;justify-content:center;\n}\n.ips-lightbox.open{display:flex}\n.ips-lightbox-inner{\n  width:min(1100px,100%);\n  height:min(880px,calc(100svh - 48px));\n  display:flex;\n  flex-direction:column;\n  overflow:hidden;\n}\n.ips-lightbox-top{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;margin-bottom:18px;flex-shrink:0}\n.ips-lightbox-name{font-family:Georgia,serif !important;font-size:2rem;line-height:1.1}\n.ips-lightbox-desc{margin-top:6px;font-size:.92rem;color:rgba(255,255,255,.72);max-width:58ch;line-height:1.55}\n.ips-lightbox-close{\n  width:40px;height:40px;border-radius:50%;\n  background:rgba(255,255,255,.10);\n  border:1px solid rgba(255,255,255,.14);\n  color:#fff;font-size:1.05rem;flex-shrink:0;\n  display:grid;place-items:center;transition:.18s;\n}\n.ips-lightbox-close:hover{background:rgba(255,255,255,.20)}\n.ips-lightbox-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:repeat(3,minmax(0,1fr));gap:12px;flex:1;min-height:0}\n.ips-lb-tile{border-radius:18px;overflow:hidden;background:rgba(255,255,255,.06)}\n.ips-lb-tile img{display:block;width:100%;height:100%;object-fit:cover}\n.ips-lightbox-footer{\n  margin-top:20px;\n  padding-top:18px;\n  border-top:1px solid rgba(255,255,255,.14);\n  background:rgba(8,4,2,.88);\n  display:flex;\n  gap:12px;\n  flex-shrink:0;\n  position:relative !important;\n  z-index:1;\n}\n.ips-lb-back-btn{\n  flex:1;\n  background:rgba(255,255,255,.13);\n  color:#fff;\n  border:none;\n}\n.ips-lb-back-btn:hover:not(:disabled){background:rgba(255,255,255,.20)}\n.ips-lb-select-btn{\n  flex:1;\n  background:#cfb36f;\n  color:#20150b;\n  border:none;\n  box-shadow:0 14px 30px rgba(0,0,0,.20),inset 0 1px 0 rgba(255,255,255,.18);\n  font-weight:800;\n}\n.ips-lb-select-btn:hover:not(:disabled){background:#d5bb79}\n\n\/* \u2500\u2500\u2500 Result modal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n.ips-result{\n  position:fixed;inset:0;z-index:9999;display:none;\n  background:rgba(8,4,2,.72);\n  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);\n  padding:20px;align-items:center;justify-content:center;\n}\n.ips-result.open{display:flex}\n.ips-result-card{\n  width:min(980px,100%);max-height:90vh;overflow:auto;\n  background:linear-gradient(160deg,#f8f1e7,#ecdfd0);\n  color:var(--ips-text);border-radius:28px;\n  border:1px solid var(--ips-line);\n  box-shadow:0 44px 120px rgba(8,4,2,.32);\n  padding:20px;scrollbar-width:none;\n}\n.ips-result-card::-webkit-scrollbar{display:none}\n.ips-result-head{display:flex;justify-content:space-between;align-items:flex-start;gap:18px;margin-bottom:12px}\n.ips-result-eyebrow{font-size:clamp(.74rem,1vw,.85rem);font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:var(--ips-gold-2);margin-bottom:6px}\n.ips-result-head h3{font-family:Georgia,serif !important;font-size:clamp(1.55rem,2.8vw,2.25rem);line-height:1.08;color:var(--ips-text)}\n.ips-result-close{\n  width:40px;height:40px;border-radius:50%;\n  background:#fff;border:1px solid var(--ips-line);\n  font-size:1.05rem;cursor:pointer;\n  box-shadow:0 6px 16px rgba(0,0,0,.08);\n  flex-shrink:0;display:grid;place-items:center;transition:.18s;\n}\n.ips-result-close:hover{background:#f5ede1}\n.ips-result-grid{display:grid;grid-template-columns:1.02fr .98fr;gap:12px;margin-bottom:10px}\n.ips-result-box{background:rgba(255,255,255,.64);border:1px solid var(--ips-line);border-radius:18px;padding:16px}\n.ips-result-box-label{font-size:.72rem;font-weight:800;letter-spacing:.13em;text-transform:uppercase;color:var(--ips-muted);margin-bottom:10px}\n.ips-price{font-size:clamp(1.8rem,3.3vw,2.8rem);font-weight:900;line-height:1.02;color:var(--ips-text)}\n.ips-price-caveat{margin-top:10px;font-size:clamp(.94rem,1.1vw,1.04rem);font-weight:600;color:#5b4c40;line-height:1.52}\n.ips-line-mobile-cta{display:none}\n.ips-result-row{display:flex;justify-content:space-between;gap:10px;padding:7px 0;border-bottom:1px solid var(--ips-line);font-size:.88rem}\n.ips-result-row:last-child{border-bottom:0}\n.ips-result-row span:first-child{color:var(--ips-muted)}\n.ips-result-row span:last-child{font-weight:700;text-align:right}\n.ips-next{border-radius:18px;background:rgba(138,122,76,.07);border:1px solid rgba(138,122,76,.16);padding:10px 14px 12px;margin-bottom:10px}\n.ips-next h4{font-size:1rem;font-weight:800;margin:0 0 8px}\n.ips-next-list{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}\n.ips-next-item{display:flex;gap:10px;align-items:flex-start}\n.ips-next-num{\n  width:26px;height:26px;border-radius:50%;\n  background:var(--ips-gold-2);color:#fff;\n  font-size:.8rem;font-weight:800;\n  display:grid;place-items:center;flex-shrink:0;\n}\n.ips-next-item strong{display:block;font-size:.92rem;margin-bottom:3px}\n.ips-next-item span{font-size:.88rem;color:#5b4c40;line-height:1.45}\n.ips-result-actions{display:flex;justify-content:flex-end;gap:16px;flex-wrap:wrap;align-items:center}\n\n@media (max-width:1180px){\n  .ips-shell{padding:88px 24px}\n  .ips-brand{padding:8px 14px 8px 12px;gap:10px}\n  .ips-estimator .ips-brand-logo{height:36px !important}\n  .ips-brand-label{font-size:.76rem;padding:7px 10px}\n}\n@media (min-width:961px) and (max-width:1180px){\n  \/* Half-window desktop: retain headline presence while tightening the short intro card. *\/\n  .ips-estimator.ips-at-intro .ips-card{max-width:650px}\n  .ips-estimator.ips-at-intro .ips-view{padding:22px 24px 20px}\n  .ips-estimator.ips-at-intro .ips-display{font-size:clamp(3.15rem,4.2vw,3.5rem)}\n}\n\/* \u2500\u2500\u2500 Responsive \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n@media (max-width:960px){\n  .ips-estimator{min-height:100svh;overflow:visible}\n  .ips-intro,\n  .ips-choice-grid,\n  .ips-build-wrap,\n  .ips-style-grid,\n  .ips-scale-grid,\n  .ips-timing-grid,\n  .ips-contact-grid{flex:0 0 auto;min-height:auto}\n  .ips-shell{padding:84px 16px;align-items:center}\n  .ips-card{\n    height:auto;min-height:0;\n    max-height:none;\n    border-radius:24px;\n  }\n  .ips-viewport{overflow:visible}\n  .ips-view{padding:14px 22px 16px;overflow:visible;height:auto}\n  .ips-card-head{padding:16px 22px 0}\n  .ips-choice-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}\n  .ips-choice{height:auto;min-height:230px}\n  .ips-build-tabs{\n    grid-auto-flow:row;\n    grid-auto-columns:unset;\n    grid-template-columns:repeat(2,1fr);\n    gap:8px;\n  }\n  .ips-build-panel{\n    grid-template-columns:1fr;\n    padding:10px;gap:8px;min-height:0;\n  }\n  .ips-build-wrap{gap:8px}\n  .ips-build-tabs{gap:6px}\n  .ips-build-tab{padding:11px 10px}\n  .ips-build-info-eyebrow{margin-bottom:6px}\n  .ips-build-info-name{margin-bottom:6px}\n  .ips-build-info-desc{margin-bottom:10px}\n  .ips-build-gallery{\n    grid-template-columns:1fr 1fr;\n    grid-template-rows:repeat(2,105px);\n  }\n  .ips-gallery-tile.tall{grid-row:span 1}\n  .ips-style-grid{grid-template-columns:1fr;gap:10px}\n  .ips-style-card{min-height:150px}\n  .ips-scale-grid{grid-template-columns:1fr;gap:12px}\n  .ips-scale-panel{padding:18px 24px}\n  .ips-scale-desc{min-height:4.5em}\n  .ips-scale-photo{min-height:180px}\n  .ips-timing-grid{grid-template-columns:1fr;gap:10px}\n  .ips-timing-card-inner{padding:17px 20px}\n  .ips-timing-label{font-size:1.18rem}\n  .ips-timing-copy span{font-size:.88rem}\n  .ips-contact-grid,\n  .ips-contact-grid.compact{grid-template-columns:1fr;gap:10px}\n  .ips-summary{display:none}\n  .ips-summary-compact{grid-template-columns:1fr 1fr}\n  .ips-textarea{display:none}\n  .ips-field:has(.ips-textarea){display:none}\n  .ips-actions{margin-top:12px !important;padding-top:10px !important}\n  .ips-lightbox-inner{height:calc(100svh - 28px);max-height:none;overflow:hidden}\n  .ips-lightbox-grid{grid-template-columns:1fr 1fr;grid-template-rows:repeat(3,minmax(0,1fr));grid-auto-rows:auto;flex:1}\n  .ips-lb-tile{aspect-ratio:auto}\n  .ips-result-grid{grid-template-columns:1fr}\n  .ips-next-list{grid-template-columns:1fr}\n}\n@media (min-width:621px) and (max-width:960px){\n  .ips-shell{padding:84px 16px}\n  .ips-build-tabs{grid-template-columns:repeat(3,1fr)}\n}\n@media (max-width:620px){\n  .ips-estimator{min-height:100svh}\n  .ips-mobile-break{display:block}\n  .ips-intro,\n  .ips-choice-grid,\n  .ips-build-wrap,\n  .ips-style-grid,\n  .ips-scale-grid,\n  .ips-timing-grid,\n  .ips-contact-grid{flex:0 0 auto;min-height:auto}\n  .ips-shell{padding:clamp(82px,10svh,104px) 10px;align-items:center}\n  .ips-card{border-radius:20px;min-height:auto}\n  .ips-card-head{padding:14px 18px 0;gap:12px}\n  .ips-prog-track{flex:0 1 140px;min-width:120px}\n  .ips-view{padding:12px 16px 12px;overflow:visible}\n  .ips-topbar{width:calc(100% - 20px);padding:14px 0;gap:8px}\n  .ips-brand,.ips-return{padding:8px 12px;font-size:.76rem}\n  .ips-brand{gap:8px;padding:8px 12px 8px 10px}\n  .ips-estimator .ips-brand-logo{height:28px !important}\n  .ips-brand-label{font-size:.72rem;padding:6px 10px}\n  .ips-top-actions{gap:4px}\n  .ips-language{padding:3px;gap:2px}\n  .ips-lang{min-width:32px;padding:7px 8px;font-size:.76rem}\n  .ips-return{padding:8px 10px;font-size:.82rem;gap:6px}\n  .ips-return-desktop{display:none}\n  .ips-return-mobile{display:inline}\n  .ips-display{font-size:2.7rem}\n  .ips-intro{justify-content:center;text-align:center;align-items:center}\n  .ips-step-head{margin-bottom:12px}\n  .ips-title{font-size:2rem}\n  .ips-pills{\n    display:grid;\n    grid-template-columns:repeat(2,max-content);\n    justify-content:center;\n    gap:10px;\n    margin:16px 0 24px;\n  }\n  .ips-pill{\n    justify-content:center;\n    padding:10px 12px;\n    font-size:clamp(.8rem,3.5vw,.9rem);\n    white-space:nowrap;\n  }\n  .ips-pill:nth-child(3){grid-column:1 \/ -1;justify-self:center}\n  .ips-form-grid{grid-template-columns:1fr}\n  .ips-choice-grid{grid-template-columns:1fr;gap:10px}\n  .ips-choice{min-height:180px}\n  .ips-scale-panel{padding:16px 20px}\n  .ips-actions{flex-direction:row;gap:10px;justify-content:center;margin-top:10px !important;padding-top:10px !important}\n  .ips-timing-view .ips-actions{margin-top:10px !important;padding-top:10px !important}\n  .ips-timing-card-inner{padding:17px 16px;gap:12px}\n  .ips-summary{display:none}\n  .ips-textarea{display:none}\n  .ips-field:has(.ips-textarea){display:none}\n  .ips-summary-compact{grid-template-columns:1fr 1fr}\n  .ips-actions .ips-btn{width:auto;min-width:150px;justify-content:center}\n  .ips-contact-actions{flex-direction:column;align-items:stretch}\n  .ips-contact-actions .ips-contact-submit{order:-1}\n  .ips-contact-actions .ips-btn,.ips-contact-submit{width:100%;min-width:0}\n  .ips-build-tabs{grid-template-columns:repeat(2,1fr)}\n  .ips-build-tab{font-size:1rem;padding:16px 10px}\n  .ips-build-info-name{font-size:1.3rem}\n  .ips-build-info-desc{margin-bottom:10px}\n  .ips-result-card{padding:20px;border-radius:22px}\n  .ips-result-actions{flex-direction:column;gap:12px}\n  .ips-result-actions .ips-btn{width:100%;justify-content:center}\n  .ips-line-mobile-cta{\n    display:flex;\n    width:100%;\n    min-height:52px;\n    margin-top:16px;\n    justify-content:center;\n  }\n  .ips-result-actions #ipsLineLink{display:none}\n  .ips-lightbox{padding:14px}\n  .ips-lightbox-name{font-size:1.5rem}\n  .ips-lightbox-desc{display:none}\n  .ips-lightbox-grid{grid-template-rows:repeat(3,minmax(0,1fr));grid-auto-rows:auto;gap:8px}\n  .ips-lightbox-footer{margin-top:10px;padding-top:10px;gap:10px}\n}\n\n\/* \u2500\u2500\u2500 v13 mobile app concept \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   After the welcome screen, the estimator becomes a fixed-height\n   app surface. The document itself does not scroll; an individual\n   view can scroll internally as a fallback on unusually short\n   screens or while the software keyboard is open. Target viewport:\n   iPhone 16 at 393 \u00d7 852 CSS px. \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n@media (max-width:620px){\n  .ips-estimator:not(.ips-at-intro){\n    height:100svh;\n    height:100dvh;\n    min-height:0;\n    overflow:hidden;\n  }\n\n  \/* Keep language and exit controls, but collapse the large brand bar. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-topbar{\n    position:absolute;\n    top:max(6px,env(safe-area-inset-top));\n    right:10px;left:auto;\n    width:auto;\n    transform:none;\n    justify-content:flex-end;\n    padding:0;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-brand{display:none}\n  .ips-estimator:not(.ips-at-intro) .ips-top-actions{gap:5px}\n  .ips-estimator:not(.ips-at-intro) .ips-language{\n    min-height:36px;\n    padding:3px;\n    background:rgba(20,13,8,.70);\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-lang{\n    min-width:31px;\n    padding:6px 7px;\n    font-size:.71rem;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-return{\n    width:36px;height:36px;\n    padding:0;\n    justify-content:center;\n    border-radius:50%;\n    background:rgba(20,13,8,.70);\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-return span{display:none}\n  .ips-estimator:not(.ips-at-intro) .ips-home-icon{width:15px;height:15px}\n\n  \/* Use the full phone viewport below the compact app controls. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-shell{\n    height:100svh;\n    height:100dvh;\n    min-height:0;\n    padding-top:max(48px,calc(env(safe-area-inset-top) + 44px));\n    padding-right:8px;\n    padding-bottom:max(8px,env(safe-area-inset-bottom));\n    padding-left:8px;\n    align-items:stretch;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-card{\n    height:100%;\n    min-height:0;\n    max-height:100%;\n    border-radius:18px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-card-head{\n    min-height:44px;\n    padding:7px 13px 0;\n    gap:10px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-prog-label strong{font-size:.78rem}\n  .ips-estimator:not(.ips-at-intro) .ips-prog-label span{font-size:.63rem;margin-top:0}\n  .ips-estimator:not(.ips-at-intro) .ips-prog-track{\n    flex:1 1 auto;\n    min-width:70px;\n    max-width:none;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-viewport{\n    flex:1 1 auto;\n    min-height:0;\n    overflow:hidden;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-track{height:100%;min-height:0}\n  .ips-estimator:not(.ips-at-intro) .ips-view{\n    height:100%;\n    min-height:0;\n    padding:7px 12px 9px;\n    overflow-x:hidden;\n    overflow-y:auto;\n    overscroll-behavior:contain;\n    -webkit-overflow-scrolling:touch;\n  }\n\n  \/* Compact type without removing instructions that support usability. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-step-head{margin-bottom:7px}\n  .ips-estimator:not(.ips-at-intro) .ips-title{\n    font-size:1.48rem;\n    line-height:1.04;\n    margin-bottom:4px !important;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-lead{\n    font-size:.82rem;\n    line-height:1.32;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-eyebrow{\n    font-size:.67rem;\n    margin-bottom:4px;\n  }\n\n  \/* The action row rests at the bottom and remains reachable if a\n     short viewport needs contained scrolling. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-actions{\n    position:sticky;\n    bottom:-9px;\n    z-index:5;\n    flex-wrap:nowrap;\n    gap:8px;\n    margin-top:auto !important;\n    padding:8px 0 2px !important;\n    background:linear-gradient(180deg,rgba(24,16,10,0),rgba(24,16,10,.94) 34%);\n    border-top:0;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-actions .ips-btn{\n    min-width:0;\n    min-height:44px;\n    padding:9px 18px;\n    font-size:.86rem;\n    flex:1 1 0;\n  }\n\n  \/* Setting: two readable image choices still fit comfortably in one view. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-choice-grid{gap:7px}\n  .ips-estimator:not(.ips-at-intro) .ips-choice{min-height:142px}\n  .ips-estimator:not(.ips-at-intro) .ips-choice-body{padding:11px 13px 12px}\n  .ips-estimator:not(.ips-at-intro) .ips-choice-header{margin-bottom:3px}\n  .ips-estimator:not(.ips-at-intro) .ips-choice-name{font-size:1.06rem}\n  .ips-estimator:not(.ips-at-intro) .ips-choice-desc{font-size:.76rem;line-height:1.32}\n  .ips-estimator:not(.ips-at-intro) .ips-check{width:22px;height:22px}\n\n  \/* Build: six choices become two rows; examples become one thumbnail strip. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-build-wrap{gap:6px}\n  .ips-estimator:not(.ips-at-intro) .ips-build-tabs{\n    grid-template-columns:repeat(3,minmax(0,1fr));\n    gap:5px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-build-tab{\n    min-height:42px;\n    padding:6px 3px;\n    font-size:.74rem;\n    line-height:1.16;\n    border-radius:10px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-build-panel{\n    grid-template-columns:1fr;\n    gap:7px;\n    padding:8px;\n    border-radius:14px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-build-info{justify-content:flex-start}\n  .ips-estimator:not(.ips-at-intro) .ips-build-info-eyebrow{font-size:.62rem;margin-bottom:2px}\n  .ips-estimator:not(.ips-at-intro) .ips-build-info-name{font-size:1.08rem;margin-bottom:3px}\n  .ips-estimator:not(.ips-at-intro) .ips-build-info-desc{\n    font-size:.74rem;\n    line-height:1.3;\n    margin-bottom:6px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-build-info-action{\n    min-height:34px;\n    padding:6px 10px;\n    font-size:.72rem;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-build-gallery{\n    grid-template-columns:repeat(4,minmax(0,1fr));\n    grid-template-rows:82px;\n    gap:5px;\n    height:82px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-gallery-tile{\n    min-height:82px;\n    border-radius:9px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-gallery-more{\n    padding:4px;\n    text-align:center;\n    font-size:.62rem;\n    line-height:1.15;\n  }\n\n  \/* Style: retain the photography but reduce card and copy height. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-style-grid{gap:7px}\n  .ips-estimator:not(.ips-at-intro) .ips-style-card{\n    min-height:112px;\n    border-radius:14px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-style-body{padding:11px 13px}\n  .ips-estimator:not(.ips-at-intro) .ips-style-name{font-size:1rem;margin-bottom:2px}\n  .ips-estimator:not(.ips-at-intro) .ips-style-desc{\n    display:-webkit-box;\n    overflow:hidden;\n    -webkit-box-orient:vertical;\n    -webkit-line-clamp:2;\n    font-size:.72rem;\n    line-height:1.28;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-style-check{\n    top:9px;right:9px;\n    width:22px;height:22px;\n  }\n\n  \/* Scale: preserve the visual feedback with a shorter supporting image. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-scale-grid{gap:7px}\n  .ips-estimator:not(.ips-at-intro) .ips-scale-panel{padding:12px 20px;border-radius:14px}\n  .ips-estimator:not(.ips-at-intro) .ips-scale-row{margin-bottom:4px}\n  .ips-estimator:not(.ips-at-intro) .ips-scale-row h3{font-size:.65rem}\n  .ips-estimator:not(.ips-at-intro) .ips-scale-val{font-size:1.36rem}\n  .ips-estimator:not(.ips-at-intro) .ips-scale-desc{\n    min-height:0;\n    margin-top:8px;\n    font-size:.76rem;\n    line-height:1.3;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-scale-photo{\n    min-height:138px;\n    max-height:156px;\n    border-radius:14px;\n  }\n\n  \/* Readiness: a 2 \u00d7 2 decision grid replaces four tall rows. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-timing-grid{\n    grid-template-columns:repeat(2,minmax(0,1fr));\n    gap:7px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-card{border-radius:13px}\n  .ips-estimator:not(.ips-at-intro) .ips-timing-card-inner{\n    min-height:108px;\n    align-items:flex-start;\n    gap:6px;\n    padding:10px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-copy{gap:3px}\n  .ips-estimator:not(.ips-at-intro) .ips-timing-label{font-size:.92rem;line-height:1.12}\n  .ips-estimator:not(.ips-at-intro) .ips-timing-copy span{font-size:.69rem;line-height:1.28}\n  .ips-estimator:not(.ips-at-intro) .ips-timing-radio{width:19px;height:19px}\n\n  \/* Contact: two-column pairs at the 393px target, with one-row actions. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view{padding-top:5px}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view .ips-step-head{margin-bottom:6px}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view .ips-title{font-size:1.42rem}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view .ips-lead{font-size:.75rem;line-height:1.28}\n  .ips-estimator:not(.ips-at-intro) .ips-form.compact{padding:9px}\n  .ips-estimator:not(.ips-at-intro) .ips-form-grid{\n    grid-template-columns:repeat(2,minmax(0,1fr));\n    gap:6px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-form-grid>.ips-field:nth-child(5){grid-column:1\/-1}\n  .ips-estimator:not(.ips-at-intro) .ips-field{gap:2px}\n  .ips-estimator:not(.ips-at-intro) .ips-field-label{font-size:.68rem;line-height:1.2}\n  .ips-estimator:not(.ips-at-intro) .ips-form.compact .ips-input,\n  .ips-estimator:not(.ips-at-intro) .ips-form.compact .ips-select{\n    min-height:39px;\n    padding:7px 9px;\n    font-size:.78rem !important;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-privacy{font-size:.62rem;line-height:1.2}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-actions{\n    flex-direction:row;\n    align-items:stretch;\n    gap:7px;\n    margin-top:6px;\n    padding-top:0;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-contact-actions .ips-btn{\n    min-height:44px;\n    padding:8px 10px;\n    font-size:.82rem;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-contact-actions .ips-btn-ghost{flex:0 0 34%}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-actions .ips-contact-submit{\n    order:initial;\n    flex:1 1 auto;\n  }\n}\n\n\/* \u2500\u2500\u2500 v14 balanced mobile sizing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   v13 proved that every step can fit. This revision gives the saved\n   height back to the interactive content. The header and action bar\n   keep fixed allowances; the active choice area receives everything\n   between them and stretches differently for each step. \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n@media (max-width:620px){\n  .ips-estimator:not(.ips-at-intro) .ips-card-head{\n    min-height:48px;\n    padding:8px 14px 0;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-prog-label strong{font-size:.88rem}\n  .ips-estimator:not(.ips-at-intro) .ips-prog-label span{font-size:.69rem;margin-top:1px}\n\n  \/* Use an explicit three-row app layout: step heading, flexible stage,\n     then navigation. This prevents spare space from pushing the buttons\n     below the visible card. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-view{\n    padding:9px 14px;\n    overflow-x:hidden;\n    overflow-y:auto;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-view:not(.ips-contact-view){\n    display:grid;\n    grid-template-rows:auto minmax(0,1fr) 58px;\n    overflow:hidden;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-actions{\n    position:static;\n    right:auto;\n    bottom:auto;\n    left:auto;\n    z-index:6;\n    min-height:52px;\n    align-self:end;\n    margin:0 !important;\n    padding:5px 0 0 !important;\n    background:linear-gradient(180deg,rgba(24,16,10,0),rgba(24,16,10,.97) 36%);\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-actions .ips-btn{\n    min-height:48px;\n    padding:10px 20px;\n    font-size:.92rem;\n  }\n\n  \/* Restore comfortable reading sizes now that vertical space is\n     distributed rather than discarded. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-step-head{margin-bottom:9px}\n  .ips-estimator:not(.ips-at-intro) .ips-title{\n    font-size:1.7rem;\n    line-height:1.04;\n    margin-bottom:5px !important;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-lead{\n    font-size:.9rem;\n    line-height:1.36;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-eyebrow{\n    font-size:.72rem;\n    margin-bottom:5px;\n  }\n\n  \/* Every main step region is allowed to claim the remaining height. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-choice-grid,\n  .ips-estimator:not(.ips-at-intro) .ips-build-wrap,\n  .ips-estimator:not(.ips-at-intro) .ips-style-grid,\n  .ips-estimator:not(.ips-at-intro) .ips-scale-grid,\n  .ips-estimator:not(.ips-at-intro) .ips-timing-grid{\n    flex:1 1 auto;\n    min-height:0;\n    height:100%;\n    overflow-y:auto;\n    overscroll-behavior:contain;\n    scrollbar-width:none;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-choice-grid::-webkit-scrollbar,\n  .ips-estimator:not(.ips-at-intro) .ips-build-wrap::-webkit-scrollbar,\n  .ips-estimator:not(.ips-at-intro) .ips-style-grid::-webkit-scrollbar,\n  .ips-estimator:not(.ips-at-intro) .ips-scale-grid::-webkit-scrollbar,\n  .ips-estimator:not(.ips-at-intro) .ips-timing-grid::-webkit-scrollbar{display:none}\n\n  \/* Setting: two equal photographic panels fill the stage. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-choice-grid{\n    grid-template-rows:repeat(2,minmax(0,1fr));\n    gap:9px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-choice{\n    height:auto;\n    min-height:0;\n    border-radius:17px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-choice-body{padding:15px 16px}\n  .ips-estimator:not(.ips-at-intro) .ips-choice-name{font-size:1.2rem}\n  .ips-estimator:not(.ips-at-intro) .ips-choice-desc{font-size:.83rem;line-height:1.35}\n  .ips-estimator:not(.ips-at-intro) .ips-check{width:25px;height:25px}\n\n  \/* Build: keep compact type tabs, then show four square project\n     previews in a two-column mobile grid. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-build-wrap{gap:8px}\n  .ips-estimator:not(.ips-at-intro) .ips-build-tabs{gap:6px}\n  .ips-estimator:not(.ips-at-intro) .ips-build-tab{\n    min-height:46px;\n    padding:8px 4px;\n    font-size:.8rem;\n    border-radius:11px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-build-panel{\n    flex:1 1 auto;\n    min-height:0;\n    grid-template-rows:auto minmax(120px,1fr);\n    gap:10px;\n    padding:12px;\n    border-radius:17px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-build-info-eyebrow{font-size:.67rem;margin-bottom:3px}\n  .ips-estimator:not(.ips-at-intro) .ips-build-info-name{font-size:1.24rem;margin-bottom:4px}\n  .ips-estimator:not(.ips-at-intro) .ips-build-info-desc{\n    font-size:.81rem;\n    line-height:1.34;\n    margin-bottom:8px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-build-info-action{\n    min-height:38px;\n    padding:8px 12px;\n    font-size:.78rem;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-build-gallery{\n    grid-template-columns:repeat(2,minmax(0,1fr));\n    grid-template-rows:repeat(2,minmax(0,1fr));\n    width:100%;\n    min-height:0;\n    height:auto;\n    aspect-ratio:1 \/ 1;\n    align-self:start;\n    gap:8px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-gallery-tile{\n    min-height:0;\n    height:100%;\n    border-radius:12px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-gallery-more{font-size:.68rem}\n\n  \/* Style: three equal-height visual choices use the whole stage. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-style-grid{\n    grid-template-rows:repeat(3,minmax(0,1fr));\n    gap:9px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-style-card{\n    height:auto;\n    min-height:0;\n    border-radius:17px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-style-body{padding:14px 16px}\n  .ips-estimator:not(.ips-at-intro) .ips-style-name{font-size:1.16rem;margin-bottom:3px}\n  .ips-estimator:not(.ips-at-intro) .ips-style-desc{\n    -webkit-line-clamp:3;\n    font-size:.79rem;\n    line-height:1.32;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-style-check{\n    top:11px;right:11px;\n    width:25px;height:25px;\n  }\n\n  \/* Scale: the information panel stays content-sized; the photograph\n     becomes the flexible visual anchor for the rest of the screen. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-scale-grid{\n    grid-template-rows:auto minmax(190px,1fr);\n    gap:9px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-scale-panel{\n    padding:15px 20px;\n    border-radius:17px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-scale-row{margin-bottom:6px}\n  .ips-estimator:not(.ips-at-intro) .ips-scale-row h3{font-size:.7rem}\n  .ips-estimator:not(.ips-at-intro) .ips-scale-val{font-size:1.58rem}\n  .ips-estimator:not(.ips-at-intro) .ips-scale-desc{\n    margin-top:10px;\n    font-size:.84rem;\n    line-height:1.36;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-scale-photo{\n    height:auto;\n    min-height:190px;\n    max-height:none;\n    border-radius:17px;\n  }\n\n  \/* Readiness: each decision gets a generous quarter of the stage. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-timing-grid{\n    grid-template-rows:repeat(2,minmax(0,1fr));\n    gap:9px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-card{border-radius:16px}\n  .ips-estimator:not(.ips-at-intro) .ips-timing-card-inner{\n    height:100%;\n    min-height:0;\n    align-items:flex-start;\n    gap:8px;\n    padding:14px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-label{font-size:1.04rem;line-height:1.14}\n  .ips-estimator:not(.ips-at-intro) .ips-timing-copy span{font-size:.77rem;line-height:1.34}\n  .ips-estimator:not(.ips-at-intro) .ips-timing-radio{width:22px;height:22px}\n\n  \/* Contact is content-led rather than image-led, so use the available\n     room for larger tap targets and clearer form rhythm. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view{padding-bottom:12px}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view .ips-title{font-size:1.62rem}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view .ips-lead{font-size:.82rem;line-height:1.34}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-grid{\n    flex:1 1 auto;\n    min-height:0;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-form.compact{\n    height:100%;\n    min-height:0;\n    display:flex;\n    flex-direction:column;\n    padding:12px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-form-grid{\n    flex:1 1 auto;\n    align-content:space-evenly;\n    gap:8px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-field{gap:3px}\n  .ips-estimator:not(.ips-at-intro) .ips-field-label{font-size:.72rem}\n  .ips-estimator:not(.ips-at-intro) .ips-form.compact .ips-input,\n  .ips-estimator:not(.ips-at-intro) .ips-form.compact .ips-select{\n    min-height:44px;\n    padding:9px 11px;\n    font-size:.82rem !important;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-contact-actions{\n    margin-top:auto;\n    padding-top:8px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-contact-actions .ips-btn{min-height:48px;font-size:.88rem}\n}\n\n\/* On genuinely short screens, maintain the anchored controls and allow\n   only the content stage to scroll. Minimums keep choices comfortably\n   tappable rather than shrinking them indefinitely. *\/\n@media (max-width:620px) and (max-height:660px){\n  .ips-estimator:not(.ips-at-intro) .ips-choice-grid{grid-template-rows:repeat(2,minmax(140px,1fr))}\n  .ips-estimator:not(.ips-at-intro) .ips-style-grid{grid-template-rows:repeat(3,minmax(112px,1fr))}\n  .ips-estimator:not(.ips-at-intro) .ips-timing-grid{grid-template-rows:repeat(2,minmax(112px,1fr))}\n  .ips-estimator:not(.ips-at-intro) .ips-build-panel{grid-template-rows:auto minmax(105px,1fr)}\n  .ips-estimator:not(.ips-at-intro) .ips-build-gallery{min-height:105px}\n  .ips-estimator:not(.ips-at-intro) .ips-scale-grid{grid-template-rows:auto minmax(160px,1fr)}\n  .ips-estimator:not(.ips-at-intro) .ips-scale-photo{min-height:160px}\n}\n\n\/* Smaller phones keep the same app shell, but use a single-column\n   contact form with contained scrolling rather than cramped inputs. *\/\n@media (max-width:360px){\n  .ips-estimator:not(.ips-at-intro) .ips-form-grid{grid-template-columns:1fr}\n  .ips-estimator:not(.ips-at-intro) .ips-form-grid>.ips-field:nth-child(5){grid-column:auto}\n}\n\n\/* Short landscape-like mobile viewports retain the fixed app surface;\n   optional supporting copy yields before interactive controls do. *\/\n@media (max-width:620px) and (max-height:560px){\n  .ips-estimator:not(.ips-at-intro) .ips-step-head .ips-lead{display:none}\n  .ips-estimator:not(.ips-at-intro) .ips-style-desc{display:none}\n  .ips-estimator:not(.ips-at-intro) .ips-choice{min-height:118px}\n}\n\n\/* \u2500\u2500\u2500 v15 premium readiness + compact final step \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n@media (max-width:620px){\n  \/* Readiness choices are presented as four centred decisions rather\n     than form-like rows. The selected state is warm and restrained. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-timing-card{\n    border-color:rgba(255,255,255,.15);\n    background:linear-gradient(150deg,rgba(255,255,255,.09),rgba(255,255,255,.035));\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-card-inner{\n    position:relative;\n    align-items:center;\n    justify-content:center;\n    text-align:center;\n    padding:18px 15px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-copy{\n    align-items:center;\n    justify-content:center;\n    gap:7px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-label{\n    max-width:14ch;\n    font-size:1.16rem;\n    line-height:1.12;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-copy span{\n    max-width:20ch;\n    font-size:.79rem;\n    line-height:1.34;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-radio{\n    position:absolute;\n    top:12px;\n    right:12px;\n    width:22px;\n    height:22px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-card.sel{\n    border-color:rgba(208,180,118,.82);\n    background:linear-gradient(150deg,rgba(208,180,118,.20),rgba(208,180,118,.08));\n    box-shadow:inset 0 0 0 1px rgba(208,180,118,.14),0 12px 28px rgba(0,0,0,.16);\n  }\n\n  \/* Restore the selections as a compact briefing strip above the form. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view{\n    padding-top:6px;\n    padding-bottom:9px;\n    overflow-y:auto;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view .ips-step-head{margin-bottom:7px}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view .ips-eyebrow{margin-bottom:3px}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view .ips-title{\n    font-size:1.52rem;\n    margin-bottom:3px !important;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view .ips-lead{\n    font-size:.77rem;\n    line-height:1.28;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-contact-grid,\n  .ips-estimator:not(.ips-at-intro) .ips-contact-grid.compact{\n    display:grid;\n    grid-template-columns:1fr;\n    grid-template-rows:auto minmax(0,1fr);\n    gap:7px;\n    min-height:0;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-summary{\n    display:block;\n    position:static;\n    padding:8px 9px;\n    border-radius:13px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-summary-title{\n    margin-bottom:5px;\n    font-size:.58rem;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-summary-compact{\n    display:grid;\n    grid-template-columns:repeat(2,minmax(0,1fr));\n    gap:4px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-summary-chip{\n    min-width:0;\n    padding:5px 7px;\n    border-radius:9px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-summary-chip:last-child{grid-column:1\/-1}\n  .ips-estimator:not(.ips-at-intro) .ips-summary-chip span:first-child{\n    margin-bottom:2px;\n    font-size:.52rem;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-summary-chip span:last-child{\n    font-size:.67rem;\n    line-height:1.18;\n  }\n\n  \/* Remove v14's space-even distribution. Fields now sit in a tight,\n     predictable grid, with a compact notes field restored below them. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-form.compact{\n    height:100%;\n    padding:9px;\n    overflow-y:auto;\n    scrollbar-width:none;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-form.compact::-webkit-scrollbar{display:none}\n  .ips-estimator:not(.ips-at-intro) .ips-form-grid{\n    flex:0 0 auto;\n    align-content:start;\n    column-gap:7px;\n    row-gap:6px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-field{gap:2px}\n  .ips-estimator:not(.ips-at-intro) .ips-field-label{\n    font-size:.67rem;\n    line-height:1.16;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-form.compact .ips-input,\n  .ips-estimator:not(.ips-at-intro) .ips-form.compact .ips-select{\n    min-height:40px;\n    padding:7px 9px;\n    font-size:.78rem !important;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view .ips-field:has(.ips-textarea){display:grid}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view .ips-textarea{\n    display:block;\n    min-height:62px;\n    max-height:62px;\n    resize:none;\n    padding:8px 9px;\n    font-size:.78rem !important;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-privacy{\n    margin-top:5px;\n    font-size:.61rem;\n    color:rgba(255,255,255,.60);\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-contact-actions{\n    margin-top:5px;\n    padding-top:4px;\n    gap:7px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-contact-actions .ips-btn{\n    min-height:44px;\n    font-size:.82rem;\n  }\n}\n\n\/* \u2500\u2500\u2500 v16 readability refinement \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n@media (max-width:620px){\n  .ips-estimator:not(.ips-at-intro) .ips-timing-label{\n    max-width:16ch;\n    font-size:1.28rem;\n    line-height:1.1;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-copy span{\n    max-width:21ch;\n    font-size:.86rem;\n    line-height:1.36;\n  }\n}\n\n\/* \u2500\u2500\u2500 v18 tablet layout: 621\u20131180px \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   A capped, centred stage uses tablet space without stretching every\n   panel to the full height of a tall portrait screen. Type scales with\n   the available width and images crop through cover sizing. *\/\n@media (min-width:621px) and (max-width:1180px){\n  .ips-estimator:not(.ips-at-intro){\n    height:100svh;\n    height:100dvh;\n    min-height:0;\n    overflow:hidden;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-shell{\n    height:100svh;\n    height:100dvh;\n    min-height:0;\n    padding:82px 18px 18px;\n    align-items:center;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-card{\n    height:min(920px,calc(100dvh - 112px));\n    min-height:0;\n    max-height:calc(100dvh - 112px);\n    border-radius:24px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-card-head{\n    min-height:54px;\n    padding:12px 20px 0;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-prog-label strong{font-size:clamp(.94rem,1.45vw,1.04rem)}\n  .ips-estimator:not(.ips-at-intro) .ips-prog-label span{font-size:clamp(.73rem,1.1vw,.8rem)}\n  .ips-estimator:not(.ips-at-intro) .ips-prog-track{\n    flex:1 1 auto;\n    max-width:420px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-viewport{\n    flex:1 1 auto;\n    min-height:0;\n    overflow:hidden;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-track{height:100%;min-height:0}\n  .ips-estimator:not(.ips-at-intro) .ips-view{\n    height:100%;\n    min-height:0;\n    padding:12px 20px;\n    overflow:hidden;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-view:not(.ips-contact-view){\n    display:grid;\n    grid-template-rows:auto minmax(0,1fr) 64px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-step-head{margin-bottom:11px}\n  .ips-estimator:not(.ips-at-intro) .ips-title{\n    font-size:clamp(2.05rem,3.6vw,2.8rem);\n    line-height:1.04;\n    margin-bottom:7px !important;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-lead{\n    font-size:clamp(1rem,1.9vw,1.2rem);\n    line-height:1.42;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-actions{\n    position:static;\n    align-self:end;\n    flex-wrap:nowrap;\n    gap:12px;\n    min-height:58px;\n    margin:0 !important;\n    padding:8px 0 0 !important;\n    background:linear-gradient(180deg,rgba(24,16,10,0),rgba(24,16,10,.94) 38%);\n    border-top:0;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-actions .ips-btn{\n    flex:1 1 0;\n    min-width:0;\n    min-height:50px;\n    padding:10px 24px;\n    font-size:1rem;\n  }\n\n  .ips-estimator:not(.ips-at-intro) .ips-choice-grid,\n  .ips-estimator:not(.ips-at-intro) .ips-build-wrap,\n  .ips-estimator:not(.ips-at-intro) .ips-style-grid,\n  .ips-estimator:not(.ips-at-intro) .ips-scale-grid,\n  .ips-estimator:not(.ips-at-intro) .ips-timing-grid{\n    height:100%;\n    min-height:0;\n    overflow-y:auto;\n    overscroll-behavior:contain;\n    scrollbar-width:none;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-choice-grid::-webkit-scrollbar,\n  .ips-estimator:not(.ips-at-intro) .ips-build-wrap::-webkit-scrollbar,\n  .ips-estimator:not(.ips-at-intro) .ips-style-grid::-webkit-scrollbar,\n  .ips-estimator:not(.ips-at-intro) .ips-scale-grid::-webkit-scrollbar,\n  .ips-estimator:not(.ips-at-intro) .ips-timing-grid::-webkit-scrollbar{display:none}\n\n  \/* Stable image containers prevent wide tablet cards from distorting media. *\/\n  .ips-estimator .ips-choice-bg,\n  .ips-estimator .ips-style-bg,\n  .ips-estimator .ips-gallery-tile{\n    background-size:cover;\n    background-position:center;\n    background-repeat:no-repeat;\n  }\n  .ips-estimator .ips-scale-photo img,\n  .ips-estimator .ips-lb-tile img{\n    width:100%;\n    height:100%;\n    object-fit:cover;\n    object-position:center;\n  }\n\n  \/* Setting: preserve the strong two-panel composition. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-choice-grid{\n    grid-template-columns:repeat(2,minmax(0,1fr));\n    grid-template-rows:1fr;\n    gap:14px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-choice{\n    height:auto;\n    min-height:0;\n    border-radius:20px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-choice-body{padding:20px}\n  .ips-estimator:not(.ips-at-intro) .ips-choice-name{font-size:clamp(1.45rem,2.35vw,1.75rem)}\n  .ips-estimator:not(.ips-at-intro) .ips-choice-desc{font-size:clamp(.96rem,1.5vw,1.08rem);line-height:1.46}\n\n  \/* Build: tabs remain compact while details and examples share the stage. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-build-wrap{gap:10px}\n  .ips-estimator:not(.ips-at-intro) .ips-build-panel{\n    flex:1 1 auto;\n    min-height:0;\n    grid-template-columns:minmax(210px,.82fr) minmax(280px,1.18fr);\n    grid-template-rows:1fr;\n    gap:14px;\n    padding:14px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-build-info{justify-content:center}\n  .ips-estimator:not(.ips-at-intro) .ips-build-tab{font-size:clamp(.92rem,1.45vw,1.05rem)}\n  .ips-estimator:not(.ips-at-intro) .ips-build-info-name{font-size:clamp(1.7rem,3vw,2.2rem)}\n  .ips-estimator:not(.ips-at-intro) .ips-build-info-desc{font-size:clamp(.96rem,1.5vw,1.08rem)}\n  .ips-estimator:not(.ips-at-intro) .ips-build-info-action{font-size:clamp(.9rem,1.35vw,1rem)}\n  .ips-estimator:not(.ips-at-intro) .ips-build-gallery{\n    height:100%;\n    min-height:0;\n    grid-template-columns:repeat(2,minmax(0,1fr));\n    grid-template-rows:repeat(2,minmax(0,1fr));\n    gap:8px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-gallery-tile{min-height:0;height:auto}\n\n  \/* Style: three proportional cards retain their image composition. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-style-grid{\n    grid-template-columns:repeat(3,minmax(0,1fr));\n    grid-template-rows:1fr;\n    gap:12px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-style-card{\n    height:auto;\n    min-height:0;\n    border-radius:20px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-style-overlay{\n    background:linear-gradient(180deg,rgba(8,4,2,0) 40%,rgba(8,4,2,.22) 66%,rgba(8,4,2,.84) 100%);\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-style-body{padding:24px}\n  .ips-estimator:not(.ips-at-intro) .ips-style-name{\n    font-size:clamp(1.65rem,2.7vw,2.05rem);\n    line-height:1.08;\n    margin-bottom:9px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-style-desc{\n    max-width:31ch;\n    font-size:clamp(.98rem,1.6vw,1.14rem);\n    line-height:1.46;\n  }\n\n  \/* Scale: information and image remain side by side at tablet widths. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-scale-grid{\n    grid-template-columns:minmax(260px,.9fr) minmax(0,1.1fr);\n    grid-template-rows:1fr;\n    gap:14px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-scale-panel,\n  .ips-estimator:not(.ips-at-intro) .ips-scale-photo{\n    height:auto;\n    min-height:0;\n    border-radius:20px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-scale-panel{\n    justify-content:center;\n    padding:clamp(28px,3.2vw,42px);\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-scale-row{gap:9px;margin-bottom:14px}\n  .ips-estimator:not(.ips-at-intro) .ips-scale-row h3{font-size:clamp(.9rem,1.4vw,1.04rem)}\n  .ips-estimator:not(.ips-at-intro) .ips-scale-val{font-size:clamp(2.65rem,4.4vw,3.4rem)}\n  .ips-estimator:not(.ips-at-intro) .ips-scale-slider{margin:4px 0 0!important}\n  .ips-estimator:not(.ips-at-intro) .ips-scale-ticks{font-size:clamp(.82rem,1.45vw,.96rem)}\n  .ips-estimator:not(.ips-at-intro) .ips-scale-desc{\n    max-width:31ch;\n    margin-top:22px;\n    font-size:clamp(1.12rem,1.85vw,1.3rem);\n    line-height:1.52;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-scale-photo{max-height:none}\n\n  \/* Readiness: retain the centred format and use a spacious 2 \u00d7 2 grid. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-timing-grid{\n    grid-template-columns:repeat(2,minmax(0,1fr));\n    grid-template-rows:repeat(2,minmax(0,1fr));\n    gap:12px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-card{\n    border-radius:18px;\n    background:rgba(255,255,255,.075);\n    border-color:rgba(255,255,255,.16);\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-card.sel{\n    background:rgba(208,180,118,.16);\n    border-color:rgba(208,180,118,.88);\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-card-inner{\n    position:relative;\n    height:100%;\n    min-height:0;\n    align-items:center;\n    justify-content:center;\n    text-align:center;\n    padding:24px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-copy{\n    align-items:center;\n    justify-content:center;\n    gap:8px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-label{\n    max-width:18ch;\n    font-size:clamp(1.42rem,2.8vw,1.85rem);\n    line-height:1.12;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-copy span{\n    max-width:34ch;\n    font-size:clamp(.92rem,1.5vw,1.05rem);\n    line-height:1.42;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-timing-radio{\n    position:absolute;\n    top:15px;\n    right:15px;\n    width:24px;\n    height:24px;\n  }\n\n  \/* Contact: selections and details remain visible together on tablets. *\/\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view{\n    display:flex;\n    flex-direction:column;\n    overflow-y:auto;\n  }\n  .ips-estimator.ips-at-contact .ips-card{\n    height:auto;\n    max-height:calc(100dvh - 112px);\n  }\n  .ips-estimator.ips-at-contact .ips-viewport,\n  .ips-estimator.ips-at-contact .ips-track,\n  .ips-estimator.ips-at-contact .ips-contact-view{height:auto}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view .ips-step-head{margin-bottom:12px}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view .ips-title{font-size:clamp(2.15rem,3.5vw,2.65rem)}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view .ips-lead{font-size:clamp(.98rem,1.55vw,1.1rem);line-height:1.45}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-grid,\n  .ips-estimator:not(.ips-at-intro) .ips-contact-grid.compact{\n    display:grid;\n    grid-template-columns:minmax(190px,.74fr) minmax(320px,1.26fr);\n    gap:12px;\n    flex:0 0 auto;\n    min-height:auto;\n    align-items:stretch;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-summary{\n    display:block;\n    position:static;\n    height:auto;\n    padding:18px;\n    overflow:visible;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-summary-compact{\n    grid-template-columns:1fr;\n    gap:7px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-form.compact{\n    height:auto;\n    min-height:auto;\n    padding:18px;\n    overflow:visible;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-summary-title{font-size:.76rem}\n  .ips-estimator:not(.ips-at-intro) .ips-summary-chip span:first-child{font-size:clamp(.7rem,1.1vw,.78rem)}\n  .ips-estimator:not(.ips-at-intro) .ips-summary-chip span:last-child{font-size:clamp(.92rem,1.45vw,1.06rem)}\n  .ips-estimator:not(.ips-at-intro) .ips-field-label{font-size:clamp(.82rem,1.25vw,.92rem)}\n  .ips-estimator:not(.ips-at-intro) .ips-form.compact .ips-input,\n  .ips-estimator:not(.ips-at-intro) .ips-form.compact .ips-select,\n  .ips-estimator:not(.ips-at-intro) .ips-form.compact .ips-textarea{font-size:1rem}\n  .ips-estimator:not(.ips-at-intro) .ips-form-grid{\n    grid-template-columns:repeat(2,minmax(0,1fr));\n    gap:8px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view .ips-field:has(.ips-textarea){display:grid}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-view .ips-textarea{\n    display:block;\n    min-height:72px;\n    resize:none;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-contact-actions{\n    flex-direction:row;\n    align-items:stretch;\n    gap:10px;\n    margin-top:8px;\n    padding-top:6px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-contact-actions .ips-btn{\n    width:auto;\n    min-width:0;\n    min-height:50px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-contact-actions .ips-btn-ghost{flex:0 0 34%}\n  .ips-estimator:not(.ips-at-intro) .ips-contact-actions .ips-contact-submit{\n    order:initial;\n    flex:1 1 auto;\n  }\n}\n\n\/* Portrait and compact tablets use two rows of build tabs. *\/\n@media (min-width:621px) and (max-width:900px){\n  .ips-estimator:not(.ips-at-intro) .ips-build-tabs{\n    grid-auto-flow:row;\n    grid-auto-columns:unset;\n    grid-template-columns:repeat(3,minmax(0,1fr));\n    gap:7px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-build-tab{\n    min-height:44px;\n    padding:8px 6px;\n    font-size:.85rem;\n  }\n}\n\n\/* Wider tablets can show the summary chips in two columns. *\/\n@media (min-width:901px) and (max-width:1180px){\n  .ips-estimator:not(.ips-at-intro) .ips-summary-compact{\n    grid-template-columns:repeat(2,minmax(0,1fr));\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-summary-chip:last-child{grid-column:1\/-1}\n}\n\n\/* Short tablet landscape views keep navigation fixed and let only the\n   central stage scroll when its minimum comfortable size is exceeded. *\/\n@media (min-width:621px) and (max-width:1180px) and (max-height:720px){\n  .ips-estimator:not(.ips-at-intro) .ips-shell{padding-top:76px;padding-bottom:12px}\n  .ips-estimator:not(.ips-at-intro) .ips-card{\n    height:calc(100dvh - 88px);\n    max-height:calc(100dvh - 88px);\n  }\n  .ips-estimator.ips-at-contact .ips-card{\n    height:auto;\n    max-height:calc(100dvh - 88px);\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-card-head{min-height:50px;padding-top:9px}\n  .ips-estimator:not(.ips-at-intro) .ips-view:not(.ips-contact-view){\n    grid-template-rows:auto minmax(0,1fr) 58px;\n  }\n  .ips-estimator:not(.ips-at-intro) .ips-title{font-size:1.72rem}\n  .ips-estimator:not(.ips-at-intro) .ips-lead{font-size:.88rem}\n  .ips-estimator:not(.ips-at-intro) .ips-actions{min-height:54px}\n}\n\n\/* \u2500\u2500\u2500 v19 view-specific constraints \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   Desktop style choices receive a taller photographic stage. Slider\n   stops use five dedicated cells. Extra-tall phone previews and the\n   final form size to their content instead of stretching indefinitely. *\/\n@media (min-width:1181px) and (min-height:760px){\n  .ips-estimator.ips-at-style .ips-card{\n    height:min(820px,calc(100dvh - 124px));\n    min-height:620px;\n  }\n  .ips-estimator.ips-at-style .ips-viewport{\n    flex:1 1 auto;\n    min-height:0;\n    overflow:hidden;\n  }\n  .ips-estimator.ips-at-style .ips-track,\n  .ips-estimator.ips-at-style .ips-view{height:100%;min-height:0}\n  .ips-estimator.ips-at-style .ips-view{\n    display:grid;\n    grid-template-rows:auto minmax(0,1fr) auto;\n    overflow:hidden;\n  }\n  .ips-estimator.ips-at-style .ips-style-grid{\n    height:100%;\n    min-height:0;\n  }\n  .ips-estimator.ips-at-style .ips-style-card{\n    height:auto;\n    min-height:0;\n  }\n  .ips-estimator.ips-at-style .ips-style-overlay{\n    background:linear-gradient(180deg,rgba(8,4,2,0) 42%,rgba(8,4,2,.20) 67%,rgba(8,4,2,.84) 100%);\n  }\n  .ips-estimator.ips-at-style .ips-style-body{padding:24px}\n  .ips-estimator.ips-at-style .ips-style-name{\n    font-size:clamp(1.65rem,2vw,2rem);\n    line-height:1.08;\n    margin-bottom:8px;\n  }\n  .ips-estimator.ips-at-style .ips-style-desc{\n    max-width:31ch;\n    font-size:clamp(.98rem,1.15vw,1.1rem);\n    line-height:1.46;\n  }\n}\n\n\/* At compact-tablet widths, a half-width scale panel does not leave\n   enough breathing room for five translated labels. Stack the scale\n   controls above the photograph until the full two-column layout has\n   a genuinely comfortable control width. *\/\n@media (min-width:621px) and (max-width:960px){\n  .ips-estimator.ips-at-scale .ips-scale-grid{\n    grid-template-columns:1fr;\n    grid-template-rows:auto minmax(250px,1fr);\n    gap:12px;\n  }\n  .ips-estimator.ips-at-scale .ips-scale-panel{\n    height:auto;\n    min-height:0;\n    justify-content:flex-start;\n    padding:22px 26px;\n  }\n  .ips-estimator.ips-at-scale .ips-scale-row{margin-bottom:10px}\n  .ips-estimator.ips-at-scale .ips-scale-val{font-size:clamp(2.25rem,5vw,2.8rem)}\n  .ips-estimator.ips-at-scale .ips-scale-desc{\n    max-width:none;\n    margin-top:14px;\n    font-size:clamp(1rem,2.1vw,1.14rem);\n  }\n  .ips-estimator.ips-at-scale .ips-scale-photo{\n    height:auto;\n    min-height:250px;\n    max-height:none;\n  }\n}\n\n\/* In the side-by-side scale layout, the controls occupy the fixed\n   middle row. The description has its own row below, so line wrapping\n   can grow downward without re-centring the selector group. *\/\n@media (min-width:961px){\n  .ips-estimator.ips-at-scale .ips-scale-panel{\n    display:grid;\n    grid-template-columns:minmax(0,1fr);\n    grid-template-rows:minmax(0,1fr) auto minmax(0,1fr);\n    align-items:stretch;\n    justify-content:stretch;\n  }\n  .ips-estimator.ips-at-scale .ips-scale-controls{\n    grid-row:2;\n    width:100%;\n    align-self:center;\n  }\n  .ips-estimator.ips-at-scale .ips-scale-desc{\n    grid-row:3;\n    min-height:4.5em;\n    align-self:start;\n  }\n}\n\n@media (max-width:620px){\n  #ipsEstimator.ips-at-scale .ips-scale-desc.ips-scale-copy-stack{min-height:4.5em!important}\n  .ips-estimator.ips-at-contact .ips-shell{align-items:flex-start}\n  \/* The final-step title already communicates context. Removing the duplicate\n     progress header reclaims the space normally covered by mobile browser UI. *\/\n  .ips-estimator.ips-at-contact .ips-card-head{display:none}\n  .ips-estimator.ips-at-contact .ips-card{\n    height:100%;\n    min-height:0;\n    max-height:100%;\n  }\n  .ips-estimator.ips-at-contact .ips-viewport{\n    flex:1 1 auto;\n    height:100%;\n    min-height:0;\n    overflow:hidden;\n  }\n  .ips-estimator.ips-at-contact .ips-track{height:100%;min-height:0}\n  .ips-estimator.ips-at-contact .ips-contact-view{\n    height:100%;\n    min-height:0;\n    max-height:none;\n    overflow-y:auto;\n    overscroll-behavior-y:contain;\n    padding-bottom:18px;\n  }\n  .ips-estimator.ips-at-contact .ips-contact-grid,\n  .ips-estimator.ips-at-contact .ips-contact-grid.compact{\n    grid-template-rows:auto auto;\n    gap:12px;\n    flex:0 0 auto;\n    min-height:auto;\n  }\n  .ips-estimator.ips-at-contact .ips-summary{padding:10px 11px}\n  .ips-estimator.ips-at-contact .ips-summary-title{margin-bottom:7px;font-size:.68rem}\n  .ips-estimator.ips-at-contact .ips-summary-chip{padding:7px 9px}\n  .ips-estimator.ips-at-contact .ips-summary-chip span:first-child{font-size:.6rem;line-height:1.12;margin-bottom:3px}\n  .ips-estimator.ips-at-contact .ips-summary-chip span:last-child{font-size:.78rem;line-height:1.18}\n  .ips-estimator.ips-at-contact .ips-form.compact{\n    display:block;\n    height:auto;\n    min-height:0;\n    overflow:visible;\n  }\n  .ips-estimator.ips-at-contact .ips-form-grid{\n    flex:0 0 auto;\n    align-content:start;\n  }\n  .ips-estimator.ips-at-contact .ips-contact-actions{margin-top:5px}\n}\n\n@media (max-width:620px) and (min-height:980px){\n  .ips-estimator.ips-at-scale .ips-shell{align-items:flex-start}\n  .ips-estimator.ips-at-scale .ips-card{\n    height:auto;\n    min-height:0;\n    max-height:none;\n  }\n  .ips-estimator.ips-at-scale .ips-viewport{\n    flex:0 0 auto;\n    height:auto;\n    overflow:visible;\n  }\n  .ips-estimator.ips-at-scale .ips-track,\n  .ips-estimator.ips-at-scale .ips-view{height:auto}\n  .ips-estimator.ips-at-scale .ips-view:not(.ips-contact-view){\n    grid-template-rows:auto auto 58px;\n    overflow:visible;\n  }\n  .ips-estimator.ips-at-scale .ips-scale-grid{\n    height:auto;\n    overflow:visible;\n    grid-template-rows:auto clamp(300px,44dvh,500px);\n  }\n  .ips-estimator.ips-at-scale .ips-scale-photo{\n    height:clamp(300px,44dvh,500px);\n    min-height:300px;\n    max-height:500px;\n  }\n}\n\n\/* \u2500\u2500\u2500 Live-site CSS bleed defence \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n   Elementor's global stylesheet can override font-family and\n   text-transform on arbitrary descendants. These rules use\n   !important only on properties that Elementor is known to clobber.\n   Eyebrow elements intentionally keep text-transform:uppercase so\n   they are excluded here. \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n\n\/* Block Elementor text-transform on non-eyebrow elements *\/\n.ips-estimator .ips-title,\n.ips-estimator .ips-display,\n.ips-estimator .ips-lead,\n.ips-estimator .ips-choice-name,\n.ips-estimator .ips-choice-desc,\n.ips-estimator .ips-build-info-name,\n.ips-estimator .ips-build-info-desc,\n.ips-estimator .ips-build-tab,\n.ips-estimator .ips-style-name,\n.ips-estimator .ips-style-desc,\n.ips-estimator .ips-timing-label,\n.ips-estimator .ips-timing-copy span,\n.ips-estimator .ips-scale-val,\n.ips-estimator .ips-scale-desc,\n.ips-estimator .ips-lightbox-name,\n.ips-estimator .ips-lightbox-desc,\n.ips-estimator .ips-prog-label strong,\n.ips-estimator .ips-prog-label span,\n.ips-estimator .ips-pill,\n.ips-estimator .ips-btn,\n.ips-estimator .ips-field-label,\n.ips-estimator .ips-input,\n.ips-estimator .ips-select,\n.ips-estimator .ips-textarea,\n.ips-estimator .ips-privacy {\n  text-transform: none !important;\n}\n\n\/* Block Elementor heading\/link colour on white-text elements *\/\n.ips-estimator .ips-choice-name,\n.ips-estimator .ips-style-name,\n.ips-estimator .ips-scale-val,\n.ips-estimator .ips-lightbox-name,\n.ips-estimator .ips-prog-label strong,\n.ips-estimator .ips-build-info-name {\n  color: #fff !important;\n}\n.ips-estimator .ips-choice-desc,\n.ips-estimator .ips-style-desc,\n.ips-estimator .ips-build-info-desc,\n.ips-estimator .ips-scale-desc,\n.ips-estimator .ips-lightbox-desc,\n.ips-estimator .ips-lead {\n  color: rgba(255,255,255,.82) !important;\n}\n\n\/* Ensure card body text stays above the DOM overlay divs *\/\n.ips-estimator .ips-choice-body {\n  position: absolute !important;\n  z-index: 1 !important;\n}\n.ips-estimator .ips-style-body {\n  position: absolute !important;\n  z-index: 1 !important;\n}\n\/* DOM overlay divs must be positioned \u2014 Elementor can't reset a real element *\/\n.ips-estimator .ips-choice-overlay,\n.ips-estimator .ips-style-overlay {\n  position: absolute !important;\n  inset: 0 !important;\n  pointer-events: none !important;\n  z-index: 0 !important;\n}\n\n\/* Ensure photo card containers stay positioned so ::after overlays render *\/\n.ips-estimator .ips-choice,\n.ips-estimator .ips-style-card {\n  position: relative !important;\n  overflow: hidden !important;\n}\n.ips-estimator .ips-choice-bg,\n.ips-estimator .ips-style-bg {\n  position: absolute !important;\n}\n.ips-estimator .ips-scale-photo {\n  position: relative !important;\n  overflow: hidden !important;\n}\n\n\/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\n\n\/* Keep the native location field consistently legible regardless of the\n   device or WordPress colour scheme. *\/\n#ipsEstimator .ips-select,\n#ipsEstimator .ips-select:focus{\n  color:#17130f !important;\n  -webkit-text-fill-color:#17130f !important;\n  background-color:#fff !important;\n  color-scheme:light !important;\n  opacity:1 !important;\n}\n#ipsEstimator .ips-select option{\n  color:#17130f !important;\n  -webkit-text-fill-color:#17130f !important;\n  background:#fff !important;\n}\n\n\/* iPhone Safari zooms the page when a focused form control computes below\n   16px. Keep controls at the native no-zoom threshold without disabling the\n   user's normal pinch-to-zoom accessibility gesture. *\/\n@media (max-width:620px){\n  \/* The scale slide is a fixed app surface. Its photo absorbs any height\n     reduction so the stage never becomes a second vertical scroller. *\/\n  #ipsEstimator.ips-at-scale .ips-scale-ticks{font-size:.64rem}\n  #ipsEstimator.ips-at-scale .ips-card{\n    height:100%;\n    min-height:0;\n    max-height:100%;\n  }\n  #ipsEstimator.ips-at-scale .ips-viewport,\n  #ipsEstimator.ips-at-scale .ips-track,\n  #ipsEstimator.ips-at-scale .ips-view{\n    height:100%;\n    min-height:0;\n    overflow:hidden;\n  }\n  #ipsEstimator.ips-at-scale .ips-view:not(.ips-contact-view){\n    grid-template-rows:auto minmax(0,1fr) 58px;\n  }\n  #ipsEstimator.ips-at-scale .ips-scale-grid{\n    height:100%;\n    min-height:0;\n    overflow:hidden;\n    grid-template-rows:auto minmax(0,1fr);\n  }\n  #ipsEstimator.ips-at-scale .ips-scale-photo{\n    height:100%;\n    min-height:0;\n    max-height:none;\n  }\n  #ipsEstimator.ips-at-contact .ips-input,\n  #ipsEstimator.ips-at-contact .ips-select,\n  #ipsEstimator.ips-at-contact .ips-textarea{\n    font-size:16px !important;\n    -webkit-text-size-adjust:100%;\n  }\n}\n\n\/* Standalone preview reset. The class sits on <html> in this concept file;\n   an Elementor widget embed should omit the document wrapper. *\/\n.ips-standalone,\n.ips-standalone body{\n  margin:0;padding:0;background:#120c08;\n  overflow-x:clip;overflow-y:auto;min-height:100%;\n}\n<\/style>\n<\/head>\n<body>\n\n\n<!-- Root wrapper \u2014 all styles are scoped under this class for Elementor. -->\n<!-- This is an English-specific tool. Keep client-side translation layers from\n     reprocessing its dynamic interface when it is embedded on another language page. -->\n<div class=\"ips-estimator ips-at-intro notranslate\" id=\"ipsEstimator\" lang=\"en\" translate=\"no\" data-wg-notranslate>\n\n  <!-- Stage background (cross-fades between steps) -->\n  <div class=\"ips-stage\" id=\"ipsStage\">\n    <div class=\"ips-stage-bg\" id=\"ipsStageBg\"><\/div>\n    <div class=\"ips-stage-bg-next\" id=\"ipsStageBgNext\"><\/div>\n    <div class=\"ips-stage-mask\"><\/div>\n  <\/div>\n\n  <!-- Floating top pills -->\n  <div class=\"ips-topbar\">\n    <div class=\"ips-brand\"><img decoding=\"async\" class=\"ips-brand-logo\" src=\"https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/06\/Logo-White-Letter-scaled.png\" alt=\"Interpool Spa\"><\/div>\n    <div class=\"ips-top-actions\">\n      <nav class=\"ips-language\" aria-label=\"Select estimator language\">\n        <a class=\"ips-lang\" href=\"\/th\/instant-estimate-th\/\" lang=\"th\" hreflang=\"th\" aria-label=\"Open the Thai estimator\">TH<\/a>\n        <a class=\"ips-lang is-active\" href=\"\/en\/instant-estimate-en\/\" lang=\"en\" hreflang=\"en\" aria-current=\"page\" aria-label=\"English estimator\">EN<\/a>\n      <\/nav>\n      <a class=\"ips-return\" href=\"\/en\/\" aria-label=\"Home\">\n        <svg class=\"ips-home-icon\" viewbox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M3 10.5 12 3l9 7.5\"><\/path><path d=\"M5 9.5V21h14V9.5\"><\/path><path d=\"M9 21v-7h6v7\"><\/path><\/svg>\n        <span class=\"ips-return-desktop\">Back to site<\/span><span class=\"ips-return-mobile\">Home<\/span>\n      <\/a>\n    <\/div>\n  <\/div>\n\n  <!-- Centred glass card -->\n  <div class=\"ips-shell\">\n    <div class=\"ips-card\">\n      <div class=\"ips-card-head\">\n        <div class=\"ips-prog-label\">\n          <strong id=\"ipsProgLabel\">Welcome<\/strong>\n          <span id=\"ipsProgMeta\">Step 1 of 7<\/span>\n        <\/div>\n        <div class=\"ips-prog-track\"><div class=\"ips-prog-fill\" id=\"ipsProgFill\"><\/div><\/div>\n      <\/div>\n      <div class=\"ips-viewport\">\n        <div class=\"ips-track\" id=\"ipsTrack\"><\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <!-- Gallery lightbox -->\n  <div class=\"ips-lightbox\" id=\"ipsLightbox\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"ipsLbName\">\n    <div class=\"ips-lightbox-inner\">\n      <div class=\"ips-lightbox-top\">\n        <div>\n          <div class=\"ips-lightbox-name\" id=\"ipsLbName\"><\/div>\n          <div class=\"ips-lightbox-desc\" id=\"ipsLbDesc\"><\/div>\n        <\/div>\n        <button class=\"ips-lightbox-close\" id=\"ipsLbClose\" aria-label=\"Close gallery\">\u2715<\/button>\n      <\/div>\n      <div class=\"ips-lightbox-grid\" id=\"ipsLbGrid\"><\/div>\n      <div class=\"ips-lightbox-footer\">\n        <button class=\"ips-btn ips-lb-back-btn\" id=\"ipsLbBack\" type=\"button\">\u2190 Back<\/button>\n        <button class=\"ips-btn ips-lb-select-btn\" id=\"ipsLbSelect\" type=\"button\">I Want This<\/button>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <!-- Result modal -->\n  <div class=\"ips-result\" id=\"ipsResult\" role=\"dialog\" aria-modal=\"true\">\n    <div class=\"ips-result-card\">\n      <div class=\"ips-result-head\">\n        <div>\n          <div class=\"ips-result-eyebrow\" id=\"ipsResultEyebrow\">Your personalised estimate<\/div>\n          <h3 id=\"ipsResultTitle\">Let's bring your vision to life.<\/h3>\n        <\/div>\n        <button class=\"ips-result-close\" id=\"ipsResultClose\" aria-label=\"Close\">\u2715<\/button>\n      <\/div>\n      <div class=\"ips-result-grid\">\n        <div class=\"ips-result-box\">\n          <div class=\"ips-result-box-label\" id=\"ipsPriceLabel\">Estimated investment range<\/div>\n          <div class=\"ips-price\" id=\"ipsPrice\">\u2014<\/div>\n          <div class=\"ips-price-caveat\" id=\"ipsPriceCaveat\">This is a planning guide to help you budget with confidence. Final pricing is confirmed after a site visit, design consultation, and review of your property's specific requirements.<\/div>\n          <a class=\"ips-btn ips-btn-line ips-line-mobile-cta\" id=\"ipsLineLinkMobile\" href=\"https:\/\/line.me\/R\/ti\/p\/@interpoolspa\" target=\"_blank\" rel=\"noopener\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewbox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M12 2C6.48 2 2 5.83 2 10.43c0 4.07 3.42 7.49 8.05 8.14.31.07.74.21.85.48.1.25.06.63.03.88l-.14.83c-.04.25-.2.97.85.53s5.61-3.3 7.66-5.65h-.01C21.36 13.36 22 11.96 22 10.43 22 5.83 17.52 2 12 2zm-3.08 11.11h-2.2a.5.5 0 0 1-.5-.5V8.56a.5.5 0 0 1 1 0v3.55h1.7a.5.5 0 1 1 0 1zm1.62-.5a.5.5 0 0 1-1 0V8.56a.5.5 0 0 1 1 0v4.05zm4.14 0a.5.5 0 0 1-.34.47.5.5 0 0 1-.56-.12L11.97 10v2.61a.5.5 0 0 1-1 0V8.56a.5.5 0 0 1 .34-.47.5.5 0 0 1 .56.12l1.81 2.46V8.56a.5.5 0 0 1 1 0v4.05zm3.12-2.85a.5.5 0 1 1 0 1h-1.7v.85h1.7a.5.5 0 1 1 0 1h-2.2a.5.5 0 0 1-.5-.5V8.56a.5.5 0 0 1 .5-.5h2.2a.5.5 0 1 1 0 1h-1.7v.7h1.7z\"\/><\/svg> Continue in LINE<\/a>\n        <\/div>\n        <div class=\"ips-result-box\">\n          <div class=\"ips-result-box-label\">Your project<\/div>\n          <div id=\"ipsResultSummary\"><\/div>\n        <\/div>\n      <\/div>\n      <div class=\"ips-next\">\n        <h4>What happens next<\/h4>\n        <div class=\"ips-next-list\">\n          <div class=\"ips-next-item\"><div class=\"ips-next-num\">1<\/div><div><strong>We receive your project brief<\/strong><span>Your details and selections go to the Interpool project team.<\/span><\/div><\/div>\n          <div class=\"ips-next-item\"><div class=\"ips-next-num\">2<\/div><div><strong>Our build team reviews your project<\/strong><span>We consider your vision, project stage and location before recommending the right path.<\/span><\/div><\/div>\n          <div class=\"ips-next-item\"><div class=\"ips-next-num\">3<\/div><div><strong>The right next step<\/strong><span>We will recommend a budget review, design consultation or site visit.<\/span><\/div><\/div>\n        <\/div>\n      <\/div>\n      <div class=\"ips-result-actions\">\n        <button class=\"ips-btn ips-btn-close-result\" id=\"ipsResultClose2\" type=\"button\">Close<\/button>\n        <a class=\"ips-btn ips-btn-line\" id=\"ipsLineLink\" href=\"https:\/\/line.me\/R\/ti\/p\/@interpoolspa\" target=\"_blank\" rel=\"noopener\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewbox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 5.83 2 10.43c0 4.07 3.42 7.49 8.05 8.14.31.07.74.21.85.48.1.25.06.63.03.88l-.14.83c-.04.25-.2.97.85.53s5.61-3.3 7.66-5.65h-.01C21.36 13.36 22 11.96 22 10.43 22 5.83 17.52 2 12 2zm-3.08 11.11h-2.2a.5.5 0 0 1-.5-.5V8.56a.5.5 0 0 1 1 0v3.55h1.7a.5.5 0 1 1 0 1zm1.62-.5a.5.5 0 0 1-1 0V8.56a.5.5 0 0 1 1 0v4.05zm4.14 0a.5.5 0 0 1-.34.47.5.5 0 0 1-.56-.12L11.97 10v2.61a.5.5 0 0 1-1 0V8.56a.5.5 0 0 1 .34-.47.5.5 0 0 1 .56.12l1.81 2.46V8.56a.5.5 0 0 1 1 0v4.05zm3.12-2.85a.5.5 0 1 1 0 1h-1.7v.85h1.7a.5.5 0 1 1 0 1h-2.2a.5.5 0 0 1-.5-.5V8.56a.5.5 0 0 1 .5-.5h2.2a.5.5 0 1 1 0 1h-1.7v.7h1.7z\"\/><\/svg> Continue in LINE<\/a>\n      <\/div>\n    <\/div>\n  <\/div>\n\n<\/div>\n\n<script>\n(function(){\n\n\/\/ \u2500\u2500\u2500 Data \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst D = {\n  bg:{\n    intro:   'https:\/\/images.unsplash.com\/photo-1644413638617-02369c89c156?auto=format&fit=crop&w=1800&q=80',\n    setting: 'https:\/\/images.unsplash.com\/photo-1707327085506-c4f31c951a1a?auto=format&fit=crop&w=1800&q=80',\n    build:   'https:\/\/images.unsplash.com\/photo-1728404259075-209cfb5bb89c?auto=format&fit=crop&w=1800&q=80',\n    style:   'https:\/\/images.pexels.com\/photos\/31817157\/pexels-photo-31817157.jpeg?auto=compress&cs=tinysrgb&w=1800',\n    scale:   'https:\/\/images.unsplash.com\/photo-1512917774080-9991f1c4c750?auto=format&fit=crop&w=1800&q=80',\n    timing:  'https:\/\/images.unsplash.com\/photo-1507652313519-d4e9174996dd?auto=format&fit=crop&w=1800&q=80',\n    contact: 'https:\/\/images.unsplash.com\/photo-1713270176378-45fbf4a27099?auto=format&fit=crop&w=1800&q=80'\n  },\n  setting:[\n    {id:'home',     name:'Personal Project',desc:'Private villa, residence, or personal wellness retreat.',        img:'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Mr.-Tobias-House-3-850x520.jpg'},\n    {id:'business', name:'Business Project',desc:'Commercial spa, wellness venue, or branded concept space.',      img:'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Shin-Onsen-SpaBangkok-6-850x520.jpg'}\n  ],\n  build:[\n    {id:'onsen', name:'Onsen Spa',   desc:'Hot, cold, or combined bathing spaces with premium stone, timber, and refined mineral-water design.',\n     img:'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Shin-Onsen-SpaBangkok-6-850x520.jpg',\n     gallery:['https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Shin-Onsen-SpaBangkok-6-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/The-stage-Mindscape-Ratchada-Huai-Khawang-1-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Diora-Onsen-Spa-Sathorn-2-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Shin-Onsen-SpaBangkok-3-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/The-stage-Mindscape-Ratchada-Huai-Khawang-3-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Diora-Onsen-Spa-Sathorn-4-850x520.jpg']},\n    {id:'sauna', name:'Sauna',       desc:'Traditional Finnish or infrared sauna spaces, built in your choice of Spruce or Abachi timber.',\n     img:'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Mr.Jiratiwat-Private-Outdoor-Sauna-Residence-9-850x520.jpg',\n     gallery:['https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Mr.Jiratiwat-Private-Outdoor-Sauna-Residence-9-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Anantara-Hotel-4-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Mr.-Tobias-House-3-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Mr.Jiratiwat-Private-Outdoor-Sauna-Residence-6-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Anantara-Hotel-3-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Mr.-Tobias-House-5-850x520.jpg']},\n    {id:'steam', name:'Steam Room',  desc:'Wet steam enclosures with full mosaic tile finish \u2014 built for home sanctuaries and commercial spas alike.',\n     img:'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Anantara-Hotel-5-850x520.jpg',\n     gallery:['https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Anantara-Hotel-5-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/The-stage-Mindscape-Ratchada-Huai-Khawang-5-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Anantara-Hotel-6-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Anantara-Hotel-2-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Anantara-Hotel-1-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Anantara-Hotel-8-850x520.jpg']},\n    {id:'plunge',name:'Ice Bath',    desc:'Cold-water immersion designed to support physical recovery, renewed energy, and everyday wellbeing.',\n     img:'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Decode-Wellness-1-850x520.jpg',\n     gallery:['https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Decode-Wellness-1-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Rechill-3-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Rechill-1-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Bangkok-Glass-Group-Yamaoka-Hanasaka-Academy-1-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Decode-Wellness-4-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Rechill-4-850x520.jpg']},\n    {id:'hydro', name:'Hydrotherapy',desc:'Therapeutic jet pools, contrast circuits, and water massage systems designed for recovery and deep wellness.',\n     img:'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Naresuan-Univercity-3-850x520.jpg',\n     gallery:['https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Naresuan-Univercity-3-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Sukumvit-Hospital-3-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Wellness-world-Ayutthaya-4-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Wellness-world-Ayutthaya-5-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Naresuan-Univercity-1-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Sukumvit-Hospital-1-850x520.jpg']},\n    {id:'pool',  name:'Pool',        desc:'Custom pools, infinity edges, and swim spas built for visual impact and lasting enjoyment.',\n     img:'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Private-Pool-Villa-Oxygen-Valley-Khaoyai-1-850x520.jpg',\n     gallery:['https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Private-Pool-Villa-Oxygen-Valley-Khaoyai-1-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Mr.-Thongchai-House-5-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Passorn-Private-Pool-villa-5-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Private-Pool-Villa-Oxygen-Valley-Khaoyai-3-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Mr.-Thongchai-House-2-850x520.jpg','https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Passorn-Private-Pool-villa-2-850x520.jpg']}\n  ],\n  style:[\n    {id:'natural',  name:'Natural & Organic',desc:'Stone, timber, and earthy materials. A warm spa-retreat energy that feels rooted in the landscape.',    img:'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Rechill-1-850x520.jpg', mult:1.0},\n    {id:'modern',   name:'Modern & Minimal', desc:'Clean lines, polished surfaces, and precise detailing. A contemporary luxury statement.',              img:'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Decode-Wellness-1-850x520.jpg', mult:1.12},\n    {id:'custom',   name:'Custom',           desc:'Your vision \u2014 materials, mood, and atmosphere \u2014 designed around your property and requirements.', img:'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Shin-Onsen-SpaBangkok-3-850x520.jpg', mult:1.30}\n  ],\n  scale:{\n    0:{name:'Not Sure',desc:'Not sure yet? We will help shape the right wellness space for your property.', img:'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Rechill-3-850x520.jpg', mult:1.00},\n    1:{name:'Small',  desc:'A private wellness space for 1\u20132 people, ideal for a personal daily escape.', img:'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Decode-Wellness-5-850x520.jpg', pos:'center 62%', mult:0.70},\n    2:{name:'Medium', desc:'A shared wellness space for couples, family, or guests, with room to slow down together.',img:'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Mr.-Tobias-House-3-850x520.jpg', mult:1.00},\n    3:{name:'Large',  desc:'A social wellness space for groups, villas, or hospitality\u2014an amenity people will remember.',              img:'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Shin-Onsen-SpaBangkok-6-850x520.jpg', mult:1.62},\n    4:{name:'Luxury', desc:'A bespoke wellness space for exceptional properties\u2014created around what you imagine.', img:'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Private-Pool-Villa-Oxygen-Valley-Khaoyai-1-850x520.jpg', mult:2.45}\n  },\n  scaleImages:{\n    onsen:[\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/The-stage-Mindscape-Ratchada-Huai-Khawang-3-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Diora-Onsen-Spa-Sathorn-1-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Diora-Onsen-Spa-Sathorn-4-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Shin-Onsen-SpaBangkok-3-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Shin-Onsen-SpaBangkok-6-850x520.jpg'\n    ],\n    sauna:[\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Mr.Jiratiwat-Private-Outdoor-Sauna-Residence-9-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Mr.-Tobias-House-1-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Mr.-Tobias-House-5-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Mr.Jiratiwat-Private-Outdoor-Sauna-Residence-7-850x520.jpg',\n      'https:\/\/images.unsplash.com\/photo-1757940661240-f2e8d2ff93bf?auto=format&fit=crop&w=1600&q=82'\n    ],\n    steam:[\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Anantara-Hotel-7-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Anantara-Hotel-5-850x520.jpg',\n      'https:\/\/images.pexels.com\/photos\/18408807\/pexels-photo-18408807.jpeg?auto=compress&cs=tinysrgb&w=1600',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Anantara-Hotel-6-850x520.jpg',\n      'https:\/\/images.pexels.com\/photos\/33852650\/pexels-photo-33852650.jpeg?auto=compress&cs=tinysrgb&w=1600'\n    ],\n    plunge:[\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Decode-Wellness-1-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Rechill-1-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Decode-Wellness-5-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Rechill-4-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Rechill-3-850x520.jpg'\n    ],\n    hydro:[\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Wellness-world-Ayutthaya-1-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Wellness-world-Ayutthaya-5-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Sukumvit-Hospital-3-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Naresuan-Univercity-3-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Wellness-world-Ayutthaya-3-850x520.jpg'\n    ],\n    pool:[\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Private-Pool-Villa-Oxygen-Valley-Khaoyai-1-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Private-Pool-Villa-Oxygen-Valley-Khaoyai-5-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Private-Pool-Villa-Oxygen-Valley-Khaoyai-3-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Mr.-Thongchai-House-4-850x520.jpg',\n      'https:\/\/interpoolspa.com\/wp-content\/uploads\/2026\/05\/Passorn-Private-Pool-villa-5-850x520.jpg'\n    ]\n  },\n  pricing:{\n    byBuild:{\n      onsen:{0:{from:300000}, 1:{lo:300000,hi:300000}, 2:{lo:450000,hi:450000}, 3:{lo:850000,hi:850000}},\n      plunge:{0:{from:400000}, 1:{lo:400000,hi:400000}, 2:{lo:400000,hi:400000}, 3:{lo:400000,hi:400000}},\n      sauna:{0:{from:120000}, 1:{lo:120000,hi:120000}, 2:{lo:500000,hi:500000}, 3:{lo:800000,hi:800000}},\n      steam:{0:{from:75000},  1:{lo:75000,hi:75000},   2:{lo:140000,hi:140000}, 3:{lo:300000,hi:300000}}\n    }\n  },\n  timing:[\n    {id:'exploring', label:'Exploring ideas and prices', desc:'I\u2019m comparing options and planning my budget.'},\n    {id:'planning',  label:'Planning a project',         desc:'I have a project in mind and want to understand what is possible.'},\n    {id:'ready',     label:'Ready to build',             desc:'I\u2019m ready to discuss design, site details and next steps.'},\n    {id:'not-sure',  label:'Not sure yet',               desc:'I\u2019d like guidance on the right approach.'}\n  ],\n  lineOaId:'@interpoolspa',\n  lineFallback:'https:\/\/line.me\/R\/ti\/p\/@interpoolspa'\n};\n\nconst STEPS = ['intro','setting','build','style','scale','timing','contact'];\nconst STEP_LABELS = {\n  intro:'Welcome',\n  setting:'Project setting',\n  build:'Build type',\n  style:'Preferred style',\n  scale:'Project scale',\n  timing:'Project readiness',\n  contact:'Your details'\n};\n\n\/\/ App state\nconst st = {step:0, setting:null, build:'onsen', style:null, scale:0, timeline:null,\n            name:'', email:'', whatsapp:'', line:'', location:'', notes:'', reference:''};\nconst SESSION_STATE_KEY = 'ips-estimator-v28-en-session';\nconst SESSION_STATE_FIELDS = Object.keys(st);\nfunction restoreSessionState(){\n  try{\n    const navigation=performance.getEntriesByType?.('navigation')?.[0];\n    const isReload=navigation?.type==='reload' || performance.navigation?.type===1;\n    if(!isReload){sessionStorage.removeItem(SESSION_STATE_KEY);return}\n    const saved = JSON.parse(sessionStorage.getItem(SESSION_STATE_KEY) || 'null');\n    if(!saved || typeof saved!=='object') return;\n    SESSION_STATE_FIELDS.forEach(key=>{\n      if(Object.prototype.hasOwnProperty.call(saved,key)) st[key]=saved[key];\n    });\n    st.step=Math.max(0,Math.min(STEPS.length-1,Number(st.step)||0));\n    st.scale=Math.max(0,Math.min(4,Number(st.scale)||0));\n  }catch(_error){}\n}\nfunction persistSessionState(){\n  try{\n    const snapshot={};\n    SESSION_STATE_FIELDS.forEach(key=>{snapshot[key]=st[key]});\n    sessionStorage.setItem(SESSION_STATE_KEY,JSON.stringify(snapshot));\n  }catch(_error){}\n}\nrestoreSessionState();\nconst FLUENT_FORM = {\n  id:4,\n  endpoint:'https:\/\/interpoolspa.com\/wp-admin\/admin-ajax.php'\n};\nlet inquirySubmitting = false;\nlet lastSubmittedInquiry = '';\n\n\/\/ \u2500\u2500\u2500 Element refs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst root       = document.getElementById('ipsEstimator');\nconst stageBg    = document.getElementById('ipsStageBg');\nconst stageBgNext= document.getElementById('ipsStageBgNext');\nconst track      = document.getElementById('ipsTrack');\nconst progLabel  = document.getElementById('ipsProgLabel');\nconst progMeta   = document.getElementById('ipsProgMeta');\nconst progFill   = document.getElementById('ipsProgFill');\n\n\/\/ \u2500\u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction thb(v){return '\u0e3f'+Math.round(v).toLocaleString('en-US')}\nfunction esc(s){return String(s||'').replace(\/&\/g,'&amp;').replace(\/<\/g,'&lt;').replace(\/>\/g,'&gt;').replace(\/\"\/g,'&quot;')}\nfunction buildById(id){return D.build.find(x=>x.id===id) || D.build[0]}\nfunction settingById(id){return D.setting.find(x=>x.id===id)}\nfunction scalePhotoForBuild(scale=st.scale){\n  const build=buildById(st.build);\n  const image=D.scaleImages[build.id]?.[scale] || build.gallery?.[scale];\n  return image\n    ? {img:image,pos:'center'}\n    : D.scale[scale];\n}\n\nfunction priceGuide(){\n  const guides = D.pricing.byBuild[st.build];\n  if(!guides) return null;\n  if(st.scale===4){\n    const highest = Math.max(...Object.values(guides).map(g=>g.hi ?? g.lo ?? g.from ?? 0));\n    return highest ? {from:highest,plus:true} : null;\n  }\n  return guides[st.scale] || null;\n}\nfunction sizeDescription(){return D.scale[st.scale].desc}\nfunction priceText(guide){\n  if(guide.plus) return `Starting at ${thb(guide.from)}+`;\n  if(guide.from) return `From ${thb(guide.from)}`;\n  return guide.lo===guide.hi ? thb(guide.lo) : `${thb(guide.lo)} \u2013 ${thb(guide.hi)}`;\n}\n\nfunction isCustomBuild(){return st.build==='pool' || st.build==='hydro'}\nfunction createProjectReference(){\n  if(!st.reference) st.reference = `IPS-${Date.now().toString(36).toUpperCase()}`;\n  return st.reference;\n}\nfunction lineHandoffUrl(message){\n  if(!D.lineOaId) return D.lineFallback;\n  return `https:\/\/line.me\/R\/oaMessage\/${encodeURIComponent(D.lineOaId)}\/?${encodeURIComponent(message)}`;\n}\n\n\/\/ Preload only the opening and next-step imagery. Build galleries, style\n\/\/ references, scale references, and later stage backgrounds load when the\n\/\/ visitor reaches them instead of competing with the estimator's first view.\nfunction preloadInitial(){\n  const urls = new Set([D.bg.intro,D.bg.setting]);\n  D.setting.forEach(s=>urls.add(s.img));\n  urls.forEach(u=>{const i=new Image(); i.src=u;});\n}\n\nfunction setBg(key){\n  const url = D.bg[key] || D.bg.intro;\n  \/\/ If the background hasn't changed, do nothing at all.\n  const current = stageBg.style.backgroundImage;\n  const incoming = `url('${url}')`;\n  if(current === incoming) return;\n\n  \/\/ Load the new image into the top layer and animate it in.\n  stageBgNext.style.backgroundImage = incoming;\n  stageBgNext.style.animation = 'none';\n  \/\/ Force reflow so removing 'none' triggers a fresh animation.\n  stageBgNext.offsetWidth; \/\/ eslint-disable-line no-unused-expressions\n  stageBgNext.style.animation = 'ips-bg-in .7s ease forwards';\n\n  \/\/ Once faded in, promote to base layer and reset the top layer silently.\n  clearTimeout(setBg._t);\n  setBg._t = setTimeout(()=>{\n    stageBg.style.backgroundImage = incoming;\n    stageBgNext.style.animation = 'none';\n    stageBgNext.style.backgroundImage = '';\n  }, 720);\n}\n\n\/\/ \u2500\u2500\u2500 Templates \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction tplIntro(){return `\n  <div class=\"ips-view\">\n    <div class=\"ips-intro\">\n      <div class=\"ips-eyebrow\">Luxury Wellness \u2014 Thailand<\/div>\n      <h1 class=\"ips-display\">Design your dream<br>wellness space<\/h1>\n      <p class=\"ips-lead\">A few visual choices.<br class=\"ips-mobile-break\"> Your real budget range.<br class=\"ips-mobile-break\"> Ready in under 2 minutes.<\/p>\n      <div class=\"ips-pills\">\n        <div class=\"ips-pill\"><span class=\"ips-pill-dot\"><\/span>No commitment<\/div>\n        <div class=\"ips-pill\"><span class=\"ips-pill-dot\"><\/span>Real price ranges<\/div>\n        <div class=\"ips-pill\"><span class=\"ips-pill-dot\"><\/span>Personal follow-up<\/div>\n      <\/div>\n      <div class=\"ips-actions\"><button class=\"ips-btn ips-btn-primary\" data-next>Start<\/button><\/div>\n    <\/div>\n  <\/div>`}\n\nfunction tplSetting(){return `\n  <div class=\"ips-view\">\n    <div class=\"ips-step-head\">\n      <h2 class=\"ips-title\">Where will we build?<\/h2>\n      <p class=\"ips-lead\">Choose the setting for your project.<\/p>\n    <\/div>\n    <div class=\"ips-choice-grid\">\n      ${D.setting.map(s=>`\n        <button class=\"ips-choice${st.setting===s.id?' sel':''}\" type=\"button\" data-set=\"${s.id}\">\n          <div class=\"ips-choice-bg\" style=\"background-image:url('${s.img}')\"><\/div>\n          <div class=\"ips-choice-overlay\"><\/div>\n          <div class=\"ips-choice-body\">\n            <div class=\"ips-choice-header\">\n              <div class=\"ips-choice-name\">${s.name}<\/div>\n              <div class=\"ips-check\">\u2713<\/div>\n            <\/div>\n            <div class=\"ips-choice-desc\">${s.desc}<\/div>\n          <\/div>\n        <\/button>`).join('')}\n    <\/div>\n    <div class=\"ips-actions\">\n      <button class=\"ips-btn ips-btn-ghost\" data-back>Back<\/button>\n      <button class=\"ips-btn ips-btn-primary\" data-next${st.setting?'':' disabled'}>Continue<\/button>\n    <\/div>\n  <\/div>`}\n\nfunction tplBuildPanel(b){\n  \/\/ Gallery: first 4 tiles shown inline; 4th overlay invites viewing more.\n  const tiles = b.gallery.slice(0,4).map((src,i)=>{\n    const isMore = (i===3 && b.gallery.length>4);\n    return `\n      <div class=\"ips-gallery-tile${isMore?' more-overlay':''}\"\n           style=\"background-image:url('${src}')\"\n           data-gallery=\"${b.id}\"\n           role=\"button\"\n           tabindex=\"0\"\n           aria-label=\"${b.name} example ${i+1}${isMore?' \u2014 view all':''}\">\n        ${isMore?`<div class=\"ips-gallery-more\">+${b.gallery.length-4} more \u2192<\/div>`:''}\n      <\/div>`;\n  }).join('');\n\n  return `\n        <div class=\"ips-build-info\">\n          <div class=\"ips-build-info-eyebrow\">Selected build<\/div>\n          <div class=\"ips-build-info-name\">${b.name}<\/div>\n          <div class=\"ips-build-info-desc\">${b.desc}<\/div>\n          <button class=\"ips-build-info-action\" type=\"button\" data-gallery=\"${b.id}\">\n            <span class=\"ips-gallery-icon\"><span><\/span><span><\/span><span><\/span><span><\/span><\/span>\n            Explore all examples \u2192\n          <\/button>\n        <\/div>\n        <div class=\"ips-build-gallery\">${tiles}<\/div>`;\n}\n\nfunction tplBuild(){\n  const b = buildById(st.build);\n  return `\n  <div class=\"ips-view\">\n    <div class=\"ips-step-head\">\n      <h2 class=\"ips-title\">What are we building?<\/h2>\n      <p class=\"ips-lead\">Select a build type. Tap any image to explore examples.<\/p>\n    <\/div>\n    <div class=\"ips-build-wrap\">\n      <div class=\"ips-build-tabs\" role=\"tablist\">\n        ${D.build.map(item=>`\n          <button class=\"ips-build-tab${st.build===item.id?' sel':''}\"\n                  type=\"button\" role=\"tab\" aria-selected=\"${st.build===item.id}\"\n                  data-tab=\"${item.id}\">${item.name}<\/button>`).join('')}\n      <\/div>\n      <div class=\"ips-build-panel\" id=\"ipsBuildPanel\">${tplBuildPanel(b)}<\/div>\n    <\/div>\n    <div class=\"ips-actions\">\n      <button class=\"ips-btn ips-btn-ghost\" data-back>Back<\/button>\n      <button class=\"ips-btn ips-btn-primary\" data-next>Continue<\/button>\n    <\/div>\n  <\/div>`;\n}\n\nfunction tplStyle(){return `\n  <div class=\"ips-view\">\n    <div class=\"ips-step-head\">\n      <h2 class=\"ips-title\">Choose your Style<\/h2>\n      <p class=\"ips-lead\">Your style shapes the materials and overall atmosphere.<\/p>\n    <\/div>\n    <div class=\"ips-style-grid\">\n      ${D.style.map(s=>`\n        <button class=\"ips-style-card${st.style===s.id?' sel':''}\" type=\"button\" data-style=\"${s.id}\">\n          <div class=\"ips-style-bg\" style=\"background-image:url('${s.img}')\"><\/div>\n          <div class=\"ips-style-overlay\"><\/div>\n          <div class=\"ips-style-check\">\u2713<\/div>\n          <div class=\"ips-style-body\">\n            <div class=\"ips-style-name\">${s.name}<\/div>\n            <div class=\"ips-style-desc\">${s.desc}<\/div>\n          <\/div>\n        <\/button>`).join('')}\n    <\/div>\n    <div class=\"ips-actions\">\n      <button class=\"ips-btn ips-btn-ghost\" data-back>Back<\/button>\n      <button class=\"ips-btn ips-btn-primary\" data-next${st.style?'':' disabled'}>Continue<\/button>\n    <\/div>\n  <\/div>`}\n\nfunction tplScale(){\n  const s = D.scale[st.scale];\n  const photo = scalePhotoForBuild();\n  return `\n  <div class=\"ips-view\">\n    <div class=\"ips-step-head\">\n      <h2 class=\"ips-title\">How large should this be?<\/h2>\n    <\/div>\n    <div class=\"ips-scale-grid\">\n      <div class=\"ips-scale-panel notranslate\" translate=\"no\" data-wg-notranslate>\n        <div class=\"ips-scale-controls\">\n          <div class=\"ips-scale-row\">\n            <h3>Approximate size &amp; fit<\/h3>\n            <div class=\"ips-scale-val\" id=\"ipsScaleLabel\">\n              ${Object.values(D.scale).map((option,index)=>`<span class=\"ips-scale-copy-option${st.scale===index?' is-active':''}\" data-scale-label=\"${index}\" aria-hidden=\"${st.scale!==index}\">${option.name}<\/span>`).join('')}\n            <\/div>\n          <\/div>\n          <input class=\"ips-scale-slider\" id=\"ipsScaleSlider\" type=\"range\" min=\"0\" max=\"4\" step=\"1\" value=\"${st.scale}\" style=\"--ips-scale-progress:${st.scale*25}%\" aria-label=\"Approximate size\">\n          <div class=\"ips-scale-ticks\" role=\"group\" aria-label=\"Choose approximate size\">\n            <button type=\"button\" data-scale-value=\"0\" aria-pressed=\"${st.scale===0}\" class=\"${st.scale===0?'sel':''}\">Not sure<\/button>\n            <button type=\"button\" data-scale-value=\"1\" aria-pressed=\"${st.scale===1}\" class=\"${st.scale===1?'sel':''}\">Small<\/button>\n            <button type=\"button\" data-scale-value=\"2\" aria-pressed=\"${st.scale===2}\" class=\"${st.scale===2?'sel':''}\">Medium<\/button>\n            <button type=\"button\" data-scale-value=\"3\" aria-pressed=\"${st.scale===3}\" class=\"${st.scale===3?'sel':''}\">Large<\/button>\n            <button type=\"button\" data-scale-value=\"4\" aria-pressed=\"${st.scale===4}\" class=\"${st.scale===4?'sel':''}\">Luxury<\/button>\n          <\/div>\n        <\/div>\n        <div class=\"ips-scale-desc ips-scale-copy-stack\" id=\"ipsScaleDesc\">\n          ${Object.values(D.scale).map((option,index)=>`<span class=\"ips-scale-copy-option${st.scale===index?' is-active':''}\" data-scale-description=\"${index}\" aria-hidden=\"${st.scale!==index}\">${option.desc}<\/span>`).join('')}\n        <\/div>\n      <\/div>\n      <div class=\"ips-scale-photo\">\n        <img decoding=\"async\" id=\"ipsScaleImg\" src=\"${photo.img}\" alt=\"${buildById(st.build).name} \u2014 ${s.name} size example\" style=\"object-position:${photo.pos||'center'}\">\n        <div class=\"ips-scale-badge\" id=\"ipsScaleBadge\">${s.name}<\/div>\n      <\/div>\n    <\/div>\n    <div class=\"ips-actions\">\n      <button class=\"ips-btn ips-btn-ghost\" data-back>Back<\/button>\n      <button class=\"ips-btn ips-btn-primary\" data-next>Continue<\/button>\n    <\/div>\n  <\/div>`;\n}\n\nfunction tplTiming(){return `\n  <div class=\"ips-view ips-timing-view\">\n    <div class=\"ips-step-head\">\n      <h2 class=\"ips-title\">How ready are you to begin?<\/h2>\n      <p class=\"ips-lead\">Your answer helps us show you the right next step.<\/p>\n    <\/div>\n    <div class=\"ips-timing-grid\">\n      ${D.timing.map(t=>`\n        <button class=\"ips-timing-card${st.timeline===t.id?' sel':''}\" type=\"button\" data-time=\"${t.id}\">\n          <div class=\"ips-timing-card-inner\">\n            <div class=\"ips-timing-copy\">\n              <strong class=\"ips-timing-label\">${t.label}<\/strong>\n              <span>${t.desc}<\/span>\n            <\/div>\n            <div class=\"ips-timing-radio\" aria-hidden=\"true\"><\/div>\n          <\/div>\n        <\/button>`).join('')}\n    <\/div>\n    <div class=\"ips-actions\">\n      <button class=\"ips-btn ips-btn-ghost\" data-back>Back<\/button>\n      <button class=\"ips-btn ips-btn-primary\" data-next${st.timeline?'':' disabled'}>Continue<\/button>\n    <\/div>\n  <\/div>`}\n\nfunction tplContact(){\n  const b  = buildById(st.build);\n  const sv = settingById(st.setting);\n  const sc = D.scale[st.scale];\n  const sty= D.style.find(x=>x.id===st.style);\n  return `\n  <div class=\"ips-view ips-contact-view\">\n    <div class=\"ips-step-head\">\n      <div class=\"ips-eyebrow\">Final step<\/div>\n      <h2 class=\"ips-title\">Your estimate is ready<\/h2>\n      <p class=\"ips-lead\">Your choices have shaped a personalised starting point. Add your details to reveal it; WhatsApp and LINE are optional.<\/p>\n    <\/div>\n    <div class=\"ips-contact-grid compact\">\n      <div class=\"ips-summary\">\n        <div class=\"ips-summary-title\">Your selections<\/div>\n        <div class=\"ips-summary-compact\">\n          <div class=\"ips-summary-chip\"><span>Setting<\/span><span>${sv?.name || '\u2014'}<\/span><\/div>\n          <div class=\"ips-summary-chip\"><span>Build type<\/span><span>${b.name}<\/span><\/div>\n          <div class=\"ips-summary-chip\"><span>Style<\/span><span>${sty?.name || '\u2014'}<\/span><\/div>\n          <div class=\"ips-summary-chip\"><span>Scale<\/span><span>${sc.name}<\/span><\/div>\n          <div class=\"ips-summary-chip\"><span>Readiness<\/span><span>${D.timing.find(x=>x.id===st.timeline)?.label || '\u2014'}<\/span><\/div>\n        <\/div>\n      <\/div>\n      <div class=\"ips-form compact\">\n        <div class=\"ips-form-grid\">\n          <div class=\"ips-field\">\n            <label class=\"ips-field-label\" for=\"ips-f-name\">Full name *<\/label>\n            <input class=\"ips-input\" id=\"ips-f-name\" type=\"text\" placeholder=\"Your name\" value=\"${esc(st.name)}\">\n          <\/div>\n          <div class=\"ips-field\">\n            <label class=\"ips-field-label\" for=\"ips-f-email\">Email *<\/label>\n            <input class=\"ips-input\" id=\"ips-f-email\" type=\"email\" placeholder=\"you@example.com\" value=\"${esc(st.email)}\">\n          <\/div>\n          <div class=\"ips-field\">\n            <label class=\"ips-field-label\" for=\"ips-f-whatsapp\">WhatsApp <span style=\"font-weight:400;opacity:.7\">(optional)<\/span><\/label>\n            <input class=\"ips-input\" id=\"ips-f-whatsapp\" type=\"tel\" placeholder=\"+66...\" value=\"${esc(st.whatsapp)}\">\n          <\/div>\n          <div class=\"ips-field\">\n            <label class=\"ips-field-label\" for=\"ips-f-line\">LINE ID <span style=\"font-weight:400;opacity:.7\">(optional)<\/span><\/label>\n            <input class=\"ips-input\" id=\"ips-f-line\" type=\"text\" placeholder=\"Your LINE ID\" value=\"${esc(st.line)}\">\n          <\/div>\n          <div class=\"ips-field\">\n            <label class=\"ips-field-label\" for=\"ips-f-loc\">Project location<\/label>\n            <select class=\"ips-select\" id=\"ips-f-loc\">\n              <option value=\"\">Select region<\/option>\n              ${['Bangkok','Chiang Mai','Chiang Rai','Phuket','Koh Samui','Pattaya','Hua Hin','Other']\n                .map(l=>`<option${st.location===l?' selected':''}>${l}<\/option>`).join('')}\n            <\/select>\n          <\/div>\n          <div class=\"ips-field full\">\n            <label class=\"ips-field-label\" for=\"ips-f-notes\">About your project <span style=\"font-weight:400;opacity:.7\">(optional)<\/span><\/label>\n            <textarea class=\"ips-textarea\" id=\"ips-f-notes\" placeholder=\"Vision, property details, specific requirements\u2026\">${esc(st.notes)}<\/textarea>\n          <\/div>\n        <\/div>\n        <div class=\"ips-contact-actions\">\n          <button class=\"ips-btn ips-btn-ghost\" data-back type=\"button\">Back<\/button>\n          <button class=\"ips-btn ips-btn-primary ips-contact-submit\" data-submit type=\"button\">Get Estimate<\/button>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>`;\n}\n\n\/\/ \u2500\u2500\u2500 Render loop \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction render(){\n  const key = STEPS[st.step];\n  setBg(key);\n  progLabel.textContent = STEP_LABELS[key];\n  progMeta.textContent  = `Step ${st.step+1} of ${STEPS.length}`;\n  progFill.style.width  = `${((st.step+1)\/STEPS.length)*100}%`;\n\n  const views = [tplIntro,tplSetting,tplBuild,tplStyle,tplScale,tplTiming,tplContact];\n  \/\/ Apply step-specific sizing before inserting its content so the first paint\n  \/\/ already uses the final typography and layout.\n  root.classList.toggle('ips-at-intro', key==='intro');\n  root.classList.toggle('ips-at-timing', key==='timing');\n  root.classList.toggle('ips-at-style', key==='style');\n  root.classList.toggle('ips-at-scale', key==='scale');\n  root.classList.toggle('ips-at-contact', key==='contact');\n  document.documentElement.classList.toggle('ips-estimator-contact-active',key==='contact');\n  document.body.classList.toggle('ips-estimator-contact-active',key==='contact');\n  track.innerHTML = views[st.step]();\n  bind();\n}\n\n\/\/ \u2500\u2500\u2500 Event bindings (re-bound on each render) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction updateSelectedOption(selector, dataKey, value){\n  track.querySelectorAll(selector).forEach(el=>{\n    const selected = el.dataset[dataKey]===value;\n    el.classList.toggle('sel',selected);\n    el.setAttribute('aria-pressed',String(selected));\n  });\n  track.querySelectorAll('[data-next]').forEach(btn=>{btn.disabled=false});\n}\n\nfunction bindGallery(scope=track){\n  scope.querySelectorAll('[data-gallery]').forEach(el=>{\n    el.addEventListener('click',()=>openGallery(el.dataset.gallery));\n    el.addEventListener('keydown',e=>{\n      if(e.key==='Enter' || e.key===' '){e.preventDefault(); openGallery(el.dataset.gallery);}\n    });\n  });\n}\n\nfunction selectBuild(id){\n  st.build=id;\n  persistSessionState();\n  updateSelectedOption('[data-tab]','tab',id);\n  track.querySelectorAll('[data-tab]').forEach(el=>{\n    el.setAttribute('aria-selected',String(el.dataset.tab===id));\n  });\n  const panel=document.getElementById('ipsBuildPanel');\n  if(panel){\n    panel.innerHTML=tplBuildPanel(buildById(id));\n    bindGallery(panel);\n  }\n}\n\nfunction bind(){\n  track.querySelectorAll('[data-next]').forEach(b=>b.addEventListener('click',()=>{if(validate())goTo(st.step+1)}));\n  track.querySelectorAll('[data-back]').forEach(b=>b.addEventListener('click',()=>goTo(st.step-1)));\n\n  track.querySelectorAll('[data-set]').forEach(b=>b.addEventListener('click',()=>{st.setting=b.dataset.set;persistSessionState();updateSelectedOption('[data-set]','set',st.setting)}));\n  track.querySelectorAll('[data-tab]').forEach(b=>b.addEventListener('click',()=>selectBuild(b.dataset.tab)));\n  track.querySelectorAll('[data-style]').forEach(b=>b.addEventListener('click',()=>{st.style=b.dataset.style;persistSessionState();updateSelectedOption('[data-style]','style',st.style)}));\n  track.querySelectorAll('[data-time]').forEach(b=>b.addEventListener('click',()=>{st.timeline=b.dataset.time;persistSessionState();updateSelectedOption('[data-time]','time',st.timeline)}));\n  bindGallery();\n  track.querySelector('[data-submit]')?.addEventListener('click',e=>{\n    if(validate(true)) submitInquiry(e.currentTarget);\n  });\n\n  const slider = document.getElementById('ipsScaleSlider');\n  if(slider){\n    const updateScaleSelection=value=>{\n      st.scale = Math.max(0,Math.min(4,+value));\n      persistSessionState();\n      const s = D.scale[st.scale];\n      const photo = scalePhotoForBuild();\n      slider.value = String(st.scale);\n      slider.style.setProperty('--ips-scale-progress',`${st.scale*25}%`);\n      track.querySelectorAll('[data-scale-label]').forEach(option=>{\n        const selected=+option.dataset.scaleLabel===st.scale;\n        option.classList.toggle('is-active',selected);\n        option.setAttribute('aria-hidden',String(!selected));\n      });\n      track.querySelectorAll('[data-scale-description]').forEach(option=>{\n        const selected=+option.dataset.scaleDescription===st.scale;\n        option.classList.toggle('is-active',selected);\n        option.setAttribute('aria-hidden',String(!selected));\n      });\n      document.getElementById('ipsScaleBadge').textContent = s.name;\n      const img = document.getElementById('ipsScaleImg');\n      img.src=photo.img;\n      img.alt=`${buildById(st.build).name} \u2014 ${s.name} size example`;\n      img.style.objectPosition=photo.pos||'center';\n      img.style.opacity='1';\n      track.querySelectorAll('[data-scale-value]').forEach(button=>{\n        const selected=+button.dataset.scaleValue===st.scale;\n        button.classList.toggle('sel',selected);\n        button.setAttribute('aria-pressed',String(selected));\n      });\n    };\n    slider.addEventListener('input',e=>updateScaleSelection(e.target.value));\n    track.querySelectorAll('[data-scale-value]').forEach(button=>{\n      button.addEventListener('click',()=>updateScaleSelection(button.dataset.scaleValue));\n    });\n  }\n  ['ips-f-name','ips-f-email','ips-f-whatsapp','ips-f-line','ips-f-loc','ips-f-notes'].forEach(id=>{\n    const el=document.getElementById(id);\n    const map={'ips-f-name':'name','ips-f-email':'email','ips-f-whatsapp':'whatsapp','ips-f-line':'line','ips-f-loc':'location','ips-f-notes':'notes'};\n    if(el) el.addEventListener('input',()=>{st[map[id]]=el.value;persistSessionState()});\n  });\n}\n\nfunction goTo(n){\n  saveContactFields();\n  st.step = Math.max(0, Math.min(STEPS.length-1, n));\n  persistSessionState();\n  render();\n  requestAnimationFrame(()=>{\n    track.querySelectorAll('.ips-view').forEach(v=>v.scrollTop=0);\n    \/\/ Only scroll the page if the estimator has been scrolled past.\n    \/\/ Prevents a jarring jump when the user is already looking at the tool.\n    const top = root.getBoundingClientRect().top;\n    if(top < -40){\n      root.scrollIntoView({block:'start', behavior:'smooth'});\n    }\n  });\n}\nfunction saveContactFields(){\n  ['ips-f-name','ips-f-email','ips-f-whatsapp','ips-f-line','ips-f-loc','ips-f-notes'].forEach(id=>{\n    const el=document.getElementById(id);\n    const map={'ips-f-name':'name','ips-f-email':'email','ips-f-whatsapp':'whatsapp','ips-f-line':'line','ips-f-loc':'location','ips-f-notes':'notes'};\n    if(el) st[map[id]] = el.value;\n  });\n  persistSessionState();\n}\nfunction validate(isFinal=false){\n  const key=STEPS[st.step];\n  if(key==='setting' && !st.setting){alert('Please choose your project setting.'); return false;}\n  if(key==='style'   && !st.style){  alert('Please choose a preferred style.'); return false;}\n  if(key==='timing'  && !st.timeline){alert('Please choose where you are in your project.'); return false;}\n  if(isFinal || key==='contact'){\n    saveContactFields();\n    if(!st.name || !st.email){alert('Please fill in your name and email.'); return false;}\n    if(!\/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$\/.test(st.email)){alert('Please enter a valid email address.'); return false;}\n  }\n  return true;\n}\n\nfunction inquiryPayload(){\n  const b = buildById(st.build);\n  const sv = settingById(st.setting);\n  const sty = D.style.find(x=>x.id===st.style);\n  const readiness = D.timing.find(x=>x.id===st.timeline);\n  const guide = priceGuide();\n  return {\n    customer_name:st.name,\n    email:st.email,\n    whatsapp:st.whatsapp,\n    customer_line_id:st.line,\n    project_location:st.location,\n    project_notes:st.notes,\n    project_reference:createProjectReference(),\n    submission_language:'English',\n    project_setting:sv?.name || 'Not specified',\n    build_type:b.name,\n    preferred_style:sty?.name || 'Not specified',\n    project_scale:D.scale[st.scale].name,\n    project_readiness:readiness?.label || 'Not specified',\n    estimated_investment:isCustomBuild() ? 'On-site pricing review' : priceText(guide),\n    source_page:window.location.href\n  };\n}\n\nasync function submitInquiry(button){\n  if(inquirySubmitting) return;\n  const payload = inquiryPayload();\n  const signature = JSON.stringify(payload);\n  if(signature===lastSubmittedInquiry){showResult(); return;}\n\n  inquirySubmitting = true;\n  const originalText = button.textContent;\n  button.disabled = true;\n  button.textContent = 'Sending\u2026';\n  try{\n    const body = new URLSearchParams({\n      action:'fluentform_submit',\n      form_id:String(FLUENT_FORM.id),\n      data:new URLSearchParams(payload).toString()\n    });\n    const response = await fetch(FLUENT_FORM.endpoint, {\n      method:'POST',\n      credentials:'same-origin',\n      headers:{'Content-Type':'application\/x-www-form-urlencoded; charset=UTF-8'},\n      body:body.toString()\n    });\n    const result = await response.json();\n    if(!response.ok || !result?.success || !result?.data?.result){\n      throw new Error('Fluent Forms did not accept the inquiry.');\n    }\n    lastSubmittedInquiry = signature;\n    showResult();\n  }catch(error){\n    console.error('Sales inquiry submission failed:', error);\n    alert('We could not send your inquiry right now. Please try again, or continue with us on LINE.');\n    showResult();\n  }finally{\n    inquirySubmitting = false;\n    button.disabled = false;\n    button.textContent = originalText;\n  }\n}\n\n\/\/ \u2500\u2500\u2500 Lightbox \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction openGallery(id){\n  const b = buildById(id);\n  document.getElementById('ipsLbName').textContent = b.name;\n  document.getElementById('ipsLbDesc').textContent = b.desc;\n  const grid = document.getElementById('ipsLbGrid');\n  grid.innerHTML = b.gallery.map((src,i)=>\n    `<div class=\"ips-lb-tile\"><img src=\"${src}\" alt=\"${b.name} example ${i+1}\" loading=\"lazy\" decoding=\"async\"><\/div>`\n  ).join('');\n  const selBtn = document.getElementById('ipsLbSelect');\n  selBtn.textContent = 'I Want This';\n  selBtn.onclick = ()=>{\n    selectBuild(id);\n    closeLightbox();\n    goTo(st.step+1);\n  };\n  document.getElementById('ipsLbBack').onclick = closeLightbox;\n  document.getElementById('ipsLightbox').classList.add('open');\n}\nfunction closeLightbox(){document.getElementById('ipsLightbox').classList.remove('open')}\ndocument.getElementById('ipsLbClose').addEventListener('click',closeLightbox);\ndocument.getElementById('ipsLightbox').addEventListener('click',e=>{\n  if(e.target.id==='ipsLightbox') closeLightbox();\n});\n\n\/\/ \u2500\u2500\u2500 Result modal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction showResult(){\n  const b  = buildById(st.build);\n  const sv = settingById(st.setting);\n  const sty= D.style.find(x=>x.id===st.style);\n  const custom = isCustomBuild();\n  const guide = priceGuide();\n  if(!custom && !guide) return;\n  const reference = createProjectReference();\n  const shownPrice = custom ? 'On-site pricing review' : priceText(guide);\n\n  document.getElementById('ipsResultEyebrow').textContent = custom ? 'Your priority project brief' : 'Your personalised estimate';\n  document.getElementById('ipsResultTitle').textContent = custom ? 'Your project qualifies for a priority site visit.' : 'Your personalised wellness estimate is ready.';\n  document.getElementById('ipsPriceLabel').textContent = custom ? 'Your priority care' : (guide.from ? 'Starting investment' : 'Typical project cost');\n  document.getElementById('ipsPrice').textContent = shownPrice;\n  document.getElementById('ipsPriceCaveat').textContent = custom\n    ? 'Your project qualifies you for an on-site visit so our build team can offer the best price for your build. You will receive priority care from our team.'\n    : (guide.plus\n      ? 'This is the starting point for a bespoke wellness space. Our build team will refine the investment around your property and vision.'\n      : (guide.from\n        ? 'A considered starting point based on your choices. Our build team will refine the right investment with you.'\n        : 'A personalised guide based on your selections. Materials, features and site details may shape the final investment.'));\n\n  document.getElementById('ipsResultSummary').innerHTML = [\n    ['Reference',reference],\n    ['Setting',sv?.name || '\u2014'],\n    ['Build type',b.name],\n    ['Style',sty?.name || '\u2014'],\n    ['Size',D.scale[st.scale].name],\n    ['Readiness',D.timing.find(x=>x.id===st.timeline)?.label || '\u2014'],\n    ['Location',st.location || 'Not specified']\n  ].map(row=>`<div class=\"ips-result-row\"><span>${row[0]}<\/span><span>${row[1]}<\/span><\/div>`).join('');\n  const msg = [\n    'Hello, I completed the Interpool Spa project tool.',\n    `Reference: ${reference}`,\n    `Name: ${st.name}`,\n    `Email: ${st.email}`,\n    `Project: ${D.scale[st.scale].name} ${b.name}`,\n    `Setting: ${sv?.name || 'Not specified'}`,\n    `Style: ${sty?.name || 'Not specified'}`,\n    `Project stage: ${D.timing.find(x=>x.id===st.timeline)?.label || 'Not specified'}`,\n    `Location: ${st.location || 'Not specified'}`,\n    ...(st.notes ? [`Notes: ${st.notes}`] : []),\n    custom ? 'I would like a custom budget review.' : `Indicative investment shown: ${shownPrice}`\n  ].join('\\n');\n  const lineUrl = lineHandoffUrl(msg);\n  document.getElementById('ipsLineLink').href = lineUrl;\n  document.getElementById('ipsLineLinkMobile').href = lineUrl;\n  document.getElementById('ipsResult').classList.add('open');\n}\nfunction closeResult(){document.getElementById('ipsResult').classList.remove('open')}\ndocument.getElementById('ipsResultClose').addEventListener('click',closeResult);\ndocument.getElementById('ipsResultClose2').addEventListener('click',closeResult);\ndocument.getElementById('ipsResult').addEventListener('click',e=>{\n  if(e.target.id==='ipsResult') closeResult();\n});\ndocument.addEventListener('keydown',e=>{\n  if(e.key==='Escape'){closeLightbox(); closeResult();}\n});\n\n\/\/ \u2500\u2500\u2500 Boot \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\npreloadInitial();\nstageBg.style.backgroundImage   = `url('${D.bg.intro}')`;\nstageBg.style.backgroundPosition= 'center center';\nrender();\n\n})();\n<\/script>\n<\/body>\n<\/html>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>",
        "protected": false
    },
    "excerpt": {
        "rendered": "<p>Interpool Spa Estimator \u2014 English TH EN Back to siteHome Welcome Step 1 of 7 \u2715 \u2190 Back I Want This Your personalised estimate Let&#8217;s bring your vision to life. \u2715 Estimated investment range \u2014 This is a planning guide to help you budget with confidence. Final pricing is confirmed after a site visit, design [&hellip;]<\/p>",
        "protected": false
    },
    "author": 1,
    "featured_media": 0,
    "parent": 0,
    "menu_order": 0,
    "comment_status": "closed",
    "ping_status": "closed",
    "template": "elementor_canvas",
    "meta": {
        "inline_featured_image": false,
        "footnotes": ""
    },
    "class_list": [
        "post-16183",
        "page",
        "type-page",
        "status-publish",
        "hentry"
    ],
    "_links": {
        "self": [
            {
                "href": "https:\/\/interpoolspa.com\/en\/wp-json\/wp\/v2\/pages\/16183",
                "targetHints": {
                    "allow": [
                        "GET"
                    ]
                }
            }
        ],
        "collection": [
            {
                "href": "https:\/\/interpoolspa.com\/en\/wp-json\/wp\/v2\/pages"
            }
        ],
        "about": [
            {
                "href": "https:\/\/interpoolspa.com\/en\/wp-json\/wp\/v2\/types\/page"
            }
        ],
        "author": [
            {
                "embeddable": true,
                "href": "https:\/\/interpoolspa.com\/en\/wp-json\/wp\/v2\/users\/1"
            }
        ],
        "replies": [
            {
                "embeddable": true,
                "href": "https:\/\/interpoolspa.com\/en\/wp-json\/wp\/v2\/comments?post=16183"
            }
        ],
        "version-history": [
            {
                "count": 102,
                "href": "https:\/\/interpoolspa.com\/en\/wp-json\/wp\/v2\/pages\/16183\/revisions"
            }
        ],
        "predecessor-version": [
            {
                "id": 17852,
                "href": "https:\/\/interpoolspa.com\/en\/wp-json\/wp\/v2\/pages\/16183\/revisions\/17852"
            }
        ],
        "wp:attachment": [
            {
                "href": "https:\/\/interpoolspa.com\/en\/wp-json\/wp\/v2\/media?parent=16183"
            }
        ],
        "curies": [
            {
                "name": "wp",
                "href": "https:\/\/api.w.org\/{rel}",
                "templated": true
            }
        ]
    }
}