{"id":59083,"date":"2026-05-12T18:38:16","date_gmt":"2026-05-12T18:38:16","guid":{"rendered":"https:\/\/staging.nxtprocess.com\/demonstration-de-lentonnoir\/"},"modified":"2026-05-12T18:44:57","modified_gmt":"2026-05-12T18:44:57","slug":"demonstration-de-lentonnoir","status":"publish","type":"page","link":"https:\/\/staging.nxtprocess.com\/fr\/demonstration-de-lentonnoir\/","title":{"rendered":"D\u00e9monstration de l\u2019entonnoir"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"59083\" class=\"elementor elementor-59083 elementor-59077\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-77cfd9c e-flex e-con-boxed e-con e-parent\" data-id=\"77cfd9c\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-8ac370a e-flex e-con-boxed e-con e-parent\" data-id=\"8ac370a\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-567c420 elementor-widget elementor-widget-html\" data-id=\"567c420\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div>\n\n\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>NXT Process \u2014 Solutions pour les proc\u00e9d\u00e9s liquides<\/title>\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Outfit:wght@300;400;500;600;700;800&display=swap\" rel=\"stylesheet\">\n<style>\n  * { margin:0; padding:0; box-sizing:border-box; }\n  body { font-family: 'Outfit', system-ui, sans-serif; }\n  #root { min-height: 100vh; }\n<\/style>\n\n\n<div id=\"root\"><\/div>\n\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/react\/18.2.0\/umd\/react.production.min.js\"><\/script>\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/react-dom\/18.2.0\/umd\/react-dom.production.min.js\"><\/script>\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/babel-standalone\/7.23.9\/babel.min.js\"><\/script>\n\n<script type=\"text\/babel\">\nconst { useState, useRef, useEffect } = React;\n\n\/\/ \u2500\u2500\u2500 Product catalog \u2500\u2500\u2500\nconst CATALOG = [\n  {n:\"Ampco CB+ series\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/pump\/centrifugal-pump\/ampco-cb-series\/\",d:\"Centrifugal pump designed for the brewing industry. Optimized for hot, vapor-laden fluids.\",c:\"Pump\",b:\"Ampco\"},\n  {n:\"Deoxygenator\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/deox\/\",d:\"Modular in-line membrane deaeration system removes almost all oxygen from water in minutes.\",c:\"Skid equipment\",b:\"NXT\"},\n  {n:\"Hop incorporator\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/hop-incorporator\/\",d:\"Precise and efficient hop additions. Optimal extraction of hop flavors and aromas.\",c:\"Skid equipment\",b:\"NXT\"},\n  {n:\"Wort aerator\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/wort-aerator\/\",d:\"Maximize yeast performance and fermentation efficiency with precise oxygen dosing.\",c:\"Skid equipment\",b:\"NXT\"},\n  {n:\"Ampco AC\/AC+ series\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/pump\/hygenic-centrifugal-pumps\/ampco-ac-ac-series\/\",d:\"Leading centrifugal pump for hygienic applications. 100% interchangeable with competing brands.\",c:\"Pump\",b:\"Ampco\"},\n  {n:\"Tri-Clamp Butterfly Valve\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/valves\/butterfly\/tri-clamp-butterfly-valve-with-stainless-steel-handle\/\",d:\"Precision control butterfly valve. Engineered for reliability and cleanability.\",c:\"Valves\",b:\"NXT\"},\n  {n:\"Mobile pump\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/mobile-pump\/\",d:\"Portable pump on cart for transferring beer, CIP, and more. Various HP and connections.\",c:\"Skid equipment\",b:\"NXT\"},\n  {n:\"Beer filtration membrane\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/pentair-bmf-beer-filtration-membrane\/\",d:\"Reliable membrane filtration for consistent, flexible, and long-lasting beer filtration.\",c:\"Skid equipment\",b:\"NXT\"},\n  {n:\"Heating and cooling systems\",u:\"https:\/\/staging.nxtprocess.com\/shop\/systems\/cooling\/heating-cooling\/\",d:\"Custom thermal regulation systems for any liquid process.\",c:\"Systems\",b:\"NXT\"},\n  {n:\"Clean-in-place systems\",u:\"https:\/\/staging.nxtprocess.com\/shop\/systems\/cleaning\/clean-in-place-system\/\",d:\"Fully automated CIP solution to clean equipment without disassembly.\",c:\"Systems\",b:\"NXT\"},\n  {n:\"Ampco ZP series\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/pump\/hygienic-circumferential-pumps\/ampco-zp-series\/\",d:\"Hygienic circumferential piston pump for high-viscosity sanitary applications.\",c:\"Pump\",b:\"Ampco\"},\n  {n:\"Ampco AL series\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/pump\/hygenic-lobe-pumps\/ampco-al-series\/\",d:\"Hygienic rotary lobe pump for food, beverage, and pharma.\",c:\"Pump\",b:\"Ampco\"},\n  {n:\"Drum unloader\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/drum-unloader\/\",d:\"Sanitary drum unloading with tracking plates for various barrel diameters.\",c:\"Skid equipment\",b:\"NXT\"},\n  {n:\"JET-shear in-tank mixer\",u:\"https:\/\/staging.nxtprocess.com\/shop\/food\/jet-shear-in-tank-mixer\/\",d:\"Advanced inline shear mixer for mixing, emulsification, and dispersion.\",c:\"Mixers\",b:\"NXT\"},\n  {n:\"Inline powder mixing\",u:\"https:\/\/staging.nxtprocess.com\/shop\/food\/inline-powder-induction-products\/\",d:\"Powder induction for precision blending. Multiple options available.\",c:\"Mixers\",b:\"NXT\"},\n  {n:\"Beer Chamber Pasteurizer\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/chamber-pasteurizer\/\",d:\"Compact pasteurizer for craft breweries to extend shelf life.\",c:\"Skid equipment\",b:\"NXT\"},\n  {n:\"Haffmans CBR Carbo Blender\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/haffman-cbr-carbo-blender\/\",d:\"Precise and consistent carbonation for professional breweries.\",c:\"Skid equipment\",b:\"Pentair Haffmans\"},\n  {n:\"Haffmans CCR Carbo Controller\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/pentair-haffmans-ccr-carbo-controller\/\",d:\"In-line carbonation system for perfect CO2 levels continuously.\",c:\"Skid equipment\",b:\"Pentair Haffmans\"},\n  {n:\"Mixing systems\",u:\"https:\/\/staging.nxtprocess.com\/shop\/systems\/mixing\/mixing-system\/\",d:\"Custom mixing for blending, homogenizing, or dissolving.\",c:\"Systems\",b:\"NXT\"},\n  {n:\"CO2 recovery systems\",u:\"https:\/\/staging.nxtprocess.com\/shop\/systems\/gas-recovery\/co2-recovery-system\/\",d:\"Capture and reuse CO2 from fermentation. Reduce costs and carbon footprint.\",c:\"Systems\",b:\"NXT\"},\n  {n:\"Pigging systems\",u:\"https:\/\/staging.nxtprocess.com\/shop\/systems\/cleaning\/pigging-systems\/\",d:\"Product recovery rate over 99.5%. Reduce losses in pipelines.\",c:\"Systems\",b:\"NXT\"},\n  {n:\"40MP Tri-Clamp Gasket\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/hardware\/tri-clamp-fittings\/40mp-tri-clamp-gasket\/\",d:\"Certified, hygienic, leak-free seal. Multiple materials.\",c:\"Fittings\",b:\"Dixon\"},\n  {n:\"Ampco SB shear mixers\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/mixers\/shear-mixer\/ampco-sb-series-shear-mixers\/\",d:\"High-performance inline shear mixer. Up to 100,000 cps.\",c:\"Mixers\",b:\"Ampco\"},\n  {n:\"NXT static mixer\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/mixers\/static-mixers\/static-mixer\/\",d:\"Zero moving parts, zero maintenance. Compact inline mixing.\",c:\"Mixers\",b:\"NXT\"},\n  {n:\"Plate heat exchanger\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/heat-exchangers\/plate-heat-exchangers\/plate\/\",d:\"Plate heat exchanger for heating, cooling, pasteurization.\",c:\"Heat Exchangers\",b:\"NXT\"},\n  {n:\"Tubular heat exchanger\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/heat-exchangers\/shell-tube-heat-exchangers\/tubular\/\",d:\"Shell and tube heat exchanger for sanitary applications.\",c:\"Heat Exchangers\",b:\"NXT\"},\n  {n:\"Bulk bag unloader\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/bulk-bag-unloader\/\",d:\"Efficient, dust-free handling of bulk ingredients.\",c:\"Skid equipment\",b:\"NXT\"},\n];\n\nconst CATALOG_STR = JSON.stringify(CATALOG.map((p,i) => ({i, name:p.n, desc:p.d, cat:p.c, brand:p.b})));\n\n\/\/ \u2500\u2500\u2500 Search index for part finder \u2500\u2500\u2500\nconst SEARCH_INDEX = CATALOG.map((p, i) => ({\n  i,\n  text: [p.n, p.c||\"\", p.b||\"\", p.d].join(\" \").toLowerCase()\n}));\n\nfunction preFilter(query, max = 20) {\n  const q = query.toLowerCase();\n  const terms = q.split(\/\\s+\/).filter(t => t.length > 1);\n  return SEARCH_INDEX.map(entry => {\n    let score = 0;\n    if (entry.text.includes(q)) score += 100;\n    for (const t of terms) {\n      if (entry.text.includes(t)) score += 10;\n      if (CATALOG[entry.i].n.toLowerCase().includes(t)) score += 20;\n      if ((CATALOG[entry.i].b||\"\").toLowerCase().includes(t)) score += 15;\n    }\n    return { i: entry.i, score };\n  }).filter(e => e.score > 0).sort((a, b) => b.score - a.score).slice(0, max).map(e => e.i);\n}\n\nconst BEST_MATCHES = [\n  {\n    keywords:[\"brewery pump\",\"brewing pump\",\"craft beer pump\",\"beer pump\"],\n    product:{\n      name:\"Ampco CB+ Centrifugal Pump\",\n      url:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/pump\/centrifugal-pump\/ampco-cb-series\/\",\n      reason:\"The Ampco CB+ is the industry standard for breweries \u2014 designed for sanitary CIP-compatible pumping of beer, wort, and other brewing fluids.\",\n    }\n  }\n];\n\nfunction findBestMatch(query) {\n  const q = query.toLowerCase();\n  for (const bm of BEST_MATCHES) {\n    for (const kw of bm.keywords) { if (q.includes(kw)) return bm.product; }\n  }\n  return null;\n}\n\n\/\/ \u2500\u2500\u2500 Industry tiles config \u2500\u2500\u2500\nconst INDUSTRIES = [\n  { id:\"food\", label:\"Food\", icon:\"\ud83c\udfed\", desc:\"Processing & packaging\" },\n  { id:\"beverages\", label:\"Beverages\", icon:\"\ud83e\udd64\", desc:\"Juice, water, seltzer\" },\n  { id:\"brewing\", label:\"Brewing\", icon:\"\ud83c\udf7a\", desc:\"Craft & industrial\" },\n  { id:\"chemical\", label:\"Chemical\", icon:\"\u2697\ufe0f\", desc:\"Industrial processing\" },\n  { id:\"hydrometallurgy\", label:\"Hydrometallurgy\", icon:\"\u26cf\ufe0f\", desc:\"Metal extraction\" },\n  { id:\"cosmetics\", label:\"Cosmetics\", icon:\"\u2728\", desc:\"Personal care & beauty\" },\n  { id:\"other\", label:\"Other\", icon:\"\ud83d\udd27\", desc:\"Tell us more\" },\n];\n\nasync function callAPI(system, userMsg) {\n  const resp = await fetch(\"https:\/\/api.anthropic.com\/v1\/messages\", {\n    method:\"POST\", headers:{\"Content-Type\":\"application\/json\"},\n    body:JSON.stringify({ model:\"claude-sonnet-4-20250514\", max_tokens:1500, system, messages:[{role:\"user\",content:userMsg}] })\n  });\n  const data = await resp.json();\n  return data.content.map(c => c.text||\"\").join(\"\").replace(\/```json|```\/g,\"\").trim();\n}\n\n\/\/ \u2500\u2500\u2500 Problem tiles config \u2500\u2500\u2500\nconst PROBLEMS = [\n  { id:\"quality\", label:\"Increase quality\", icon:\"\u2705\", desc:\"Better consistency & standards\" },\n  { id:\"productivity\", label:\"Increase productivity\", icon:\"\u26a1\", desc:\"Higher throughput & efficiency\" },\n  { id:\"automate\", label:\"Automate production\", icon:\"\ud83e\udd16\", desc:\"Reduce manual operations\" },\n  { id:\"part\", label:\"Find a specific part\", icon:\"\ud83d\udd29\", desc:\"Fittings, pumps, sensors...\" },\n  { id:\"energy\", label:\"Recuperate energy\", icon:\"\u267b\ufe0f\", desc:\"Heat recovery & sustainability\" },\n  { id:\"factory\", label:\"Build a new factory\", icon:\"\ud83c\udfd7\ufe0f\", desc:\"Greenfield project\" },\n  { id:\"codevelop\", label:\"Co-develop a new process\", icon:\"\ud83e\uddea\", desc:\"R&D partnership\" },\n  { id:\"else\", label:\"Something else\", icon:\"\ud83d\udcac\", desc:\"Tell us more\" },\n];\n\n\/\/ \u2500\u2500\u2500 Sub-problems: industry+problem \u2192 specific options \u2500\u2500\u2500\n\/\/ Key format: \"industryId:problemId\"\nconst SUB_PROBLEMS = {\n  \"brewing:quality\": {\n    question: \"What aspect of quality do you want to improve?\",\n    subtitle: \"Select your focus area\",\n    options: [\n      { id:\"oxygen\", label:\"Oxygen management\", icon:\"\ud83d\udca8\", desc:\"Control dissolved O\u2082 levels\" },\n      { id:\"carbonation\", label:\"Carbonation management\", icon:\"\ud83e\udee7\", desc:\"Precise CO\u2082 control\" },\n      { id:\"filtration\", label:\"Filtration\", icon:\"\ud83d\udd2c\", desc:\"Clarity & consistency\" },\n      { id:\"general_quality\", label:\"General improvement\", icon:\"\ud83d\udcc8\", desc:\"Overall quality uplift\" },\n    ]\n  },\n  \/\/ Add more combos here:\n  \/\/ \"brewing:productivity\": { question: \"...\", options: [...] },\n  \/\/ \"food:quality\": { question: \"...\", options: [...] },\n};\n\n\/\/ \u2500\u2500\u2500 Curated solutions: industry:problem:subproblem \u2192 expert answer \u2500\u2500\u2500\n\/\/ When a curated solution exists, skip the chat and show the answer directly.\nconst CURATED_SOLUTIONS = {\n  \"brewing:quality:oxygen\": {\n    title: \"Oxygen Management\",\n    text: \"Oxygen management starts with accurate dissolved gas monitoring. The industry standard is Pentair-Haffmans instruments and NXT is the certified distributor for Canada.\",\n    product: {\n      name: \"Pentair-Haffmans Gehaltemeter\",\n      url: \"https:\/\/staging.nxtprocess.com\/shop\/distribution\/probes\/co2-o2-tpo-mobile-analysis-unit\/gehaltemeter-c-dgm-o-dgm-i-dgm\/\",\n      reason: \"Pentair-Haffmans' flagship product for dissolved gas analysis. Measures CO\u2082, O\u2082, and TPO in one portable unit \u2014 the industry reference for brewery quality control.\",\n      brand: \"Pentair Haffmans\",\n    },\n    relatedProducts: [\n      { index: 1, reason: \"Remove dissolved oxygen from water before it enters your process.\" },\n      { index: 3, reason: \"Precisely dose oxygen into wort for optimal yeast performance.\" },\n    ],\n    cta: { type:\"quote\", label:\"Get a quote for oxygen management\" },\n  },\n  \/\/ Add more curated solutions:\n  \/\/ \"brewing:quality:carbonation\": { title, text, product, cta },\n  \/\/ \"brewing:quality:filtration\": { title, text, product, cta },\n};\n\nfunction App() {\n  const [stage, setStage] = useState(\"home\"); \/\/ home, problem, subproblem, solution, chat, parts\n  const [industry, setIndustry] = useState(null);\n  const [problem, setProblem] = useState(null);\n  const [subProblem, setSubProblem] = useState(null);\n  const [curatedSolution, setCuratedSolution] = useState(null);\n  const [messages, setMessages] = useState([]);\n  const [input, setInput] = useState(\"\");\n  const [loading, setLoading] = useState(false);\n  const [partQuery, setPartQuery] = useState(\"\");\n  const [partResults, setPartResults] = useState(null);\n  const [partLoading, setPartLoading] = useState(false);\n  const threadRef = useRef(null);\n  const inputRef = useRef(null);\n  const partInputRef = useRef(null);\n  const contextRef = useRef({ industry:\"\", problem:\"\", subProblem:\"\", needs:[], history:[] });\n\n  useEffect(() => {\n    if (threadRef.current) threadRef.current.scrollTop = threadRef.current.scrollHeight;\n  }, [messages, loading]);\n\n  function selectIndustry(ind) {\n    setIndustry(ind);\n    setStage(\"problem\");\n    contextRef.current.industry = ind.label;\n  }\n\n  function selectProblem(prob) {\n    setProblem(prob);\n    if (prob.id === \"part\") {\n      setStage(\"parts\");\n      return;\n    }\n    \/\/ Check if there are sub-problems for this industry+problem combo\n    const key = `${industry.id}:${prob.id}`;\n    if (SUB_PROBLEMS[key]) {\n      setStage(\"subproblem\");\n      return;\n    }\n    goToChat(prob.label);\n  }\n\n  function selectSubProblem(sub) {\n    setSubProblem(sub);\n    contextRef.current.subProblem = sub.label;\n    \/\/ Check for curated solution\n    const key = `${industry.id}:${problem.id}:${sub.id}`;\n    if (CURATED_SOLUTIONS[key]) {\n      setCuratedSolution(CURATED_SOLUTIONS[key]);\n      setStage(\"solution\");\n      return;\n    }\n    goToChat(`${problem.label} \u2014 specifically: ${sub.label}`);\n  }\n\n  function goToChat(problemDesc) {\n    setStage(\"chat\");\n    contextRef.current.problem = problemDesc;\n    contextRef.current.history = [\n      { role:\"user\", content:`My industry is ${industry.label}. I want to: ${problemDesc}` }\n    ];\n    send(`My industry is ${industry.label}. I want to: ${problemDesc}`, true);\n  }\n\n  async function send(text, isFirst = false) {\n    if (!text.trim()) return;\n    const userMsg = { role:\"user\", text:text.trim() };\n    if (!isFirst) {\n      setMessages(prev => [...prev, userMsg]);\n      contextRef.current.history.push({ role:\"user\", content:text.trim() });\n    } else {\n      setMessages([userMsg]);\n    }\n    setInput(\"\");\n    setLoading(true);\n\n    try {\n      const historyStr = contextRef.current.history.map(h => `${h.role}: ${h.content}`).join(\"\\n\");\n      const raw = await callAPI(\n`You are the NXT Process advisor \u2014 a conversational product advisor for NXT Process, a liquid process engineering firm based in Canada that sells sanitary parts (fittings, pumps, sensors, valves) and designs complete systems for breweries, dairies, food processing, pharma, cosmetics, chemical, and hydrometallurgy industries.\n\nYour job is to guide visitors from their industry\/project to the right products and services. You are friendly, knowledgeable, and efficient.\n\nALWAYS respond with ONLY valid JSON (no markdown, no backticks):\n\n{\n  \"message\": \"Your conversational response (2-4 sentences max). Be warm and specific to their industry.\",\n  \"options\": [\"Option 1\", \"Option 2\", \"Option 3\", \"Option 4\"] | null,\n  \"products\": [{\"index\": 0, \"reason\": \"why this fits\"}] | null,\n  \"cta\": {\"type\": \"buy\"|\"quote\"|\"consult\", \"label\": \"Button text\"} | null\n}\n\nRules:\n- The visitor already selected their industry. Your first response should acknowledge it and ask what they need help with \u2014 offer 3-4 clickable options specific to their industry.\n- Keep to ONE question at a time. Each question should have options.\n- When you have enough info: recommend specific products from the catalog using \"products\" (index = catalog index). Also suggest a CTA.\n- For simple parts: CTA type = \"buy\". For complex systems: \"quote\". For engineering projects: \"consult\".\n- \"options\" should be short (3-8 words each), practical choices specific to what they said.\n- Keep \"message\" concise and natural.\n\nProduct catalog (use index to reference):\n${CATALOG_STR}`,\n        `Conversation so far:\\n${historyStr}\\n\\nRespond to the latest message.`\n      );\n\n      const parsed = JSON.parse(raw);\n      contextRef.current.history.push({ role:\"assistant\", content:parsed.message });\n      setMessages(prev => [...prev, { role:\"ai\", ...parsed }]);\n    } catch(e) {\n      console.error(e);\n      setMessages(prev => [...prev, { role:\"ai\", message:\"Sorry, something went wrong. Could you try rephrasing that?\" }]);\n    }\n    setLoading(false);\n    setTimeout(() => inputRef.current?.focus(), 100);\n  }\n\n  \/\/ \u2500\u2500\u2500 HOME PAGE \u2500\u2500\u2500\n  if (stage === \"home\") {\n    return (\n      <div style={{ minHeight:\"100vh\", background:\"#0c1222\", color:\"#fff\", fontFamily:\"'Outfit',system-ui,sans-serif\" }}>\n        {\/* Nav *\/}\n        <div style={{ padding:\"20px 24px\", display:\"flex\", alignItems:\"center\", justifyContent:\"space-between\" }}>\n          <div style={{ display:\"flex\", alignItems:\"baseline\", gap:6 }}>\n            <span style={{ fontSize:\"1.4rem\", fontWeight:800, letterSpacing:\"0.06em\", color:\"#fff\" }}>NXT<\/span>\n            <span style={{ fontSize:\"0.7rem\", fontWeight:500, letterSpacing:\"0.08em\", color:\"#4a9eed\", textTransform:\"uppercase\" }}>Process<\/span>\n          <\/div>\n          <a href=\"https:\/\/staging.nxtprocess.com\/contact\/\" target=\"_blank\" rel=\"noopener noreferrer\" style={{ fontSize:\"0.8rem\", fontWeight:500, color:\"#4a9eed\", textDecoration:\"none\", padding:\"6px 14px\", border:\"1px solid #1e3a5f\", borderRadius:6 }}>\n            Contact us\n          <\/a>\n        <\/div>\n\n        {\/* Hero *\/}\n        <div style={{ textAlign:\"center\", padding:\"60px 24px 40px\", maxWidth:680, margin:\"0 auto\" }}>\n          <h1 style={{ fontSize:\"clamp(1.8rem, 5vw, 2.8rem)\", fontWeight:700, lineHeight:1.15, letterSpacing:\"-0.03em\", marginBottom:16, background:\"linear-gradient(135deg, #fff 0%, #a0c4f0 100%)\", WebkitBackgroundClip:\"text\", WebkitTextFillColor:\"transparent\" }}>\n            Optimizing your future, one liquid process at a time\n          <\/h1>\n          <p style={{ fontSize:\"clamp(0.9rem, 2.5vw, 1.05rem)\", color:\"#8b9cc0\", lineHeight:1.7, maxWidth:560, margin:\"0 auto\" }}>\n            NXT Process engineers design innovative liquid process solutions that combine precision, reliability and rapid return on investment\u2014enabling you to grow efficiently while reducing costs.\n          <\/p>\n        <\/div>\n\n        {\/* Industry question *\/}\n        <div style={{ textAlign:\"center\", padding:\"0 24px 20px\" }}>\n          <h2 style={{ fontSize:\"clamp(1.2rem, 3.5vw, 1.6rem)\", fontWeight:700, color:\"#4a9eed\", marginBottom:8 }}>\n            What is your industry?\n          <\/h2>\n          <p style={{ fontSize:\"0.88rem\", color:\"#5a6a8a\", marginBottom:32 }}>Select your sector and we'll guide you to the right solutions<\/p>\n        <\/div>\n\n        {\/* Industry tiles *\/}\n        <div style={{ maxWidth:720, margin:\"0 auto\", padding:\"0 24px 60px\", display:\"grid\", gridTemplateColumns:\"repeat(auto-fill, minmax(200px, 1fr))\", gap:12 }}>\n          {INDUSTRIES.map(ind => (\n            <button key={ind.id} onClick={() => selectIndustry(ind)}\n              style={{\n                fontFamily:\"inherit\", border:\"1px solid #1e2d45\", borderRadius:12,\n                background:\"linear-gradient(180deg, #131d30 0%, #0f1829 100%)\",\n                padding:0, cursor:\"pointer\", overflow:\"hidden\", textAlign:\"left\",\n                transition:\"all 0.25s ease\", position:\"relative\",\n              }}\n              onMouseEnter={e => {\n                e.currentTarget.style.borderColor = \"#4a9eed\";\n                e.currentTarget.style.transform = \"translateY(-3px)\";\n                e.currentTarget.style.boxShadow = \"0 8px 30px rgba(74,158,237,0.15)\";\n              }}\n              onMouseLeave={e => {\n                e.currentTarget.style.borderColor = \"#1e2d45\";\n                e.currentTarget.style.transform = \"translateY(0)\";\n                e.currentTarget.style.boxShadow = \"none\";\n              }}>\n              {\/* Image area with gradient overlay *\/}\n              <div style={{ height:120, position:\"relative\", overflow:\"hidden\", background:`linear-gradient(135deg, #1a2a42 0%, #0d1a2e 100%)`, display:\"flex\", alignItems:\"center\", justifyContent:\"center\", }}>\n                <span style={{ fontSize:\"2.8rem\", opacity:0.6, filter:\"grayscale(50%)\" }}>{ind.icon}<\/span>\n                {\/* Bottom gradient fade *\/}\n                <div style={{ position:\"absolute\", bottom:0, left:0, right:0, height:40, background:\"linear-gradient(transparent, #131d30)\" }} \/>\n              <\/div>\n              {\/* Label *\/}\n              <div style={{ padding:\"14px 16px 16px\" }}>\n                <div style={{ fontSize:\"1rem\", fontWeight:700, color:\"#fff\", marginBottom:2, letterSpacing:\"-0.01em\" }}>{ind.label}<\/div>\n                <div style={{ fontSize:\"0.78rem\", color:\"#5a6a8a\" }}>{ind.desc}<\/div>\n              <\/div>\n            <\/button>\n          ))}\n        <\/div>\n\n        {\/* Bottom text input for free-form *\/}\n        <div style={{ maxWidth:560, margin:\"0 auto\", padding:\"0 24px 48px\" }}>\n          <div style={{ display:\"flex\", gap:8, background:\"#131d30\", border:\"1px solid #1e2d45\", borderRadius:12, padding:6 }}>\n            <input\n              value={input} onChange={e => setInput(e.target.value)}\n              onKeyDown={e => {\n                if (e.key === \"Enter\" && input.trim()) {\n                  setStage(\"chat\");\n                  contextRef.current.industry = \"Unknown\";\n                  contextRef.current.history = [{ role:\"user\", content:input.trim() }];\n                  send(input.trim(), true);\n                }\n              }}\n              placeholder=\"Or describe your project in your own words...\"\n              style={{ flex:1, border:\"none\", outline:\"none\", fontFamily:\"inherit\", fontSize:\"0.9rem\", padding:\"10px 12px\", background:\"transparent\", color:\"#c0ccde\" }}\n            \/>\n            <button onClick={() => {\n              if (input.trim()) {\n                setStage(\"chat\");\n                contextRef.current.industry = \"Unknown\";\n                contextRef.current.history = [{ role:\"user\", content:input.trim() }];\n                send(input.trim(), true);\n              }\n            }}\n              style={{ padding:\"10px 18px\", fontFamily:\"inherit\", fontSize:\"0.82rem\", fontWeight:600, background:\"#4a9eed\", color:\"#fff\", border:\"none\", borderRadius:8, cursor:\"pointer\" }}>\n              Go\n            <\/button>\n          <\/div>\n        <\/div>\n      <\/div>\n    );\n  }\n\n  \/\/ \u2500\u2500\u2500 PROBLEM PAGE \u2500\u2500\u2500\n  if (stage === \"problem\") {\n    return (\n      <div style={{ minHeight:\"100vh\", background:\"#0c1222\", color:\"#fff\", fontFamily:\"'Outfit',system-ui,sans-serif\" }}>\n        {\/* Nav *\/}\n        <div style={{ padding:\"20px 24px\", display:\"flex\", alignItems:\"center\", justifyContent:\"space-between\" }}>\n          <div style={{ display:\"flex\", alignItems:\"center\", gap:12 }}>\n            <button onClick={() => { setStage(\"home\"); setIndustry(null); }}\n              style={{ background:\"none\", border:\"none\", color:\"#4a9eed\", fontSize:\"0.85rem\", fontWeight:500, cursor:\"pointer\", fontFamily:\"inherit\", padding:\"4px 0\" }}>\n              \u2190 Back\n            <\/button>\n            <div style={{ width:1, height:16, background:\"#1e2d45\" }} \/>\n            <span style={{ fontSize:\"1.2rem\", fontWeight:800, letterSpacing:\"0.06em\", color:\"#fff\" }}>NXT<\/span>\n            <span style={{ fontSize:\"0.6rem\", fontWeight:500, letterSpacing:\"0.08em\", color:\"#4a9eed\", textTransform:\"uppercase\" }}>Process<\/span>\n          <\/div>\n          <span style={{ fontSize:\"0.78rem\", fontWeight:500, color:\"#4a9eed\", background:\"#131d30\", padding:\"5px 14px\", borderRadius:20, border:\"1px solid #1e2d45\" }}>\n            {industry?.icon} {industry?.label}\n          <\/span>\n        <\/div>\n\n        {\/* Problem question *\/}\n        <div style={{ textAlign:\"center\", padding:\"50px 24px 20px\" }}>\n          <h2 style={{ fontSize:\"clamp(1.3rem, 3.5vw, 1.8rem)\", fontWeight:700, color:\"#4a9eed\", marginBottom:8 }}>\n            Which problem do you want to solve?\n          <\/h2>\n          <p style={{ fontSize:\"0.88rem\", color:\"#5a6a8a\", marginBottom:36 }}>Tell us what you're looking to achieve and we'll point you in the right direction<\/p>\n        <\/div>\n\n        {\/* Problem tiles *\/}\n        <div style={{ maxWidth:720, margin:\"0 auto\", padding:\"0 24px 40px\", display:\"grid\", gridTemplateColumns:\"repeat(auto-fill, minmax(160px, 1fr))\", gap:10 }}>\n          {PROBLEMS.map(prob => (\n            <button key={prob.id} onClick={() => selectProblem(prob)}\n              style={{\n                fontFamily:\"inherit\", border:\"1px solid #1e2d45\", borderRadius:12,\n                background:\"linear-gradient(180deg, #131d30 0%, #0f1829 100%)\",\n                padding:\"20px 16px\", cursor:\"pointer\", textAlign:\"center\",\n                transition:\"all 0.25s ease\",\n              }}\n              onMouseEnter={e => {\n                e.currentTarget.style.borderColor = \"#4a9eed\";\n                e.currentTarget.style.transform = \"translateY(-3px)\";\n                e.currentTarget.style.boxShadow = \"0 8px 30px rgba(74,158,237,0.15)\";\n              }}\n              onMouseLeave={e => {\n                e.currentTarget.style.borderColor = \"#1e2d45\";\n                e.currentTarget.style.transform = \"translateY(0)\";\n                e.currentTarget.style.boxShadow = \"none\";\n              }}>\n              <div style={{ fontSize:\"1.8rem\", marginBottom:8 }}>{prob.icon}<\/div>\n              <div style={{ fontSize:\"0.9rem\", fontWeight:600, color:\"#fff\", marginBottom:3, lineHeight:1.3 }}>{prob.label}<\/div>\n              <div style={{ fontSize:\"0.73rem\", color:\"#5a6a8a\", lineHeight:1.3 }}>{prob.desc}<\/div>\n            <\/button>\n          ))}\n        <\/div>\n\n        {\/* Free-form input *\/}\n        <div style={{ maxWidth:560, margin:\"0 auto\", padding:\"0 24px 48px\" }}>\n          <div style={{ display:\"flex\", gap:8, background:\"#131d30\", border:\"1px solid #1e2d45\", borderRadius:12, padding:6 }}>\n            <input\n              value={input} onChange={e => setInput(e.target.value)}\n              onKeyDown={e => {\n                if (e.key === \"Enter\" && input.trim()) {\n                  setProblem({ id:\"custom\", label:input.trim(), icon:\"\ud83d\udcac\", desc:\"\" });\n                  setStage(\"chat\");\n                  contextRef.current.problem = input.trim();\n                  contextRef.current.history = [\n                    { role:\"user\", content:`My industry is ${industry.label}. My problem: ${input.trim()}` }\n                  ];\n                  send(`My industry is ${industry.label}. My problem: ${input.trim()}`, true);\n                }\n              }}\n              placeholder=\"Or describe your challenge in your own words...\"\n              style={{ flex:1, border:\"none\", outline:\"none\", fontFamily:\"inherit\", fontSize:\"0.9rem\", padding:\"10px 12px\", background:\"transparent\", color:\"#c0ccde\" }}\n            \/>\n            <button onClick={() => {\n              if (input.trim()) {\n                setProblem({ id:\"custom\", label:input.trim(), icon:\"\ud83d\udcac\", desc:\"\" });\n                setStage(\"chat\");\n                contextRef.current.problem = input.trim();\n                contextRef.current.history = [\n                  { role:\"user\", content:`My industry is ${industry.label}. My problem: ${input.trim()}` }\n                ];\n                send(`My industry is ${industry.label}. My problem: ${input.trim()}`, true);\n              }\n            }}\n              style={{ padding:\"10px 18px\", fontFamily:\"inherit\", fontSize:\"0.82rem\", fontWeight:600, background:\"#4a9eed\", color:\"#fff\", border:\"none\", borderRadius:8, cursor:\"pointer\" }}>\n              Go\n            <\/button>\n          <\/div>\n        <\/div>\n      <\/div>\n    );\n  }\n\n  \/\/ \u2500\u2500\u2500 SUB-PROBLEM PAGE \u2500\u2500\u2500\n  if (stage === \"subproblem\") {\n    const key = `${industry?.id}:${problem?.id}`;\n    const subConfig = SUB_PROBLEMS[key];\n    if (!subConfig) { setStage(\"chat\"); return null; }\n\n    return (\n      <div style={{ minHeight:\"100vh\", background:\"#0c1222\", color:\"#fff\", fontFamily:\"'Outfit',system-ui,sans-serif\" }}>\n        {\/* Nav *\/}\n        <div style={{ padding:\"20px 24px\", display:\"flex\", alignItems:\"center\", justifyContent:\"space-between\" }}>\n          <div style={{ display:\"flex\", alignItems:\"center\", gap:12 }}>\n            <button onClick={() => { setStage(\"problem\"); setProblem(null); setSubProblem(null); }}\n              style={{ background:\"none\", border:\"none\", color:\"#4a9eed\", fontSize:\"0.85rem\", fontWeight:500, cursor:\"pointer\", fontFamily:\"inherit\" }}>\n              \u2190 Back\n            <\/button>\n            <div style={{ width:1, height:16, background:\"#1e2d45\" }} \/>\n            <span style={{ fontSize:\"1.2rem\", fontWeight:800, letterSpacing:\"0.06em\", color:\"#fff\" }}>NXT<\/span>\n            <span style={{ fontSize:\"0.6rem\", fontWeight:500, letterSpacing:\"0.08em\", color:\"#4a9eed\", textTransform:\"uppercase\" }}>Process<\/span>\n          <\/div>\n          <div style={{ display:\"flex\", gap:6 }}>\n            <span style={{ fontSize:\"0.73rem\", fontWeight:500, color:\"#4a9eed\", background:\"#131d30\", padding:\"4px 10px\", borderRadius:20, border:\"1px solid #1e2d45\" }}>\n              {industry?.icon} {industry?.label}\n            <\/span>\n            <span style={{ fontSize:\"0.73rem\", fontWeight:500, color:\"#8bc4f6\", background:\"#131d30\", padding:\"4px 10px\", borderRadius:20, border:\"1px solid #1e2d45\" }}>\n              {problem?.icon} {problem?.label}\n            <\/span>\n          <\/div>\n        <\/div>\n\n        {\/* Question *\/}\n        <div style={{ textAlign:\"center\", padding:\"50px 24px 20px\" }}>\n          <h2 style={{ fontSize:\"clamp(1.3rem, 3.5vw, 1.8rem)\", fontWeight:700, color:\"#4a9eed\", marginBottom:8 }}>\n            {subConfig.question}\n          <\/h2>\n          <p style={{ fontSize:\"0.88rem\", color:\"#5a6a8a\", marginBottom:36 }}>{subConfig.subtitle}<\/p>\n        <\/div>\n\n        {\/* Sub-problem tiles *\/}\n        <div style={{ maxWidth:640, margin:\"0 auto\", padding:\"0 24px 40px\", display:\"grid\", gridTemplateColumns:\"repeat(auto-fill, minmax(180px, 1fr))\", gap:10 }}>\n          {subConfig.options.map(sub => (\n            <button key={sub.id} onClick={() => selectSubProblem(sub)}\n              style={{\n                fontFamily:\"inherit\", border:\"1px solid #1e2d45\", borderRadius:12,\n                background:\"linear-gradient(180deg, #131d30 0%, #0f1829 100%)\",\n                padding:\"22px 16px\", cursor:\"pointer\", textAlign:\"center\",\n                transition:\"all 0.25s ease\",\n              }}\n              onMouseEnter={e => {\n                e.currentTarget.style.borderColor = \"#4a9eed\";\n                e.currentTarget.style.transform = \"translateY(-3px)\";\n                e.currentTarget.style.boxShadow = \"0 8px 30px rgba(74,158,237,0.15)\";\n              }}\n              onMouseLeave={e => {\n                e.currentTarget.style.borderColor = \"#1e2d45\";\n                e.currentTarget.style.transform = \"translateY(0)\";\n                e.currentTarget.style.boxShadow = \"none\";\n              }}>\n              <div style={{ fontSize:\"1.8rem\", marginBottom:8 }}>{sub.icon}<\/div>\n              <div style={{ fontSize:\"0.9rem\", fontWeight:600, color:\"#fff\", marginBottom:3, lineHeight:1.3 }}>{sub.label}<\/div>\n              <div style={{ fontSize:\"0.73rem\", color:\"#5a6a8a\", lineHeight:1.3 }}>{sub.desc}<\/div>\n            <\/button>\n          ))}\n        <\/div>\n\n        {\/* Free-form input *\/}\n        <div style={{ maxWidth:560, margin:\"0 auto\", padding:\"0 24px 48px\" }}>\n          <div style={{ display:\"flex\", gap:8, background:\"#131d30\", border:\"1px solid #1e2d45\", borderRadius:12, padding:6 }}>\n            <input\n              value={input} onChange={e => setInput(e.target.value)}\n              onKeyDown={e => {\n                if (e.key === \"Enter\" && input.trim()) {\n                  setSubProblem({ id:\"custom\", label:input.trim(), icon:\"\ud83d\udcac\", desc:\"\" });\n                  goToChat(`${problem.label} \u2014 specifically: ${input.trim()}`);\n                }\n              }}\n              placeholder=\"Or describe your specific challenge...\"\n              style={{ flex:1, border:\"none\", outline:\"none\", fontFamily:\"inherit\", fontSize:\"0.9rem\", padding:\"10px 12px\", background:\"transparent\", color:\"#c0ccde\" }}\n            \/>\n            <button onClick={() => {\n              if (input.trim()) {\n                setSubProblem({ id:\"custom\", label:input.trim(), icon:\"\ud83d\udcac\", desc:\"\" });\n                goToChat(`${problem.label} \u2014 specifically: ${input.trim()}`);\n              }\n            }}\n              style={{ padding:\"10px 18px\", fontFamily:\"inherit\", fontSize:\"0.82rem\", fontWeight:600, background:\"#4a9eed\", color:\"#fff\", border:\"none\", borderRadius:8, cursor:\"pointer\" }}>\n              Go\n            <\/button>\n          <\/div>\n        <\/div>\n      <\/div>\n    );\n  }\n\n  \/\/ \u2500\u2500\u2500 CURATED SOLUTION PAGE \u2500\u2500\u2500\n  if (stage === \"solution\" && curatedSolution) {\n    const sol = curatedSolution;\n    return (\n      <div style={{ minHeight:\"100vh\", background:\"#fafbfc\", fontFamily:\"'Outfit',system-ui,sans-serif\" }}>\n        {\/* Header *\/}\n        <div style={{ background:\"#0c1222\", padding:\"14px 24px\", display:\"flex\", alignItems:\"center\", justifyContent:\"space-between\" }}>\n          <div style={{ display:\"flex\", alignItems:\"center\", gap:12 }}>\n            <button onClick={() => { setStage(\"subproblem\"); setCuratedSolution(null); setSubProblem(null); }}\n              style={{ background:\"none\", border:\"none\", color:\"#4a9eed\", fontSize:\"0.85rem\", fontWeight:500, cursor:\"pointer\", fontFamily:\"inherit\" }}>\n              \u2190 Back\n            <\/button>\n            <div style={{ width:1, height:16, background:\"#1e2d45\" }} \/>\n            <span style={{ fontSize:\"0.8rem\", fontWeight:600, letterSpacing:\"0.06em\", color:\"#fff\" }}>NXT<\/span>\n            <span style={{ fontSize:\"0.65rem\", color:\"#4a9eed\", fontWeight:500, letterSpacing:\"0.06em\", textTransform:\"uppercase\" }}>Process Advisor<\/span>\n          <\/div>\n          <div style={{ display:\"flex\", gap:6, flexWrap:\"wrap\", justifyContent:\"flex-end\" }}>\n            <span style={{ fontSize:\"0.73rem\", fontWeight:500, color:\"#4a9eed\", background:\"#131d30\", padding:\"4px 10px\", borderRadius:20, border:\"1px solid #1e2d45\" }}>\n              {industry?.icon} {industry?.label}\n            <\/span>\n            <span style={{ fontSize:\"0.73rem\", fontWeight:500, color:\"#8bc4f6\", background:\"#131d30\", padding:\"4px 10px\", borderRadius:20, border:\"1px solid #1e2d45\" }}>\n              {problem?.icon} {problem?.label}\n            <\/span>\n          <\/div>\n        <\/div>\n\n        <div style={{ maxWidth:680, margin:\"0 auto\", padding:\"32px 16px\" }}>\n          {\/* Solution title *\/}\n          <div style={{ marginBottom:24 }}>\n            <div style={{ fontSize:\"0.73rem\", fontWeight:600, textTransform:\"uppercase\", letterSpacing:\"0.06em\", color:\"#1a6fd4\", marginBottom:6 }}>NXT Recommendation<\/div>\n            <h2 style={{ fontSize:\"1.5rem\", fontWeight:700, letterSpacing:\"-0.02em\", color:\"#0f1729\", marginBottom:12 }}>{sol.title}<\/h2>\n            <p style={{ fontSize:\"0.95rem\", color:\"#3d4654\", lineHeight:1.7 }}>{sol.text}<\/p>\n          <\/div>\n\n          {\/* Featured product *\/}\n          {sol.product && (\n            <a href={sol.product.url} target=\"_blank\" rel=\"noopener noreferrer\" style={{ display:\"block\", background:\"linear-gradient(135deg, #e6f5ed 0%, #fff 100%)\", border:\"2px solid #0b7a3e\", borderRadius:12, padding:\"20px 24px\", textDecoration:\"none\", color:\"inherit\", marginBottom:12 }}>\n              <div style={{ display:\"flex\", justifyContent:\"space-between\", alignItems:\"flex-start\", gap:10, marginBottom:6 }}>\n                <span style={{ fontSize:\"1.05rem\", fontWeight:700, color:\"#0b7a3e\" }}>{sol.product.name}<\/span>\n                <span style={{ fontSize:\"0.7rem\", fontWeight:600, padding:\"4px 10px\", borderRadius:20, background:\"#0b7a3e\", color:\"#fff\", whiteSpace:\"nowrap\" }}>\u2605 NXT Recommended<\/span>\n              <\/div>\n              {sol.product.brand && (\n                <p style={{ fontSize:\"0.78rem\", fontWeight:600, color:\"#0b7a3e\", marginBottom:6, opacity:0.7 }}>{sol.product.brand}<\/p>\n              )}\n              <p style={{ fontSize:\"0.88rem\", color:\"#3d4654\", lineHeight:1.6, marginBottom:8 }}>{sol.product.reason}<\/p>\n              <span style={{ fontSize:\"0.85rem\", fontWeight:600, color:\"#0b7a3e\" }}>View product \u2192<\/span>\n            <\/a>\n          )}\n\n          {\/* Related products *\/}\n          {sol.relatedProducts && sol.relatedProducts.length > 0 && (\n            <div style={{ marginTop:16 }}>\n              <p style={{ fontSize:\"0.75rem\", fontWeight:600, textTransform:\"uppercase\", letterSpacing:\"0.04em\", color:\"#8b95a5\", marginBottom:10 }}>You might also need<\/p>\n              {sol.relatedProducts.map((rp, j) => {\n                const p = CATALOG[rp.index];\n                if (!p) return null;\n                return (\n                  <a key={j} href={p.u} target=\"_blank\" rel=\"noopener noreferrer\" style={{ display:\"block\", background:\"#fff\", border:\"1px solid #e0e4ea\", borderRadius:12, padding:\"16px 20px\", textDecoration:\"none\", color:\"inherit\", marginBottom:8, transition:\"all 0.2s\" }} onMouseEnter={e => { e.currentTarget.style.boxShadow=\"0 4px 16px rgba(0,0,0,0.08)\"; e.currentTarget.style.borderColor=\"#1a6fd4\"; }}\n                    onMouseLeave={e => { e.currentTarget.style.boxShadow=\"none\"; e.currentTarget.style.borderColor=\"#e0e4ea\"; }}>\n                    <div style={{ display:\"flex\", justifyContent:\"space-between\", alignItems:\"flex-start\", gap:10, marginBottom:4 }}>\n                      <span style={{ fontSize:\"0.95rem\", fontWeight:600, color:\"#1a6fd4\" }}>{p.n}<\/span>\n                      <span style={{ fontSize:\"0.68rem\", fontWeight:600, padding:\"3px 9px\", borderRadius:20, background:\"#e6f5ed\", color:\"#0b7a3e\" }}>{p.b}<\/span>\n                    <\/div>\n                    <p style={{ fontSize:\"0.84rem\", color:\"#5f6b7a\", lineHeight:1.5, marginBottom:4 }}>{rp.reason}<\/p>\n                    <span style={{ fontSize:\"0.82rem\", fontWeight:600, color:\"#1a6fd4\" }}>View product \u2192<\/span>\n                  <\/a>\n                );\n              })}\n            <\/div>\n          )}\n\n          {\/* CTA *\/}\n          {sol.cta && (\n            <div style={{ background:\"#f3f5f8\", border:\"1px dashed #d0d5dd\", borderRadius:12, padding:\"20px\", marginTop:16, display:\"flex\", flexDirection:\"column\", gap:10 }}>\n              <a href=\"https:\/\/staging.nxtprocess.com\/contact\/\" target=\"_blank\" rel=\"noopener noreferrer\" style={{ fontFamily:\"inherit\", fontSize:\"0.9rem\", fontWeight:600, padding:\"14px 24px\", borderRadius:10, border:\"none\", textAlign:\"center\", textDecoration:\"none\", display:\"block\", color:\"#fff\", background: sol.cta.type === \"buy\" ? \"#1a6fd4\" : sol.cta.type === \"quote\" ? \"#0b7a3e\" : \"#0c1222\" }}>\n                {sol.cta.label}\n              <\/a>\n              <p style={{ fontSize:\"0.78rem\", color:\"#8b95a5\", textAlign:\"center\" }}>Our engineers respond within 24 hours<\/p>\n            <\/div>\n          )}\n\n          {\/* Continue to chat option *\/}\n          <div style={{ textAlign:\"center\", marginTop:20 }}>\n            <button onClick={() => {\n              goToChat(`${problem.label} \u2014 specifically: ${subProblem.label}`);\n            }}\n              style={{ fontFamily:\"inherit\", fontSize:\"0.85rem\", fontWeight:500, color:\"#1a6fd4\", background:\"none\", border:\"none\", cursor:\"pointer\", textDecoration:\"underline\" }}>\n              I have more questions \u2014 talk to the advisor\n            <\/button>\n          <\/div>\n        <\/div>\n      <\/div>\n    );\n  }\n\n  \/\/ \u2500\u2500\u2500 PARTS FINDER PAGE \u2500\u2500\u2500\n  if (stage === \"parts\") {\n    async function searchParts(q) {\n      if (!q.trim()) return;\n      setPartLoading(true);\n      setPartResults(null);\n      const candidates = preFilter(q);\n      const candidateData = candidates.map(i => ({ index:i, name:CATALOG[i].n, brand:CATALOG[i].b||\"\", description:CATALOG[i].d, categories:CATALOG[i].c||\"\" }));\n      const bestMatch = findBestMatch(q);\n      try {\n        const raw = await callAPI(\n          `Product matcher for NXT Process. Given pre-filtered candidates, return ONLY JSON:\n{\"results\":[{\"index\":<original_index>,\"relevance\":\"high\"|\"medium\",\"reason\":\"why this matches\"}]}\nReturn 1-6 results ranked by relevance.`,\n          `Query: \"${q}\"\\nIndustry context: ${industry?.label || \"unknown\"}\\nCandidates:\\n${JSON.stringify(candidateData)}`\n        );\n        const data = JSON.parse(raw);\n        setPartResults({ items: data.results || [], bestMatch, query: q });\n      } catch(e) {\n        console.error(e);\n        setPartResults({ items: [], bestMatch, query: q, error: true });\n      }\n      setPartLoading(false);\n    }\n\n    const examples = industry?.id === \"brewing\"\n      ? [\"Tri-clamp gasket\", \"Centrifugal pump\", \"Butterfly valve\", \"Sight glass\"]\n      : [\"Tri-clamp fitting\", \"Pressure sensor\", \"Check valve\", \"Heat exchanger\"];\n\n    return (\n      <div style={{ minHeight:\"100vh\", background:\"#fafbfc\", fontFamily:\"'Outfit',system-ui,sans-serif\" }}>\n        {\/* Header *\/}\n        <div style={{ background:\"#0c1222\", padding:\"14px 24px\", display:\"flex\", alignItems:\"center\", justifyContent:\"space-between\" }}>\n          <div style={{ display:\"flex\", alignItems:\"center\", gap:12 }}>\n            <button onClick={() => { setStage(\"problem\"); setPartResults(null); setPartQuery(\"\"); }}\n              style={{ background:\"none\", border:\"none\", color:\"#4a9eed\", fontSize:\"0.85rem\", fontWeight:500, cursor:\"pointer\", fontFamily:\"inherit\" }}>\n              \u2190 Back\n            <\/button>\n            <div style={{ width:1, height:16, background:\"#1e2d45\" }} \/>\n            <span style={{ fontSize:\"0.8rem\", fontWeight:600, letterSpacing:\"0.06em\", color:\"#fff\" }}>NXT<\/span>\n            <span style={{ fontSize:\"0.65rem\", color:\"#4a9eed\", fontWeight:500, letterSpacing:\"0.06em\", textTransform:\"uppercase\" }}>Part Finder<\/span>\n          <\/div>\n          {industry && (\n            <span style={{ fontSize:\"0.73rem\", fontWeight:500, color:\"#4a9eed\", background:\"#131d30\", padding:\"4px 10px\", borderRadius:20, border:\"1px solid #1e2d45\" }}>\n              {industry.icon} {industry.label}\n            <\/span>\n          )}\n        <\/div>\n\n        <div style={{ maxWidth:680, margin:\"0 auto\", padding:\"32px 16px\" }}>\n          {\/* Title *\/}\n          <div style={{ textAlign:\"center\", marginBottom:28 }}>\n            <h2 style={{ fontSize:\"1.5rem\", fontWeight:700, letterSpacing:\"-0.02em\", color:\"#0f1729\", marginBottom:6 }}>Find the Right Part<\/h2>\n            <p style={{ fontSize:\"0.9rem\", color:\"#5f6b7a\" }}>Search by part number, spec, type, or describe what you need.<\/p>\n          <\/div>\n\n          {\/* Search bar *\/}\n          <div style={{ display:\"flex\", gap:8, background:\"#fff\", border:\"2px solid #e0e4ea\", borderRadius:14, padding:6, boxShadow:\"0 2px 12px rgba(0,0,0,0.06)\", marginBottom:12 }}>\n            <input ref={partInputRef} value={partQuery} onChange={e => setPartQuery(e.target.value)}\n              onKeyDown={e => e.key === \"Enter\" && searchParts(partQuery)}\n              placeholder='e.g. \"2 inch tri-clamp\" or \"brewery pump\"'\n              style={{ flex:1, border:\"none\", outline:\"none\", fontFamily:\"inherit\", fontSize:\"0.95rem\", padding:\"10px 12px\", background:\"transparent\", color:\"#111\" }}\n            \/>\n            <button onClick={() => searchParts(partQuery)} disabled={partLoading || !partQuery.trim()}\n              style={{ padding:\"10px 20px\", fontFamily:\"inherit\", fontSize:\"0.85rem\", fontWeight:600, background:\"#1a6fd4\", color:\"#fff\", border:\"none\", borderRadius:10, cursor: partLoading||!partQuery.trim() ? \"not-allowed\":\"pointer\", opacity: partLoading||!partQuery.trim() ? 0.5:1, whiteSpace:\"nowrap\" }}>\n              Search\n            <\/button>\n          <\/div>\n\n          {\/* Example queries *\/}\n          <div style={{ display:\"flex\", flexWrap:\"wrap\", gap:6, marginBottom:28 }}>\n            {examples.map(ex => (\n              <button key={ex} onClick={() => { setPartQuery(ex); searchParts(ex); }}\n                style={{ fontFamily:\"inherit\", fontSize:\"0.78rem\", padding:\"5px 12px\", border:\"1px solid #e0e4ea\", borderRadius:20, background:\"#fff\", color:\"#5f6b7a\", cursor:\"pointer\" }}>\n                {ex}\n              <\/button>\n            ))}\n          <\/div>\n\n          {\/* Loading *\/}\n          {partLoading && (\n            <div style={{ textAlign:\"center\", padding:\"40px 0\" }}>\n              <div style={{ display:\"inline-flex\", gap:5, marginBottom:12 }}>\n                {[0,1,2].map(i => <div key={i} style={{ width:9, height:9, background:\"#1a6fd4\", borderRadius:\"50%\", animation:`pulse 1.1s infinite ${i*0.13}s` }} \/>)}\n              <\/div>\n              <p style={{ fontSize:\"0.85rem\", color:\"#5f6b7a\" }}>Searching products...<\/p>\n              <style>{`@keyframes pulse { 0%,80%,100% { transform:scale(0.55); opacity:0.35; } 40% { transform:scale(1); opacity:1; } }`}<\/style>\n            <\/div>\n          )}\n\n          {\/* Results *\/}\n          {partResults && !partLoading && (\n            <div>\n              {\/* Best match *\/}\n              {partResults.bestMatch && (\n                <a href={partResults.bestMatch.url} target=\"_blank\" rel=\"noopener noreferrer\" style={{ display:\"block\", background:\"linear-gradient(135deg, #e6f5ed 0%, #fff 100%)\", border:\"2px solid #0b7a3e\", borderRadius:12, padding:\"16px 20px\", textDecoration:\"none\", color:\"inherit\", marginBottom:10 }}>\n                  <div style={{ display:\"flex\", justifyContent:\"space-between\", alignItems:\"flex-start\", gap:10, marginBottom:4 }}>\n                    <span style={{ fontSize:\"0.95rem\", fontWeight:600, color:\"#0b7a3e\" }}>{partResults.bestMatch.name}<\/span>\n                    <span style={{ fontSize:\"0.7rem\", fontWeight:600, padding:\"3px 9px\", borderRadius:20, background:\"#0b7a3e\", color:\"#fff\" }}>\u2605 NXT Recommended<\/span>\n                  <\/div>\n                  <p style={{ fontSize:\"0.84rem\", color:\"#5f6b7a\", lineHeight:1.5, marginBottom:6 }}>{partResults.bestMatch.reason}<\/p>\n                  <span style={{ fontSize:\"0.82rem\", fontWeight:600, color:\"#0b7a3e\" }}>View product \u2192<\/span>\n                <\/a>\n              )}\n\n              {\/* AI results *\/}\n              {partResults.items.length > 0 && (\n                <>\n                  {partResults.bestMatch && <p style={{ fontSize:\"0.75rem\", fontWeight:600, textTransform:\"uppercase\", letterSpacing:\"0.04em\", color:\"#8b95a5\", margin:\"16px 0 10px\" }}>Also from our catalog<\/p>}\n                  {partResults.items.map((r, j) => {\n                    const p = CATALOG[r.index];\n                    if (!p) return null;\n                    const isHigh = r.relevance === \"high\";\n                    return (\n                      <a key={j} href={p.u} target=\"_blank\" rel=\"noopener noreferrer\" style={{ display:\"block\", background:\"#fff\", border:\"1px solid #e0e4ea\", borderRadius:12, padding:\"16px 20px\", textDecoration:\"none\", color:\"inherit\", marginBottom:8, transition:\"all 0.2s\" }} onMouseEnter={e => { e.currentTarget.style.boxShadow=\"0 4px 16px rgba(0,0,0,0.08)\"; e.currentTarget.style.borderColor=\"#1a6fd4\"; }}\n                        onMouseLeave={e => { e.currentTarget.style.boxShadow=\"none\"; e.currentTarget.style.borderColor=\"#e0e4ea\"; }}>\n                        <div style={{ display:\"flex\", justifyContent:\"space-between\", alignItems:\"flex-start\", gap:10, marginBottom:4 }}>\n                          <span style={{ fontSize:\"0.95rem\", fontWeight:600, color:\"#1a6fd4\" }}>{p.n}<\/span>\n                          <span style={{ fontSize:\"0.68rem\", fontWeight:500, padding:\"3px 9px\", borderRadius:20, background:isHigh?\"#e6f5ed\":\"#fef6e0\", color:isHigh?\"#0b7a3e\":\"#9a6700\", fontFamily:\"monospace\" }}>\n                            {isHigh ? \"Best match\" : \"Related\"}\n                          <\/span>\n                        <\/div>\n                        <p style={{ fontSize:\"0.84rem\", color:\"#5f6b7a\", lineHeight:1.5, marginBottom:4 }}>{r.reason}<\/p>\n                        <p style={{ fontSize:\"0.76rem\", color:\"#8b95a5\" }}>{p.b ? <strong style={{color:\"#1a6fd4\"}}>{p.b}<\/strong> : null}{p.b ? \" \u00b7 \" : \"\"}{p.c}<\/p>\n                        <span style={{ display:\"inline-block\", marginTop:6, fontSize:\"0.82rem\", fontWeight:600, color:\"#1a6fd4\" }}>View product \u2192<\/span>\n                      <\/a>\n                    );\n                  })}\n                <\/>\n              )}\n\n              {!partResults.bestMatch && partResults.items.length === 0 && (\n                <p style={{ textAlign:\"center\", color:\"#5f6b7a\", padding:20, fontSize:\"0.9rem\" }}>No matches found. Try different terms or <button onClick={() => { setStage(\"chat\"); setProblem({id:\"part\",label:\"Find a specific part\",icon:\"\ud83d\udd29\",desc:\"\"}); contextRef.current.problem=\"Find a specific part\"; contextRef.current.history=[{role:\"user\",content:`My industry is ${industry?.label}. I'm looking for: ${partResults.query}`}]; send(`My industry is ${industry?.label}. I'm looking for: ${partResults.query}`, true); }} style={{ background:\"none\", border:\"none\", color:\"#1a6fd4\", fontWeight:600, cursor:\"pointer\", fontFamily:\"inherit\", fontSize:\"inherit\", textDecoration:\"underline\" }}>ask our advisor<\/button>.<\/p>\n              )}\n\n              {\/* Contact CTA *\/}\n              <div style={{ background:\"#f3f5f8\", border:\"1px dashed #d0d5dd\", borderRadius:12, padding:\"16px 20px\", marginTop:14, display:\"flex\", alignItems:\"center\", justifyContent:\"space-between\", flexWrap:\"wrap\", gap:10 }}>\n                <div>\n                  <p style={{ fontSize:\"0.88rem\", fontWeight:600, color:\"#0f1729\", marginBottom:2 }}>Can't find what you need?<\/p>\n                  <p style={{ fontSize:\"0.8rem\", color:\"#5f6b7a\" }}>Our engineers can help you find the right part.<\/p>\n                <\/div>\n                <a href=\"https:\/\/staging.nxtprocess.com\/contact\/\" target=\"_blank\" rel=\"noopener noreferrer\" style={{ fontFamily:\"inherit\", fontSize:\"0.83rem\", fontWeight:600, padding:\"9px 18px\", background:\"#0f1729\", color:\"#fff\", textDecoration:\"none\", borderRadius:8, whiteSpace:\"nowrap\" }}>\n                  Contact NXT\n                <\/a>\n              <\/div>\n            <\/div>\n          )}\n        <\/div>\n      <\/div>\n    );\n  }\n\n  if (stage === \"chat\") return (\n    <div style={{ minHeight:\"100vh\", background:\"#fafbfc\", fontFamily:\"'Outfit',system-ui,sans-serif\" }}>\n      {\/* Chat header *\/}\n      <div style={{ background:\"#0c1222\", padding:\"14px 24px\", display:\"flex\", alignItems:\"center\", justifyContent:\"space-between\", position:\"sticky\", top:0, zIndex:10 }}>\n        <div style={{ display:\"flex\", alignItems:\"center\", gap:12 }}>\n          <button onClick={() => { setStage(\"problem\"); setMessages([]); setProblem(null); contextRef.current = {industry:contextRef.current.industry,problem:\"\",needs:[],history:[]}; }}\n            style={{ background:\"none\", border:\"none\", color:\"#4a9eed\", fontSize:\"0.85rem\", fontWeight:500, cursor:\"pointer\", fontFamily:\"inherit\", padding:\"4px 0\" }}>\n            \u2190 Back\n          <\/button>\n          <div style={{ width:1, height:16, background:\"#1e2d45\" }} \/>\n          <span style={{ fontSize:\"0.8rem\", fontWeight:600, letterSpacing:\"0.06em\", color:\"#fff\" }}>NXT<\/span>\n          <span style={{ fontSize:\"0.65rem\", color:\"#4a9eed\", fontWeight:500, letterSpacing:\"0.06em\", textTransform:\"uppercase\" }}>Process Advisor<\/span>\n        <\/div>\n        <div style={{ display:\"flex\", gap:6, flexWrap:\"wrap\", justifyContent:\"flex-end\" }}>\n          {industry && (\n            <span style={{ fontSize:\"0.73rem\", fontWeight:500, color:\"#4a9eed\", background:\"#131d30\", padding:\"4px 10px\", borderRadius:20, border:\"1px solid #1e2d45\" }}>\n              {industry.icon} {industry.label}\n            <\/span>\n          )}\n          {problem && (\n            <span style={{ fontSize:\"0.73rem\", fontWeight:500, color:\"#8bc4f6\", background:\"#131d30\", padding:\"4px 10px\", borderRadius:20, border:\"1px solid #1e2d45\" }}>\n              {problem.icon} {problem.label}\n            <\/span>\n          )}\n        <\/div>\n      <\/div>\n\n      {\/* Messages *\/}\n      <div ref={threadRef} style={{ maxWidth:680, margin:\"0 auto\", padding:\"24px 16px 140px\", display:\"flex\", flexDirection:\"column\", gap:16 }}>\n        {messages.map((msg, i) => (\n          <div key={i}>\n            {msg.role === \"user\" && (\n              <div style={{ alignSelf:\"flex-end\", maxWidth:\"85%\", background:\"#1a6fd4\", color:\"#fff\", padding:\"12px 18px\", borderRadius:\"16px 16px 4px 16px\", fontSize:\"0.92rem\", lineHeight:1.5, marginLeft:\"auto\", width:\"fit-content\" }}>\n                {msg.text}\n              <\/div>\n            )}\n            {msg.role === \"ai\" && (\n              <div style={{ maxWidth:\"100%\", fontSize:\"0.92rem\", lineHeight:1.6 }}>\n                <p style={{ marginBottom:14, color:\"#2d3748\" }}>{msg.message}<\/p>\n\n                {msg.options && (\n                  <div style={{ display:\"grid\", gridTemplateColumns:\"1fr 1fr\", gap:8, marginBottom:8 }}>\n                    {msg.options.map((opt, j) => (\n                      <button key={j} onClick={() => send(opt)}\n                        style={{ fontFamily:\"inherit\", fontSize:\"0.85rem\", fontWeight:500, padding:\"13px 16px\", border:\"2px solid #e0e4ea\", borderRadius:10, background:\"#fff\", color:\"#1a1d23\", cursor:\"pointer\", textAlign:\"left\", transition:\"all 0.15s\", lineHeight:1.4 }}\n                        onMouseEnter={e => { e.target.style.borderColor=\"#1a6fd4\"; e.target.style.background=\"#f0f5ff\"; }}\n                        onMouseLeave={e => { e.target.style.borderColor=\"#e0e4ea\"; e.target.style.background=\"#fff\"; }}>\n                        {opt}\n                      <\/button>\n                    ))}\n                  <\/div>\n                )}\n\n                {msg.products && msg.products.length > 0 && (\n                  <div style={{ marginTop:8 }}>\n                    <div style={{ fontSize:\"0.73rem\", fontWeight:600, textTransform:\"uppercase\", letterSpacing:\"0.05em\", color:\"#8b95a5\", marginBottom:8 }}>Recommended for you<\/div>\n                    {msg.products.map((pr, j) => {\n                      const p = CATALOG[pr.index];\n                      if (!p) return null;\n                      return (\n                        <a key={j} href={p.u} target=\"_blank\" rel=\"noopener noreferrer\" style={{ display:\"block\", background:\"#fff\", border:\"1px solid #e0e4ea\", borderRadius:12, padding:\"16px 20px\", textDecoration:\"none\", color:\"inherit\", marginBottom:8, transition:\"all 0.2s\" }} onMouseEnter={e => { e.currentTarget.style.boxShadow=\"0 4px 16px rgba(0,0,0,0.08)\"; e.currentTarget.style.borderColor=\"#1a6fd4\"; }}\n                          onMouseLeave={e => { e.currentTarget.style.boxShadow=\"none\"; e.currentTarget.style.borderColor=\"#e0e4ea\"; }}>\n                          <div style={{ display:\"flex\", justifyContent:\"space-between\", alignItems:\"flex-start\", gap:10, marginBottom:4 }}>\n                            <span style={{ fontSize:\"0.95rem\", fontWeight:600, color:\"#1a6fd4\" }}>{p.n}<\/span>\n                            <span style={{ fontSize:\"0.68rem\", fontWeight:600, padding:\"3px 9px\", borderRadius:20, background:\"#e6f5ed\", color:\"#0b7a3e\" }}>{p.b}<\/span>\n                          <\/div>\n                          <p style={{ fontSize:\"0.84rem\", color:\"#5f6b7a\", lineHeight:1.5, marginBottom:6 }}>{pr.reason}<\/p>\n                          <span style={{ fontSize:\"0.82rem\", fontWeight:600, color:\"#1a6fd4\" }}>View product \u2192<\/span>\n                        <\/a>\n                      );\n                    })}\n                  <\/div>\n                )}\n\n                {msg.cta && (\n                  <div style={{ background:\"#f3f5f8\", border:\"1px dashed #d0d5dd\", borderRadius:12, padding:\"18px 20px\", marginTop:10, display:\"flex\", flexDirection:\"column\", gap:10 }}>\n                    <a href=\"https:\/\/staging.nxtprocess.com\/contact\/\" target=\"_blank\" rel=\"noopener noreferrer\" style={{ fontFamily:\"inherit\", fontSize:\"0.88rem\", fontWeight:600, padding:\"12px 20px\", borderRadius:10, border:\"none\", cursor:\"pointer\", textAlign:\"center\", textDecoration:\"none\", display:\"block\", color:\"#fff\", background: msg.cta.type === \"buy\" ? \"#1a6fd4\" : msg.cta.type === \"quote\" ? \"#0b7a3e\" : \"#0c1222\" }}>\n                      {msg.cta.label}\n                    <\/a>\n                    <p style={{ fontSize:\"0.78rem\", color:\"#8b95a5\", textAlign:\"center\" }}>Our engineers respond within 24 hours<\/p>\n                  <\/div>\n                )}\n              <\/div>\n            )}\n          <\/div>\n        ))}\n\n        {loading && (\n          <div style={{ display:\"inline-flex\", gap:4, padding:\"12px 0\" }}>\n            {[0,1,2].map(i => (\n              <div key={i} style={{ width:8, height:8, borderRadius:\"50%\", background:\"#1a6fd4\", animation:`pulse 1.1s infinite ${i*0.15}s` }} \/>\n            ))}\n            <style>{`@keyframes pulse { 0%,80%,100% { transform:scale(0.5); opacity:0.3; } 40% { transform:scale(1); opacity:1; } }`}<\/style>\n          <\/div>\n        )}\n      <\/div>\n\n      {\/* Input bar *\/}\n      <div style={{ position:\"fixed\", bottom:0, left:0, right:0, background:\"linear-gradient(transparent, #fafbfc 20%)\", padding:\"24px 16px 16px\" }}>\n        <div style={{ maxWidth:680, margin:\"0 auto\" }}>\n          <div style={{ display:\"flex\", gap:8, background:\"#fff\", border:\"2px solid #e0e4ea\", borderRadius:14, padding:6, boxShadow:\"0 2px 12px rgba(0,0,0,0.06)\" }}>\n            <input ref={inputRef} value={input} onChange={e => setInput(e.target.value)}\n              onKeyDown={e => e.key === \"Enter\" && !loading && send(input)}\n              placeholder=\"Type your answer or ask anything...\"\n              style={{ flex:1, border:\"none\", outline:\"none\", fontFamily:\"inherit\", fontSize:\"0.95rem\", padding:\"10px 12px\", background:\"transparent\", color:\"#111\" }}\n              disabled={loading} \/>\n            <button onClick={() => send(input)} disabled={loading || !input.trim()}\n              style={{ padding:\"10px 20px\", fontFamily:\"inherit\", fontSize:\"0.85rem\", fontWeight:600, background:\"#1a6fd4\", color:\"#fff\", border:\"none\", borderRadius:10, cursor: loading||!input.trim() ? \"not-allowed\" : \"pointer\", opacity: loading||!input.trim() ? 0.5 : 1, whiteSpace:\"nowrap\" }}>\n              Send\n            <\/button>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  );\n}\n\n\nReactDOM.createRoot(document.getElementById('root')).render(<App \/>);\n<\/script> \n\n<\/div>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-69cc4c8 elementor-widget elementor-widget-html\" data-id=\"69cc4c8\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div>\n\n\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>NXT Process \u2014 Solutions pour les proc\u00e9d\u00e9s liquides<\/title>\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Outfit:wght@300;400;500;600;700;800&display=swap\" rel=\"stylesheet\">\n<style>\n  * { margin:0; padding:0; box-sizing:border-box; }\n  body { font-family: 'Outfit', system-ui, sans-serif; }\n  #root { min-height: 100vh; }\n<\/style>\n\n\n<div id=\"root\"><\/div>\n\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/react\/18.2.0\/umd\/react.production.min.js\"><\/script>\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/react-dom\/18.2.0\/umd\/react-dom.production.min.js\"><\/script>\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/babel-standalone\/7.23.9\/babel.min.js\"><\/script>\n\n<script type=\"text\/babel\">\nconst { useState, useRef, useEffect } = React;\n\n\/\/ \u2500\u2500\u2500 Product catalog \u2500\u2500\u2500\nconst CATALOG = [\n  {n:\"Ampco CB+ series\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/pump\/centrifugal-pump\/ampco-cb-series\/\",d:\"Centrifugal pump designed for the brewing industry. Optimized for hot, vapor-laden fluids.\",c:\"Pump\",b:\"Ampco\"},\n  {n:\"Deoxygenator\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/deox\/\",d:\"Modular in-line membrane deaeration system removes almost all oxygen from water in minutes.\",c:\"Skid equipment\",b:\"NXT\"},\n  {n:\"Hop incorporator\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/hop-incorporator\/\",d:\"Precise and efficient hop additions. Optimal extraction of hop flavors and aromas.\",c:\"Skid equipment\",b:\"NXT\"},\n  {n:\"Wort aerator\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/wort-aerator\/\",d:\"Maximize yeast performance and fermentation efficiency with precise oxygen dosing.\",c:\"Skid equipment\",b:\"NXT\"},\n  {n:\"Ampco AC\/AC+ series\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/pump\/hygenic-centrifugal-pumps\/ampco-ac-ac-series\/\",d:\"Leading centrifugal pump for hygienic applications. 100% interchangeable with competing brands.\",c:\"Pump\",b:\"Ampco\"},\n  {n:\"Tri-Clamp Butterfly Valve\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/valves\/butterfly\/tri-clamp-butterfly-valve-with-stainless-steel-handle\/\",d:\"Precision control butterfly valve. Engineered for reliability and cleanability.\",c:\"Valves\",b:\"NXT\"},\n  {n:\"Mobile pump\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/mobile-pump\/\",d:\"Portable pump on cart for transferring beer, CIP, and more. Various HP and connections.\",c:\"Skid equipment\",b:\"NXT\"},\n  {n:\"Beer filtration membrane\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/pentair-bmf-beer-filtration-membrane\/\",d:\"Reliable membrane filtration for consistent, flexible, and long-lasting beer filtration.\",c:\"Skid equipment\",b:\"NXT\"},\n  {n:\"Heating and cooling systems\",u:\"https:\/\/staging.nxtprocess.com\/shop\/systems\/cooling\/heating-cooling\/\",d:\"Custom thermal regulation systems for any liquid process.\",c:\"Systems\",b:\"NXT\"},\n  {n:\"Clean-in-place systems\",u:\"https:\/\/staging.nxtprocess.com\/shop\/systems\/cleaning\/clean-in-place-system\/\",d:\"Fully automated CIP solution to clean equipment without disassembly.\",c:\"Systems\",b:\"NXT\"},\n  {n:\"Ampco ZP series\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/pump\/hygienic-circumferential-pumps\/ampco-zp-series\/\",d:\"Hygienic circumferential piston pump for high-viscosity sanitary applications.\",c:\"Pump\",b:\"Ampco\"},\n  {n:\"Ampco AL series\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/pump\/hygenic-lobe-pumps\/ampco-al-series\/\",d:\"Hygienic rotary lobe pump for food, beverage, and pharma.\",c:\"Pump\",b:\"Ampco\"},\n  {n:\"Drum unloader\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/drum-unloader\/\",d:\"Sanitary drum unloading with tracking plates for various barrel diameters.\",c:\"Skid equipment\",b:\"NXT\"},\n  {n:\"JET-shear in-tank mixer\",u:\"https:\/\/staging.nxtprocess.com\/shop\/food\/jet-shear-in-tank-mixer\/\",d:\"Advanced inline shear mixer for mixing, emulsification, and dispersion.\",c:\"Mixers\",b:\"NXT\"},\n  {n:\"Inline powder mixing\",u:\"https:\/\/staging.nxtprocess.com\/shop\/food\/inline-powder-induction-products\/\",d:\"Powder induction for precision blending. Multiple options available.\",c:\"Mixers\",b:\"NXT\"},\n  {n:\"Beer Chamber Pasteurizer\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/chamber-pasteurizer\/\",d:\"Compact pasteurizer for craft breweries to extend shelf life.\",c:\"Skid equipment\",b:\"NXT\"},\n  {n:\"Haffmans CBR Carbo Blender\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/haffman-cbr-carbo-blender\/\",d:\"Precise and consistent carbonation for professional breweries.\",c:\"Skid equipment\",b:\"Pentair Haffmans\"},\n  {n:\"Haffmans CCR Carbo Controller\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/pentair-haffmans-ccr-carbo-controller\/\",d:\"In-line carbonation system for perfect CO2 levels continuously.\",c:\"Skid equipment\",b:\"Pentair Haffmans\"},\n  {n:\"Mixing systems\",u:\"https:\/\/staging.nxtprocess.com\/shop\/systems\/mixing\/mixing-system\/\",d:\"Custom mixing for blending, homogenizing, or dissolving.\",c:\"Systems\",b:\"NXT\"},\n  {n:\"CO2 recovery systems\",u:\"https:\/\/staging.nxtprocess.com\/shop\/systems\/gas-recovery\/co2-recovery-system\/\",d:\"Capture and reuse CO2 from fermentation. Reduce costs and carbon footprint.\",c:\"Systems\",b:\"NXT\"},\n  {n:\"Pigging systems\",u:\"https:\/\/staging.nxtprocess.com\/shop\/systems\/cleaning\/pigging-systems\/\",d:\"Product recovery rate over 99.5%. Reduce losses in pipelines.\",c:\"Systems\",b:\"NXT\"},\n  {n:\"40MP Tri-Clamp Gasket\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/hardware\/tri-clamp-fittings\/40mp-tri-clamp-gasket\/\",d:\"Certified, hygienic, leak-free seal. Multiple materials.\",c:\"Fittings\",b:\"Dixon\"},\n  {n:\"Ampco SB shear mixers\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/mixers\/shear-mixer\/ampco-sb-series-shear-mixers\/\",d:\"High-performance inline shear mixer. Up to 100,000 cps.\",c:\"Mixers\",b:\"Ampco\"},\n  {n:\"NXT static mixer\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/mixers\/static-mixers\/static-mixer\/\",d:\"Zero moving parts, zero maintenance. Compact inline mixing.\",c:\"Mixers\",b:\"NXT\"},\n  {n:\"Plate heat exchanger\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/heat-exchangers\/plate-heat-exchangers\/plate\/\",d:\"Plate heat exchanger for heating, cooling, pasteurization.\",c:\"Heat Exchangers\",b:\"NXT\"},\n  {n:\"Tubular heat exchanger\",u:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/heat-exchangers\/shell-tube-heat-exchangers\/tubular\/\",d:\"Shell and tube heat exchanger for sanitary applications.\",c:\"Heat Exchangers\",b:\"NXT\"},\n  {n:\"Bulk bag unloader\",u:\"https:\/\/staging.nxtprocess.com\/shop\/skid-equipment\/bulk-bag-unloader\/\",d:\"Efficient, dust-free handling of bulk ingredients.\",c:\"Skid equipment\",b:\"NXT\"},\n];\n\nconst CATALOG_STR = JSON.stringify(CATALOG.map((p,i) => ({i, name:p.n, desc:p.d, cat:p.c, brand:p.b})));\n\n\/\/ \u2500\u2500\u2500 Search index for part finder \u2500\u2500\u2500\nconst SEARCH_INDEX = CATALOG.map((p, i) => ({\n  i,\n  text: [p.n, p.c||\"\", p.b||\"\", p.d].join(\" \").toLowerCase()\n}));\n\nfunction preFilter(query, max = 20) {\n  const q = query.toLowerCase();\n  const terms = q.split(\/\\s+\/).filter(t => t.length > 1);\n  return SEARCH_INDEX.map(entry => {\n    let score = 0;\n    if (entry.text.includes(q)) score += 100;\n    for (const t of terms) {\n      if (entry.text.includes(t)) score += 10;\n      if (CATALOG[entry.i].n.toLowerCase().includes(t)) score += 20;\n      if ((CATALOG[entry.i].b||\"\").toLowerCase().includes(t)) score += 15;\n    }\n    return { i: entry.i, score };\n  }).filter(e => e.score > 0).sort((a, b) => b.score - a.score).slice(0, max).map(e => e.i);\n}\n\nconst BEST_MATCHES = [\n  {\n    keywords:[\"brewery pump\",\"brewing pump\",\"craft beer pump\",\"beer pump\"],\n    product:{\n      name:\"Ampco CB+ Centrifugal Pump\",\n      url:\"https:\/\/staging.nxtprocess.com\/shop\/distribution\/pump\/centrifugal-pump\/ampco-cb-series\/\",\n      reason:\"The Ampco CB+ is the industry standard for breweries \u2014 designed for sanitary CIP-compatible pumping of beer, wort, and other brewing fluids.\",\n    }\n  }\n];\n\nfunction findBestMatch(query) {\n  const q = query.toLowerCase();\n  for (const bm of BEST_MATCHES) {\n    for (const kw of bm.keywords) { if (q.includes(kw)) return bm.product; }\n  }\n  return null;\n}\n\n\/\/ \u2500\u2500\u2500 Industry tiles config \u2500\u2500\u2500\nconst INDUSTRIES = [\n  { id:\"food\", label:\"Food\", icon:\"\ud83c\udfed\", desc:\"Processing & packaging\" },\n  { id:\"beverages\", label:\"Beverages\", icon:\"\ud83e\udd64\", desc:\"Juice, water, seltzer\" },\n  { id:\"brewing\", label:\"Brewing\", icon:\"\ud83c\udf7a\", desc:\"Craft & industrial\" },\n  { id:\"chemical\", label:\"Chemical\", icon:\"\u2697\ufe0f\", desc:\"Industrial processing\" },\n  { id:\"hydrometallurgy\", label:\"Hydrometallurgy\", icon:\"\u26cf\ufe0f\", desc:\"Metal extraction\" },\n  { id:\"cosmetics\", label:\"Cosmetics\", icon:\"\u2728\", desc:\"Personal care & beauty\" },\n  { id:\"other\", label:\"Other\", icon:\"\ud83d\udd27\", desc:\"Tell us more\" },\n];\n\nasync function callAPI(system, userMsg) {\n  const resp = await fetch(\"https:\/\/api.anthropic.com\/v1\/messages\", {\n    method:\"POST\", headers:{\"Content-Type\":\"application\/json\"},\n    body:JSON.stringify({ model:\"claude-sonnet-4-20250514\", max_tokens:1500, system, messages:[{role:\"user\",content:userMsg}] })\n  });\n  const data = await resp.json();\n  return data.content.map(c => c.text||\"\").join(\"\").replace(\/```json|```\/g,\"\").trim();\n}\n\n\/\/ \u2500\u2500\u2500 Problem tiles config \u2500\u2500\u2500\nconst PROBLEMS = [\n  { id:\"quality\", label:\"Increase quality\", icon:\"\u2705\", desc:\"Better consistency & standards\" },\n  { id:\"productivity\", label:\"Increase productivity\", icon:\"\u26a1\", desc:\"Higher throughput & efficiency\" },\n  { id:\"automate\", label:\"Automate production\", icon:\"\ud83e\udd16\", desc:\"Reduce manual operations\" },\n  { id:\"part\", label:\"Find a specific part\", icon:\"\ud83d\udd29\", desc:\"Fittings, pumps, sensors...\" },\n  { id:\"energy\", label:\"Recuperate energy\", icon:\"\u267b\ufe0f\", desc:\"Heat recovery & sustainability\" },\n  { id:\"factory\", label:\"Build a new factory\", icon:\"\ud83c\udfd7\ufe0f\", desc:\"Greenfield project\" },\n  { id:\"codevelop\", label:\"Co-develop a new process\", icon:\"\ud83e\uddea\", desc:\"R&D partnership\" },\n  { id:\"else\", label:\"Something else\", icon:\"\ud83d\udcac\", desc:\"Tell us more\" },\n];\n\n\/\/ \u2500\u2500\u2500 Sub-problems: industry+problem \u2192 specific options \u2500\u2500\u2500\n\/\/ Key format: \"industryId:problemId\"\nconst SUB_PROBLEMS = {\n  \"brewing:quality\": {\n    question: \"What aspect of quality do you want to improve?\",\n    subtitle: \"Select your focus area\",\n    options: [\n      { id:\"oxygen\", label:\"Oxygen management\", icon:\"\ud83d\udca8\", desc:\"Control dissolved O\u2082 levels\" },\n      { id:\"carbonation\", label:\"Carbonation management\", icon:\"\ud83e\udee7\", desc:\"Precise CO\u2082 control\" },\n      { id:\"filtration\", label:\"Filtration\", icon:\"\ud83d\udd2c\", desc:\"Clarity & consistency\" },\n      { id:\"general_quality\", label:\"General improvement\", icon:\"\ud83d\udcc8\", desc:\"Overall quality uplift\" },\n    ]\n  },\n  \/\/ Add more combos here:\n  \/\/ \"brewing:productivity\": { question: \"...\", options: [...] },\n  \/\/ \"food:quality\": { question: \"...\", options: [...] },\n};\n\n\/\/ \u2500\u2500\u2500 Curated solutions: industry:problem:subproblem \u2192 expert answer \u2500\u2500\u2500\n\/\/ When a curated solution exists, skip the chat and show the answer directly.\nconst CURATED_SOLUTIONS = {\n  \"brewing:quality:oxygen\": {\n    title: \"Oxygen Management\",\n    text: \"Oxygen management starts with accurate dissolved gas monitoring. The industry standard is Pentair-Haffmans instruments and NXT is the certified distributor for Canada.\",\n    product: {\n      name: \"Pentair-Haffmans Gehaltemeter\",\n      url: \"https:\/\/staging.nxtprocess.com\/shop\/distribution\/probes\/co2-o2-tpo-mobile-analysis-unit\/gehaltemeter-c-dgm-o-dgm-i-dgm\/\",\n      reason: \"Pentair-Haffmans' flagship product for dissolved gas analysis. Measures CO\u2082, O\u2082, and TPO in one portable unit \u2014 the industry reference for brewery quality control.\",\n      brand: \"Pentair Haffmans\",\n    },\n    relatedProducts: [\n      { index: 1, reason: \"Remove dissolved oxygen from water before it enters your process.\" },\n      { index: 3, reason: \"Precisely dose oxygen into wort for optimal yeast performance.\" },\n    ],\n    cta: { type:\"quote\", label:\"Get a quote for oxygen management\" },\n  },\n  \/\/ Add more curated solutions:\n  \/\/ \"brewing:quality:carbonation\": { title, text, product, cta },\n  \/\/ \"brewing:quality:filtration\": { title, text, product, cta },\n};\n\nfunction App() {\n  const [stage, setStage] = useState(\"home\"); \/\/ home, problem, subproblem, solution, chat, parts\n  const [industry, setIndustry] = useState(null);\n  const [problem, setProblem] = useState(null);\n  const [subProblem, setSubProblem] = useState(null);\n  const [curatedSolution, setCuratedSolution] = useState(null);\n  const [messages, setMessages] = useState([]);\n  const [input, setInput] = useState(\"\");\n  const [loading, setLoading] = useState(false);\n  const [partQuery, setPartQuery] = useState(\"\");\n  const [partResults, setPartResults] = useState(null);\n  const [partLoading, setPartLoading] = useState(false);\n  const threadRef = useRef(null);\n  const inputRef = useRef(null);\n  const partInputRef = useRef(null);\n  const contextRef = useRef({ industry:\"\", problem:\"\", subProblem:\"\", needs:[], history:[] });\n\n  useEffect(() => {\n    if (threadRef.current) threadRef.current.scrollTop = threadRef.current.scrollHeight;\n  }, [messages, loading]);\n\n  function selectIndustry(ind) {\n    setIndustry(ind);\n    setStage(\"problem\");\n    contextRef.current.industry = ind.label;\n  }\n\n  function selectProblem(prob) {\n    setProblem(prob);\n    if (prob.id === \"part\") {\n      setStage(\"parts\");\n      return;\n    }\n    \/\/ Check if there are sub-problems for this industry+problem combo\n    const key = `${industry.id}:${prob.id}`;\n    if (SUB_PROBLEMS[key]) {\n      setStage(\"subproblem\");\n      return;\n    }\n    goToChat(prob.label);\n  }\n\n  function selectSubProblem(sub) {\n    setSubProblem(sub);\n    contextRef.current.subProblem = sub.label;\n    \/\/ Check for curated solution\n    const key = `${industry.id}:${problem.id}:${sub.id}`;\n    if (CURATED_SOLUTIONS[key]) {\n      setCuratedSolution(CURATED_SOLUTIONS[key]);\n      setStage(\"solution\");\n      return;\n    }\n    goToChat(`${problem.label} \u2014 specifically: ${sub.label}`);\n  }\n\n  function goToChat(problemDesc) {\n    setStage(\"chat\");\n    contextRef.current.problem = problemDesc;\n    contextRef.current.history = [\n      { role:\"user\", content:`My industry is ${industry.label}. I want to: ${problemDesc}` }\n    ];\n    send(`My industry is ${industry.label}. I want to: ${problemDesc}`, true);\n  }\n\n  async function send(text, isFirst = false) {\n    if (!text.trim()) return;\n    const userMsg = { role:\"user\", text:text.trim() };\n    if (!isFirst) {\n      setMessages(prev => [...prev, userMsg]);\n      contextRef.current.history.push({ role:\"user\", content:text.trim() });\n    } else {\n      setMessages([userMsg]);\n    }\n    setInput(\"\");\n    setLoading(true);\n\n    try {\n      const historyStr = contextRef.current.history.map(h => `${h.role}: ${h.content}`).join(\"\\n\");\n      const raw = await callAPI(\n`You are the NXT Process advisor \u2014 a conversational product advisor for NXT Process, a liquid process engineering firm based in Canada that sells sanitary parts (fittings, pumps, sensors, valves) and designs complete systems for breweries, dairies, food processing, pharma, cosmetics, chemical, and hydrometallurgy industries.\n\nYour job is to guide visitors from their industry\/project to the right products and services. You are friendly, knowledgeable, and efficient.\n\nALWAYS respond with ONLY valid JSON (no markdown, no backticks):\n\n{\n  \"message\": \"Your conversational response (2-4 sentences max). Be warm and specific to their industry.\",\n  \"options\": [\"Option 1\", \"Option 2\", \"Option 3\", \"Option 4\"] | null,\n  \"products\": [{\"index\": 0, \"reason\": \"why this fits\"}] | null,\n  \"cta\": {\"type\": \"buy\"|\"quote\"|\"consult\", \"label\": \"Button text\"} | null\n}\n\nRules:\n- The visitor already selected their industry. Your first response should acknowledge it and ask what they need help with \u2014 offer 3-4 clickable options specific to their industry.\n- Keep to ONE question at a time. Each question should have options.\n- When you have enough info: recommend specific products from the catalog using \"products\" (index = catalog index). Also suggest a CTA.\n- For simple parts: CTA type = \"buy\". For complex systems: \"quote\". For engineering projects: \"consult\".\n- \"options\" should be short (3-8 words each), practical choices specific to what they said.\n- Keep \"message\" concise and natural.\n\nProduct catalog (use index to reference):\n${CATALOG_STR}`,\n        `Conversation so far:\\n${historyStr}\\n\\nRespond to the latest message.`\n      );\n\n      const parsed = JSON.parse(raw);\n      contextRef.current.history.push({ role:\"assistant\", content:parsed.message });\n      setMessages(prev => [...prev, { role:\"ai\", ...parsed }]);\n    } catch(e) {\n      console.error(e);\n      setMessages(prev => [...prev, { role:\"ai\", message:\"Sorry, something went wrong. Could you try rephrasing that?\" }]);\n    }\n    setLoading(false);\n    setTimeout(() => inputRef.current?.focus(), 100);\n  }\n\n  \/\/ \u2500\u2500\u2500 HOME PAGE \u2500\u2500\u2500\n  if (stage === \"home\") {\n    return (\n      <div style={{ minHeight:\"100vh\", background:\"#0c1222\", color:\"#fff\", fontFamily:\"'Outfit',system-ui,sans-serif\" }}>\n        {\/* Nav *\/}\n        <div style={{ padding:\"20px 24px\", display:\"flex\", alignItems:\"center\", justifyContent:\"space-between\" }}>\n          <div style={{ display:\"flex\", alignItems:\"baseline\", gap:6 }}>\n            <span style={{ fontSize:\"1.4rem\", fontWeight:800, letterSpacing:\"0.06em\", color:\"#fff\" }}>NXT<\/span>\n            <span style={{ fontSize:\"0.7rem\", fontWeight:500, letterSpacing:\"0.08em\", color:\"#4a9eed\", textTransform:\"uppercase\" }}>Process<\/span>\n          <\/div>\n          <a href=\"https:\/\/staging.nxtprocess.com\/contact\/\" target=\"_blank\" rel=\"noopener noreferrer\" style={{ fontSize:\"0.8rem\", fontWeight:500, color:\"#4a9eed\", textDecoration:\"none\", padding:\"6px 14px\", border:\"1px solid #1e3a5f\", borderRadius:6 }}>\n            Contact us\n          <\/a>\n        <\/div>\n\n        {\/* Hero *\/}\n        <div style={{ textAlign:\"center\", padding:\"60px 24px 40px\", maxWidth:680, margin:\"0 auto\" }}>\n          <h1 style={{ fontSize:\"clamp(1.8rem, 5vw, 2.8rem)\", fontWeight:700, lineHeight:1.15, letterSpacing:\"-0.03em\", marginBottom:16, background:\"linear-gradient(135deg, #fff 0%, #a0c4f0 100%)\", WebkitBackgroundClip:\"text\", WebkitTextFillColor:\"transparent\" }}>\n            Optimizing your future, one liquid process at a time\n          <\/h1>\n          <p style={{ fontSize:\"clamp(0.9rem, 2.5vw, 1.05rem)\", color:\"#8b9cc0\", lineHeight:1.7, maxWidth:560, margin:\"0 auto\" }}>\n            NXT Process engineers design innovative liquid process solutions that combine precision, reliability and rapid return on investment\u2014enabling you to grow efficiently while reducing costs.\n          <\/p>\n        <\/div>\n\n        {\/* Industry question *\/}\n        <div style={{ textAlign:\"center\", padding:\"0 24px 20px\" }}>\n          <h2 style={{ fontSize:\"clamp(1.2rem, 3.5vw, 1.6rem)\", fontWeight:700, color:\"#4a9eed\", marginBottom:8 }}>\n            What is your industry?\n          <\/h2>\n          <p style={{ fontSize:\"0.88rem\", color:\"#5a6a8a\", marginBottom:32 }}>Select your sector and we'll guide you to the right solutions<\/p>\n        <\/div>\n\n        {\/* Industry tiles *\/}\n        <div style={{ maxWidth:720, margin:\"0 auto\", padding:\"0 24px 60px\", display:\"grid\", gridTemplateColumns:\"repeat(auto-fill, minmax(200px, 1fr))\", gap:12 }}>\n          {INDUSTRIES.map(ind => (\n            <button key={ind.id} onClick={() => selectIndustry(ind)}\n              style={{\n                fontFamily:\"inherit\", border:\"1px solid #1e2d45\", borderRadius:12,\n                background:\"linear-gradient(180deg, #131d30 0%, #0f1829 100%)\",\n                padding:0, cursor:\"pointer\", overflow:\"hidden\", textAlign:\"left\",\n                transition:\"all 0.25s ease\", position:\"relative\",\n              }}\n              onMouseEnter={e => {\n                e.currentTarget.style.borderColor = \"#4a9eed\";\n                e.currentTarget.style.transform = \"translateY(-3px)\";\n                e.currentTarget.style.boxShadow = \"0 8px 30px rgba(74,158,237,0.15)\";\n              }}\n              onMouseLeave={e => {\n                e.currentTarget.style.borderColor = \"#1e2d45\";\n                e.currentTarget.style.transform = \"translateY(0)\";\n                e.currentTarget.style.boxShadow = \"none\";\n              }}>\n              {\/* Image area with gradient overlay *\/}\n              <div style={{ height:120, position:\"relative\", overflow:\"hidden\", background:`linear-gradient(135deg, #1a2a42 0%, #0d1a2e 100%)`, display:\"flex\", alignItems:\"center\", justifyContent:\"center\", }}>\n                <span style={{ fontSize:\"2.8rem\", opacity:0.6, filter:\"grayscale(50%)\" }}>{ind.icon}<\/span>\n                {\/* Bottom gradient fade *\/}\n                <div style={{ position:\"absolute\", bottom:0, left:0, right:0, height:40, background:\"linear-gradient(transparent, #131d30)\" }} \/>\n              <\/div>\n              {\/* Label *\/}\n              <div style={{ padding:\"14px 16px 16px\" }}>\n                <div style={{ fontSize:\"1rem\", fontWeight:700, color:\"#fff\", marginBottom:2, letterSpacing:\"-0.01em\" }}>{ind.label}<\/div>\n                <div style={{ fontSize:\"0.78rem\", color:\"#5a6a8a\" }}>{ind.desc}<\/div>\n              <\/div>\n            <\/button>\n          ))}\n        <\/div>\n\n        {\/* Bottom text input for free-form *\/}\n        <div style={{ maxWidth:560, margin:\"0 auto\", padding:\"0 24px 48px\" }}>\n          <div style={{ display:\"flex\", gap:8, background:\"#131d30\", border:\"1px solid #1e2d45\", borderRadius:12, padding:6 }}>\n            <input\n              value={input} onChange={e => setInput(e.target.value)}\n              onKeyDown={e => {\n                if (e.key === \"Enter\" && input.trim()) {\n                  setStage(\"chat\");\n                  contextRef.current.industry = \"Unknown\";\n                  contextRef.current.history = [{ role:\"user\", content:input.trim() }];\n                  send(input.trim(), true);\n                }\n              }}\n              placeholder=\"Or describe your project in your own words...\"\n              style={{ flex:1, border:\"none\", outline:\"none\", fontFamily:\"inherit\", fontSize:\"0.9rem\", padding:\"10px 12px\", background:\"transparent\", color:\"#c0ccde\" }}\n            \/>\n            <button onClick={() => {\n              if (input.trim()) {\n                setStage(\"chat\");\n                contextRef.current.industry = \"Unknown\";\n                contextRef.current.history = [{ role:\"user\", content:input.trim() }];\n                send(input.trim(), true);\n              }\n            }}\n              style={{ padding:\"10px 18px\", fontFamily:\"inherit\", fontSize:\"0.82rem\", fontWeight:600, background:\"#4a9eed\", color:\"#fff\", border:\"none\", borderRadius:8, cursor:\"pointer\" }}>\n              Go\n            <\/button>\n          <\/div>\n        <\/div>\n      <\/div>\n    );\n  }\n\n  \/\/ \u2500\u2500\u2500 PROBLEM PAGE \u2500\u2500\u2500\n  if (stage === \"problem\") {\n    return (\n      <div style={{ minHeight:\"100vh\", background:\"#0c1222\", color:\"#fff\", fontFamily:\"'Outfit',system-ui,sans-serif\" }}>\n        {\/* Nav *\/}\n        <div style={{ padding:\"20px 24px\", display:\"flex\", alignItems:\"center\", justifyContent:\"space-between\" }}>\n          <div style={{ display:\"flex\", alignItems:\"center\", gap:12 }}>\n            <button onClick={() => { setStage(\"home\"); setIndustry(null); }}\n              style={{ background:\"none\", border:\"none\", color:\"#4a9eed\", fontSize:\"0.85rem\", fontWeight:500, cursor:\"pointer\", fontFamily:\"inherit\", padding:\"4px 0\" }}>\n              \u2190 Back\n            <\/button>\n            <div style={{ width:1, height:16, background:\"#1e2d45\" }} \/>\n            <span style={{ fontSize:\"1.2rem\", fontWeight:800, letterSpacing:\"0.06em\", color:\"#fff\" }}>NXT<\/span>\n            <span style={{ fontSize:\"0.6rem\", fontWeight:500, letterSpacing:\"0.08em\", color:\"#4a9eed\", textTransform:\"uppercase\" }}>Process<\/span>\n          <\/div>\n          <span style={{ fontSize:\"0.78rem\", fontWeight:500, color:\"#4a9eed\", background:\"#131d30\", padding:\"5px 14px\", borderRadius:20, border:\"1px solid #1e2d45\" }}>\n            {industry?.icon} {industry?.label}\n          <\/span>\n        <\/div>\n\n        {\/* Problem question *\/}\n        <div style={{ textAlign:\"center\", padding:\"50px 24px 20px\" }}>\n          <h2 style={{ fontSize:\"clamp(1.3rem, 3.5vw, 1.8rem)\", fontWeight:700, color:\"#4a9eed\", marginBottom:8 }}>\n            Which problem do you want to solve?\n          <\/h2>\n          <p style={{ fontSize:\"0.88rem\", color:\"#5a6a8a\", marginBottom:36 }}>Tell us what you're looking to achieve and we'll point you in the right direction<\/p>\n        <\/div>\n\n        {\/* Problem tiles *\/}\n        <div style={{ maxWidth:720, margin:\"0 auto\", padding:\"0 24px 40px\", display:\"grid\", gridTemplateColumns:\"repeat(auto-fill, minmax(160px, 1fr))\", gap:10 }}>\n          {PROBLEMS.map(prob => (\n            <button key={prob.id} onClick={() => selectProblem(prob)}\n              style={{\n                fontFamily:\"inherit\", border:\"1px solid #1e2d45\", borderRadius:12,\n                background:\"linear-gradient(180deg, #131d30 0%, #0f1829 100%)\",\n                padding:\"20px 16px\", cursor:\"pointer\", textAlign:\"center\",\n                transition:\"all 0.25s ease\",\n              }}\n              onMouseEnter={e => {\n                e.currentTarget.style.borderColor = \"#4a9eed\";\n                e.currentTarget.style.transform = \"translateY(-3px)\";\n                e.currentTarget.style.boxShadow = \"0 8px 30px rgba(74,158,237,0.15)\";\n              }}\n              onMouseLeave={e => {\n                e.currentTarget.style.borderColor = \"#1e2d45\";\n                e.currentTarget.style.transform = \"translateY(0)\";\n                e.currentTarget.style.boxShadow = \"none\";\n              }}>\n              <div style={{ fontSize:\"1.8rem\", marginBottom:8 }}>{prob.icon}<\/div>\n              <div style={{ fontSize:\"0.9rem\", fontWeight:600, color:\"#fff\", marginBottom:3, lineHeight:1.3 }}>{prob.label}<\/div>\n              <div style={{ fontSize:\"0.73rem\", color:\"#5a6a8a\", lineHeight:1.3 }}>{prob.desc}<\/div>\n            <\/button>\n          ))}\n        <\/div>\n\n        {\/* Free-form input *\/}\n        <div style={{ maxWidth:560, margin:\"0 auto\", padding:\"0 24px 48px\" }}>\n          <div style={{ display:\"flex\", gap:8, background:\"#131d30\", border:\"1px solid #1e2d45\", borderRadius:12, padding:6 }}>\n            <input\n              value={input} onChange={e => setInput(e.target.value)}\n              onKeyDown={e => {\n                if (e.key === \"Enter\" && input.trim()) {\n                  setProblem({ id:\"custom\", label:input.trim(), icon:\"\ud83d\udcac\", desc:\"\" });\n                  setStage(\"chat\");\n                  contextRef.current.problem = input.trim();\n                  contextRef.current.history = [\n                    { role:\"user\", content:`My industry is ${industry.label}. My problem: ${input.trim()}` }\n                  ];\n                  send(`My industry is ${industry.label}. My problem: ${input.trim()}`, true);\n                }\n              }}\n              placeholder=\"Or describe your challenge in your own words...\"\n              style={{ flex:1, border:\"none\", outline:\"none\", fontFamily:\"inherit\", fontSize:\"0.9rem\", padding:\"10px 12px\", background:\"transparent\", color:\"#c0ccde\" }}\n            \/>\n            <button onClick={() => {\n              if (input.trim()) {\n                setProblem({ id:\"custom\", label:input.trim(), icon:\"\ud83d\udcac\", desc:\"\" });\n                setStage(\"chat\");\n                contextRef.current.problem = input.trim();\n                contextRef.current.history = [\n                  { role:\"user\", content:`My industry is ${industry.label}. My problem: ${input.trim()}` }\n                ];\n                send(`My industry is ${industry.label}. My problem: ${input.trim()}`, true);\n              }\n            }}\n              style={{ padding:\"10px 18px\", fontFamily:\"inherit\", fontSize:\"0.82rem\", fontWeight:600, background:\"#4a9eed\", color:\"#fff\", border:\"none\", borderRadius:8, cursor:\"pointer\" }}>\n              Go\n            <\/button>\n          <\/div>\n        <\/div>\n      <\/div>\n    );\n  }\n\n  \/\/ \u2500\u2500\u2500 SUB-PROBLEM PAGE \u2500\u2500\u2500\n  if (stage === \"subproblem\") {\n    const key = `${industry?.id}:${problem?.id}`;\n    const subConfig = SUB_PROBLEMS[key];\n    if (!subConfig) { setStage(\"chat\"); return null; }\n\n    return (\n      <div style={{ minHeight:\"100vh\", background:\"#0c1222\", color:\"#fff\", fontFamily:\"'Outfit',system-ui,sans-serif\" }}>\n        {\/* Nav *\/}\n        <div style={{ padding:\"20px 24px\", display:\"flex\", alignItems:\"center\", justifyContent:\"space-between\" }}>\n          <div style={{ display:\"flex\", alignItems:\"center\", gap:12 }}>\n            <button onClick={() => { setStage(\"problem\"); setProblem(null); setSubProblem(null); }}\n              style={{ background:\"none\", border:\"none\", color:\"#4a9eed\", fontSize:\"0.85rem\", fontWeight:500, cursor:\"pointer\", fontFamily:\"inherit\" }}>\n              \u2190 Back\n            <\/button>\n            <div style={{ width:1, height:16, background:\"#1e2d45\" }} \/>\n            <span style={{ fontSize:\"1.2rem\", fontWeight:800, letterSpacing:\"0.06em\", color:\"#fff\" }}>NXT<\/span>\n            <span style={{ fontSize:\"0.6rem\", fontWeight:500, letterSpacing:\"0.08em\", color:\"#4a9eed\", textTransform:\"uppercase\" }}>Process<\/span>\n          <\/div>\n          <div style={{ display:\"flex\", gap:6 }}>\n            <span style={{ fontSize:\"0.73rem\", fontWeight:500, color:\"#4a9eed\", background:\"#131d30\", padding:\"4px 10px\", borderRadius:20, border:\"1px solid #1e2d45\" }}>\n              {industry?.icon} {industry?.label}\n            <\/span>\n            <span style={{ fontSize:\"0.73rem\", fontWeight:500, color:\"#8bc4f6\", background:\"#131d30\", padding:\"4px 10px\", borderRadius:20, border:\"1px solid #1e2d45\" }}>\n              {problem?.icon} {problem?.label}\n            <\/span>\n          <\/div>\n        <\/div>\n\n        {\/* Question *\/}\n        <div style={{ textAlign:\"center\", padding:\"50px 24px 20px\" }}>\n          <h2 style={{ fontSize:\"clamp(1.3rem, 3.5vw, 1.8rem)\", fontWeight:700, color:\"#4a9eed\", marginBottom:8 }}>\n            {subConfig.question}\n          <\/h2>\n          <p style={{ fontSize:\"0.88rem\", color:\"#5a6a8a\", marginBottom:36 }}>{subConfig.subtitle}<\/p>\n        <\/div>\n\n        {\/* Sub-problem tiles *\/}\n        <div style={{ maxWidth:640, margin:\"0 auto\", padding:\"0 24px 40px\", display:\"grid\", gridTemplateColumns:\"repeat(auto-fill, minmax(180px, 1fr))\", gap:10 }}>\n          {subConfig.options.map(sub => (\n            <button key={sub.id} onClick={() => selectSubProblem(sub)}\n              style={{\n                fontFamily:\"inherit\", border:\"1px solid #1e2d45\", borderRadius:12,\n                background:\"linear-gradient(180deg, #131d30 0%, #0f1829 100%)\",\n                padding:\"22px 16px\", cursor:\"pointer\", textAlign:\"center\",\n                transition:\"all 0.25s ease\",\n              }}\n              onMouseEnter={e => {\n                e.currentTarget.style.borderColor = \"#4a9eed\";\n                e.currentTarget.style.transform = \"translateY(-3px)\";\n                e.currentTarget.style.boxShadow = \"0 8px 30px rgba(74,158,237,0.15)\";\n              }}\n              onMouseLeave={e => {\n                e.currentTarget.style.borderColor = \"#1e2d45\";\n                e.currentTarget.style.transform = \"translateY(0)\";\n                e.currentTarget.style.boxShadow = \"none\";\n              }}>\n              <div style={{ fontSize:\"1.8rem\", marginBottom:8 }}>{sub.icon}<\/div>\n              <div style={{ fontSize:\"0.9rem\", fontWeight:600, color:\"#fff\", marginBottom:3, lineHeight:1.3 }}>{sub.label}<\/div>\n              <div style={{ fontSize:\"0.73rem\", color:\"#5a6a8a\", lineHeight:1.3 }}>{sub.desc}<\/div>\n            <\/button>\n          ))}\n        <\/div>\n\n        {\/* Free-form input *\/}\n        <div style={{ maxWidth:560, margin:\"0 auto\", padding:\"0 24px 48px\" }}>\n          <div style={{ display:\"flex\", gap:8, background:\"#131d30\", border:\"1px solid #1e2d45\", borderRadius:12, padding:6 }}>\n            <input\n              value={input} onChange={e => setInput(e.target.value)}\n              onKeyDown={e => {\n                if (e.key === \"Enter\" && input.trim()) {\n                  setSubProblem({ id:\"custom\", label:input.trim(), icon:\"\ud83d\udcac\", desc:\"\" });\n                  goToChat(`${problem.label} \u2014 specifically: ${input.trim()}`);\n                }\n              }}\n              placeholder=\"Or describe your specific challenge...\"\n              style={{ flex:1, border:\"none\", outline:\"none\", fontFamily:\"inherit\", fontSize:\"0.9rem\", padding:\"10px 12px\", background:\"transparent\", color:\"#c0ccde\" }}\n            \/>\n            <button onClick={() => {\n              if (input.trim()) {\n                setSubProblem({ id:\"custom\", label:input.trim(), icon:\"\ud83d\udcac\", desc:\"\" });\n                goToChat(`${problem.label} \u2014 specifically: ${input.trim()}`);\n              }\n            }}\n              style={{ padding:\"10px 18px\", fontFamily:\"inherit\", fontSize:\"0.82rem\", fontWeight:600, background:\"#4a9eed\", color:\"#fff\", border:\"none\", borderRadius:8, cursor:\"pointer\" }}>\n              Go\n            <\/button>\n          <\/div>\n        <\/div>\n      <\/div>\n    );\n  }\n\n  \/\/ \u2500\u2500\u2500 CURATED SOLUTION PAGE \u2500\u2500\u2500\n  if (stage === \"solution\" && curatedSolution) {\n    const sol = curatedSolution;\n    return (\n      <div style={{ minHeight:\"100vh\", background:\"#fafbfc\", fontFamily:\"'Outfit',system-ui,sans-serif\" }}>\n        {\/* Header *\/}\n        <div style={{ background:\"#0c1222\", padding:\"14px 24px\", display:\"flex\", alignItems:\"center\", justifyContent:\"space-between\" }}>\n          <div style={{ display:\"flex\", alignItems:\"center\", gap:12 }}>\n            <button onClick={() => { setStage(\"subproblem\"); setCuratedSolution(null); setSubProblem(null); }}\n              style={{ background:\"none\", border:\"none\", color:\"#4a9eed\", fontSize:\"0.85rem\", fontWeight:500, cursor:\"pointer\", fontFamily:\"inherit\" }}>\n              \u2190 Back\n            <\/button>\n            <div style={{ width:1, height:16, background:\"#1e2d45\" }} \/>\n            <span style={{ fontSize:\"0.8rem\", fontWeight:600, letterSpacing:\"0.06em\", color:\"#fff\" }}>NXT<\/span>\n            <span style={{ fontSize:\"0.65rem\", color:\"#4a9eed\", fontWeight:500, letterSpacing:\"0.06em\", textTransform:\"uppercase\" }}>Process Advisor<\/span>\n          <\/div>\n          <div style={{ display:\"flex\", gap:6, flexWrap:\"wrap\", justifyContent:\"flex-end\" }}>\n            <span style={{ fontSize:\"0.73rem\", fontWeight:500, color:\"#4a9eed\", background:\"#131d30\", padding:\"4px 10px\", borderRadius:20, border:\"1px solid #1e2d45\" }}>\n              {industry?.icon} {industry?.label}\n            <\/span>\n            <span style={{ fontSize:\"0.73rem\", fontWeight:500, color:\"#8bc4f6\", background:\"#131d30\", padding:\"4px 10px\", borderRadius:20, border:\"1px solid #1e2d45\" }}>\n              {problem?.icon} {problem?.label}\n            <\/span>\n          <\/div>\n        <\/div>\n\n        <div style={{ maxWidth:680, margin:\"0 auto\", padding:\"32px 16px\" }}>\n          {\/* Solution title *\/}\n          <div style={{ marginBottom:24 }}>\n            <div style={{ fontSize:\"0.73rem\", fontWeight:600, textTransform:\"uppercase\", letterSpacing:\"0.06em\", color:\"#1a6fd4\", marginBottom:6 }}>NXT Recommendation<\/div>\n            <h2 style={{ fontSize:\"1.5rem\", fontWeight:700, letterSpacing:\"-0.02em\", color:\"#0f1729\", marginBottom:12 }}>{sol.title}<\/h2>\n            <p style={{ fontSize:\"0.95rem\", color:\"#3d4654\", lineHeight:1.7 }}>{sol.text}<\/p>\n          <\/div>\n\n          {\/* Featured product *\/}\n          {sol.product && (\n            <a href={sol.product.url} target=\"_blank\" rel=\"noopener noreferrer\" style={{ display:\"block\", background:\"linear-gradient(135deg, #e6f5ed 0%, #fff 100%)\", border:\"2px solid #0b7a3e\", borderRadius:12, padding:\"20px 24px\", textDecoration:\"none\", color:\"inherit\", marginBottom:12 }}>\n              <div style={{ display:\"flex\", justifyContent:\"space-between\", alignItems:\"flex-start\", gap:10, marginBottom:6 }}>\n                <span style={{ fontSize:\"1.05rem\", fontWeight:700, color:\"#0b7a3e\" }}>{sol.product.name}<\/span>\n                <span style={{ fontSize:\"0.7rem\", fontWeight:600, padding:\"4px 10px\", borderRadius:20, background:\"#0b7a3e\", color:\"#fff\", whiteSpace:\"nowrap\" }}>\u2605 NXT Recommended<\/span>\n              <\/div>\n              {sol.product.brand && (\n                <p style={{ fontSize:\"0.78rem\", fontWeight:600, color:\"#0b7a3e\", marginBottom:6, opacity:0.7 }}>{sol.product.brand}<\/p>\n              )}\n              <p style={{ fontSize:\"0.88rem\", color:\"#3d4654\", lineHeight:1.6, marginBottom:8 }}>{sol.product.reason}<\/p>\n              <span style={{ fontSize:\"0.85rem\", fontWeight:600, color:\"#0b7a3e\" }}>View product \u2192<\/span>\n            <\/a>\n          )}\n\n          {\/* Related products *\/}\n          {sol.relatedProducts && sol.relatedProducts.length > 0 && (\n            <div style={{ marginTop:16 }}>\n              <p style={{ fontSize:\"0.75rem\", fontWeight:600, textTransform:\"uppercase\", letterSpacing:\"0.04em\", color:\"#8b95a5\", marginBottom:10 }}>You might also need<\/p>\n              {sol.relatedProducts.map((rp, j) => {\n                const p = CATALOG[rp.index];\n                if (!p) return null;\n                return (\n                  <a key={j} href={p.u} target=\"_blank\" rel=\"noopener noreferrer\" style={{ display:\"block\", background:\"#fff\", border:\"1px solid #e0e4ea\", borderRadius:12, padding:\"16px 20px\", textDecoration:\"none\", color:\"inherit\", marginBottom:8, transition:\"all 0.2s\" }} onMouseEnter={e => { e.currentTarget.style.boxShadow=\"0 4px 16px rgba(0,0,0,0.08)\"; e.currentTarget.style.borderColor=\"#1a6fd4\"; }}\n                    onMouseLeave={e => { e.currentTarget.style.boxShadow=\"none\"; e.currentTarget.style.borderColor=\"#e0e4ea\"; }}>\n                    <div style={{ display:\"flex\", justifyContent:\"space-between\", alignItems:\"flex-start\", gap:10, marginBottom:4 }}>\n                      <span style={{ fontSize:\"0.95rem\", fontWeight:600, color:\"#1a6fd4\" }}>{p.n}<\/span>\n                      <span style={{ fontSize:\"0.68rem\", fontWeight:600, padding:\"3px 9px\", borderRadius:20, background:\"#e6f5ed\", color:\"#0b7a3e\" }}>{p.b}<\/span>\n                    <\/div>\n                    <p style={{ fontSize:\"0.84rem\", color:\"#5f6b7a\", lineHeight:1.5, marginBottom:4 }}>{rp.reason}<\/p>\n                    <span style={{ fontSize:\"0.82rem\", fontWeight:600, color:\"#1a6fd4\" }}>View product \u2192<\/span>\n                  <\/a>\n                );\n              })}\n            <\/div>\n          )}\n\n          {\/* CTA *\/}\n          {sol.cta && (\n            <div style={{ background:\"#f3f5f8\", border:\"1px dashed #d0d5dd\", borderRadius:12, padding:\"20px\", marginTop:16, display:\"flex\", flexDirection:\"column\", gap:10 }}>\n              <a href=\"https:\/\/staging.nxtprocess.com\/contact\/\" target=\"_blank\" rel=\"noopener noreferrer\" style={{ fontFamily:\"inherit\", fontSize:\"0.9rem\", fontWeight:600, padding:\"14px 24px\", borderRadius:10, border:\"none\", textAlign:\"center\", textDecoration:\"none\", display:\"block\", color:\"#fff\", background: sol.cta.type === \"buy\" ? \"#1a6fd4\" : sol.cta.type === \"quote\" ? \"#0b7a3e\" : \"#0c1222\" }}>\n                {sol.cta.label}\n              <\/a>\n              <p style={{ fontSize:\"0.78rem\", color:\"#8b95a5\", textAlign:\"center\" }}>Our engineers respond within 24 hours<\/p>\n            <\/div>\n          )}\n\n          {\/* Continue to chat option *\/}\n          <div style={{ textAlign:\"center\", marginTop:20 }}>\n            <button onClick={() => {\n              goToChat(`${problem.label} \u2014 specifically: ${subProblem.label}`);\n            }}\n              style={{ fontFamily:\"inherit\", fontSize:\"0.85rem\", fontWeight:500, color:\"#1a6fd4\", background:\"none\", border:\"none\", cursor:\"pointer\", textDecoration:\"underline\" }}>\n              I have more questions \u2014 talk to the advisor\n            <\/button>\n          <\/div>\n        <\/div>\n      <\/div>\n    );\n  }\n\n  \/\/ \u2500\u2500\u2500 PARTS FINDER PAGE \u2500\u2500\u2500\n  if (stage === \"parts\") {\n    async function searchParts(q) {\n      if (!q.trim()) return;\n      setPartLoading(true);\n      setPartResults(null);\n      const candidates = preFilter(q);\n      const candidateData = candidates.map(i => ({ index:i, name:CATALOG[i].n, brand:CATALOG[i].b||\"\", description:CATALOG[i].d, categories:CATALOG[i].c||\"\" }));\n      const bestMatch = findBestMatch(q);\n      try {\n        const raw = await callAPI(\n          `Product matcher for NXT Process. Given pre-filtered candidates, return ONLY JSON:\n{\"results\":[{\"index\":<original_index>,\"relevance\":\"high\"|\"medium\",\"reason\":\"why this matches\"}]}\nReturn 1-6 results ranked by relevance.`,\n          `Query: \"${q}\"\\nIndustry context: ${industry?.label || \"unknown\"}\\nCandidates:\\n${JSON.stringify(candidateData)}`\n        );\n        const data = JSON.parse(raw);\n        setPartResults({ items: data.results || [], bestMatch, query: q });\n      } catch(e) {\n        console.error(e);\n        setPartResults({ items: [], bestMatch, query: q, error: true });\n      }\n      setPartLoading(false);\n    }\n\n    const examples = industry?.id === \"brewing\"\n      ? [\"Tri-clamp gasket\", \"Centrifugal pump\", \"Butterfly valve\", \"Sight glass\"]\n      : [\"Tri-clamp fitting\", \"Pressure sensor\", \"Check valve\", \"Heat exchanger\"];\n\n    return (\n      <div style={{ minHeight:\"100vh\", background:\"#fafbfc\", fontFamily:\"'Outfit',system-ui,sans-serif\" }}>\n        {\/* Header *\/}\n        <div style={{ background:\"#0c1222\", padding:\"14px 24px\", display:\"flex\", alignItems:\"center\", justifyContent:\"space-between\" }}>\n          <div style={{ display:\"flex\", alignItems:\"center\", gap:12 }}>\n            <button onClick={() => { setStage(\"problem\"); setPartResults(null); setPartQuery(\"\"); }}\n              style={{ background:\"none\", border:\"none\", color:\"#4a9eed\", fontSize:\"0.85rem\", fontWeight:500, cursor:\"pointer\", fontFamily:\"inherit\" }}>\n              \u2190 Back\n            <\/button>\n            <div style={{ width:1, height:16, background:\"#1e2d45\" }} \/>\n            <span style={{ fontSize:\"0.8rem\", fontWeight:600, letterSpacing:\"0.06em\", color:\"#fff\" }}>NXT<\/span>\n            <span style={{ fontSize:\"0.65rem\", color:\"#4a9eed\", fontWeight:500, letterSpacing:\"0.06em\", textTransform:\"uppercase\" }}>Part Finder<\/span>\n          <\/div>\n          {industry && (\n            <span style={{ fontSize:\"0.73rem\", fontWeight:500, color:\"#4a9eed\", background:\"#131d30\", padding:\"4px 10px\", borderRadius:20, border:\"1px solid #1e2d45\" }}>\n              {industry.icon} {industry.label}\n            <\/span>\n          )}\n        <\/div>\n\n        <div style={{ maxWidth:680, margin:\"0 auto\", padding:\"32px 16px\" }}>\n          {\/* Title *\/}\n          <div style={{ textAlign:\"center\", marginBottom:28 }}>\n            <h2 style={{ fontSize:\"1.5rem\", fontWeight:700, letterSpacing:\"-0.02em\", color:\"#0f1729\", marginBottom:6 }}>Find the Right Part<\/h2>\n            <p style={{ fontSize:\"0.9rem\", color:\"#5f6b7a\" }}>Search by part number, spec, type, or describe what you need.<\/p>\n          <\/div>\n\n          {\/* Search bar *\/}\n          <div style={{ display:\"flex\", gap:8, background:\"#fff\", border:\"2px solid #e0e4ea\", borderRadius:14, padding:6, boxShadow:\"0 2px 12px rgba(0,0,0,0.06)\", marginBottom:12 }}>\n            <input ref={partInputRef} value={partQuery} onChange={e => setPartQuery(e.target.value)}\n              onKeyDown={e => e.key === \"Enter\" && searchParts(partQuery)}\n              placeholder='e.g. \"2 inch tri-clamp\" or \"brewery pump\"'\n              style={{ flex:1, border:\"none\", outline:\"none\", fontFamily:\"inherit\", fontSize:\"0.95rem\", padding:\"10px 12px\", background:\"transparent\", color:\"#111\" }}\n            \/>\n            <button onClick={() => searchParts(partQuery)} disabled={partLoading || !partQuery.trim()}\n              style={{ padding:\"10px 20px\", fontFamily:\"inherit\", fontSize:\"0.85rem\", fontWeight:600, background:\"#1a6fd4\", color:\"#fff\", border:\"none\", borderRadius:10, cursor: partLoading||!partQuery.trim() ? \"not-allowed\":\"pointer\", opacity: partLoading||!partQuery.trim() ? 0.5:1, whiteSpace:\"nowrap\" }}>\n              Search\n            <\/button>\n          <\/div>\n\n          {\/* Example queries *\/}\n          <div style={{ display:\"flex\", flexWrap:\"wrap\", gap:6, marginBottom:28 }}>\n            {examples.map(ex => (\n              <button key={ex} onClick={() => { setPartQuery(ex); searchParts(ex); }}\n                style={{ fontFamily:\"inherit\", fontSize:\"0.78rem\", padding:\"5px 12px\", border:\"1px solid #e0e4ea\", borderRadius:20, background:\"#fff\", color:\"#5f6b7a\", cursor:\"pointer\" }}>\n                {ex}\n              <\/button>\n            ))}\n          <\/div>\n\n          {\/* Loading *\/}\n          {partLoading && (\n            <div style={{ textAlign:\"center\", padding:\"40px 0\" }}>\n              <div style={{ display:\"inline-flex\", gap:5, marginBottom:12 }}>\n                {[0,1,2].map(i => <div key={i} style={{ width:9, height:9, background:\"#1a6fd4\", borderRadius:\"50%\", animation:`pulse 1.1s infinite ${i*0.13}s` }} \/>)}\n              <\/div>\n              <p style={{ fontSize:\"0.85rem\", color:\"#5f6b7a\" }}>Searching products...<\/p>\n              <style>{`@keyframes pulse { 0%,80%,100% { transform:scale(0.55); opacity:0.35; } 40% { transform:scale(1); opacity:1; } }`}<\/style>\n            <\/div>\n          )}\n\n          {\/* Results *\/}\n          {partResults && !partLoading && (\n            <div>\n              {\/* Best match *\/}\n              {partResults.bestMatch && (\n                <a href={partResults.bestMatch.url} target=\"_blank\" rel=\"noopener noreferrer\" style={{ display:\"block\", background:\"linear-gradient(135deg, #e6f5ed 0%, #fff 100%)\", border:\"2px solid #0b7a3e\", borderRadius:12, padding:\"16px 20px\", textDecoration:\"none\", color:\"inherit\", marginBottom:10 }}>\n                  <div style={{ display:\"flex\", justifyContent:\"space-between\", alignItems:\"flex-start\", gap:10, marginBottom:4 }}>\n                    <span style={{ fontSize:\"0.95rem\", fontWeight:600, color:\"#0b7a3e\" }}>{partResults.bestMatch.name}<\/span>\n                    <span style={{ fontSize:\"0.7rem\", fontWeight:600, padding:\"3px 9px\", borderRadius:20, background:\"#0b7a3e\", color:\"#fff\" }}>\u2605 NXT Recommended<\/span>\n                  <\/div>\n                  <p style={{ fontSize:\"0.84rem\", color:\"#5f6b7a\", lineHeight:1.5, marginBottom:6 }}>{partResults.bestMatch.reason}<\/p>\n                  <span style={{ fontSize:\"0.82rem\", fontWeight:600, color:\"#0b7a3e\" }}>View product \u2192<\/span>\n                <\/a>\n              )}\n\n              {\/* AI results *\/}\n              {partResults.items.length > 0 && (\n                <>\n                  {partResults.bestMatch && <p style={{ fontSize:\"0.75rem\", fontWeight:600, textTransform:\"uppercase\", letterSpacing:\"0.04em\", color:\"#8b95a5\", margin:\"16px 0 10px\" }}>Also from our catalog<\/p>}\n                  {partResults.items.map((r, j) => {\n                    const p = CATALOG[r.index];\n                    if (!p) return null;\n                    const isHigh = r.relevance === \"high\";\n                    return (\n                      <a key={j} href={p.u} target=\"_blank\" rel=\"noopener noreferrer\" style={{ display:\"block\", background:\"#fff\", border:\"1px solid #e0e4ea\", borderRadius:12, padding:\"16px 20px\", textDecoration:\"none\", color:\"inherit\", marginBottom:8, transition:\"all 0.2s\" }} onMouseEnter={e => { e.currentTarget.style.boxShadow=\"0 4px 16px rgba(0,0,0,0.08)\"; e.currentTarget.style.borderColor=\"#1a6fd4\"; }}\n                        onMouseLeave={e => { e.currentTarget.style.boxShadow=\"none\"; e.currentTarget.style.borderColor=\"#e0e4ea\"; }}>\n                        <div style={{ display:\"flex\", justifyContent:\"space-between\", alignItems:\"flex-start\", gap:10, marginBottom:4 }}>\n                          <span style={{ fontSize:\"0.95rem\", fontWeight:600, color:\"#1a6fd4\" }}>{p.n}<\/span>\n                          <span style={{ fontSize:\"0.68rem\", fontWeight:500, padding:\"3px 9px\", borderRadius:20, background:isHigh?\"#e6f5ed\":\"#fef6e0\", color:isHigh?\"#0b7a3e\":\"#9a6700\", fontFamily:\"monospace\" }}>\n                            {isHigh ? \"Best match\" : \"Related\"}\n                          <\/span>\n                        <\/div>\n                        <p style={{ fontSize:\"0.84rem\", color:\"#5f6b7a\", lineHeight:1.5, marginBottom:4 }}>{r.reason}<\/p>\n                        <p style={{ fontSize:\"0.76rem\", color:\"#8b95a5\" }}>{p.b ? <strong style={{color:\"#1a6fd4\"}}>{p.b}<\/strong> : null}{p.b ? \" \u00b7 \" : \"\"}{p.c}<\/p>\n                        <span style={{ display:\"inline-block\", marginTop:6, fontSize:\"0.82rem\", fontWeight:600, color:\"#1a6fd4\" }}>View product \u2192<\/span>\n                      <\/a>\n                    );\n                  })}\n                <\/>\n              )}\n\n              {!partResults.bestMatch && partResults.items.length === 0 && (\n                <p style={{ textAlign:\"center\", color:\"#5f6b7a\", padding:20, fontSize:\"0.9rem\" }}>No matches found. Try different terms or <button onClick={() => { setStage(\"chat\"); setProblem({id:\"part\",label:\"Find a specific part\",icon:\"\ud83d\udd29\",desc:\"\"}); contextRef.current.problem=\"Find a specific part\"; contextRef.current.history=[{role:\"user\",content:`My industry is ${industry?.label}. I'm looking for: ${partResults.query}`}]; send(`My industry is ${industry?.label}. I'm looking for: ${partResults.query}`, true); }} style={{ background:\"none\", border:\"none\", color:\"#1a6fd4\", fontWeight:600, cursor:\"pointer\", fontFamily:\"inherit\", fontSize:\"inherit\", textDecoration:\"underline\" }}>ask our advisor<\/button>.<\/p>\n              )}\n\n              {\/* Contact CTA *\/}\n              <div style={{ background:\"#f3f5f8\", border:\"1px dashed #d0d5dd\", borderRadius:12, padding:\"16px 20px\", marginTop:14, display:\"flex\", alignItems:\"center\", justifyContent:\"space-between\", flexWrap:\"wrap\", gap:10 }}>\n                <div>\n                  <p style={{ fontSize:\"0.88rem\", fontWeight:600, color:\"#0f1729\", marginBottom:2 }}>Can't find what you need?<\/p>\n                  <p style={{ fontSize:\"0.8rem\", color:\"#5f6b7a\" }}>Our engineers can help you find the right part.<\/p>\n                <\/div>\n                <a href=\"https:\/\/staging.nxtprocess.com\/contact\/\" target=\"_blank\" rel=\"noopener noreferrer\" style={{ fontFamily:\"inherit\", fontSize:\"0.83rem\", fontWeight:600, padding:\"9px 18px\", background:\"#0f1729\", color:\"#fff\", textDecoration:\"none\", borderRadius:8, whiteSpace:\"nowrap\" }}>\n                  Contact NXT\n                <\/a>\n              <\/div>\n            <\/div>\n          )}\n        <\/div>\n      <\/div>\n    );\n  }\n\n  if (stage === \"chat\") return (\n    <div style={{ minHeight:\"100vh\", background:\"#fafbfc\", fontFamily:\"'Outfit',system-ui,sans-serif\" }}>\n      {\/* Chat header *\/}\n      <div style={{ background:\"#0c1222\", padding:\"14px 24px\", display:\"flex\", alignItems:\"center\", justifyContent:\"space-between\", position:\"sticky\", top:0, zIndex:10 }}>\n        <div style={{ display:\"flex\", alignItems:\"center\", gap:12 }}>\n          <button onClick={() => { setStage(\"problem\"); setMessages([]); setProblem(null); contextRef.current = {industry:contextRef.current.industry,problem:\"\",needs:[],history:[]}; }}\n            style={{ background:\"none\", border:\"none\", color:\"#4a9eed\", fontSize:\"0.85rem\", fontWeight:500, cursor:\"pointer\", fontFamily:\"inherit\", padding:\"4px 0\" }}>\n            \u2190 Back\n          <\/button>\n          <div style={{ width:1, height:16, background:\"#1e2d45\" }} \/>\n          <span style={{ fontSize:\"0.8rem\", fontWeight:600, letterSpacing:\"0.06em\", color:\"#fff\" }}>NXT<\/span>\n          <span style={{ fontSize:\"0.65rem\", color:\"#4a9eed\", fontWeight:500, letterSpacing:\"0.06em\", textTransform:\"uppercase\" }}>Process Advisor<\/span>\n        <\/div>\n        <div style={{ display:\"flex\", gap:6, flexWrap:\"wrap\", justifyContent:\"flex-end\" }}>\n          {industry && (\n            <span style={{ fontSize:\"0.73rem\", fontWeight:500, color:\"#4a9eed\", background:\"#131d30\", padding:\"4px 10px\", borderRadius:20, border:\"1px solid #1e2d45\" }}>\n              {industry.icon} {industry.label}\n            <\/span>\n          )}\n          {problem && (\n            <span style={{ fontSize:\"0.73rem\", fontWeight:500, color:\"#8bc4f6\", background:\"#131d30\", padding:\"4px 10px\", borderRadius:20, border:\"1px solid #1e2d45\" }}>\n              {problem.icon} {problem.label}\n            <\/span>\n          )}\n        <\/div>\n      <\/div>\n\n      {\/* Messages *\/}\n      <div ref={threadRef} style={{ maxWidth:680, margin:\"0 auto\", padding:\"24px 16px 140px\", display:\"flex\", flexDirection:\"column\", gap:16 }}>\n        {messages.map((msg, i) => (\n          <div key={i}>\n            {msg.role === \"user\" && (\n              <div style={{ alignSelf:\"flex-end\", maxWidth:\"85%\", background:\"#1a6fd4\", color:\"#fff\", padding:\"12px 18px\", borderRadius:\"16px 16px 4px 16px\", fontSize:\"0.92rem\", lineHeight:1.5, marginLeft:\"auto\", width:\"fit-content\" }}>\n                {msg.text}\n              <\/div>\n            )}\n            {msg.role === \"ai\" && (\n              <div style={{ maxWidth:\"100%\", fontSize:\"0.92rem\", lineHeight:1.6 }}>\n                <p style={{ marginBottom:14, color:\"#2d3748\" }}>{msg.message}<\/p>\n\n                {msg.options && (\n                  <div style={{ display:\"grid\", gridTemplateColumns:\"1fr 1fr\", gap:8, marginBottom:8 }}>\n                    {msg.options.map((opt, j) => (\n                      <button key={j} onClick={() => send(opt)}\n                        style={{ fontFamily:\"inherit\", fontSize:\"0.85rem\", fontWeight:500, padding:\"13px 16px\", border:\"2px solid #e0e4ea\", borderRadius:10, background:\"#fff\", color:\"#1a1d23\", cursor:\"pointer\", textAlign:\"left\", transition:\"all 0.15s\", lineHeight:1.4 }}\n                        onMouseEnter={e => { e.target.style.borderColor=\"#1a6fd4\"; e.target.style.background=\"#f0f5ff\"; }}\n                        onMouseLeave={e => { e.target.style.borderColor=\"#e0e4ea\"; e.target.style.background=\"#fff\"; }}>\n                        {opt}\n                      <\/button>\n                    ))}\n                  <\/div>\n                )}\n\n                {msg.products && msg.products.length > 0 && (\n                  <div style={{ marginTop:8 }}>\n                    <div style={{ fontSize:\"0.73rem\", fontWeight:600, textTransform:\"uppercase\", letterSpacing:\"0.05em\", color:\"#8b95a5\", marginBottom:8 }}>Recommended for you<\/div>\n                    {msg.products.map((pr, j) => {\n                      const p = CATALOG[pr.index];\n                      if (!p) return null;\n                      return (\n                        <a key={j} href={p.u} target=\"_blank\" rel=\"noopener noreferrer\" style={{ display:\"block\", background:\"#fff\", border:\"1px solid #e0e4ea\", borderRadius:12, padding:\"16px 20px\", textDecoration:\"none\", color:\"inherit\", marginBottom:8, transition:\"all 0.2s\" }} onMouseEnter={e => { e.currentTarget.style.boxShadow=\"0 4px 16px rgba(0,0,0,0.08)\"; e.currentTarget.style.borderColor=\"#1a6fd4\"; }}\n                          onMouseLeave={e => { e.currentTarget.style.boxShadow=\"none\"; e.currentTarget.style.borderColor=\"#e0e4ea\"; }}>\n                          <div style={{ display:\"flex\", justifyContent:\"space-between\", alignItems:\"flex-start\", gap:10, marginBottom:4 }}>\n                            <span style={{ fontSize:\"0.95rem\", fontWeight:600, color:\"#1a6fd4\" }}>{p.n}<\/span>\n                            <span style={{ fontSize:\"0.68rem\", fontWeight:600, padding:\"3px 9px\", borderRadius:20, background:\"#e6f5ed\", color:\"#0b7a3e\" }}>{p.b}<\/span>\n                          <\/div>\n                          <p style={{ fontSize:\"0.84rem\", color:\"#5f6b7a\", lineHeight:1.5, marginBottom:6 }}>{pr.reason}<\/p>\n                          <span style={{ fontSize:\"0.82rem\", fontWeight:600, color:\"#1a6fd4\" }}>View product \u2192<\/span>\n                        <\/a>\n                      );\n                    })}\n                  <\/div>\n                )}\n\n                {msg.cta && (\n                  <div style={{ background:\"#f3f5f8\", border:\"1px dashed #d0d5dd\", borderRadius:12, padding:\"18px 20px\", marginTop:10, display:\"flex\", flexDirection:\"column\", gap:10 }}>\n                    <a href=\"https:\/\/staging.nxtprocess.com\/contact\/\" target=\"_blank\" rel=\"noopener noreferrer\" style={{ fontFamily:\"inherit\", fontSize:\"0.88rem\", fontWeight:600, padding:\"12px 20px\", borderRadius:10, border:\"none\", cursor:\"pointer\", textAlign:\"center\", textDecoration:\"none\", display:\"block\", color:\"#fff\", background: msg.cta.type === \"buy\" ? \"#1a6fd4\" : msg.cta.type === \"quote\" ? \"#0b7a3e\" : \"#0c1222\" }}>\n                      {msg.cta.label}\n                    <\/a>\n                    <p style={{ fontSize:\"0.78rem\", color:\"#8b95a5\", textAlign:\"center\" }}>Our engineers respond within 24 hours<\/p>\n                  <\/div>\n                )}\n              <\/div>\n            )}\n          <\/div>\n        ))}\n\n        {loading && (\n          <div style={{ display:\"inline-flex\", gap:4, padding:\"12px 0\" }}>\n            {[0,1,2].map(i => (\n              <div key={i} style={{ width:8, height:8, borderRadius:\"50%\", background:\"#1a6fd4\", animation:`pulse 1.1s infinite ${i*0.15}s` }} \/>\n            ))}\n            <style>{`@keyframes pulse { 0%,80%,100% { transform:scale(0.5); opacity:0.3; } 40% { transform:scale(1); opacity:1; } }`}<\/style>\n          <\/div>\n        )}\n      <\/div>\n\n      {\/* Input bar *\/}\n      <div style={{ position:\"fixed\", bottom:0, left:0, right:0, background:\"linear-gradient(transparent, #fafbfc 20%)\", padding:\"24px 16px 16px\" }}>\n        <div style={{ maxWidth:680, margin:\"0 auto\" }}>\n          <div style={{ display:\"flex\", gap:8, background:\"#fff\", border:\"2px solid #e0e4ea\", borderRadius:14, padding:6, boxShadow:\"0 2px 12px rgba(0,0,0,0.06)\" }}>\n            <input ref={inputRef} value={input} onChange={e => setInput(e.target.value)}\n              onKeyDown={e => e.key === \"Enter\" && !loading && send(input)}\n              placeholder=\"Type your answer or ask anything...\"\n              style={{ flex:1, border:\"none\", outline:\"none\", fontFamily:\"inherit\", fontSize:\"0.95rem\", padding:\"10px 12px\", background:\"transparent\", color:\"#111\" }}\n              disabled={loading} \/>\n            <button onClick={() => send(input)} disabled={loading || !input.trim()}\n              style={{ padding:\"10px 20px\", fontFamily:\"inherit\", fontSize:\"0.85rem\", fontWeight:600, background:\"#1a6fd4\", color:\"#fff\", border:\"none\", borderRadius:10, cursor: loading||!input.trim() ? \"not-allowed\" : \"pointer\", opacity: loading||!input.trim() ? 0.5 : 1, whiteSpace:\"nowrap\" }}>\n              Send\n            <\/button>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  );\n}\n\n\nReactDOM.createRoot(document.getElementById('root')).render(<App \/>);\n<\/script> \n\n<\/div>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>NXT Process \u2014 Solutions pour les proc\u00e9d\u00e9s liquides NXT Process \u2014 Solutions pour les proc\u00e9d\u00e9s liquides<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-59083","page","type-page","status-publish","hentry"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>D\u00e9monstration de l\u2019entonnoir | NXT Process<\/title>\n<meta name=\"robots\" content=\"noindex, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"D\u00e9monstration de l\u2019entonnoir | NXT Process\" \/>\n<meta property=\"og:description\" content=\"NXT Process \u2014 Solutions pour les proc\u00e9d\u00e9s liquides NXT Process \u2014 Solutions pour les proc\u00e9d\u00e9s liquides\" \/>\n<meta property=\"og:url\" content=\"https:\/\/staging.nxtprocess.com\/funnel-demo\/\" \/>\n<meta property=\"og:site_name\" content=\"NXT Process\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/people\/NXT-Process\/61560023431243\/\" \/>\n<meta property=\"article:modified_time\" content=\"2026-05-12T18:44:57+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/staging.nxtprocess.com\\\/funnel-demo\\\/\",\"url\":\"https:\\\/\\\/staging.nxtprocess.com\\\/funnel-demo\\\/\",\"name\":\"D\u00e9monstration de l\u2019entonnoir | NXT Process\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/staging.nxtprocess.com\\\/#website\"},\"datePublished\":\"2026-05-12T18:38:16+00:00\",\"dateModified\":\"2026-05-12T18:44:57+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/staging.nxtprocess.com\\\/funnel-demo\\\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/staging.nxtprocess.com\\\/funnel-demo\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/staging.nxtprocess.com\\\/funnel-demo\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/staging.nxtprocess.com\\\/fr\\\/accueil-1\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"D\u00e9monstration de l\u2019entonnoir\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/staging.nxtprocess.com\\\/#website\",\"url\":\"https:\\\/\\\/staging.nxtprocess.com\\\/\",\"name\":\"NXT Process\",\"description\":\"Optimizing your future, one liquid process at a time\",\"publisher\":{\"@id\":\"https:\\\/\\\/staging.nxtprocess.com\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/staging.nxtprocess.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fr-FR\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/staging.nxtprocess.com\\\/#organization\",\"name\":\"Processus NXT\",\"url\":\"https:\\\/\\\/staging.nxtprocess.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/staging.nxtprocess.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"http:\\\/\\\/staging.nxtprocess.com\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/Screenshot_1.png\",\"contentUrl\":\"http:\\\/\\\/staging.nxtprocess.com\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/Screenshot_1.png\",\"width\":255,\"height\":186,\"caption\":\"Processus NXT\"},\"image\":{\"@id\":\"https:\\\/\\\/staging.nxtprocess.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/people\\\/NXT-Process\\\/61560023431243\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/11569305\\\/\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"D\u00e9monstration de l\u2019entonnoir | NXT Process","robots":{"index":"noindex","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"og_locale":"fr_FR","og_type":"article","og_title":"D\u00e9monstration de l\u2019entonnoir | NXT Process","og_description":"NXT Process \u2014 Solutions pour les proc\u00e9d\u00e9s liquides NXT Process \u2014 Solutions pour les proc\u00e9d\u00e9s liquides","og_url":"https:\/\/staging.nxtprocess.com\/funnel-demo\/","og_site_name":"NXT Process","article_publisher":"https:\/\/www.facebook.com\/people\/NXT-Process\/61560023431243\/","article_modified_time":"2026-05-12T18:44:57+00:00","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/staging.nxtprocess.com\/funnel-demo\/","url":"https:\/\/staging.nxtprocess.com\/funnel-demo\/","name":"D\u00e9monstration de l\u2019entonnoir | NXT Process","isPartOf":{"@id":"https:\/\/staging.nxtprocess.com\/#website"},"datePublished":"2026-05-12T18:38:16+00:00","dateModified":"2026-05-12T18:44:57+00:00","breadcrumb":{"@id":"https:\/\/staging.nxtprocess.com\/funnel-demo\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/staging.nxtprocess.com\/funnel-demo\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/staging.nxtprocess.com\/funnel-demo\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/staging.nxtprocess.com\/fr\/accueil-1\/"},{"@type":"ListItem","position":2,"name":"D\u00e9monstration de l\u2019entonnoir"}]},{"@type":"WebSite","@id":"https:\/\/staging.nxtprocess.com\/#website","url":"https:\/\/staging.nxtprocess.com\/","name":"NXT Process","description":"Optimizing your future, one liquid process at a time","publisher":{"@id":"https:\/\/staging.nxtprocess.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/staging.nxtprocess.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fr-FR"},{"@type":"Organization","@id":"https:\/\/staging.nxtprocess.com\/#organization","name":"Processus NXT","url":"https:\/\/staging.nxtprocess.com\/","logo":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/staging.nxtprocess.com\/#\/schema\/logo\/image\/","url":"http:\/\/staging.nxtprocess.com\/wp-content\/uploads\/2025\/06\/Screenshot_1.png","contentUrl":"http:\/\/staging.nxtprocess.com\/wp-content\/uploads\/2025\/06\/Screenshot_1.png","width":255,"height":186,"caption":"Processus NXT"},"image":{"@id":"https:\/\/staging.nxtprocess.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/people\/NXT-Process\/61560023431243\/","https:\/\/www.linkedin.com\/company\/11569305\/"]}]}},"_links":{"self":[{"href":"https:\/\/staging.nxtprocess.com\/fr\/wp-json\/wp\/v2\/pages\/59083","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/staging.nxtprocess.com\/fr\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/staging.nxtprocess.com\/fr\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/staging.nxtprocess.com\/fr\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/staging.nxtprocess.com\/fr\/wp-json\/wp\/v2\/comments?post=59083"}],"version-history":[{"count":0,"href":"https:\/\/staging.nxtprocess.com\/fr\/wp-json\/wp\/v2\/pages\/59083\/revisions"}],"wp:attachment":[{"href":"https:\/\/staging.nxtprocess.com\/fr\/wp-json\/wp\/v2\/media?parent=59083"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}