/* AUTOPILOT — sections (React components) */
const { useEffect, useRef, useState } = React;

/* Single source of truth for the audit-booking destination. Both the Final
   CTA buttons and the sticky mobile CTA bar read from this constant.
   TODO: replace with your real Cal.com / Calendly / Tally URL when ready. */
const BOOKING_URL = '#book';
const CONTACT_EMAIL = 'autopilotyourworkflow@gmail.com';

/* i18n strings (EN only for now; TH copy will be added later) */
const I18N = {
 EN: {
 nav: { gap: 'The Gap', how: 'How it works', caps: 'Capabilities', results: 'Results', why: 'Why us', about: 'About', pricing: 'Pricing', faq: 'FAQ', cta: 'Free audit' },
 hero: {
 eyebrow: 'AI Automation Studio',
 stackTop: 'YOUR WORKFLOWS',
 stackBottomPre: 'ON ',
 stackBottomAccent: 'AUTOPILOT',
 mainSingle: 'Your workflow,',
 mainSingleAccent: 'on autopilot.',
 sub: 'AI automations for SMBs without a tech team. We work free until it works, or refund you 100%. No exceptions.',
 cta1: 'Claim Your Free Audit',
 cta2: 'See Capabilities',
 micro: '30 minutes. No pitch deck. Just a clear answer on whether automation is worth it for your business.',
 guarantee: 'Outcome guarantee · Free until it works, or 100% refund',
 },
 tools: {
 eyebrow: '§ 01 · Stack',
 title: 'We Build on the Tools You Already Use',
 closing: "Don't see yours? We probably know it. If we don't, we'll learn it before kickoff.",
 },
 problem: {
 eyebrow: '§ 02 · The Problem',
 title: 'AI Is Eating Your Competitors’ Overhead',
 title2: "You're Still Doing the Work by Hand",
 lead: "You're not avoiding automation. You're stuck because the options are bad",
 bullets: [
 'Every Monday: 3 hours rebuilding the same KPI report by hand.',
 'Every contract: 90 minutes copy-pasting client details into a template.',
 'Every customer inquiry: 4 tools, one task. Repeat. Repeat. Repeat.',
 ],
 promise: 'AUTOPILOT runs hundreds of loops like these. While you sleep.',
 },
 how: {
 eyebrow: '§ 04 · How It Works',
 title: 'Three Steps. No Tech Team Required',
 steps: [
 { stage: '1. Discover',           t: 'We map your bottlenecks',                  body: "A 30-minute call to find the work that's quietly costing you the most time and money. You'll leave with clarity whether or not we work together." },
 { stage: '2. Build',              t: 'We build on the tools you already use',    body: "Google Sheets, your CRM, Make, n8n, LINE, Notion, whatever you've got. Less friction. Faster adoption. No new logins for your team." },
 { stage: '3. Deliver & Support',  t: 'We deliver the outcome, guaranteed',       body: "If the automation doesn't do what we agreed it would, we work for free until it does. Or 100% refund. Your call." },
 ],
 },
 caps: {
 eyebrow: '§ 06 · Capabilities',
 title: 'If Your Team Does It the Same Way Every Time,',
 title2: 'We Can Probably Automate It',
 lede: "We don't sell a product. We build whatever your business needs, tailored to your tools, your team, and your way of working. Some of what we've built:",
 closing: "Don't see your use case? Tell us what's eating your week. There's a good chance we've already built something close.",
 items: [
 { id: 'CAP-01', tag: 'Reporting', title: 'Real-Time Dashboards and Reporting', body: 'Replace 3-day monthly reporting marathons with live executive dashboards. Looker Studio, custom builds, or pulled into the tools you already use.' },
 { id: 'CAP-02', tag: 'Documents', title: 'Document Generation', body: 'Contracts, proposals, invoices, reports. Cut document drafting from 90 minutes to seconds, with zero copy-paste errors.' },
 { id: 'CAP-03', tag: 'Finance', title: 'Accounting and Finance Automations', body: 'Employee reimbursements, partner dividend calculations, invoice flows, expense tracking. Errors gone. Hours back.' },
 { id: 'CAP-04', tag: 'Messaging', title: 'Chat and Messaging Bots', body: 'Auto-organize attachments, route inquiries, respond to leads. LINE, WhatsApp, email, web chat. Wherever your customers are.' },
 { id: 'CAP-05', tag: 'CRM / DB', title: 'CRM and Databases', body: 'Custom databases (Supabase, Cloudflare D1), CRM cleanup, lead routing, pipeline automation. Keep your data clean and actually usable.' },
 { id: 'CAP-06', tag: 'AI / RAG', title: 'AI Agents and RAG Systems', body: 'LLM-powered assistants trained on your business, your documents, your tone. Internal Q&A bots, customer support agents, research assistants.' },
 { id: 'CAP-07', tag: 'Tools', title: 'Custom Calculators and Internal Tools', body: "Replace 10 messy spreadsheets with one purpose-built tool that does exactly what your team needs and nothing they don't." },
 { id: 'CAP-08', tag: 'API', title: 'API Integrations', body: 'Connect anything to anything. If both tools have an API, we can make them talk, and trigger automations off the conversation.' },
 ],
 },
 results: {
 eyebrow: '§ 03 · Results',
 title: 'Real Outcomes From Real Clients',
 // First two items render as hero cards on the top row; the last three render
 // as smaller cards on the bottom row (2 + 3 mosaic). `count` + `suffix`
 // splits the stat so the number can animate from 0 on scroll-into-view;
 // items without `count` render the `stat` string statically.
 items: [
 { stat: 'Entire dept.',            unit: 'automated',           body: 'For a Bangkok law firm: employee reimbursement system and partner dividend calculations. What used to be a manual, error-prone monthly grind now runs itself.' },
 { count: 3,  suffix: '+ days',     unit: 'saved every month',  body: 'A monthly executive report took the head of support 3 full days to compile by hand. We replaced it with a real-time dashboard the executives can check anytime. The 3 days came back to the team. Every month. Forever.' },
 { count: 90, suffix: ' min',       unit: 'saved per contract',  body: 'The same Bangkok law firm was spending an hour and a half drafting each contract by hand. We built a document generation system. Contracts now go out in seconds, error-free. Multiply by every contract they sign.' },
 { count: 45, suffix: ' min',       unit: 'back every day',      body: 'A custom indicator that compresses 45 minutes of daily market analysis into a glance. Built originally for our founder, a 9-year trader, then deployed to clients.' },
 { stat: 'Zero',                    unit: 'lost attachments',    body: 'A LINE bot that automatically saves, renames, and organizes every file sent in chat. Straight to the cloud, in the right folder, with the right name. No more "where did we save that file?"' },
 ],
 footer: 'Real outcomes from real engagements. Numbers vary by scope. That’s why we cap what we take.',
 },
 why: {
 eyebrow: '§ 07 · Why AUTOPILOT',
 title: 'Why Clients Pick Us',
 title2: 'Over Custom Dev Shops, Freelancers, and "Set Up AI Automation yourself" YouTube Tutorials',
 items: [
 { num: '01', t: 'Outcomes, not deliverables.', body: "Most agencies hand you software and walk away. We guarantee the result. If what we build doesn't do what we said it would, we work for free until it does, or refund you 100%. We can offer this because we don't take projects we can't deliver." },
 { num: '02', t: '20 to 30% ahead of schedule. Every project.', body: "We don't pad timelines and we don't slip. If we say 3 weeks, expect 2." },
 { num: '03', t: 'Half the cost of a custom build.', body: "We've delivered work clients were quoted 2x for elsewhere, at the same quality, sometimes better, because we build on what you already pay for instead of reinventing the wheel." },
 { num: '04', t: 'Tool-agnostic by design.', body: "We don't push a stack. We adapt to yours. Google Workspace, Microsoft 365, n8n, Make, Zapier, Supabase, your CRM. Whatever your team already uses, we build on it." },
 { num: '05', t: 'Built by an operator, not a salesperson.', body: '4+ years building backends and automations. 9+ years as a trader, where every system has to actually work or you lose money. We think in outcomes because that\u2019s the only way we know how.' },
 ],
 },
 about: {
 eyebrow: '§ 05 · Founder',
 title: 'Meet the Operator Behind ',
 titleAccent: 'AUTOPILOT',
 byline: 'Chanon Poovaviranon (Beam) · Founder & Automation Architect',
 credentials: ['4+ Yrs Automation', '9+ Yrs Trader'],
 paras: [
 "I'm a trader by training and a builder by heart. Nine years running my own positions taught me that systems either work or they cost you money. There's no middle ground.",
 "It started with tools for myself: a dashboard, a database, a position size calculator. Someone noticed and asked me to do the same for their company. One project became another. Four years later, AUTOPILOT.",
 "I run on one principle: \u0e2a\u0e31\u0e08\u0e08\u0e30. It's a Thai word that doesn't translate cleanly. The closest English version is integrity, but the meaning runs deeper. Being a person of your word. Following through on what you said you'd do, even when it costs you. That's why I guarantee outcomes instead of deliverables. Not as a marketing line. As a personal one.",
 "When I'm not building, I'm trading my own positions, gaming, or hanging out with my two dogs and two cats.",
 "Got a process that's eating your week? Let's talk.",
 ],
 quote: 'Systems either work or they cost you money. There\u2019s no middle ground.',
 portraitNote: '[ founder portrait — Beam ]',
 },
 pricing: {
 eyebrow: '§ 08 · Pricing',
 title: 'Three Project Bands',
 title2: 'Pick the One That Matches Your Bottleneck',
 popularLabel: 'Most Common',
 tiers: [
 {
 name: 'Quick Win',
 range: '฿3K – ฿20K',
 timeline: '1–2 weeks',
 body: 'A single, focused automation that pays for itself within months. The right first project to see how we work.',
 includes: [
 'One process automated end-to-end',
 'Built on tools you already pay for',
 'Full handoff and plain-English docs',
 ],
 },
 {
 name: 'System Build',
 range: '฿20K – ฿80K',
 timeline: '2–4 weeks',
 body: 'A multi-step workflow that connects 3–5 tools and replaces a recurring drag on your team.',
 popular: true,
 includes: [
 'Multi-step workflow across 3–5 tools',
 'Custom dashboard or internal tool',
 'Two rounds of revision included',
 'Three months of post-launch support',
 ],
 },
 {
 name: 'Multi-System',
 range: '฿80K – ฿200K+',
 timeline: '4–10 weeks',
 body: 'A cross-tool platform that automates a meaningful chunk of how your business runs day-to-day.',
 includes: [
 'End-to-end platform across your stack',
 'AI agents, RAG, or custom databases',
 'Full team training and documentation',
 'Ten months of post-launch support',
 ],
 },
 ],
 closing: "Not sure which fits? Book the audit. We'll tell you which band makes sense, or whether the project is worth doing at all.",
 },
 faq: {
 eyebrow: '§ 09 · Questions',
 title: 'Questions We Get on Every Audit Call',
 items: [
 { category: 'Pricing',      q: 'How much does this cost?', a: "See the Pricing section above for the three project bands. We don't sell a product, we sell the result. We scope every project so what you get back is multiples of what you pay in, or we don't take the project. If you're not sure whether the numbers work for your business, ask us on the audit. We'll tell you straight." },
 { category: 'Process',      q: 'What does the process look like?', a: 'Five steps. (1) Free 30-minute audit — we diagnose your bottleneck and tell you whether it\u2019s worth automating. (2) Scoped proposal — fixed price, fixed outcome, fixed timeline. No "we\u2019ll see how it goes." (3) Build phase — weekly check-ins. You don\u2019t chase us. (4) Handoff and training — your team learns what they need to. We document the rest in plain English. (5) Support window — we don\u2019t disappear after launch.' },
 { category: 'Risk & Trust', q: "What if the automation doesn't work?", a: "Then we work for free until it does. Or we refund 100%. We deliver outcomes, not software. We can offer this because we only take on projects we're confident we can deliver." },
 { category: 'Process',      q: "We don't have a tech team. Can we still use this?", a: "That's exactly who we build for. We use the tools your team already knows, train you on the parts you'll touch, and document everything in plain English." },
 { category: 'Process',      q: 'How long does it take?', a: 'Depends on scope. A simple automation can ship in days. A larger system might take weeks. Whatever we quote, we consistently deliver 20 to 30% ahead of schedule.' },
 { category: 'Tech & Fit',   q: 'Do you work with our existing tools?', a: 'Almost certainly. Google Workspace, Microsoft 365, n8n, Make, Zapier, Supabase, Notion, your CRM, LINE, WhatsApp, custom APIs. We build on what you already use so your team doesn\u2019t have to learn a new stack.' },
 { category: 'Process',      q: 'What if our needs change after launch?', a: "We document everything and stay available for ongoing support. Most clients come back to expand once the first build pays for itself." },
 { category: 'Risk & Trust', q: 'Do you sign NDAs?', a: 'Yes. Happy to sign one before any sensitive details are shared.' },
 { category: 'Tech & Fit',   q: 'Where are you based and who do you work with?', a: "Based in Bangkok, Thailand. Every client we've worked with so far has been local, but the work is mostly remote. We'd love to build for clients anywhere. Automation doesn't care where you are." },
 ],
 contactCard: {
 title: 'Still have questions?',
 body: 'Email me directly. I read every one.',
 cta: 'Send a message',
 },
 },
 cta: {
 eyebrow: '► Book the Audit',
 title1: 'Stop doing the work', title2: 'software should do', title3: 'for you',
 body: "Book a free 30-minute automation audit. We'll find your biggest bottleneck and tell you honestly whether automation is worth it for your business right now. If it is, we'll give you a clear path to get it done.",
 bodyStrong: 'No pitch deck. No pressure. No fluff.',
 availability: "2 Spots Left for Q2 2026. We Don't Take More.",
 cta1: 'Get Your Free Automation Audit',
 cta2: 'Or Email Me',
 micro: "30 minutes. Free. You'll leave with clarity either way.",
 guarantee: 'Outcome guarantee · Free until it works, or 100% refund',
 },
 footer: { rights: '© 2026 · AUTOPILOT', built: 'Built in Thailand · Operator-led' },
 meta: {
 title: 'AUTOPILOT — AI Automation Studio for SMBs',
 description: 'AI automations for small and medium businesses without a tech team. Free until it works, or 100% refund.',
 },
 },
 TH: {
 nav: { gap: 'ปัญหา', how: 'เริ่มยังไง', caps: 'บริการ', results: 'ผลลัพธ์', why: 'ทำไมต้องเลือกเรา', about: 'ผู้ก่อตั้ง', pricing: 'ราคา', faq: 'คำถามที่พบบ่อย', cta: 'ปรึกษาฟรี' },
 hero: {
 eyebrow: 'AI Automation Studio',
 stackTop: 'YOUR WORKFLOWS',
 stackBottomPre: 'ON ',
 stackBottomAccent: 'AUTOPILOT',
 mainSingle: 'Your workflow,',
 mainSingleAccent: 'on autopilot',
 sub: 'AI automation สำหรับ SME ที่ยังไม่มีทีม IT เราทำงานให้ฟรีจนกว่าระบบจะใช้ได้จริง ไม่งั้นคืนเงิน 100% ไม่มีข้อยกเว้น',
 cta1: 'ปรึกษาฟรี',
 cta2: 'เพิ่มประสิทธิภาพธุรกิจของคุณ',
 micro: 'เพียง 30 นาที ไม่มีการขายของ เราตอบตรงๆว่า AI Automation เหมาะกับธุรกิจของคุณไหม',
 guarantee: 'การันตีผลลัพธ์ · ทำงานให้ฟรีจนกว่าจะใช้ได้ หรือคืนเงิน 100%',
 },
 tools: {
 eyebrow: '§ 01 · Stack',
 title: 'เราต่อยอดจากเครื่องมือที่คุณใช้อยู่แล้ว',
 closing: 'ไม่เห็นเครื่องมือที่คุณใช้? เราน่าจะรู้จักอยู่แล้ว ถ้าไม่รู้ เราจะศึกษาให้พร้อมก่อนเริ่มงาน',
 },
 problem: {
 eyebrow: '§ 02 · ปัญหา',
 title: 'AI กำลังลดต้นทุนให้คู่แข่งของคุณ',
 title2: 'ส่วนคุณและทีมงานยังทำเองทุกขั้นตอน',
 lead: 'ไม่ใช่คุณไม่อยากใช้ automation คุณแค่ยังไม่เจอตัวเลือกที่ใช้ได้จริง',
 bullets: [
 'นั่งทำรายงานเดิมๆที่ซ้ำซาก ครั้งละ 3 ชั่วโมงทุกอาทิตย์',
 '90 นาทีกับการก๊อป-วางข้อมูลลูกค้าทุกครั้งที่ต้องการสร้างเอกสารใหม่',
 'ใช้มากกว่า 4 เครื่องมือในการทำเพียง 1 งาน แต่ก็ยังทำซ้ำแล้วซ้ำอีก',
 ],
 promise: 'AUTOPILOT ทำงานแทนคุณและทีมเป็นร้อยๆครั้ง ในเวลาที่คุณนอน',
 },
 how: {
 eyebrow: '§ 04 · เริ่มยังไง',
 title: 'แค่ 3 ขั้นตอน ไม่ต้องมีทีม IT',
 steps: [
 { stage: '1. สำรวจ', t: 'เราหาคอขวดในธุรกิจของคุณ', body: 'เพียง 30 นาที ในการหากระบวนการทำงานที่กัดกินเงินและเวลาของคุณ คุณจะเห็นภาพที่ชัดเจน ไม่ว่าเราจะได้ร่วมงานกันหรือไม่' },
 { stage: '2. สร้าง', t: 'เราต่อยอดจากเครื่องมือที่คุณใช้อยู่แล้ว', body: 'Google Sheets, CRM ของคุณ, Make, n8n, LINE, Notion อะไรก็ตามที่คุณใช้อยู่แล้ว เพื่อให้ทีมงานใช้ง่าย ไม่ต้องเรียนรู้ใหม่' },
 { stage: '3. ส่งมอบ & ดูแล', t: 'เราการันตีผลลัพธ์', body: 'ถ้าระบบไม่สามารถใช้งานได้ตามที่ตกลง เรายินดีทำงานให้ฟรีจนกว่าจะใช้ได้จริง หรือคืนเงิน 100%' },
 ],
 },
 caps: {
 eyebrow: '§ 06 · บริการ',
 title: 'ถ้าทีมของคุณทำสิ่งเดิมซ้ำๆ',
 title2: 'เราสร้างระบบมาทำแทนให้ได้',
 lede: 'เราไม่ได้ขายสินค้า เราสร้างสิ่งที่ธุรกิจคุณต้องการ ปรับให้เข้ากับทีม และการทำงานของคุณ และนี่คือตัวอย่างของระบบที่เราเคยสร้าง',
 closing: 'ยังนึกไม่ออกว่าจะใช้กับธุรกิจของคุณยังไง? ไม่เป็นไรครับ! เพียงบอกเราว่าเงินหรือเวลาของคุณหมดไปกับอะไร เป็นไปได้สูงว่าเราเคยสร้างอะไรที่คล้ายกันมาแล้ว',
 items: [
 { id: 'CAP-01', tag: 'Reporting', title: 'Real-Time Dashboards & Reports', body: 'เปลี่ยนการนั่งทำรายงานที่กินเวลา 3 วันในทุกๆเดือนให้เป็น real-time dashboard สำหรับผู้บริหาร จะใช้ Power BI, Looker Studio, สร้างแบบ Custom บนเว็บไซต์ หรือเชื่อมกับเครื่องมือที่คุณใช้อยู่ก็ได้เช่นกัน' },
 { id: 'CAP-02', tag: 'Documents', title: 'สร้างเอกสารอัตโนมัติ', body: 'สัญญา, ใบเสนอราคา, ใบแจ้งหนี้, รายงาน ลดเวลาการร่างเอกสารจาก 90 นาที ให้เหลือไม่ถึง 5 นาที ลดข้อผิดพลาดจาก Human-Error' },
 { id: 'CAP-03', tag: 'Finance', title: 'ระบบบัญชีและการเงินอัตโนมัติ', body: 'ระบบเบิกค่าใช้จ่ายพนักงาน (Petty Cash), การคำนวณเงินปันผลผู้ถือหุ้น, ระบบใบแจ้งหนี้, หรือการติดตามค่าใช้จ่าย ความผิดพลาดหายไป แต่ได้เวลากลับคืนมา' },
 { id: 'CAP-04', tag: 'Messaging', title: 'ระบบตอบแชท และส่งข้อความ', body: 'จัดเก็บไฟล์ผ่านแชทอัตโนมัติ, ตอบ/ส่งต่อข้อความอัตโนมัติ ทั้ง LINE, Email, WhatsApp, เว็บไซต์ ไม่ว่าช่องทางไหนที่ลูกค้าคุณเข้ามา' },
 { id: 'CAP-05', tag: 'CRM / DB', title: 'CRM & Databases', body: 'Custom databases (Supabase, Cloudflare D1), จัดระเบียบข้อมูลใน CRM, lead routing, pipeline automation, หรืออะไรก็ตามที่ทำให้ข้อมูลของคุณสะอาด และใช้งานได้จริง' },
 { id: 'CAP-06', tag: 'AI / RAG', title: 'AI Agents & RAG', body: 'AI ที่เรียนรู้ธุรกิจของคุณ ทั้งเอกสาร สไตล์การสื่อสารของคุณ เพื่อนำไปใช้เป็น Q&A bot ภายในองค์กร, ผู้ช่วยค้นคว้าข้อมูล, หรือตอบแชทลูกค้า' },
 { id: 'CAP-07', tag: 'Tools', title: 'เครื่องมือการคำนวณ หรือระบบภายในแบบ Custom', body: 'ที่แทน Excel 10 ไฟล์ที่กระจัดกระจายด้วยเครื่องเดียวที่ออกแบบมาเพื่อทีมของคุณโดยเฉพาะ' },
 { id: 'CAP-08', tag: 'API', title: 'การเชื่อมต่อ API', body: 'เชื่อมต่อระบบไหน เข้ากับอะไรก็ได้ ถ้าทั้งสองระบบมี API เราทำให้มันคุยกัน และสร้างเป็นระบบการทำงานอัตโนมัติได้' },
 ],
 },
 results: {
 eyebrow: '§ 03 · ผลลัพธ์',
 title: 'ผลลัพธ์จริง จากลูกค้าจริง',
 items: [
 { stat: 'ทั้งแผนก', unit: 'ทำแทนด้วยระบบ', body: 'ระบบเบิกค่าใช้จ่ายพนักงาน และการคำนวณปันผลผู้ถือหุ้น ของสำนักงานกฏหมาย เคยเป็นสิ่งที่พนักงาน และเจ้าของบริษัทต้องทำเองทุกเดือน ตอนนี้ระบบทำแทนทั้งหมด' },
 { count: 3, suffix: '+ วัน', unit: 'ที่ได้คืนมาทุกเดือน', body: 'พนักงานใช้เวลามากถึงเดือนละ 3 วันเต็มเพื่อทำรายงานให้ผู้บริหาร เราแทนที่ด้วย real-time dashboard ที่ผู้บริหารสามารถเปิดดูได้ตลอดเวลา แถมยังได้เวลา 3 วันกลับคืนมา ทุกเดือน ตลอดไป' },
 { count: 90, suffix: ' นาที', unit: 'ที่ได้คืนมากับเอกสารทุกฉบับ', body: 'สำนักงานกฏหมายที่เดิม ใช้เวลามากถึง 1 ชั่วโมงครึ่งในการร่างสัญญา 1 ฉบับ เราแทนที่ระบบสร้างเอกสารอัตโนมัติ ตอนนี้สัญญา 1 ฉบับใช้เวลาไม่ถึง 5 นาที ไม่มีข้อผิดพลาด' },
 { count: 45, suffix: ' นาที', unit: 'ที่ได้คืนมาทุกวัน', body: 'ระบบช่วยวิเคราะห์ตลาดหุ้นที่ประหยัดเวลาให้กับเทรดเดอร์ได้มากถึงวันละ 45 นาที สร้างและใช้กับพอร์ตการลงทุนของตัวเอง' },
 { stat: 'ศูนย์', unit: 'คือจำนวนไฟล์ที่ตกหล่นและสูญหาย', body: 'สร้าง LINE bot จัดเก็บไฟล์ที่ส่งผ่านแชทขึ้น cloud อัตโนมัติ พร้อมตั้งชื่อ และเก็บเข้า Folder อย่างถูกต้อง ไม่ต้องถามอีกต่อไปว่า “ส่งไฟล์นั้นให้อีกรอบได้ไหม?”' },
 ],
 footer: 'ผลลัพธ์จริง จากการทำงานจริง ตัวเลขแตกต่างไปตามขอบเขตงาน เราจำกัดจำนวนลูกค้าเพื่อรักษาคุณภาพของงาน และการดูแลหลังส่งมอบที่ดีที่สุด',
 },
 why: {
 eyebrow: '§ 07 · ทำไมต้องเลือกเรา',
 title: 'ทำไมลูกค้าถึงเลือกเรา',
 title2: 'มากกว่า agency, freelance อื่นๆ หรือเลือกที่จะดู YouTube สอนสร้าง AI Automation ด้วยตัวเอง',
 items: [
 { num: '01', t: 'เราการันตี “ผลลัพธ์” ไม่ใช่ “แค่งานที่ส่งมอบ”', body: 'ส่วนใหญ่อาจจะแค่ส่งมอบระบบให้คุณแล้วก็จบกัน เราการันตีผลลัพธ์ ถ้าสิ่งที่สร้างไม่สามารถทำตามที่เราตกลงกันไว้ได้ เรายินดีทำงานให้ฟรีจนกว่าจะใช้ได้จริง หรือคืนเงิน 100%' },
 { num: '02', t: 'ส่งมอบก่อนกำหนด 20-30% ทุกโปรเจค', body: 'เราไม่บวกเวลาเพิ่ม และไม่เลื่อนกำหนด ถ้าเราบอก 3 อาทิตย์ รอรับภายใน 2 อาทิตย์ได้เลย' },
 { num: '03', t: 'เพียงครึ่งราคาของการทำระบบ Custom', body: 'เราเคยส่งมอบงานที่ลูกค้าถูกเสนอราคาแพงกว่าเรา 2 เท่าจากเจ้าอื่น โดยคุณภาพที่เท่ากัน หรือบางครั้งเราก็ดีกว่า' },
 { num: '04', t: 'ไม่ยึดติดกับเครื่องมือ', body: 'เราไม่ยัดเยียดระบบ แต่เราปรับตัวเข้าหาคุณ Google Workspace, Microsoft 365, n8n, Make, Zapier, Supabase, CRM ของคุณ ทีมคุณใช้อะไรอยู่ เราต่อยอดจากตรงนั้น' },
 { num: '05', t: 'สร้างโดยผู้ใช้งานจริง ไม่ใช่แค่คนขาย', body: 'มากกว่า 4 ปีกับการสร้างระบบหลังบ้าน กับระบบอัตโนมัติ และมากกว่า 9 ปีในฐานะเทรดเดอร์ ที่ระบบไหนไม่สามารถใช้งานได้จริง หมายถึงการขาดทุนโดยตรง เราจึงคิดในแง่ของผลลัพธ์เป็นหลัก เพราะนี่คือวิธีเดียวที่เรารู้จัก' },
 ],
 },
 about: {
 eyebrow: '§ 05 · Founder',
 title: 'ทำความรู้จักผู้ก่อตั้ง ',
 titleAccent: 'AUTOPILOT',
 byline: 'ชานน ภูววิรานนท์ (บีม) · Founder & Automation Architect',
 credentials: ['4+ ปี Automation', '9+ ปี เทรดเดอร์'],
 paras: [
 'ผมเป็นเทรดเดอร์ทีหลงใหลในการประดิษฐ์ ประสบการณ์ 9 ปีของการบริหารทั้งพอร์ตกองทุน และของตัวเองสอนผมว่า มันมีแค่ระบบที่ใช้ได้ กับระบบที่ทำให้คุณเสียเงิน ไม่มีตรงกลาง',
 'จุดเริ่มต้นมาจากการสร้างเครื่องต่างๆให้ตัวเอง ตั้งแต่ dashboard, database ไปจนถึงระบบช่วยคำนวณจำนวนหุ้นที่จะซื้อ เมื่อมีคนมาเห็นจึงถูกชักชวนให้ไปสร้างระบบให้กับบริษัทของเขาบ้าง จากหนึ่งโปรเจคกลายเป็นหลายสิบโปรเจค สี่ปีต่อมา ก็กลายเป็น AUTOPILOT',
 'ผมทำงานด้วยหลักเดียวคือ สัจจะ คือการรักษาคำพูดหรือคำมั่นสัญญาที่ให้ไว้ ทั้งต่อตัวเอง และต่อคู่ค้าทางธุรกิจ แม้ในบางครั้งอาจหมายถึงการต้องเสียสละบางสิ่งบางอย่างก็ตาม นั่นคือเหตุผลที่ผมการันตี “ผลลัพธ์” ไม่ใช่แค่ “งานที่ส่งมอบ” มันไม่ใช่ประโยคทางการตลาด แต่มันคือคุณค่าและหลักการที่ผมใช้ดำเนินชีวิต',
 'เวลาที่ไม่ได้สร้างระบบ ผมเทรด และใช้เวลากับน้องหมาน้องแมว 4 ตัวของผม',
 'มีกระบวนการทำงานอะไรที่กัดกินเงินหรือเวลาคุณอยู่ไหมครับ? ทักมาได้เลย!',
 ],
 quote: 'ระบบมีแค่สองอย่าง — ใช้ได้ หรือทำให้เสียเงิน ไม่มีตรงกลาง',
 portraitNote: '[ ภาพ founder — บีม ]',
 },
 pricing: {
 eyebrow: '§ 08 · ราคา',
 title: 'มีโปรเจค 3 ระดับ',
 title2: 'เลือกระดับที่จะสามารถช่วยธุรกิจของคุณได้มากที่สุด',
 popularLabel: 'นิยมสุด',
 tiers: [
 {
 name: 'Quick Win',
 range: '฿3K – ฿20K',
 timeline: '1–2 สัปดาห์',
 body: '1 ระบบอัตโนมัติที่คืนทุนภายในไม่กี่เดือน',
 includes: [
 '1 กระบวนการทำงานอัตโนมัติ ตั้งแต่ต้นจนจบ',
 'ต่อยอดจากเครื่องมือที่คุณใช้อยู่แล้ว',
 'ส่งมอบครบถ้วน พร้อมเอกสารแนะนำการใช้งาน',
 ],
 },
 {
 name: 'System Build',
 range: '฿20K – ฿80K',
 timeline: '2–4 สัปดาห์',
 body: 'กระบวนการทำงานหลายขั้นตอนที่เชื่อมเครื่องมือ 3-5 ตัวเข้าด้วยกัน เพื่อทดแทนงานที่กัดกินเวลาของทีมคุณ',
 popular: true,
 includes: [
 'กระบวนการทำงานหลายขั้นตอน ครอบคลุมเครื่องมือ 3-5 ตัว',
 'Dashboard หรือเครื่องมือภายในองค์กรแบบ Custom',
 'แถมการปรับแก้งานถึง 2 รอบ',
 'ดูแลหลังส่งมอบนานถึง 3 เดือน',
 ],
 },
 {
 name: 'Multi-System',
 range: '฿80K – ฿200K+',
 timeline: '4–10 สัปดาห์',
 body: 'ระบบที่เชื่อมหลากหลายเครื่องมือเข้าด้วยกันเพื่อทำให้งานส่วนใหญ่ของธุรกิจคุณเป็นอัตโนมัติ',
 includes: [
 'ครอบคลุมระบบทั้งหมดของคุณ ตั้งแต่ต้นจนจบ',
 'AI agents, RAG, หรือ database แบบ custom',
 'จัดอบรมพนักงาน พร้อมเอกสารคู่มือการใช้',
 'ดูแลหลังส่งมอบนานถึง 10 เดือน',
 ],
 },
 ],
 closing: 'ไม่แน่ใจว่าธุรกิจคุณเหมาะกับระดับไหน? คลิกที่ปุ่ม “ปรึกษาฟรี” ได้เลย เราจะช่วยหาคำตอบว่าระดับไหนเหมาะกับคุณ หรือหากไม่มีโปรเจคไหนเหมาะกับธุรกิจของคุณในตอนนี้ เราก็จะบอกตรงๆ',
 },
 faq: {
 eyebrow: '§ 09 · คำถามที่พบบ่อย',
 title: 'คำถามที่ลูกค้าถามเราบ่อยที่สุด',
 items: [
 { category: 'ราคา', q: 'ราคาเท่าไหร่?', a: 'ดูได้ที่หัวข้อราคาด้านบน เราแบ่งโปรเจคออกเป็น 3 ระดับ เราไม่ได้ขายสินค้า เราขายผลลัพธ์ ทุกโปรเจคที่เรารับต้องสร้างผลตอบแทนหลายเท่าให้กับคุณ ถ้าเราประเมินแล้วว่าไม่คุ้มสำหรับคุณ เราไม่รับ' },
 { category: 'Process', q: 'กระบวนการเป็นยังไง?', a: '5 ขั้นตอนง่ายๆ (1) ปรึกษาฟรี 30 นาที เราวิเคราะห์คอขวดในธุรกิจของคุณ และบอกตรงๆ ว่าคุ้มที่จะ automate ไหม (2) เสนอราคาชัดเจน ตั้งแต่ผลลัพธ์ ระยะเวลาส่งมอบ และราคา ทุกอย่างชัดเจน ไม่มี “จะใช้ได้ไหมค่อยว่ากัน” (3) ขั้นตอนการสร้าง อัปเดตทันที คุณไม่ต้องตามเรา แต่เราจะตามอัปเดตคุณ (4) ส่งมอบและอบรม ให้ทีมคุณเรียนรู้ เพื่อพร้อมเริ่มใช้งาน (5) ดูแลหลังส่งมอบ เราไม่หายไปไหน' },
 { category: 'ความเสี่ยงและความไว้ใจ', q: 'ถ้าระบบใช้ไม่ได้จริง ทำยังไง?', a: 'เราทำงานให้ฟรีจนกว่าจะใช้ได้จริง หรือคืนเงิน 100% เราส่งมอบผลลัพธ์ ไม่ใช่แค่ซอฟต์แวร์' },
 { category: 'Process', q: 'เราไม่มีทีม IT ใช้บริการได้ไหม?', a: 'คุณคือลูกค้าที่เราต้องการจะให้บริการโดยเฉพาะ เราใช้เครื่องมือที่ทีมคุณคุ้นเคยอยู่แล้ว อบรมเฉพาะส่วนที่ทีมคุณจะได้ใช้จริง และจัดทำคู่มือการใช้งานให้เข้าใจง่าย' },
 { category: 'Process', q: 'ใช้เวลานานแค่ไหน?', a: 'ขึ้นอยู่กับขอบเขตงาน ระบบง่ายๆ ส่งมอบได้ภายในไม่กี่วัน ระบบที่ซับซ้อนขึ้นอาจใช้เวลาเป็นอาทิตย์ ไม่ว่าจะตกลงกันที่กี่วัน เราส่งมอบก่อนกำหนด 20-30% ทุกโปรเจค' },
 { category: 'Tech & Fit', q: 'ใช้กับเครื่องมือที่เรามีอยู่แล้วได้ไหม?', a: 'ค่อนข้างมั่นใจว่าได้เกือบทั้งหมด ตั้งแต่ Google Workspace, Microsoft 365, n8n, Make, Zapier, Supabase, Notion, CRM ของคุณ, LINE, WhatsApp, custom API เราต่อยอดจากสิ่งที่คุณใช้อยู่ ทีมของคุณจึงไม่ต้องเริ่มเรียนรู้ของใหม่' },
 { category: 'Process', q: 'ถ้าหลังส่งมอบแล้วเราต้องการเปลี่ยนแปลง ทำยังไง?', a: 'เราจัดทำคู่มือ/เอกสารไว้ทุกอย่าง และพร้อมดูแลต่อเนื่อง ลูกค้าส่วนใหญ่กลับมาหาเราอีก ตั้งแต่ระบบแรกยังไม่คืนทุน' },
 { category: 'ความเสี่ยงและความไว้ใจ', q: 'เซ็น NDA ได้ไหม?', a: 'ได้ครับ ยินดีเซ็นก่อนคุยรายละเอียดที่เป็นความลับ' },
 { category: 'Tech & Fit', q: 'อยู่ที่ไหน และทำงานกับลูกค้าจากที่ไหนบ้าง?', a: 'อยู่กรุงเทพครับ ลูกค้าทั้งหมดที่เคยทำงานด้วยเป็นคนไทย แต่ส่วนใหญ่ทำงานแบบ remote ยินดีรับลูกค้าจากทุกที่' },
 ],
 contactCard: {
 title: 'มีคำถามเพิ่มเติม?',
 body: 'ส่งข้อความหาผมได้โดยตรง',
 cta: 'ส่งข้อความ',
 },
 },
 cta: {
 eyebrow: '► จองนัดปรึกษาเรา',
 title1: 'หยุดทำงานที่ระบบ', title2: '', title3: 'ทำแทนคุณได้',
 body: 'จอง automation audit ฟรี 30 นาที เราจะหาคอขวดที่ใหญ่ที่สุดและบอกตรงๆว่า automation คุ้มกับธุรกิจคุณตอนนี้หรือเปล่า ถ้าคุ้ม เราจะให้แผนชัดๆว่าจะลงมือยังไง',
 bodyStrong: 'ไม่มี pitch deck ไม่กดดัน ไม่มี fluff',
 availability: 'เหลือ 2 slot สำหรับ Q2 · เราไม่รับเกินนี้',
 cta1: 'รับบริการปรึกษาฟรี',
 cta2: 'หรือส่งอีเมลหาผม',
 micro: '30 นาที · ฟรี · ได้เห็นประโยชน์ของ AI กับธุรกิจของคุณมากขึ้น ไม่ว่าจะได้ร่วมงานกันหรือไม่',
 guarantee: 'การันตีผลลัพธ์ · ทำงานให้ฟรีจนกว่าจะใช้ได้ หรือคืนเงิน 100%',
 },
 footer: { rights: '© 2026 · AUTOPILOT', built: 'Built in Thailand · นำทีมโดย Operator' },
 meta: {
 title: 'AUTOPILOT — AI Automation Studio สำหรับ SMB',
 description: 'AI automation สำหรับธุรกิจ SMB ที่ไม่มีทีมเทค ทำฟรีจนกว่าจะใช้ได้ หรือคืนเงิน 100%',
 },
 },
};

const Icon = {
 Arrow: ({ size = 18 }) => (
 <svg className="arrow" width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
 <path d="M5 12h14M13 5l7 7-7 7"/>
 </svg>
 ),
 Check: () => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M20 6L9 17l-5-5"/></svg>,
 X: () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M18 6L6 18M6 6l12 12"/></svg>,
 Shield: () => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M12 2l8 4v6c0 5-3.5 9-8 10-4.5-1-8-5-8-10V6l8-4z"/></svg>,
 CornerArrow: () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M7 17L17 7M9 7h8v8"/></svg>,
 Target: () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/></svg>,
 Clock: () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>,
 Coins: () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><circle cx="9" cy="9" r="6"/><path d="M21 12a6 6 0 0 1-9.33 5M9 6v6l3 1.5"/></svg>,
 Layers: () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></svg>,
 Wrench: () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>,
 Compass: () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76"/></svg>,
 Blocks: () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><path d="M3 7a4 4 0 0 1 4-4h3v7H7a4 4 0 0 1-4-4z"/><path d="M14 17a4 4 0 0 0 4 4h3v-7h-3a4 4 0 0 0-4 4z"/></svg>,
 Pulse: () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>,
 BarChart: () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><line x1="3" y1="20" x2="21" y2="20"/><line x1="6" y1="20" x2="6" y2="13"/><line x1="12" y1="20" x2="12" y2="9"/><line x1="18" y1="20" x2="18" y2="5"/></svg>,
 FileText: () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><polyline points="14 3 14 9 20 9"/><line x1="8" y1="13" x2="16" y2="13"/><line x1="8" y1="17" x2="13" y2="17"/></svg>,
 MessageCircle: () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>,
 Database: () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/><path d="M3 12c0 1.66 4 3 9 3s9-1.34 9-3"/></svg>,
 Sparkle: () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M5.6 18.4l2.1-2.1M16.3 7.7l2.1-2.1"/><circle cx="12" cy="12" r="3"/></svg>,
 Plug: () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M9 2v6M15 2v6M6 8h12v4a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4z"/><path d="M12 16v6"/></svg>,
};

function GuaranteeSeal({ accent, label }) {
 return (
 <div className="guarantee-seal">
 <span className="guarantee-icon" style={{ color: accent }}><Icon.Shield /></span>
 <span className="guarantee-text">{label}</span>
 </div>
 );
}

function Nav({ accent, lang, setLang, t }) {
 const [scrolled, setScrolled] = useState(false);
 const [open, setOpen] = useState(false);
 useEffect(() => {
 const onScroll = () => setScrolled(window.scrollY > 12);
 window.addEventListener('scroll', onScroll);
 return () => window.removeEventListener('scroll', onScroll);
 }, []);
 return (
 <nav className={`nav${scrolled ? ' scrolled' : ''}${open ? ' open' : ''}`}>
 <a href="#top" className="nav-logo" onClick={() => setOpen(false)}>
 <span className="dot" style={{ background: accent, boxShadow: `0 0 14px ${accent}` }} />
 AUTOPILOT
 </a>
 <div className="nav-links">
 <a href="#results" onClick={() => setOpen(false)}>{t.nav.results}</a>
 <a href="#how" onClick={() => setOpen(false)}>{t.nav.how}</a>
 <a href="#about" onClick={() => setOpen(false)}>{t.nav.about}</a>
 <a href="#capabilities" onClick={() => setOpen(false)}>{t.nav.caps}</a>
 <a href="#why" onClick={() => setOpen(false)}>{t.nav.why}</a>
 <a href="#pricing" onClick={() => setOpen(false)}>{t.nav.pricing}</a>
 <a href="#faq" onClick={() => setOpen(false)}>{t.nav.faq}</a>
 </div>
 <div className="nav-right">
 <a href="#contact" className="nav-cta" style={{ background: accent }}>{t.nav.cta}</a>
 <button className="nav-burger" aria-label="menu" onClick={() => setOpen(!open)}>
 <span /><span /><span />
 </button>
 </div>
 {open && (
 <div className="nav-mobile">
 <a href="#results" onClick={() => setOpen(false)}>{t.nav.results}</a>
 <a href="#how" onClick={() => setOpen(false)}>{t.nav.how}</a>
 <a href="#about" onClick={() => setOpen(false)}>{t.nav.about}</a>
 <a href="#capabilities" onClick={() => setOpen(false)}>{t.nav.caps}</a>
 <a href="#why" onClick={() => setOpen(false)}>{t.nav.why}</a>
 <a href="#pricing" onClick={() => setOpen(false)}>{t.nav.pricing}</a>
 <a href="#faq" onClick={() => setOpen(false)}>{t.nav.faq}</a>
 <a href="#contact" className="nav-cta" onClick={() => setOpen(false)}>{t.nav.cta}</a>
 </div>
 )}
 </nav>
 );
}

function Hero({ taglineMode, splineOn, accent, t }) {
 const canvasRef = useRef(null);
 const heroRef = useRef(null);
 const appRef = useRef(null);

 useEffect(() => {
 if (!splineOn) return;

 // Skip Spline entirely on slow connections / save-data / low memory.
 // Saves ~3MB of runtime + scene download for users who can't afford it.
 const conn = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
 if (conn) {
 if (conn.saveData) return;
 if (/^(slow-)?2g$/.test(conn.effectiveType || '')) return;
 }
 if (typeof navigator.deviceMemory === 'number' && navigator.deviceMemory < 4) return;

 let cancelled = false;
 let mouseHandler = null;
 let touchHandler = null;
 let rafId = 0;
 let idleId = 0;
 let timeoutId = 0;
 let attempts = 0;

 const start = () => (async () => {
 try {
 while (!cancelled && (!canvasRef.current || canvasRef.current.clientWidth === 0)) {
 attempts++;
 if (attempts > 100) return;
 await new Promise(r => setTimeout(r, 50));
 }
 if (cancelled) return;
 const mod = await (new Function('return import("https://esm.sh/@splinetool/runtime@1.9.28")'))();
 if (cancelled || !canvasRef.current) return;
 const app = new mod.Application(canvasRef.current);
 appRef.current = app;
 await app.load('https://prod.spline.design/2nmaIR1cwvuKQm0V/scene.splinecode');
 if (cancelled) return;
 try { app.emitEvent('start', 'Bot'); } catch {}

 // Strip the Spline attribution badge. The runtime injects it as a
 // sibling of the canvas (or to body) after load; a MutationObserver
 // also re-strips it if Spline re-adds it later.
 const stripBadge = () => {
 const candidates = document.querySelectorAll(
 'a[href*="spline.design"], a[href*="spline.com"], [class*="watermark" i], [class*="spline-logo" i]'
 );
 candidates.forEach(el => {
 const txt = (el.textContent || '').toLowerCase();
 if (txt.includes('spline') || el.tagName === 'A') el.remove();
 });
 };
 stripBadge();
 const obs = new MutationObserver(stripBadge);
 obs.observe(document.body, { childList: true, subtree: true });
 // Disconnect after 10s — by then Spline has finished any late inserts.
 setTimeout(() => obs.disconnect(), 10000);

 const dispatch = (clientX, clientY) => {
 if (!canvasRef.current) return;
 const evt = new MouseEvent('pointermove', { clientX, clientY, bubbles: true, pointerType: 'mouse' });
 canvasRef.current.dispatchEvent(evt);
 const m = new MouseEvent('mousemove', { clientX, clientY, bubbles: true });
 canvasRef.current.dispatchEvent(m);
 };

 // Smooth + steady-cadence: lerp toward target every RAF, dispatch every Nth.
 let tx = null, ty = null;
 let sx = null, sy = null;
 const ease = 0.18;
 const sendEvery = 4;
 let frame = 0;
 const tick = () => {
 if (cancelled) return;
 if (tx != null) {
 if (sx == null) { sx = tx; sy = ty; }
 sx += (tx - sx) * ease;
 sy += (ty - sy) * ease;
 if (frame % sendEvery === 0) dispatch(sx, sy);
 }
 frame++;
 rafId = requestAnimationFrame(tick);
 };
 rafId = requestAnimationFrame(tick);

 const setTarget = (clientX, clientY) => {
 if (!heroRef.current) return;
 const r = heroRef.current.getBoundingClientRect();
 if (clientY < r.top || clientY > r.bottom) return;
 tx = clientX; ty = clientY;
 };
 mouseHandler = (e) => setTarget(e.clientX, e.clientY);
 touchHandler = (e) => {
 if (!e.touches || !e.touches[0]) return;
 setTarget(e.touches[0].clientX, e.touches[0].clientY);
 };
 window.addEventListener('mousemove', mouseHandler, { passive: true });
 window.addEventListener('touchmove', touchHandler, { passive: true });
 } catch (e) { console.warn('[Spline]', e?.message || e); }
 })();

 // Defer Spline boot until the browser is idle so it doesn't compete
 // with first-paint work. Falls back to a small timeout on browsers
 // without requestIdleCallback (mostly older Safari).
 if ('requestIdleCallback' in window) {
 idleId = window.requestIdleCallback(start, { timeout: 1500 });
 } else {
 timeoutId = setTimeout(start, 200);
 }

 return () => {
 cancelled = true;
 if (idleId && 'cancelIdleCallback' in window) window.cancelIdleCallback(idleId);
 if (timeoutId) clearTimeout(timeoutId);
 if (rafId) cancelAnimationFrame(rafId);
 if (mouseHandler) window.removeEventListener('mousemove', mouseHandler);
 if (touchHandler) window.removeEventListener('touchmove', touchHandler);
 if (appRef.current?.dispose) appRef.current.dispose();
 };
 }, [splineOn]);

 return (
 <header className="hero" id="top" data-screen-label="01 Hero" ref={heroRef}>
 {splineOn ? (
 <div className="hero-spline">
 <canvas ref={canvasRef} id="canvas3d" style={{ width:'100%', height:'100%' }} />
 </div>
 ) : (<div className="hero-fallback" />)}
 <div className="hero-grid" />
 <div className="hero-top">
 <div className="container">
 <div className="eyebrow reveal">{t.hero.eyebrow}</div>
 <div className="hero-headline reveal" data-d="1">
 {taglineMode === 'stack' ? (
 <>
 <h1 className="hero-mark hero-mark-stack">{t.hero.stackTop}</h1>
 <h1 className="hero-mark hero-mark-stack">
 {t.hero.stackBottomPre}<span style={{ color: accent }}>{t.hero.stackBottomAccent}</span>
 </h1>
 </>
 ) : (
 <h1 className="hero-mark hero-mark-line">
 {t.hero.mainSingle}<br/><span style={{ color: accent }}>{t.hero.mainSingleAccent}</span>
 </h1>
 )}
 </div>
 </div>
 </div>
 <div className="container hero-content">
 <div>
 <p className="hero-sub reveal" data-d="2">{t.hero.sub}</p>
 <div className="hero-actions reveal" data-d="3">
 <a href="#contact" className="btn btn-primary" style={{ background: accent }}>
 {t.hero.cta1} <Icon.Arrow />
 </a>
 <a href="#capabilities" className="btn btn-white">
 {t.hero.cta2} <Icon.Arrow />
 </a>
 </div>
 <div className="hero-micro reveal" data-d="4">{t.hero.micro}</div>
 </div>
 </div>
 </header>
 );
}

/* Logos are organised into named groups so individual tools or whole groups
   can be added, removed, or reordered without touching the JSX. Edit the
   arrays below to change what's shown; edit the order in TOOL_DISPLAY to
   change the on-screen sequence. Comment a group out to hide it. */
const TOOL_GROUPS = {
 workflowAutomation: [
 { name: 'n8n',                       src: 'assets/N8n-logo-new.svg.png' },
 { name: 'Make',                      src: 'assets/Make-com-Logo-500x281.png' },
 { name: 'Microsoft Power Automate',  src: 'assets/Microsoft_Power_Automate.svg.png' },
 ],
 aiPlatforms: [
 { name: 'OpenAI',                    src: 'assets/OpenAI_Logo.svg.png' },
 { name: 'Anthropic',                 src: 'assets/Claude_AI_symbol.svg.png' },
 { name: 'Gemini',                    src: 'assets/Google_Gemini_logo_2025.svg.png' },
 ],
 infrastructure: [
 { name: 'Supabase',                  src: 'assets/supabase-logo-wordmark--light.png' },
 { name: 'Cloudflare',                src: 'assets/Cloudflare_Logo.svg.png' },
 ],
 workspace: [
 { name: 'Notion',                    src: 'assets/Notion-logo.svg.png' },
 ],
 messaging: [
 { name: 'LINE',                      src: 'assets/LINE.png' },
 { name: 'WhatsApp Business',         src: 'assets/WhatsApp_Business_icon.png' },
 ],
 trading: [
 { name: 'TradingView (Pine)',        src: 'assets/Pinescript--Streamline-Simple-Icons.svg' },
 ],
};

/* Order shown on the page. Comment a line out to hide a group. */
const TOOL_DISPLAY = [
 ...TOOL_GROUPS.workflowAutomation,
 ...TOOL_GROUPS.aiPlatforms,
 ...TOOL_GROUPS.infrastructure,
 ...TOOL_GROUPS.workspace,
 ...TOOL_GROUPS.messaging,
 ...TOOL_GROUPS.trading,
];

function Tools({ t }) {
 // Duplicate the list inside the track so the -50% transform produces a
 // seamless loop. Each pill carries its own right-margin (see CSS) so the
 // duplicate's rhythm matches the original at the seam.
 const renderRow = (logos) => [...logos, ...logos].map((l, i) => (
 <div className="tool-pill" key={i} title={l.name} aria-label={l.name}>
 <img
 className="tool-pill-img"
 src={l.src}
 alt={l.name}
 loading="lazy"
 decoding="async"
 draggable="false"
 width="180"
 height="36"
 />
 </div>
 ));
 return (
 <section className="section-tools" id="tools" data-screen-label="02 Tools" aria-label="Tools we build on">
 <div className="container">
 <div className="tools-head reveal">
 <h2 className="tools-title">{t.tools.title}</h2>
 </div>
 </div>
 <div className="tool-marquee reveal" data-d="1">
 <div className="tool-marquee-track" aria-hidden="true">{renderRow(TOOL_DISPLAY)}</div>
 </div>
 <div className="container">
 <p className="tools-closing reveal" data-d="2">{t.tools.closing}</p>
 </div>
 </section>
 );
}

/* Workflow diagram modelled on the n8n editor visual: real tool logos as
   nodes, smooth bezier curves connecting them, dot-grid background, and a
   gradient stroke on the paths. Lines draw sequentially on scroll-in.
   The tools shown are real options from your stack so the diagram tells a
   concrete story: Notion task → n8n trigger → Claude AI → LINE message. */
function ProblemFlowSvg({ accent }) {
 const NODES = [
 { x: 70,  label: 'Notion', src: 'assets/Notion-logo.svg.png',         logoSize: 30 },
 { x: 220, label: 'n8n',    src: 'assets/N8n-logo-new.svg.png',         logoSize: 34 },
 { x: 370, label: 'Claude', src: 'assets/Claude_AI_symbol.svg.png',     logoSize: 30 },
 { x: 520, label: 'LINE',   src: 'assets/LINE.png',                     logoSize: 32 },
 ];
 const VBW = 590;
 const VBH = 170;
 const cy = 70;
 const r = 32;
 // Subtle alternating curves so the path has rhythm without being busy.
 const yOffsets = [-8, 12, -8];
 const labelY = 132;
 return (
 <svg viewBox={`0 0 ${VBW} ${VBH}`} className="problem-flow-svg" preserveAspectRatio="xMidYMid meet" aria-hidden="true">
 <defs>
 <pattern id="pf-dotgrid" x="0" y="0" width="14" height="14" patternUnits="userSpaceOnUse">
 <circle cx="1" cy="1" r="0.6" fill="currentColor" opacity="0.55"/>
 </pattern>
 <linearGradient id="pf-line-grad" x1="0" y1="0" x2="1" y2="0">
 <stop offset="0%"   stopColor={accent} stopOpacity="0.25"/>
 <stop offset="50%"  stopColor={accent} stopOpacity="0.85"/>
 <stop offset="100%" stopColor={accent} stopOpacity="0.25"/>
 </linearGradient>
 </defs>

 {/* dotted grid background for depth */}
 <rect x="0" y="0" width={VBW} height={VBH} fill="url(#pf-dotgrid)" />

 {/* curved connection paths */}
 {[0, 1, 2].map(i => {
 const x1 = NODES[i].x + r;
 const x2 = NODES[i+1].x - r;
 const midX = (x1 + x2) / 2;
 const midY = cy + yOffsets[i];
 return (
 <path
 key={`l${i}`}
 d={`M ${x1} ${cy} Q ${midX} ${midY}, ${x2} ${cy}`}
 stroke="url(#pf-line-grad)"
 strokeWidth="1.5"
 fill="none"
 strokeLinecap="round"
 className="problem-flow-line"
 data-d={i}
 pathLength="100"
 />
 );
 })}

 {/* nodes: outer halo, white disk, accent ring, logo, label */}
 {NODES.map((n, i) => (
 <g key={`n${i}`} className="problem-flow-node" data-d={i}>
 <circle cx={n.x} cy={cy} r={r + 8} fill="currentColor" opacity="0.05" />
 <circle cx={n.x} cy={cy} r={r}     fill="#FFFFFF" />
 <circle cx={n.x} cy={cy} r={r}     fill="none" stroke={accent} strokeOpacity="0.28" strokeWidth="1" />
 <image
 href={n.src}
 x={n.x - n.logoSize / 2}
 y={cy - n.logoSize / 2}
 width={n.logoSize}
 height={n.logoSize}
 preserveAspectRatio="xMidYMid meet"
 />
 <text x={n.x} y={labelY} textAnchor="middle" className="problem-flow-label">{n.label}</text>
 </g>
 ))}
 </svg>
 );
}

function Problem({ accent, t }) {
 return (
 <section className="section section-problem" id="problem" data-screen-label="03 Problem">
 <div className="container">
 <div className="problem-head reveal">
 <h2 className="display-2 problem-title">{t.problem.title}<br/><span style={{ color: accent }}>{t.problem.title2}</span></h2>
 <p className="problem-lead">{t.problem.lead}</p>
 </div>
 <div className="problem-split">
 <div className="problem-pain reveal" data-d="1">
 <ul className="problem-strikes">
 {t.problem.bullets.map((b, i) => (
 <li key={i}>
 <span className="problem-strike-icon" style={{ color: accent }}><Icon.X /></span>
 <span className="problem-strike-text">{b}</span>
 </li>
 ))}
 </ul>
 </div>
 <div className="problem-promise reveal" data-d="2">
 <p className="problem-promise-text">{t.problem.promise}</p>
 <div className="problem-flow reveal" data-d="3">
 <ProblemFlowSvg accent={accent} />
 </div>
 </div>
 </div>
 </div>
 </section>
 );
}

function HowItWorks({ accent, t }) {
 // Stepper journey: icon → number node → time/stage → title → body.
 // The connecting line between nodes draws on scroll-in (same one-shot
 // pattern as the Why spine). Mobile collapses to vertical with the line
 // running down the left margin.
 const stepIcons = [Icon.Compass, Icon.Blocks, Icon.Pulse];
 return (
 <section className="section section-how" id="how" data-screen-label="04 How">
 <div className="container">
 <div className="section-head reveal">
 <h2 className="display-2">{t.how.title}</h2>
 </div>
 <div className="how-stepper reveal">
 <div className="how-stepper-line" style={{ background: accent }} aria-hidden="true" />
 {t.how.steps.map((s, i) => {
 const IconComp = stepIcons[i] || stepIcons[0];
 return (
 <div className="how-step reveal" data-d={i+1} key={i}>
 <div className="how-step-node" style={{ background: accent }} aria-hidden="true">
 <IconComp />
 </div>
 <div className="how-step-stage" style={{ color: accent }}>{s.stage}</div>
 <h3 className="how-step-title">{s.t}</h3>
 <p className="how-step-body">{s.body}</p>
 </div>
 );
 })}
 </div>
 <div className="how-guarantee reveal">
 <GuaranteeSeal accent={accent} label={t.hero.guarantee} />
 </div>
 </div>
 </section>
 );
}

function Capabilities({ accent, t }) {
 // One icon per capability, ordered to match t.caps.items.
 const capIcons = [
 Icon.BarChart,      // CAP-01 Reporting
 Icon.FileText,      // CAP-02 Documents
 Icon.Coins,         // CAP-03 Finance
 Icon.MessageCircle, // CAP-04 Messaging
 Icon.Database,      // CAP-05 CRM / DB
 Icon.Sparkle,       // CAP-06 AI / RAG
 Icon.Wrench,        // CAP-07 Tools
 Icon.Plug,          // CAP-08 API
 ];
 return (
 <section className="section section-caps" id="capabilities" data-screen-label="05 Capabilities">
 <div className="container">
 <div className="section-head reveal">
 <div>
 <h2 className="display-2">{t.caps.title}<br/><span style={{ color: accent }}>{t.caps.title2}</span></h2>
 <p className="lede" style={{ marginTop: 18 }}>{t.caps.lede}</p>
 </div>
 </div>
 <div className="caps-grid">
 {t.caps.items.map((c, i) => {
 const IconComp = capIcons[i] || capIcons[0];
 return (
 <article className="cap-card reveal" data-d={(i%4)+1} key={c.id}>
 <div className="cap-card-icon" style={{ color: accent }} aria-hidden="true"><IconComp /></div>
 <span className="id">{c.tag}</span>
 <h3>{c.title}</h3>
 <p>{c.body}</p>
 </article>
 );
 })}
 </div>
 <p className="caps-closing reveal">{t.caps.closing}</p>
 </div>
 </section>
 );
}

/* CountUp — animates an integer from 0 to `value` once when its ref enters
   the viewport. Respects prefers-reduced-motion (jumps straight to value). */
function CountUp({ value, duration = 1400, suffix = '' }) {
 const [n, setN] = useState(0);
 const ref = useRef(null);
 const startedRef = useRef(false);
 useEffect(() => {
 const el = ref.current;
 if (!el || startedRef.current) return;
 const reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
 if (reduce) { startedRef.current = true; setN(value); return; }
 const io = new IntersectionObserver((entries) => {
 entries.forEach(e => {
 if (e.isIntersecting && !startedRef.current) {
 startedRef.current = true;
 const start = performance.now();
 const tick = (t) => {
 const p = Math.min((t - start) / duration, 1);
 const eased = 1 - Math.pow(1 - p, 3);
 setN(Math.round(value * eased));
 if (p < 1) requestAnimationFrame(tick);
 };
 requestAnimationFrame(tick);
 io.disconnect();
 }
 });
 }, { threshold: 0.4 });
 io.observe(el);
 return () => io.disconnect();
 }, [value, duration]);
 return <span ref={ref}>{n}{suffix}</span>;
}

function Results({ accent, t }) {
 // First 2 items = hero cards (large, top row). Remaining = small cards
 // (3-col bottom row). Edit the order in I18N to control which stats
 // get the spotlight.
 const items = t.results.items;
 const hero = items.slice(0, 2);
 const small = items.slice(2);
 const renderStat = (r) => (
 r.count != null
 ? <CountUp value={r.count} suffix={r.suffix || ''} />
 : <span>{r.stat}</span>
 );
 return (
 <section className="section section-results" id="results" data-screen-label="06 Results">
 <div className="container">
 <div className="section-head reveal">
 <h2 className="display-2">{t.results.title}</h2>
 </div>
 <div className="results-mosaic">
 <div className="results-mosaic-hero">
 {hero.map((r, i) => (
 <article className="result-card result-card-hero reveal" data-d={i+1} key={`h${i}`}>
 <div className="result-stat" style={{ color: accent }}>{renderStat(r)}</div>
 <div className="result-unit">{r.unit}</div>
 <div className="result-rule" style={{ background: accent }} />
 <p className="result-body">{r.body}</p>
 </article>
 ))}
 </div>
 <div className="results-mosaic-small">
 {small.map((r, i) => (
 <article className="result-card reveal" data-d={(i%3)+1} key={`s${i}`}>
 <div className="result-stat" style={{ color: accent }}>{renderStat(r)}</div>
 <div className="result-unit">{r.unit}</div>
 <div className="result-rule" style={{ background: accent }} />
 <p className="result-body">{r.body}</p>
 </article>
 ))}
 </div>
 </div>
 {t.results.footer && <p className="results-footer reveal">{t.results.footer}</p>}
 </div>
 </section>
 );
}

function Why({ accent, t }) {
 // One icon per differentiator, in display order. Edit / swap to taste.
 const whyIcons = [Icon.Target, Icon.Clock, Icon.Coins, Icon.Layers, Icon.Wrench];
 return (
 <section className="section section-why" id="why" data-screen-label="07 Why">
 <div className="container">
 <div className="section-head reveal">
 <h2 className="display-2">{t.why.title} <span className="display-2-soft">{t.why.title2}</span></h2>
 </div>
 <div className="why-spine reveal">
 <div className="why-spine-line" style={{ background: accent }} aria-hidden="true" />
 {t.why.items.map((it, i) => {
 const IconComp = whyIcons[i] || whyIcons[0];
 const side = i % 2 === 0 ? 'right' : 'left';
 return (
 <div className={`why-spine-row why-spine-row-${side} reveal`} data-d={(i%4)+1} key={i}>
 <div className="why-spine-content">
 <div className="why-spine-icon" style={{ color: accent }} aria-hidden="true"><IconComp /></div>
 <h3 className="why-spine-title">{it.t}</h3>
 <p className="why-spine-body">{it.body}</p>
 </div>
 <div className="why-spine-node" style={{ background: accent }}>
 <span className="why-spine-num">{it.num}</span>
 </div>
 </div>
 );
 })}
 </div>
 </div>
 </section>
 );
}

function About({ accent, t }) {
 return (
 <section className="section section-about" id="about" data-screen-label="08 About">
 <div className="container">
 <div className="section-head reveal">
 <h2 className="display-2">{t.about.title}<span style={{ color: accent }}>{t.about.titleAccent}</span></h2>
 </div>
 <div className="about">
 <div className="about-portrait reveal" />

 <div className="about-text reveal" data-d="1">
 <div className="about-byline">{t.about.byline}</div>
 {t.about.credentials && t.about.credentials.length > 0 && (
 <div className="about-credentials">
 {t.about.credentials.map((c, i) => (
 <span key={i} className="about-credential">{c}</span>
 ))}
 </div>
 )}
 {t.about.paras.map((p, i) => (
 <p key={i} className={i===0?'about-lead':'about-body'}>{p}</p>
 ))}
 </div>
 </div>
 </div>
 </section>
 );
}

function Pricing({ accent, t }) {
 return (
 <section className="section section-pricing" id="pricing" data-screen-label="08 Pricing">
 <div className="container">
 <div className="section-head reveal">
 <h2 className="display-2">{t.pricing.title} <span className="display-2-soft">{t.pricing.title2}</span></h2>
 </div>
 <div className="pricing-grid">
 {t.pricing.tiers.map((tier, i) => (
 <article className={`pricing-card${tier.popular ? ' pricing-card-popular' : ''} reveal`} data-d={i+1} key={i}>
 {tier.popular && (
 <span className="pricing-badge" style={{ background: accent }}>{t.pricing.popularLabel}</span>
 )}
 <div className="pricing-tier">{tier.name}</div>
 <div className="pricing-range" style={{ color: accent }}>{tier.range}</div>
 <div className="pricing-meta">{tier.timeline}</div>
 <div className="pricing-rule" style={{ background: accent }} />
 <p className="pricing-body">{tier.body}</p>
 <ul className="pricing-list">
 {tier.includes.map((inc, j) => (
 <li key={j}>
 <span className="pricing-check" style={{ color: accent }}><Icon.Check /></span>
 <span>{inc}</span>
 </li>
 ))}
 </ul>
 </article>
 ))}
 </div>
 <p className="pricing-closing reveal">{t.pricing.closing}</p>
 </div>
 </section>
 );
}

function FAQ({ accent, t }) {
 const [open, setOpen] = useState(0);
 // Group items by category, preserving relative order. The first time a
 // category appears in t.faq.items defines its position in the display.
 // Edit t.faq.items in i18n to add/remove/reorder questions or categories.
 const order = [];
 const groups = {};
 t.faq.items.forEach((it, idx) => {
 const cat = it.category || 'Other';
 if (!order.includes(cat)) order.push(cat);
 (groups[cat] = groups[cat] || []).push({ ...it, originalIdx: idx });
 });
 const card = t.faq.contactCard;
 return (
 <section className="section section-faq" id="faq" data-screen-label="09 FAQ">
 <div className="container">
 <div className="section-head reveal">
 <h2 className="display-2">{t.faq.title}</h2>
 </div>
 <div className="faq">
 {order.map(cat => (
 <div className="faq-group" key={cat}>
 <div className="faq-category" style={{ color: accent }}>{cat}</div>
 {groups[cat].map(it => (
 <div
 className={`faq-item${open===it.originalIdx?' open':''} reveal`}
 key={it.originalIdx}
 data-d={(it.originalIdx%4)+1}
 onClick={() => setOpen(open===it.originalIdx?-1:it.originalIdx)}
 >
 <div className="faq-q"><span>{it.q}</span><span className="faq-toggle">{open===it.originalIdx?'−':'+'}</span></div>
 <div className="faq-a-wrap"><div className="faq-a">{it.a}</div></div>
 </div>
 ))}
 </div>
 ))}
 </div>
 {card && (
 <a href={`mailto:${CONTACT_EMAIL}`} className="faq-contact reveal" data-d="1">
 <div className="faq-contact-text">
 <strong>{card.title}</strong>
 <span>{card.body}</span>
 </div>
 <span className="faq-contact-cta" style={{ color: accent }}>
 {card.cta} <Icon.Arrow />
 </span>
 </a>
 )}
 </div>
 </section>
 );
}

function CTA({ accent, t }) {
 return (
 <section className="cta" id="contact" data-screen-label="10 CTA">
 <div className="container" style={{ position:'relative' }}>
 <div className="cta-pre reveal" style={{ color: accent }}>{t.cta.eyebrow}</div>
 <h2 className="display-1 reveal" data-d="1">{t.cta.title1}{t.cta.title2 && <><br/>{t.cta.title2}</>}<br/><span style={{ color: accent }}>{t.cta.title3}</span></h2>
 <div className="cta-availability reveal" data-d="2">{t.cta.availability}</div>
 <div className="cta-actions reveal" data-d="3">
 <a href={BOOKING_URL} className="btn btn-primary" style={{ background: accent }}>{t.cta.cta1} <Icon.Arrow /></a>
 </div>
 <div className="cta-micro reveal" data-d="4">{t.cta.micro}</div>
 </div>
 </section>
 );
}

/* Sticky mobile CTA — slides up from the bottom of the viewport once the
   reader has scrolled ~35% of the page, hides again when the Final CTA
   itself is in view (so it doesn't double up). Mobile-only via CSS. */
function StickyMobileCTA({ accent, t }) {
 const [visible, setVisible] = useState(false);
 useEffect(() => {
 const cta = document.getElementById('contact');
 let ctaInView = false;
 const evaluate = () => {
 const total = document.documentElement.scrollHeight - window.innerHeight;
 const pct = total > 0 ? window.scrollY / total : 0;
 setVisible(pct > 0.35 && !ctaInView);
 };
 const io = cta
 ? new IntersectionObserver((entries) => {
 entries.forEach(e => { ctaInView = e.isIntersecting; });
 evaluate();
 }, { threshold: 0.15 })
 : null;
 if (io && cta) io.observe(cta);
 evaluate();
 window.addEventListener('scroll', evaluate, { passive: true });
 window.addEventListener('resize', evaluate);
 return () => {
 window.removeEventListener('scroll', evaluate);
 window.removeEventListener('resize', evaluate);
 if (io) io.disconnect();
 };
 }, []);
 return (
 <div className={`mobile-cta${visible ? ' show' : ''}`} aria-hidden={!visible}>
 <a
 href={BOOKING_URL}
 className="btn btn-primary mobile-cta-btn"
 style={{ background: accent }}
 tabIndex={visible ? 0 : -1}
 >
 {t.cta.cta1} <Icon.Arrow />
 </a>
 </div>
 );
}

function Footer({ t }) {
 return (
 <footer className="footer">
 <div>{t.footer.rights}</div>
 </footer>
 );
}

/* Language switcher — segmented EN | TH pill. Two render variants share
   logic: <LangSwitch> sits inside SideNav (desktop), <LangSwitchFloat>
   is fixed top-right and shown only on mobile via CSS media query, since
   SideNav is hidden below 1100px. */
function LangSwitch({ lang, setLang, className }) {
 const cls = `lang-switch${className ? ` ${className}` : ''}`;
 return (
 <div className={cls} role="group" aria-label="Language">
 <button
 type="button"
 aria-pressed={lang === 'EN'}
 aria-label="Switch to English"
 onClick={() => setLang('EN')}
 >EN</button>
 <button
 type="button"
 aria-pressed={lang === 'TH'}
 aria-label="เปลี่ยนเป็นภาษาไทย"
 onClick={() => setLang('TH')}
 >TH</button>
 </div>
 );
}

function LangSwitchFloat({ lang, setLang }) {
 return <LangSwitch lang={lang} setLang={setLang} className="lang-switch-float" />;
}

function SideNav({ accent, t, lang, setLang }) {
 const items = [
 { id: 'top',          label: 'Autopilot' },
 { id: 'problem',      label: t.nav.gap },
 { id: 'results',      label: t.nav.results },
 { id: 'how',          label: t.nav.how },
 { id: 'about',        label: t.nav.about },
 { id: 'capabilities', label: t.nav.caps },
 { id: 'why',          label: t.nav.why },
 { id: 'pricing',      label: t.nav.pricing || 'Pricing' },
 { id: 'faq',          label: t.nav.faq },
 { id: 'contact',      label: t.nav.cta, kind: 'cta' },
 ];
 // Default to 'top' so the AUTOPILOT label is highlighted at first paint,
 // even before the IntersectionObserver fires its first callback.
 const [active, setActive] = useState('top');
 const [hoverY, setHoverY] = useState(null);
 const itemRefs = useRef([]);
 const rafRef = useRef(0);

 useEffect(() => {
 const ratios = new Map(items.map(it => [it.id, 0]));
 const sections = items
 .map(it => ({ id: it.id, el: document.getElementById(it.id) }))
 .filter(s => s.el);
 if (!sections.length) return;
 const pickActive = () => {
 let best = null, bestRatio = 0;
 ratios.forEach((r, id) => { if (r > bestRatio) { bestRatio = r; best = id; } });
 if (bestRatio > 0) {
 setActive(best);
 } else if (window.scrollY < window.innerHeight * 0.5) {
 // Near the top of the page with nothing intersecting the trigger
 // zone — hold AUTOPILOT active rather than going blank.
 setActive('top');
 }
 };
 const io = new IntersectionObserver((entries) => {
 entries.forEach(e => ratios.set(e.target.id, e.intersectionRatio));
 pickActive();
 }, {
 rootMargin: '-30% 0px -55% 0px',
 threshold: [0, 0.25, 0.5, 0.75, 1]
 });
 sections.forEach(s => io.observe(s.el));
 // Scroll listener as a backstop — IO can miss edge cases near page top.
 const onScroll = () => pickActive();
 window.addEventListener('scroll', onScroll, { passive: true });
 return () => { io.disconnect(); window.removeEventListener('scroll', onScroll); };
 }, [t]);

 const handleClick = (e, id) => {
 const el = document.getElementById(id);
 if (!el) return;
 e.preventDefault();
 const top = el.getBoundingClientRect().top + window.pageYOffset - 88;
 window.scrollTo({ top, behavior: 'smooth' });
 history.replaceState(null, '', `#${id}`);
 };

 const onMove = (e) => {
 const y = e.clientY;
 if (rafRef.current) return;
 rafRef.current = requestAnimationFrame(() => {
 setHoverY(y);
 rafRef.current = 0;
 });
 };
 const onLeave = () => {
 if (rafRef.current) { cancelAnimationFrame(rafRef.current); rafRef.current = 0; }
 setHoverY(null);
 };

 // Dock-style magnification: baseline lift when cursor is anywhere over the
 // nav, peak scale on the item nearest the cursor, smooth Gaussian falloff
 // to neighbors so the bulge "flows" with the cursor.
 const MIN_LIFT = 1.05;
 const PEAK = 1.22;
 const RADIUS = 100; // px

 const getScale = (i) => {
 if (hoverY === null) return 1;
 const el = itemRefs.current[i];
 if (!el) return MIN_LIFT;
 const r = el.getBoundingClientRect();
 const center = r.top + r.height / 2;
 const d = Math.abs(hoverY - center);
 const f = Math.exp(-(d * d) / (2 * RADIUS * RADIUS));
 return MIN_LIFT + (PEAK - MIN_LIFT) * f;
 };

 const hovering = hoverY !== null;

 return (
 <nav
 className={`side-nav${active ? ' has-active' : ''}${hovering ? ' hovering' : ''}`}
 aria-label="Section navigation"
 onMouseMove={onMove}
 onMouseLeave={onLeave}
 >
 {setLang && <LangSwitch lang={lang} setLang={setLang} />}
 {items.map((it, i) => {
 const isActive = active === it.id;
 const isCta = it.kind === 'cta';
 const scale = getScale(i);
 const inline = {};
 if (isActive && isCta) {
 inline.color = '#fff';
 inline.background = accent;
 inline.borderColor = accent;
 } else if (isActive) {
 inline.color = accent;
 }
 if (hovering) inline.transform = `scale(${scale})`;
 // When not hovering, mirror the hover magnification on the active item
 // so scrolling produces the same visual effect as a hover.
 else if (isActive) inline.transform = `scale(${PEAK})`;
 return (
 <a
 key={it.id}
 ref={(el) => { itemRefs.current[i] = el; }}
 href={`#${it.id}`}
 onClick={(e) => handleClick(e, it.id)}
 className={`side-nav-item${isActive ? ' active' : ''}${isCta ? ' cta' : ''}`}
 style={inline}
 >
 <span className="side-nav-label">{it.label}</span>
 <span
 className="side-nav-tick"
 style={isActive && !isCta ? { background: accent, boxShadow: `0 0 14px ${accent}` } : undefined}
 />
 </a>
 );
 })}
 </nav>
 );
}

Object.assign(window, { Nav, Hero, Tools, Problem, HowItWorks, Capabilities, Results, Why, About, Pricing, FAQ, CTA, StickyMobileCTA, Footer, SideNav, LangSwitch, LangSwitchFloat, Icon, I18N, GuaranteeSeal });
