// Portfolio components — Jab Tawanrat · Growth Systems Consultant
const { useState, useEffect, useRef } = React;
const cx = (...xs) => xs.filter(Boolean).join(' ');

const LocaleContext = React.createContext({ lang: 'en' });
const TH_COPY = {
  'Home': 'หน้าแรก',
  'Work': 'ผลงาน',
  'About': 'เกี่ยวกับ',
  'Contact': 'ติดต่อ',
  'Email': 'อีเมล',
  'Growth Systems Consultant': 'ที่ปรึกษาด้านระบบการเติบโต',
  'Primary navigation': 'เมนูหลัก',
  'Résumé': 'ประวัติ',
  'Portfolio · 2026': 'แฟ้มผลงาน · 2026',
  'Open to conversations': 'พร้อมคุยโปรเจกต์ใหม่',
  'I build growth systems': 'ผมสร้างระบบการเติบโต',
  'teams actually use.': 'ที่ทีมใช้จริง',
  'I help growing teams replace manual CRM, lifecycle, and sales operations with practical automation and internal tools.': 'ผมช่วยทีมที่กำลังเติบโตเปลี่ยนงาน CRM, lifecycle และ sales operations ที่ทำด้วยมือ ให้เป็น automation และ internal tools ที่ใช้งานได้จริง',
  'Built from real operating experience across six APAC markets.': 'สร้างจากประสบการณ์ลงมือทำจริงใน 6 ตลาดเอเชียแปซิฟิก',
  'See selected work': 'ดูผลงานที่เลือก',
  'Get in touch': 'คุยโปรเจกต์',
  'Selected impact': 'ผลลัพธ์สำคัญ',
  'APAC markets': 'ตลาด APAC',
  'daily users': 'ผู้ใช้ต่อวัน',
  'workflows shipped': 'เวิร์กโฟลว์ที่ส่งมอบ',
  'Bangkok, Thailand': 'กรุงเทพฯ ประเทศไทย',
  'CRM · Lifecycle · AI automation': 'CRM · Lifecycle · AI automation',
  'Now · Q3 2026': 'ตอนนี้ · ไตรมาส 3 ปี 2026',
  'Leading AI & growth across the FunNow Group, overseeing both Eatigo and FunNow business units.': 'ดูแลกลยุทธ์ AI และการเติบโตระดับ FunNow Group ครอบคลุมทั้ง Eatigo และ FunNow',
  'Rolling out': 'กำลังเปิดใช้งาน',
  'Scaling': 'กำลังขยายผล',
  'Shipping': 'กำลังส่งมอบ',
  'A custom B2B sales platform that replaces the legacy CRM with auto-prospecting and AI outreach.': 'แพลตฟอร์มขาย B2B ที่แทน CRM เดิมด้วยระบบค้นหาลูกค้าและ outreach ด้วย AI',
  'A group-wide marketing automation engine: push, email, video, blog and in-app, generated and shipped at multi-market speed.': 'ระบบ marketing automation ระดับกลุ่ม ครอบคลุม push, email, video, blog และ in-app สำหรับหลายตลาด',
  'A homegrown project tracker: Kanban, Gantt and docs with an AI scribe wired into Slack.': 'ระบบติดตามโปรเจกต์ที่สร้างเอง รวม Kanban, Gantt, เอกสาร และ AI scribe ที่เชื่อมกับ Slack',
  'The operating loop': 'กระบวนการทำงาน',
  'From recurring friction to a system people keep using.': 'เปลี่ยนปัญหาซ้ำ ๆ ให้เป็นระบบที่คนอยากใช้ต่อ',
  'The technology changes. The build logic stays consistent.': 'เทคโนโลยีเปลี่ยนได้ แต่หลักการสร้างระบบยังเหมือนเดิม',
  'Find friction': 'หาจุดติดขัด',
  'Manual work': 'งานที่ทำด้วยมือ',
  'Map the logic': 'วางตรรกะ',
  'Rules & owners': 'กติกาและเจ้าของงาน',
  'Build small': 'สร้างให้เล็กก่อน',
  'Working system': 'ระบบที่ใช้งานได้',
  'Embed with teams': 'ฝังในวิธีทำงาน',
  'Daily adoption': 'การใช้งานประจำวัน',
  'Measure': 'วัดผล',
  'Time & growth': 'เวลาและการเติบโต',
  'systems shipped': 'ระบบที่ส่งมอบ',
  'Selected systems': 'ระบบที่เลือกมา',
  'Not concepts. Systems teams use every day.': 'ไม่ใช่แค่แนวคิด แต่เป็นระบบที่ทีมใช้ทุกวัน',
  'View the full work archive': 'ดูผลงานทั้งหมด',
  'Primary result': 'ผลลัพธ์หลัก',
  'Replaces': 'ทดแทน',
  'Coverage': 'ขอบเขต',
  'Volume': 'ปริมาณ',
  'Adoption': 'การใช้งาน',
  'The friction': 'ปัญหาที่ต้องแก้',
  'The system': 'ระบบที่สร้าง',
  'Proof in use': 'หลักฐานจากการใช้งาน',
  'Technology used': 'เทคโนโลยีที่ใช้',
  'Read the build story ↗': 'อ่านเบื้องหลังการสร้าง ↗',
  'Outcome': 'ผลลัพธ์',
  'How I work': 'วิธีที่ผมทำงาน',
  'Strategy → system → measurement. In that order.': 'กลยุทธ์ → ระบบ → การวัดผล ตามลำดับนี้',
  'Listen for the friction': 'เริ่มจากจุดที่งานติดขัด',
  'Strategy first, system second': 'วางกลยุทธ์ก่อนสร้างระบบ',
  'AI is a coworker, not magic': 'AI คือเพื่อนร่วมงาน ไม่ใช่เวทมนตร์',
  'Build what you can’t buy': 'สร้างสิ่งที่ซื้อสำเร็จรูปไม่ได้',
  'Measure what matters': 'วัดเฉพาะสิ่งที่สำคัญ',
  'Work with me': 'ร่วมงานกับผม',
  'Practical systems for teams that have outgrown manual work.': 'ระบบที่ใช้งานได้จริง สำหรับทีมที่โตเกินกว่าจะทำทุกอย่างด้วยมือ',
  'Growth operations audit': 'ตรวจระบบ Growth Operations',
  'CRM & lifecycle systems': 'ระบบ CRM และ Lifecycle',
  'AI automation & internal tools': 'AI Automation และ Internal Tools',
  'Tell me what’s slowing your team down': 'เล่าให้ผมฟังว่างานติดตรงไหน',
  'Experience': 'ประสบการณ์',
  'Seven years across APAC retail, e-commerce, and growth tech.': 'ประสบการณ์ 7 ปีในธุรกิจค้าปลีก อีคอมเมิร์ซ และ growth technology ทั่ว APAC',
  'Education': 'การศึกษา',
  'Skills': 'ทักษะ',
  'The toolkit: strategy, AI ops, and building.': 'เครื่องมือของผม: กลยุทธ์, AI operations และการลงมือสร้าง',
  'Growth systems': 'ระบบการเติบโต',
  'AI & automation': 'AI และระบบอัตโนมัติ',
  'Data & experimentation': 'ข้อมูลและการทดลอง',
  'Build stack': 'เครื่องมือพัฒนา',
  'Tell me where work gets stuck.': 'บอกผมว่างานติดอยู่ตรงไหน',
  'I’ll help design the system.': 'ผมจะช่วยออกแบบระบบให้',
  'Phone': 'โทรศัพท์',
  'PDF · updated Jul 2026': 'PDF · อัปเดต ก.ค. 2026',
  'Designed & built · Bangkok': 'ออกแบบและพัฒนา · กรุงเทพฯ',
  'Selected work': 'ผลงานที่เลือก',
  'Systems built around real operational friction.': 'ระบบที่เริ่มจากปัญหาในการทำงานจริง',
  'Three case studies across sales operations, lifecycle marketing, and project management. Each started with a bottleneck and ended with a system people chose to use.': '3 กรณีศึกษาด้าน sales operations, lifecycle marketing และ project management ทุกงานเริ่มจากคอขวด และจบด้วยระบบที่คนเลือกใช้จริง',
  'Independent builds': 'ผลิตภัณฑ์และงานลูกค้า',
  'Tools and client work shipped outside my core role.': 'งานที่ผมออกแบบและพัฒนานอกเหนือจากบทบาทหลัก',
  'About': 'เกี่ยวกับ',
  'A growth operator who builds.': 'นักวางระบบการเติบโตที่ลงมือสร้างเอง',
  'Seven years across CRM, lifecycle, product operations, and automation. I work between business strategy and implementation — turning operational friction into systems teams can actually own.': 'ประสบการณ์ 7 ปีด้าน CRM, lifecycle, product operations และ automation ผมเชื่อมกลยุทธ์ธุรกิจกับการลงมือสร้าง เพื่อเปลี่ยนปัญหาในการทำงานให้เป็นระบบที่ทีมดูแลต่อเองได้',
  'System map': 'แผนที่ระบบ',
  'owned systems': 'ระบบหลัก',
  'Role map': 'แผนที่บทบาท',
  'Business × delivery': 'ธุรกิจ × การส่งมอบ',
  'Decide': 'ตัดสินใจ',
  'Deliver': 'ส่งมอบ',
  'Business': 'ธุรกิจ',
  'Technology': 'เทคโนโลยี',
  'Direction': 'ทิศทาง',
  'Journeys': 'เส้นทางลูกค้า',
  'Product ops': 'Product ops',
  'Automation': 'Automation',
  'Operator + Builder': 'นักวางระบบ + นักสร้าง',
  'From the business question to the working system — without the handoff gap.': 'จากโจทย์ธุรกิจสู่ระบบที่ใช้งานได้ โดยไม่ตกหล่นระหว่างการส่งต่องาน',
};

const useCopy = () => {
  const { lang } = React.useContext(LocaleContext);
  const t = (value) => lang === 'th' ? (TH_COPY[value] || value) : value;
  return { lang, t };
};

// ─────────────────────────────────────────────────────────────
// Reveal-on-scroll
// ─────────────────────────────────────────────────────────────
const useReveal = () => {
  const ref = useRef(null);
  const [shown, setShown] = useState(false);
  useEffect(() => {
    if (!ref.current) return;
    const obs = new IntersectionObserver(
      ([e]) => { if (e.isIntersecting) { setShown(true); obs.disconnect(); } },
      { threshold: 0.12 }
    );
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);
  return [ref, shown];
};
const Reveal = ({ children, delay = 0, as: As = 'div', className = '', ...rest }) => {
  const [ref, shown] = useReveal();
  return (
    <As ref={ref} className={cx('reveal', shown && 'reveal-in', className)} style={{ transitionDelay: `${delay}ms` }} {...rest}>
      {children}
    </As>
  );
};

// ─────────────────────────────────────────────────────────────
// Top nav
// ─────────────────────────────────────────────────────────────
const NAV_LINKS = [
  { id: 'home', label: 'Home', href: '#/' },
  { id: 'work', label: 'Work', href: '#/work' },
  { id: 'about', label: 'About', href: '#/about' },
];

const Nav = ({ route, onLanguageChange }) => {
  const { lang, t } = useCopy();
  return (
    <nav className="nav" aria-label={t('Primary navigation')}>
      <div className="nav-inner">
        <a href="#/" className="nav-brand" aria-label={`Jab Tawanrat — ${t('Growth Systems Consultant')}`}>
          <span className="nav-signal" aria-hidden="true" />
          <span className="nav-identity">
            <span className="nav-name">
              <span className="nav-name-full">Jab&nbsp;Tawanrat</span>
              <span className="nav-name-short">Jab</span>
            </span>
            <span className="nav-role">{t('Growth Systems Consultant')}</span>
          </span>
        </a>
        <div className="nav-links">
          {NAV_LINKS.map((l) => (
            <a
              key={l.id}
              href={l.href}
              className={cx('nav-link', route === l.id && 'is-active')}
              aria-current={route === l.id ? 'page' : undefined}
            >
              <span>{t(l.label)}</span>
            </a>
          ))}
          <a href="mailto:chokchai.tawanrat@gmail.com" className="nav-link">{t('Contact')}</a>
        </div>
        <div className="nav-actions">
          <div className="lang-switch" role="group" aria-label={lang === 'th' ? 'เลือกภาษา' : 'Choose language'}>
            <button
              type="button"
              className={cx(lang === 'en' && 'is-active')}
              aria-pressed={lang === 'en'}
              onClick={() => onLanguageChange('en')}
            >EN</button>
            <span aria-hidden="true">/</span>
            <button
              type="button"
              className={cx(lang === 'th' && 'is-active')}
              aria-pressed={lang === 'th'}
              onClick={() => onLanguageChange('th')}
            >TH</button>
          </div>
          <a href="assets/Chokchai-Tawanrat-Resume.pdf" className="nav-cta" target="_blank" rel="noopener">
            <span className="resume-long">{t('Résumé')}</span><span className="resume-short">CV</span> ↗
          </a>
        </div>
      </div>
    </nav>
  );
};

// ─────────────────────────────────────────────────────────────
// Hero
// ─────────────────────────────────────────────────────────────
const HeroCanvas = () => {
  const { lang, t } = useCopy();
  return (
    <aside
      className="hero-landscape"
      aria-label={lang === 'th' ? 'โชคชัย ตะวันรัตน์ ในภูมิทัศน์สีเขียวพร้อมข้อมูลผลงาน' : 'Chokchai Tawanrat standing in a grass landscape with selected impact'}
    >
      <div className="landscape-sun" aria-hidden="true" />
      <div className="landscape-path" aria-hidden="true" />

      <div className="hero-person">
        <img
          src="assets/jab-hero-cutout-v3.webp"
          alt={lang === 'th' ? 'โชคชัย ตะวันรัตน์ ที่ปรึกษาด้านระบบการเติบโต' : 'Chokchai Tawanrat, AI and Growth Strategist'}
        />
      </div>

      <div className="landscape-caption">
        <span>{t('Bangkok, Thailand')}</span>
        <span>{t('CRM · Lifecycle · AI automation')}</span>
      </div>
    </aside>
  );
};

const Hero = () => {
  const { lang, t } = useCopy();
  const [now, setNow] = useState(new Date());
  useEffect(() => {
    const t = setInterval(() => setNow(new Date()), 30_000);
    return () => clearInterval(t);
  }, []);
  const bkk = new Intl.DateTimeFormat(lang === 'th' ? 'th-TH' : 'en-GB', { timeZone: 'Asia/Bangkok', hour: '2-digit', minute: '2-digit', hour12: false }).format(now);

  return (
    <header id="top" className="hero">
      <div className="hero-eyebrow">
        <span className="eyebrow-dot" />
        <span>{t('Portfolio · 2026')}</span>
        <span className="sep">·</span>
        <span>{lang === 'th' ? 'กรุงเทพฯ' : 'Bangkok'} · {bkk} ICT</span>
        <span className="sep">·</span>
        <span><span className="dot-live" /> {t('Open to conversations')}</span>
      </div>

      <div className="hero-main">
        <div className="hero-text">
          <h1 className="display">
            <span className="d-line">{t('I build growth systems')}</span>
            <span className="d-line"><em>{t('teams actually use.')}</em></span>
          </h1>
          <p className="hero-lede">
            {t('I help growing teams replace manual CRM, lifecycle, and sales operations with practical automation and internal tools.')}
            <strong> {t('Built from real operating experience across six APAC markets.')}</strong>
          </p>

          <div className="hero-ctas">
            <a href="#/work" className="btn-primary">
              <span>{t('See selected work')}</span>
              <svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 7h8M7 3l4 4-4 4" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/></svg>
            </a>
            <a href="mailto:chokchai.tawanrat@gmail.com" className="btn-ghost">{t('Get in touch')}</a>
          </div>

          <div className="hero-proof" aria-label={t('Selected impact')}>
            <div><strong>6</strong><span>{t('APAC markets')}</span></div>
            <div><strong>100+</strong><span>{t('daily users')}</span></div>
            <div><strong>15+</strong><span>{t('workflows shipped')}</span></div>
          </div>
        </div>

        <HeroCanvas />
      </div>

      <Marquee />
    </header>
  );
};

const Marquee = () => {
  const items = [
    'Claude Code', 'n8n', 'CleverTap', 'Braze', 'Supabase', 'Lovable', 'OpenAI', 'Apify',
    'Lifecycle segmentation', 'A/B testing', 'Predictive cohorts',
    'Auto cold outreach', 'AI content generation', 'Slack workflows',
    'Push · Email · In-app · WhatsApp', 'CLTV growth',
  ];
  const seq = [...items, ...items];
  return (
    <div className="marquee">
      <div className="marquee-track">
        {seq.map((it, i) => (
          <span key={i} className="marquee-item">
            <span className="marquee-bullet">◇</span>{it}
          </span>
        ))}
      </div>
    </div>
  );
};

// ─────────────────────────────────────────────────────────────
// NOW — what I'm working on this quarter
// ─────────────────────────────────────────────────────────────
const Now = () => {
  const { lang, t } = useCopy();
  return (
    <section id="now" className="section section-now">
      <div className="now-inner">
        <Reveal className="section-label" as="div">
          <span className="label-bar" />
          <span>{t('Now · Q3 2026')}</span>
        </Reveal>
        <Reveal as="h2" className="now-headline" delay={60}>
          {lang === 'th'
            ? <>ดูแลกลยุทธ์ AI และการเติบโตระดับ <em>FunNow Group</em> ครอบคลุมทั้ง Eatigo และ FunNow</>
            : <>Leading AI &amp; growth across the <em>FunNow Group</em>, overseeing both Eatigo and FunNow business units.</>}
        </Reveal>
        <div className="now-grid">
          <Reveal className="now-card" delay={80}>
            <div className="now-card-k">{t('Rolling out')}</div>
            <div className="now-card-v">{t('A custom B2B sales platform that replaces the legacy CRM with auto-prospecting and AI outreach.')}</div>
          </Reveal>
          <Reveal className="now-card" delay={140}>
            <div className="now-card-k">{t('Scaling')}</div>
            <div className="now-card-v">{t('A group-wide marketing automation engine: push, email, video, blog and in-app, generated and shipped at multi-market speed.')}</div>
          </Reveal>
          <Reveal className="now-card" delay={200}>
            <div className="now-card-k">{t('Shipping')}</div>
            <div className="now-card-v">{t('A homegrown project tracker: Kanban, Gantt and docs with an AI scribe wired into Slack.')}</div>
          </Reveal>
        </div>
      </div>
    </section>
  );
};

// ─────────────────────────────────────────────────────────────
// Home infographic — how a system gets built
// ─────────────────────────────────────────────────────────────
const SystemLoop = () => {
  const { lang, t } = useCopy();
  const stages = [
    ['01', 'Find friction', 'Manual work'],
    ['02', 'Map the logic', 'Rules & owners'],
    ['03', 'Build small', 'Working system'],
    ['04', 'Embed with teams', 'Daily adoption'],
    ['05', 'Measure', 'Time & growth'],
  ];
  return (
    <section className="system-loop-section" aria-labelledby="system-loop-title">
      <Reveal as="div" className="system-loop">
        <div className="system-loop-copy">
          <div className="section-label"><span className="label-bar" /><span>{t('The operating loop')}</span></div>
          <h2 id="system-loop-title">{t('From recurring friction to a system people keep using.')}</h2>
          <p>{t('The technology changes. The build logic stays consistent.')}</p>
        </div>
        <div className="system-loop-diagram" role="img" aria-label={lang === 'th' ? 'ห้าขั้นตอนจากการหาจุดติดขัดจนถึงการวัดผล' : 'Five stages from finding friction to measuring growth'}>
          <div className="system-loop-line" aria-hidden="true" />
          {stages.map(([num, title, detail]) => (
            <div className="system-loop-stage" key={num}>
              <span className="system-loop-node">{num}</span>
              <strong>{t(title)}</strong>
              <small>{t(detail)}</small>
            </div>
          ))}
          <div className="system-loop-return" aria-hidden="true">↺</div>
        </div>
        <div className="system-loop-proof">
          <span><strong>15+</strong> {t('systems shipped')}</span>
          <span><strong>100+</strong> {t('daily users')}</span>
          <span><strong>6</strong> {t('APAC markets')}</span>
        </div>
      </Reveal>
    </section>
  );
};

// ─────────────────────────────────────────────────────────────
// Selected Work
// ─────────────────────────────────────────────────────────────
const projects = [
  {
    id: 'b2b-sales-platform',
    num: '01',
    year: '2025–26',
    title: 'B2B Sales Platform',
    subtitle: 'A custom CRM with built-in lead generation and AI-powered cold outreach.',
    stack: ['Claude Code', 'Supabase', 'OpenAI', 'Lead enrichment', 'E-sign'],
    outcomes: [
      ['Primary result', 'merchant live in < 3 minutes'],
      ['Replaces', 'legacy Zoho workflow'],
      ['Coverage', 'lead source → signed contract'],
    ],
    problem: 'Prospecting, enrichment, outreach, and contract handoff lived in different tools. Reps spent time moving data instead of selling.',
    solution: 'I designed one owned sales system that finds and qualifies merchants, drafts sequenced outreach, classifies replies, and carries qualified leads through e-signature.',
    highlights: [
      'Fresh leads are enriched and deduplicated before reaching a rep.',
      'Outreach adapts by market, persona, channel, and reply sentiment.',
      'Used across six markets with role-specific views for reps and leaders.',
    ],
    preview: 'salesFlow',
    tags: ['B2B', 'Sales CRM', 'AI pipeline', 'Lead gen'],
    caseStudy: 'https://github.com/chokchait/automation-case-studies/blob/main/01-lead-gen-agent.md',
    th: {
      title: 'แพลตฟอร์มขาย B2B',
      subtitle: 'CRM ที่รวมการหาลูกค้าใหม่และ cold outreach ด้วย AI ไว้ในระบบเดียว',
      outcomes: [
        ['ผลลัพธ์หลัก', 'เพิ่มร้านค้าเข้าระบบได้ภายใน 3 นาที'],
        ['ทดแทน', 'กระบวนการเดิมบน Zoho CRM'],
        ['ขอบเขต', 'หาลีด → เซ็นสัญญา'],
      ],
      problem: 'การหาลูกค้า เติมข้อมูล outreach และส่งต่อสัญญาอยู่คนละเครื่องมือ ทีมขายเสียเวลาไปกับการย้ายข้อมูลแทนการขาย',
      solution: 'ผมออกแบบระบบขายที่ค้นหาและคัดกรองร้านค้า ร่าง outreach แบบเป็นลำดับ วิเคราะห์คำตอบ และพาลีดที่พร้อมซื้อไปจนถึง e-signature',
      highlights: [
        'ลีดใหม่ถูกเติมข้อมูลและตรวจรายการซ้ำก่อนถึงมือทีมขาย',
        'Outreach ปรับตามตลาด กลุ่มเป้าหมาย ช่องทาง และน้ำเสียงของคำตอบ',
        'ใช้งานใน 6 ตลาด พร้อมมุมมองแยกตามบทบาทของทีมขายและผู้บริหาร',
      ],
    },
  },
  {
    id: 'marketing-automation',
    num: '02',
    year: '2024–26',
    title: 'Marketing Automation Engine',
    subtitle: 'Group-level lifecycle and content engine across 6 APAC markets.',
    stack: ['n8n', 'CleverTap', 'Claude Code', 'CDP segments', 'Internal admin'],
    outcomes: [
      ['Primary result', '≈84 hours saved each month'],
      ['Coverage', '6 APAC markets'],
      ['Volume', '≈400 push campaigns / month'],
    ],
    problem: 'Two brands and six markets made manual campaign production slow, inconsistent, and impossible to scale without adding headcount.',
    solution: 'I rebuilt the operating flow from brief to dispatch: AI drafts and localises, people approve, an internal admin routes assets, and CleverTap delivers.',
    highlights: [
      'One workflow covers push, email, in-app, video, and blog content.',
      'Human approval stays between AI generation and every live send.',
      'CLTV, churn risk, and dormancy segments decide who receives what.',
    ],
    preview: 'channels',
    tags: ['Lifecycle', 'CRM', 'AI content', 'APAC'],
    caseStudy: 'https://github.com/chokchait/automation-case-studies/blob/main/02-campaign-auto-setup.md',
    th: {
      title: 'ระบบ Marketing Automation',
      subtitle: 'ระบบ lifecycle และ content ระดับกลุ่มสำหรับ 6 ตลาด APAC',
      outcomes: [
        ['ผลลัพธ์หลัก', 'ประหยัดเวลาประมาณ 84 ชั่วโมงต่อเดือน'],
        ['ขอบเขต', '6 ตลาด APAC'],
        ['ปริมาณ', 'ประมาณ 400 push campaigns ต่อเดือน'],
      ],
      problem: 'สองแบรนด์และหกตลาดทำให้การผลิตแคมเปญด้วยมือช้า ไม่สม่ำเสมอ และขยายต่อไม่ได้โดยไม่เพิ่มคน',
      solution: 'ผมสร้างกระบวนการใหม่ตั้งแต่ brief ถึง dispatch: AI ร่างและ localise ทีมตรวจอนุมัติ internal admin จัดเส้นทาง และ CleverTap ส่งแคมเปญ',
      highlights: [
        'เวิร์กโฟลว์เดียวครอบคลุม push, email, in-app, video และบทความ',
        'ทุกแคมเปญมี human approval ระหว่าง AI generation กับการส่งจริง',
        'ใช้ CLTV, churn risk และ dormancy ช่วยตัดสินใจว่าใครควรได้รับข้อความใด',
      ],
    },
  },
  {
    id: 'project-tracker',
    num: '03',
    year: '2025',
    title: 'Project Tracker',
    subtitle: 'Jira + Notion, rebuilt for one team that needed both.',
    stack: ['Claude Code', 'Supabase', 'React + TS', 'Slack', 'OpenAI'],
    outcomes: [
      ['Primary result', '2 SaaS subscriptions replaced'],
      ['Adoption', 'team used it from day one'],
      ['Coverage', 'Board · Gantt · Docs · Slack'],
    ],
    problem: 'Plans lived in Notion, delivery lived in Jira, and decisions lived in Slack. The team had no reliable view of the whole project.',
    solution: 'I built one source of truth with Board, Gantt, and Docs views, two-way Slack updates, and an AI-generated weekly recap.',
    highlights: [
      'Every view reads from the same project and task data.',
      'Slack updates and task status stay synchronised in both directions.',
      'The weekly recap is drafted from actual activity, not memory.',
    ],
    preview: 'tracker',
    tags: ['Internal tool', 'PM ops', 'AI scribe'],
    th: {
      title: 'ระบบติดตามโปรเจกต์',
      subtitle: 'รวมสิ่งที่ทีมต้องใช้จาก Jira และ Notion ไว้ในเครื่องมือเดียว',
      outcomes: [
        ['ผลลัพธ์หลัก', 'ทดแทน SaaS 2 รายการ'],
        ['การใช้งาน', 'ทีมเริ่มใช้ตั้งแต่วันแรก'],
        ['ขอบเขต', 'Board · Gantt · Docs · Slack'],
      ],
      problem: 'แผนอยู่ใน Notion งานส่งมอบอยู่ใน Jira และการตัดสินใจอยู่ใน Slack ทีมจึงไม่มีภาพรวมโปรเจกต์ที่เชื่อถือได้',
      solution: 'ผมสร้างแหล่งข้อมูลเดียวที่มี Board, Gantt และ Docs เชื่อมสถานะกับ Slack สองทาง และสรุปรายสัปดาห์ด้วย AI',
      highlights: [
        'ทุกมุมมองอ่านจากข้อมูลโปรเจกต์และงานชุดเดียวกัน',
        'สถานะงานกับข้อความใน Slack ซิงก์กันทั้งสองทิศทาง',
        'สรุปรายสัปดาห์สร้างจากกิจกรรมจริง ไม่ต้องอาศัยความจำ',
      ],
    },
  },
];

const Work = () => {
  const { t } = useCopy();
  return (
  <section id="work" className="section" aria-label={t('Selected work')}>
    <div className="work-list">
      {projects.map((p, i) => <ProjectCard key={p.id} p={p} idx={i} />)}
    </div>
  </section>
  );
};

const independentBuilds = [
  {
    id: 'bloom',
    name: 'Bloom',
    type: 'Sales proposal & performance platform',
    status: 'Shipped · Google Apps Script',
    description: 'A hotel-sales workspace that connects proposals, quotations, invoices, pipeline health, YoY reporting, and management-ready PDF exports.',
    proof: 'Proposal → invoice → executive report',
    nodes: ['Proposal', 'Pipeline', 'Report'],
    tags: ['Google Sheets', 'Apps Script', 'PDF'],
    th: {
      type: 'แพลตฟอร์มข้อเสนอขายและรายงานผลงาน',
      status: 'ส่งมอบแล้ว · Google Apps Script',
      description: 'พื้นที่ทำงานสำหรับทีมขายโรงแรมที่เชื่อม proposal, quotation, invoice, pipeline, รายงาน YoY และ PDF สำหรับผู้บริหาร',
      proof: 'ข้อเสนอ → ใบแจ้งหนี้ → รายงานผู้บริหาร',
      nodes: ['ข้อเสนอ', 'Pipeline', 'รายงาน'],
    },
  },
  {
    id: 'rentbill',
    name: 'RentBill',
    type: 'Thai apartment billing system',
    status: 'In build · Google Apps Script',
    description: 'A Thai-first monthly billing tool for room records, meter readings, tenant-scoped debt carry-forward, receipts, and batch invoice printing.',
    proof: 'Meters → monthly bills → payment record',
    nodes: ['Meters', 'Bills', 'Receipts'],
    tags: ['Thai UX', 'Billing logic', 'Print/PDF'],
    th: {
      type: 'ระบบจัดการบิลค่าเช่าภาษาไทย',
      status: 'กำลังพัฒนา · Google Apps Script',
      description: 'เครื่องมือออกบิลรายเดือนสำหรับจัดการห้อง จดมิเตอร์ ยกยอดค้างตามผู้เช่า ออกใบเสร็จ และพิมพ์ใบแจ้งหนี้เป็นชุด',
      proof: 'มิเตอร์ → บิลรายเดือน → บันทึกการชำระ',
      nodes: ['มิเตอร์', 'บิล', 'ใบเสร็จ'],
    },
  },
  {
    id: 'crape',
    name: 'Crape POS',
    type: 'Thai-first POS & profit tracker',
    status: 'Shipped · Google Apps Script',
    description: 'A mobile-first point-of-sale tool for a crepe shop: quick orders, ingredient purchases, cash position, estimated profit, bestseller ranking, and menu setup.',
    proof: 'Order → cost → cash & profit view',
    nodes: ['Sell', 'Buy', 'Profit'],
    tags: ['POS', 'Thai UX', 'Mobile-first'],
    th: {
      type: 'POS และระบบติดตามกำไรภาษาไทย',
      status: 'ส่งมอบแล้ว · Google Apps Script',
      description: 'เครื่องมือขายหน้าร้านสำหรับร้านเครป ออกแบบให้ใช้บนมือถือ ครอบคลุมออเดอร์ ซื้อวัตถุดิบ เงินสด กำไรประเมิน เมนูขายดี และการตั้งราคา',
      proof: 'ขาย → ต้นทุน → เงินสดและกำไร',
      nodes: ['ขาย', 'ซื้อของ', 'กำไร'],
    },
  },
  {
    id: 'janus',
    name: 'Janus',
    type: 'B2B lead-generation website',
    status: 'Client project · Astro',
    description: 'A multi-page website for a Malaysian temporary-power company, built around real equipment evidence, sector case studies, and WhatsApp-led conversion.',
    proof: '5 complete design directions under review',
    nodes: ['Position', 'Evidence', 'Convert'],
    tags: ['Astro', 'Content system', 'Responsive'],
    th: {
      type: 'เว็บไซต์ B2B สำหรับสร้างลีด',
      status: 'งานลูกค้า · Astro',
      description: 'เว็บไซต์หลายหน้าสำหรับบริษัท temporary power ในมาเลเซีย ใช้ข้อมูลอุปกรณ์จริง กรณีศึกษาตามอุตสาหกรรม และ WhatsApp เป็นเส้นทาง conversion หลัก',
      proof: '5 ทิศทางดีไซน์แบบครบเว็บไซต์ อยู่ระหว่างรีวิว',
      nodes: ['วางตำแหน่ง', 'สร้างความเชื่อถือ', 'เปลี่ยนเป็นลีด'],
    },
  },
];

const BuildVisual = ({ build }) => (
  <div className={cx('build-visual', `build-visual-${build.id}`)} aria-hidden="true">
    <div className="build-visual-top">
      <span>{build.name.toLowerCase()}</span>
      <i />
    </div>
    <div className="build-flow">
      {build.nodes.map((node, index) => (
        <React.Fragment key={node}>
          <span>{node}</span>
          {index < build.nodes.length - 1 && <b>→</b>}
        </React.Fragment>
      ))}
    </div>
    <div className="build-signal"><i /><i /><i /><i /></div>
  </div>
);

const IndependentBuilds = ({ compact = false }) => {
  const { lang, t } = useCopy();
  return (
    <section id={compact ? 'more-builds' : 'independent-builds'} className={cx('section', 'builds-section', compact && 'builds-compact')}>
      <Reveal className="section-head builds-head" as="div">
        <div>
          <div className="section-label"><span className="label-bar" /><span>{t('Independent builds')}</span></div>
          <h2 className="section-title">{t('Tools and client work shipped outside my core role.')}</h2>
        </div>
        {compact && <a href="#/work" className="text-link">{t('View the full work archive')} <span>↗</span></a>}
      </Reveal>
      <div className="builds-grid">
        {independentBuilds.map((baseBuild, index) => {
          const build = lang === 'th' ? { ...baseBuild, ...baseBuild.th } : baseBuild;
          return (
            <Reveal key={build.id} as="article" className="build-card" delay={index * 55}>
              <BuildVisual build={build} />
              <div className="build-card-copy">
                <div className="build-card-meta"><span>{build.status}</span><span>0{index + 1}</span></div>
                <h3>{build.name}</h3>
                <p className="build-type">{build.type}</p>
                {!compact && <p className="build-description">{build.description}</p>}
                <div className="build-proof">{build.proof}</div>
                {!compact && (
                  <div className="build-tags">
                    {build.tags.map(tag => <span key={tag}>{tag}</span>)}
                  </div>
                )}
              </div>
            </Reveal>
          );
        })}
      </div>
    </section>
  );
};

const ProjectCard = ({ p: baseProject, idx }) => {
  const { lang, t } = useCopy();
  const p = lang === 'th' ? { ...baseProject, ...baseProject.th } : baseProject;
  return (
  <Reveal as="article" className="project" delay={idx * 60}>
    <header className="project-header">
      <div className="project-num">{p.num}</div>
      <div className="project-headline">
        <div className="project-meta-line">
          <span className="project-year">{p.year}</span>
          <span className="project-tags">
            {p.tags.map(t => <span key={t} className="project-tag">{t}</span>)}
          </span>
        </div>
        <h3 className="project-title">{p.title}</h3>
        <p className="project-sub">{p.subtitle}</p>
      </div>
    </header>

    <div className="project-grid">
      <div className="project-preview">
        {p.preview === 'salesFlow' && <SalesFlowPreview />}
        {p.preview === 'channels' && <ChannelsPreview />}
        {p.preview === 'tracker' && <TrackerPreview />}
      </div>

      <div className="project-copy">
        <dl className="project-impact">
          {p.outcomes.map(([k, v]) => (
            <div key={k}>
              <dt>{t(k)}</dt>
              <dd>{v}</dd>
            </div>
          ))}
        </dl>

        <div className="project-story">
          <div>
            <div className="project-section-label">{t('The friction')}</div>
            <p>{p.problem}</p>
          </div>
          <div>
            <div className="project-section-label">{t('The system')}</div>
            <p>{p.solution}</p>
          </div>
        </div>

        <div className="project-section-label">{t('Proof in use')}</div>
        <ul className="project-highlights">
          {p.highlights.map((h, i) => (
            <li key={i}><span className="hl-bullet">·</span><span>{h}</span></li>
          ))}
        </ul>

        <div className="project-delivery">
          <div className="project-stack" aria-label={t('Technology used')}>
            {p.stack.map(s => <span key={s} className="chip">{s}</span>)}
          </div>
          {p.caseStudy && (
            <a href={p.caseStudy} target="_blank" rel="noopener" className="project-case-link">
              {t('Read the build story ↗')}
            </a>
          )}
        </div>
      </div>
    </div>
  </Reveal>
  );
};

// ─────────────────────────────────────────────────────────────
// Project previews
// ─────────────────────────────────────────────────────────────
const SystemPreview = ({ label, outcome, children, className }) => {
  const { t } = useCopy();
  return (
    <div className={cx('preview', 'system-preview', className)}>
      <div className="preview-head">
        <span className="preview-dot" /><span className="preview-dot" /><span className="preview-dot" />
        <span className="preview-title">{label}</span>
      </div>
      <div className="system-preview-body">{children}</div>
      <div className="preview-foot">
        <span className="ai-dot" />
        <strong>{t('Outcome')}</strong>
        <span>{outcome}</span>
      </div>
    </div>
  );
};

const SalesFlowPreview = () => {
  const { lang } = useCopy();
  const stages = lang === 'th' ? [
    ['01', 'ค้นหา', 'ร้านค้าใหม่'],
    ['02', 'คัดกรอง', 'เติมข้อมูล + ตรวจซ้ำ'],
    ['03', 'เริ่มคุย', 'outreach เป็นลำดับ'],
    ['04', 'ปิดการขาย', 'pipeline + e-sign'],
  ] : [
    ['01', 'Source', 'fresh merchants'],
    ['02', 'Qualify', 'enrich + dedupe'],
    ['03', 'Engage', 'sequenced outreach'],
    ['04', 'Close', 'pipeline + e-sign'],
  ];
  return (
    <SystemPreview
      className="preview-sales"
      label={lang === 'th' ? '01 · ระบบรายได้' : '01 · revenue system'}
      outcome={lang === 'th' ? 'เพิ่ม คัดกรอง และเตรียมร้านค้าสำหรับ outreach ได้ภายใน 3 นาที' : 'merchant added, qualified, and ready for outreach in under 3 minutes'}
    >
      <div className="preview-primary-metric">
        <span>{lang === 'th' ? 'จากลีดสู่ข้อมูลพร้อมใช้' : 'Lead to live record'}</span>
        <strong>&lt; 3 min</strong>
        <small>{lang === 'th' ? 'ครอบคลุม 6 ตลาด APAC' : 'across six APAC markets'}</small>
      </div>
      <div className="system-flow-grid system-flow-sales" role="img" aria-label={lang === 'th' ? 'กระบวนการขายตั้งแต่ค้นหาจนปิดการขาย' : 'Source, qualify, engage, and close sales workflow'}>
        {stages.map(([num, title, detail]) => (
          <div className="system-stage" key={num}>
            <span>{num}</span>
            <strong>{title}</strong>
            <small>{detail}</small>
          </div>
        ))}
      </div>
      <div className="preview-evidence">
        <span>{lang === 'th' ? 'เติมข้อมูลด้วย AI' : 'AI enrichment'}</span>
        <span>{lang === 'th' ? 'จำแนกคำตอบ' : 'Reply classification'}</span>
        <span>{lang === 'th' ? 'ส่งต่อ E-sign' : 'E-sign handoff'}</span>
      </div>
    </SystemPreview>
  );
};

const ChannelsPreview = () => {
  const { lang } = useCopy();
  const stages = lang === 'th' ? [
    ['01', 'Brief', 'เป้าหมาย + segment'],
    ['02', 'Localise', 'AI ร่างครั้งแรก'],
    ['03', 'อนุมัติ', 'ทีมตรวจสอบ'],
    ['04', 'ส่งแคมเปญ', 'CleverTap'],
  ] : [
    ['01', 'Brief', 'goal + segment'],
    ['02', 'Localise', 'AI first draft'],
    ['03', 'Approve', 'human review'],
    ['04', 'Dispatch', 'CleverTap'],
  ];
  const channels = ['Push', 'Email', 'In-app', 'Video', 'Blog'];
  const markets = ['TH', 'TW', 'MY', 'SG', 'PH', 'HK'];
  return (
    <SystemPreview
      className="preview-marketing"
      label={lang === 'th' ? '02 · ระบบ Lifecycle' : '02 · lifecycle system'}
      outcome={lang === 'th' ? 'คืนเวลาจัดเตรียมแคมเปญให้ทีมประมาณ 84 ชั่วโมงต่อเดือน' : '≈84 hours of campaign setup returned to the team every month'}
    >
      <div className="marketing-summary">
        <div className="preview-primary-metric">
          <span>{lang === 'th' ? 'ลดงานที่ทำด้วยมือ' : 'Manual work removed'}</span>
          <strong>≈84h</strong>
          <small>{lang === 'th' ? 'ต่อเดือน' : 'every month'}</small>
        </div>
        <div className="marketing-coverage">
          <span>{lang === 'th' ? 'ขอบเขตภูมิภาค' : 'Regional coverage'}</span>
          <strong>{lang === 'th' ? '2 แบรนด์ · 6 ตลาด' : '2 brands · 6 markets'}</strong>
          <div>{markets.map(m => <i key={m}>{m}</i>)}</div>
        </div>
      </div>
      <div className="system-flow-grid system-flow-marketing" role="img" aria-label={lang === 'th' ? 'กระบวนการแคมเปญตั้งแต่บรีฟจนส่ง' : 'Brief, localise, approve, and dispatch campaign workflow'}>
        {stages.map(([num, title, detail]) => (
          <div className="system-stage" key={num}>
            <span>{num}</span>
            <strong>{title}</strong>
            <small>{detail}</small>
          </div>
        ))}
      </div>
      <div className="channel-rail">
        <span>{lang === 'th' ? 'ช่องทางส่ง' : 'Distribution'}</span>
        <div>{channels.map(channel => <i key={channel}>{channel}</i>)}</div>
      </div>
    </SystemPreview>
  );
};

const TrackerPreview = () => {
  const { lang } = useCopy();
  const views = lang === 'th' ? [
    ['Board', 'งานประจำวัน'],
    ['Gantt', 'แผนงาน'],
    ['Docs', 'บริบท'],
    ['Slack', 'การตัดสินใจ'],
  ] : [
    ['Board', 'daily flow'],
    ['Gantt', 'roadmap'],
    ['Docs', 'context'],
    ['Slack', 'decisions'],
  ];
  return (
    <SystemPreview
      className="preview-tracker-map"
      label={lang === 'th' ? '03 · ระบบส่งมอบงาน' : '03 · delivery system'}
      outcome={lang === 'th' ? 'แหล่งข้อมูลเดียวทดแทน SaaS 2 รายการ' : 'one source of truth replaced two separate SaaS subscriptions'}
    >
      <div className="tracker-system-map" role="img" aria-label="Board, Gantt, Docs, and Slack connected to one source of truth">
        <div className="tracker-hub">
          <span>{lang === 'th' ? 'ข้อมูลร่วมกัน' : 'Shared data'}</span>
          <strong>{lang === 'th' ? <>ข้อมูลชุด<br/>เดียวกัน</> : <>One source<br/>of truth</>}</strong>
        </div>
        {views.map(([name, detail]) => (
          <div className={cx('tracker-map-node', `tracker-map-${name.toLowerCase()}`)} key={name}>
            <strong>{name}</strong>
            <small>{detail}</small>
          </div>
        ))}
      </div>
      <div className="tracker-recap-flow" aria-label="Weekly recap automation">
        <span>{lang === 'th' ? 'กิจกรรมของทีม' : 'Team activity'}</span><i>→</i>
        <span>{lang === 'th' ? 'AI สรุป' : 'AI summary'}</span><i>→</i>
        <strong>{lang === 'th' ? 'สรุปวันศุกร์' : 'Friday recap'}</strong>
      </div>
      <div className="preview-evidence">
        <span>{lang === 'th' ? 'ใช้จริงตั้งแต่วันแรก' : 'Day-one adoption'}</span>
        <span>{lang === 'th' ? 'Slack ซิงก์สองทาง' : 'Two-way Slack sync'}</span>
        <span>{lang === 'th' ? '3 มุมมองเชื่อมกัน' : '3 connected views'}</span>
      </div>
    </SystemPreview>
  );
};

// ─────────────────────────────────────────────────────────────
// How I Work
// ─────────────────────────────────────────────────────────────
const How = () => {
  const { lang, t } = useCopy();
  const steps = lang === 'th' ? [
    { n: '01', t: 'เริ่มจากจุดที่งานติดขัด', d: 'ผมเริ่มจากจุดที่ทีมกำลังเสียเวลา ต้นทุนมักไม่ใช่แค่เงิน แต่คือการสลับบริบท งานผลิตที่ทำด้วยมือ หรือเครื่องมือที่ไม่เข้ากับวิธีทำงานจริง' },
    { n: '02', t: 'วางกลยุทธ์ก่อนสร้างระบบ', d: 'Lifecycle, funnel และ retention ต้องเริ่มจากข้อมูล ไม่ใช่ความรู้สึก ผมกำหนด segment, cohort และ A/B logic ก่อนออกแบบระบบที่นำกลยุทธ์ไปใช้' },
    { n: '03', t: 'AI คือเพื่อนร่วมงาน ไม่ใช่เวทมนตร์', d: 'ผมปฏิบัติกับ AI เหมือนเพื่อนร่วมทีมรุ่นน้อง: ให้โจทย์ชัด ตรวจงาน และมอบส่วนที่ไม่ต้องใช้วิจารณญาณ ส่วนการตัดสินใจยังอยู่กับทีม' },
    { n: '04', t: 'สร้างสิ่งที่ซื้อสำเร็จรูปไม่ได้', d: 'ผมใช้ SaaS เมื่อมันเหมาะ แต่ถ้าเครื่องมือสำเร็จรูปบังคับให้ทีมทำงานผิดธรรมชาติ ผมจะออกแบบและสร้างระบบที่พอดีกับงานนั้น' },
    { n: '05', t: 'วัดเฉพาะสิ่งที่สำคัญ', d: 'CLTV, retention, conversion และ activation ถ้าแคมเปญหรือระบบยังไม่ขยับตัวชี้วัดเหล่านี้ ก็ยังไม่ถือว่างานจบ' },
  ] : [
    { n: '01', t: 'Listen for the friction', d: 'I start where the team is wasting time. The cost is usually not money: it\'s context-switching, manual production, or tools that don\'t fit how they actually work.' },
    { n: '02', t: 'Strategy first, system second', d: 'Lifecycle, funnel, retention: the strategy comes from data, not vibes. Segments, cohorts, A/B logic. Then I design the system that delivers it.' },
    { n: '03', t: 'AI is a coworker, not magic', d: 'I treat AI as a junior teammate: brief it well, review its output, give it the parts that don\'t need judgement. The team keeps the judgement.' },
    { n: '04', t: 'Build what you can\'t buy', d: 'I lean on SaaS where it\'s good. When the off-the-shelf option breaks our workflow, I design and ship our own, with Claude Code as my primary build partner plus Supabase, prompts, and webhooks.' },
    { n: '05', t: 'Measure what matters', d: 'CLTV, retention, conversion, activation. If a campaign or system doesn\'t move one of those, it\'s not interesting yet.' },
  ];
  return (
    <section id="how" className="section">
      <Reveal className="section-head" as="div">
        <div className="section-label"><span className="label-bar" /><span>{t('How I work')}</span></div>
        <h2 className="section-title">
          {lang === 'th' ? <>กลยุทธ์ → ระบบ → การวัดผล <em>ตามลำดับนี้</em></> : <>Strategy → system → measurement. <em>In that order.</em></>}
        </h2>
      </Reveal>

      <div className="how-list">
        {steps.map((s, i) => (
          <Reveal key={s.n} as="div" className="how-step" delay={i * 60}>
            <div className="how-n">{s.n}</div>
            <div className="how-body">
              <h3 className="how-t">{s.t}</h3>
              <p className="how-d">{s.d}</p>
            </div>
          </Reveal>
        ))}
      </div>
    </section>
  );
};

// ─────────────────────────────────────────────────────────────
// Services
// ─────────────────────────────────────────────────────────────
const services = [
  {
    k: '01',
    t: 'Growth operations audit',
    d: 'We map how work moves through your team, find the bottlenecks costing the most time, and turn them into a practical build plan with honest effort estimates.',
    th: {
      t: 'ตรวจระบบ Growth Operations',
      d: 'เราจะไล่ดูว่างานเคลื่อนผ่านทีมอย่างไร หาคอขวดที่เสียเวลามากที่สุด และเปลี่ยนเป็นแผนสร้างระบบที่ทำได้จริงพร้อมประเมินแรงอย่างตรงไปตรงมา',
    },
  },
  {
    k: '02',
    t: 'CRM & lifecycle systems',
    d: 'Lead flows, segmentation, messaging, reporting, and handoffs designed as one usable system — not a pile of disconnected tools your team has to babysit.',
    th: {
      t: 'ระบบ CRM และ Lifecycle',
      d: 'ออกแบบ lead flow, segmentation, messaging, reporting และ handoff ให้เป็นระบบเดียวที่ทีมใช้งานได้ ไม่ใช่กองเครื่องมือที่ต้องคอยดูแลตลอดเวลา',
    },
  },
  {
    k: '03',
    t: 'AI automation & internal tools',
    d: 'Purpose-built workflows, assistants, and lightweight tools that remove repetitive work. Shipped with documentation so your team can run them without me.',
    th: {
      t: 'AI Automation และ Internal Tools',
      d: 'สร้าง workflow, assistant และเครื่องมือขนาดเล็กตามโจทย์ เพื่อลดงานซ้ำ พร้อมเอกสารให้ทีมดูแลต่อได้โดยไม่ต้องพึ่งผม',
    },
  },
];

const Services = () => {
  const { lang, t } = useCopy();
  return (
  <section id="services" className="section">
    <Reveal className="section-head" as="div">
      <div className="section-label"><span className="label-bar" /><span>{t('Work with me')}</span></div>
      <h2 className="section-title">
        {lang === 'th'
          ? <>ระบบที่ใช้งานได้จริง สำหรับทีมที่ <em>โตเกินกว่าจะทำทุกอย่างด้วยมือ</em></>
          : <>Practical systems for teams that have <em>outgrown manual work</em>.</>}
      </h2>
    </Reveal>

    <div className="svc-grid">
      {services.map((baseService, i) => {
        const s = lang === 'th' ? { ...baseService, ...baseService.th } : baseService;
        return (
        <Reveal key={s.k} as="div" className="svc-card" delay={i * 60}>
          <div className="svc-k">{s.k}</div>
          <h3 className="svc-t">{s.t}</h3>
          <p className="svc-d">{s.d}</p>
        </Reveal>
        );
      })}
    </div>

    <Reveal as="div" className="svc-foot" delay={200}>
      <p className="svc-note">
        {lang === 'th'
          ? <>เราเริ่มจากปัญหาในการทำงาน ไม่ใช่รายชื่อเครื่องมือ ผมจะกำหนดระบบที่เล็กที่สุดแต่แก้โจทย์ได้ สร้าง และส่งมอบพร้อมเอกสารให้คุณเป็นเจ้าของต่อ อ่านรายละเอียดเพิ่มเติมใน <a href="https://github.com/chokchait/automation-case-studies" target="_blank" rel="noopener" className="svc-link">case studies</a></>
          : <>Start with the operational friction, not a tool list. I scope the smallest system that solves it, build it, and hand it over with clear documentation. You own the result. Deeper write-ups live in my <a href="https://github.com/chokchait/automation-case-studies" target="_blank" rel="noopener" className="svc-link">case studies</a>.</>}
      </p>
      <a href="mailto:chokchai.tawanrat@gmail.com?subject=Growth%20systems%20project" className="btn-primary">
        {lang === 'th' ? 'เล่าให้ผมฟังว่างานติดตรงไหน' : "Tell me what's slowing your team down"}
      </a>
    </Reveal>
  </section>
  );
};

// ─────────────────────────────────────────────────────────────
// Experience
// ─────────────────────────────────────────────────────────────
const experiences = [
  {
    company: 'FunNow Group',
    location: 'Bangkok',
    role: 'Senior Business Partner, AI Growth Strategy',
    period: 'Oct 2025 — Present',
    note: 'Group-level, overseeing Eatigo + FunNow business units',
    bullets: [
      'Lead AI-powered growth across the group: lifecycle, CRM, internal tooling, and sales operations. The systems are used by 100+ people across the company.',
      'Built a custom B2B sales platform with Claude Code, replacing the legacy CRM with auto-prospecting and AI outreach. BD adds a merchant in under 3 minutes.',
      'Scaled marketing automation across 6 APAC markets and built an internal project system with AI summaries.',
    ],
  },
  {
    company: 'Eatigo',
    location: 'Bangkok',
    role: 'Lifecycle Growth Manager',
    period: 'Aug 2024 — Oct 2025',
    bullets: [
      'Led end-to-end lifecycle across 6 APAC markets (activation, retention, monetization, reactivation) to grow CLTV.',
      'Ran lifecycle automation, predictive segmentation, and personalised engagement in CleverTap.',
      'Designed and tested CRM programs across gamification, loyalty, vouchers, and content production.',
    ],
  },
  {
    company: 'Lazada',
    location: 'Bangkok',
    role: 'CRM Lead · Product Operations · CRM Associate',
    period: 'Aug 2022 — Jul 2024',
    bullets: [
      'Owned Thailand CRM strategy and execution for non-paid traffic, including segmentation, personalisation, and testing.',
      'Moved into product operations to improve PDP conversion through UAT, funnel analysis, and content optimisation.',
      'Mentored the CRM team on experimentation and message relevance.',
    ],
  },
  {
    company: 'Central Department Store',
    location: 'Bangkok',
    role: 'Content Marketing & Operations',
    period: 'Mar 2021 — Aug 2022',
    bullets: [
      'Managed SKU migration across online and offline channels for data accuracy and digital UX.',
      'Progressed from coordinator to department manager and project manager while improving delivery visibility.',
    ],
  },
];

const experiencesTh = [
  {
    company: 'FunNow Group',
    location: 'กรุงเทพฯ',
    role: 'Senior Business Partner, AI Growth Strategy',
    period: 'ต.ค. 2025 — ปัจจุบัน',
    note: 'ดูแลระดับกลุ่ม ครอบคลุม Eatigo และ FunNow',
    bullets: [
      'นำกลยุทธ์การเติบโตด้วย AI ระดับกลุ่ม ทั้ง lifecycle, CRM, internal tooling และ sales operations ระบบที่สร้างมีผู้ใช้มากกว่า 100 คนในบริษัท',
      'สร้างแพลตฟอร์มขาย B2B แทน CRM เดิม เพิ่ม auto-prospecting และ AI outreach ทีม BD เพิ่มร้านค้าเข้าระบบได้ภายใน 3 นาที',
      'ขยาย marketing automation ครบ 6 ตลาด APAC และสร้างระบบโปรเจกต์ภายในที่สรุปงานด้วย AI',
    ],
  },
  {
    company: 'Eatigo',
    location: 'กรุงเทพฯ',
    role: 'Lifecycle Growth Manager',
    period: 'ส.ค. 2024 — ต.ค. 2025',
    bullets: [
      'ดูแล lifecycle ตั้งแต่ activation, retention, monetization ถึง reactivation ใน 6 ตลาด APAC เพื่อเพิ่ม CLTV',
      'วาง lifecycle automation, predictive segmentation และ personalised engagement บน CleverTap',
      'ออกแบบและทดสอบ CRM programs ทั้ง gamification, loyalty, vouchers และ content production',
    ],
  },
  {
    company: 'Lazada',
    location: 'กรุงเทพฯ',
    role: 'CRM Lead · Product Operations · CRM Associate',
    period: 'ส.ค. 2022 — ก.ค. 2024',
    bullets: [
      'ดูแลกลยุทธ์และการทำ CRM ของประเทศไทยสำหรับ non-paid traffic ทั้ง segmentation, personalisation และการทดลอง',
      'ย้ายสู่งาน product operations เพื่อเพิ่ม PDP conversion ผ่าน UAT, funnel analysis และ content optimisation',
      'พัฒนาทีม CRM ด้านการทดลองและความเกี่ยวข้องของข้อความ',
    ],
  },
  {
    company: 'Central Department Store',
    location: 'กรุงเทพฯ',
    role: 'Content Marketing & Operations',
    period: 'มี.ค. 2021 — ส.ค. 2022',
    bullets: [
      'บริหารการย้าย SKU ระหว่างช่องทางออนไลน์และออฟไลน์ เพื่อความถูกต้องของข้อมูลและ digital UX',
      'เติบโตจาก coordinator เป็น department manager และ project manager พร้อมปรับการมองเห็นสถานะส่งมอบงาน',
    ],
  },
];

const Experience = () => {
  const { lang, t } = useCopy();
  const experienceList = lang === 'th' ? experiencesTh : experiences;
  return (
  <section id="experience" className="section">
    <Reveal className="section-head" as="div">
      <div className="section-label"><span className="label-bar" /><span>{t('Experience')}</span></div>
      <h2 className="section-title">{t('Seven years across APAC retail, e-commerce, and growth tech.')}</h2>
    </Reveal>

    <div className="timeline">
      {experienceList.map((e, i) => (
        <Reveal key={i} as="div" className="tl-item" delay={i * 30}>
          <div className="tl-period"><span>{e.period}</span></div>
          <div className="tl-marker">
            <span className="tl-dot" />
            <span className="tl-line" />
          </div>
          <div className="tl-content">
            <div className="tl-head">
              <h3 className="tl-role">{e.role}</h3>
              <div className="tl-co">{e.company} <span className="tl-loc">· {e.location}</span></div>
              {e.note && <div className="tl-note">{e.note}</div>}
            </div>
            <ul className="tl-bullets">
              {e.bullets.map((b, j) => <li key={j}>{b}</li>)}
            </ul>
          </div>
        </Reveal>
      ))}
    </div>

    <Reveal className="edu-row" as="div">
      <div className="edu-label">{t('Education')}</div>
      <div className="edu-body">
        {lang === 'th'
          ? <><strong>วิทยาศาสตรบัณฑิต สาขาจิตวิทยา</strong>, มหาวิทยาลัยศรีนครินทรวิโรฒ · 2013–2017</>
          : <><strong>BSc Psychology</strong>, Srinakharinwirot University · 2013–2017</>}
      </div>
    </Reveal>
  </section>
  );
};

// ─────────────────────────────────────────────────────────────
// Skills
// ─────────────────────────────────────────────────────────────
const skillGroups = [
  { name: 'Growth systems', items: ['Lifecycle strategy', 'CRM design', 'Segmentation', 'Journey mapping', 'Retention', 'Sales operations', 'Multi-market rollout'] },
  { name: 'AI & automation', items: ['n8n', 'Claude Code', 'OpenAI API', 'Prompt design', 'Content generation', 'Reply classification', 'Workflow orchestration'] },
  { name: 'Data & experimentation', items: ['A/B testing', 'Funnels', 'Cohorts', 'CLTV', 'Churn risk', 'KPI frameworks', 'Tableau'] },
  { name: 'Build stack', items: ['Supabase', 'React + TS', 'Apify', 'CleverTap', 'Braze', 'Slack workflows', 'Webhooks'] },
];

const skillGroupsTh = [
  { name: 'ระบบการเติบโต', items: ['กลยุทธ์ Lifecycle', 'ออกแบบ CRM', 'Segmentation', 'Journey mapping', 'Retention', 'Sales operations', 'ขยายหลายตลาด'] },
  { name: 'AI และระบบอัตโนมัติ', items: ['n8n', 'Claude Code', 'OpenAI API', 'Prompt design', 'สร้างคอนเทนต์', 'จำแนกคำตอบ', 'Workflow orchestration'] },
  { name: 'ข้อมูลและการทดลอง', items: ['A/B testing', 'Funnels', 'Cohorts', 'CLTV', 'Churn risk', 'KPI frameworks', 'Tableau'] },
  { name: 'เครื่องมือพัฒนา', items: ['Supabase', 'React + TS', 'Apify', 'CleverTap', 'Braze', 'Slack workflows', 'Webhooks'] },
];

const Skills = () => {
  const { lang, t } = useCopy();
  const groups = lang === 'th' ? skillGroupsTh : skillGroups;
  return (
  <section className="section">
    <Reveal className="section-head" as="div">
      <div className="section-label"><span className="label-bar" /><span>{t('Skills')}</span></div>
      <h2 className="section-title">
        {lang === 'th' ? <>เครื่องมือของผม: <em>กลยุทธ์</em>, <em>AI operations</em> และ <em>การลงมือสร้าง</em></> : <>The toolkit: <em>strategy</em>, <em>AI ops</em>, and <em>building</em>.</>}
      </h2>
    </Reveal>
    <div className="skills-grid">
      {groups.map((g, i) => (
        <Reveal key={g.name} as="div" className="skill-group" delay={i * 50}>
          <div className="skill-head">
            <span className="skill-num">0{i + 1}</span>
            <span className="skill-name">{g.name}</span>
          </div>
          <div className="skill-items">
            {g.items.map(it => <span key={it} className="chip chip-sm">{it}</span>)}
          </div>
        </Reveal>
      ))}
    </div>
  </section>
  );
};

// ─────────────────────────────────────────────────────────────
// Contact
// ─────────────────────────────────────────────────────────────
const Contact = () => {
  const { lang, t } = useCopy();
  return (
  <section id="contact" className="section section-contact">
    <div className="contact-inner">
      <Reveal className="section-label" as="div">
        <span className="label-bar" />
        <span>{t('Contact')}</span>
      </Reveal>
      <Reveal as="h2" className="contact-display">
        {t('Tell me where work gets stuck.')}<br/>
        <em>{lang === 'th' ? 'ผมจะช่วยออกแบบระบบให้' : "I'll help design the system."}</em>
      </Reveal>
      <Reveal as="div" className="contact-grid" delay={100}>
        <a href="mailto:chokchai.tawanrat@gmail.com" className="contact-card">
          <div className="contact-k">{t('Email')}</div>
          <div className="contact-v">chokchai.tawanrat@gmail.com</div>
          <div className="contact-arrow">↗</div>
        </a>
        <a href="tel:+66626914625" className="contact-card">
          <div className="contact-k">{t('Phone')}</div>
          <div className="contact-v">062 691 4625</div>
          <div className="contact-arrow">↗</div>
        </a>
        <a href="https://www.linkedin.com/in/chokchai-tawanrat-4199081a9/" target="_blank" rel="noopener" className="contact-card">
          <div className="contact-k">LinkedIn</div>
          <div className="contact-v">in/chokchai-tawanrat</div>
          <div className="contact-arrow">↗</div>
        </a>
        <a href="https://github.com/chokchait" target="_blank" rel="noopener" className="contact-card">
          <div className="contact-k">GitHub</div>
          <div className="contact-v">github.com/chokchait</div>
          <div className="contact-arrow">↗</div>
        </a>
        <a href="assets/Chokchai-Tawanrat-Resume.pdf" target="_blank" rel="noopener" className="contact-card contact-card-wide">
          <div className="contact-k">{t('Résumé')}</div>
          <div className="contact-v">{t('PDF · updated Jul 2026')}</div>
          <div className="contact-arrow">↓</div>
        </a>
      </Reveal>
    </div>
    <footer className="footer">
      <span>© 2026 Jab Tawanrat</span>
      <span>{t('Designed & built · Bangkok')}</span>
    </footer>
  </section>
  );
};

// ─────────────────────────────────────────────────────────────
// Page views
// ─────────────────────────────────────────────────────────────
const HomeWorkPreview = () => {
  const { lang, t } = useCopy();
  return (
  <section className="section home-work">
    <Reveal className="section-head home-work-head" as="div">
      <div>
        <div className="section-label"><span className="label-bar" /><span>{t('Selected systems')}</span></div>
        <h2 className="section-title">{t('Not concepts. Systems teams use every day.')}</h2>
      </div>
      <a href="#/work" className="text-link">{t('View the full work archive')} <span>↗</span></a>
    </Reveal>

    <div className="home-work-grid">
      {projects.map((baseProject, i) => {
        const p = lang === 'th' ? { ...baseProject, ...baseProject.th } : baseProject;
        return (
        <Reveal key={p.id} as="article" className="home-work-card" delay={i * 70}>
          <div className="home-work-top">
            <span>{p.num}</span>
            <span>{p.year}</span>
          </div>
          <h3>{p.title}</h3>
          <p>{p.subtitle}</p>
          <dl>
            {p.outcomes.slice(0, 2).flatMap(([k, v]) => [
              <dt key={`${p.id}-${k}-k`}>{k}</dt>,
              <dd key={`${p.id}-${k}-v`}>{v}</dd>,
            ])}
          </dl>
          <div className="home-work-tags">
            {p.tags.slice(0, 3).map(t => <span key={t}>{t}</span>)}
          </div>
        </Reveal>
        );
      })}
    </div>
  </section>
  );
};

const WorkPortfolioMap = () => {
  const { lang, t } = useCopy();
  const nodes = lang === 'th' ? [
    ['01', 'ระบบรายได้', 'ลีด → สัญญา'],
    ['02', 'Lifecycle & CRM', 'Segment → ส่ง'],
    ['03', 'ผลิตภัณฑ์ภายใน', 'ปัญหา → เครื่องมือ'],
    ['04', 'งานลูกค้า', 'Brief → ส่งมอบ'],
  ] : [
    ['01', 'Revenue systems', 'Lead → contract'],
    ['02', 'Lifecycle & CRM', 'Segment → send'],
    ['03', 'Internal products', 'Friction → tool'],
    ['04', 'Client builds', 'Brief → delivery'],
  ];
  return (
    <aside className="intro-graphic work-map" aria-label={lang === 'th' ? 'แผนที่กลุ่มผลงาน' : 'Portfolio systems map'}>
      <div className="intro-graphic-meta"><span>{t('System map')}</span><span>2024—26</span></div>
      <div className="work-map-canvas">
        <div className="work-map-track" aria-hidden="true" />
        {nodes.map(([num, title, flow]) => (
          <div className="work-map-node" key={num}>
            <span>{num}</span>
            <strong>{title}</strong>
            <small>{flow}</small>
          </div>
        ))}
      </div>
      <div className="intro-graphic-foot">
        <span><strong>7</strong> {lang === 'th' ? 'ผลงานที่เลือก' : 'selected builds'}</span>
        <span><strong>6</strong> {lang === 'th' ? 'ตลาด' : 'markets'}</span>
        <span><strong>100+</strong> {lang === 'th' ? 'ผู้ใช้' : 'users'}</span>
      </div>
    </aside>
  );
};

const OperatorMatrix = () => {
  const { lang, t } = useCopy();
  return (
  <aside className="intro-graphic operator-matrix" aria-label={lang === 'th' ? 'แผนที่บทบาทนักวางระบบและนักสร้างของ Jab' : "Jab's operator and builder capability map"}>
    <div className="intro-graphic-meta"><span>{t('Role map')}</span><span>{t('Business × delivery')}</span></div>
    <div className="operator-matrix-canvas">
      <span className="matrix-axis matrix-axis-top">{t('Decide')}</span>
      <span className="matrix-axis matrix-axis-bottom">{t('Deliver')}</span>
      <span className="matrix-axis matrix-axis-left">{t('Business')}</span>
      <span className="matrix-axis matrix-axis-right">{t('Technology')}</span>
      <div className="matrix-cell"><strong>Growth</strong><small>{t('Direction')}</small></div>
      <div className="matrix-cell"><strong>CRM</strong><small>{t('Journeys')}</small></div>
      <div className="matrix-cell"><strong>{t('Product ops')}</strong><small>{t('Adoption')}</small></div>
      <div className="matrix-cell"><strong>{t('Automation')}</strong><small>{t('Deliver')}</small></div>
      <div className="matrix-core"><span>Jab</span><strong>{lang === 'th' ? <>นักวางระบบ<br/>+ นักสร้าง</> : <>Operator<br/>+ Builder</>}</strong></div>
    </div>
    <p>{t('From the business question to the working system — without the handoff gap.')}</p>
  </aside>
  );
};

const PageIntro = ({ eyebrow, title, body, index, visual }) => (
  <header id="top" className={cx('page-intro', visual && 'page-intro-with-visual')}>
    <div className="page-intro-index">{index}</div>
    <div className="page-intro-copy">
      <div className="section-label"><span className="label-bar" /><span>{eyebrow}</span></div>
      <h1>{title}</h1>
      <p>{body}</p>
    </div>
    {visual === 'work' && <WorkPortfolioMap />}
    {visual === 'about' && <OperatorMatrix />}
  </header>
);

const getRoute = () => {
  const route = window.location.hash.replace(/^#\/?/, '').split('/')[0];
  return route === 'work' || route === 'about' ? route : 'home';
};

const useRoute = () => {
  const [route, setRoute] = useState(getRoute);
  useEffect(() => {
    const onHashChange = () => setRoute(getRoute());
    window.addEventListener('hashchange', onHashChange);
    return () => window.removeEventListener('hashchange', onHashChange);
  }, []);
  useEffect(() => {
    window.scrollTo({ top: 0, behavior: 'auto' });
  }, [route]);
  return route;
};

// ─────────────────────────────────────────────────────────────
// Tweaks — palettes + fonts
// ─────────────────────────────────────────────────────────────
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": "editorial-earth",
  "fontPair": "geist-newsreader",
  "showMarquee": true
}/*EDITMODE-END*/;

const PALETTES = {
  'editorial-earth': {
    '--bg': '#ede9de',
    '--bg-2': '#e2ddcf',
    '--surface': '#f7f3e9',
    '--ink': '#1d251b',
    '--ink-2': '#46513f',
    '--ink-3': '#7d846f',
    '--rule': '#d0cabb',
    '--accent': '#6b7f45',
    '--accent-ink': '#fbf9f0',
    '--forest': '#293a25',
    '--forest-2': '#394c2e',
    '--moss': '#acb795',
  },
  'studio-olive': {
    '--bg': '#e7ebe4',
    '--bg-2': '#dce2d8',
    '--surface': '#f4f6f1',
    '--ink': '#0d1408',
    '--ink-2': '#3e4938',
    '--ink-3': '#727c6d',
    '--rule': '#c4cdc0',
    '--accent': '#668c2c',
    '--accent-ink': '#f8faF5',
    '--forest': '#263b1c',
    '--forest-2': '#354d1a',
    '--moss': '#aab59f',
  },
  'cream-coral': {
    '--bg': 'oklch(97% 0.012 75)',
    '--bg-2': 'oklch(94% 0.018 72)',
    '--surface': 'oklch(99% 0.006 80)',
    '--ink': 'oklch(20% 0.018 50)',
    '--ink-2': 'oklch(40% 0.018 50)',
    '--ink-3': 'oklch(60% 0.012 60)',
    '--rule': 'oklch(86% 0.015 70)',
    '--accent': 'oklch(60% 0.16 32)',
    '--accent-ink': 'oklch(99% 0 0)',
  },
  'paper-ink': {
    '--bg': 'oklch(98% 0.004 90)',
    '--bg-2': 'oklch(95% 0.006 90)',
    '--surface': 'oklch(99.5% 0.002 90)',
    '--ink': 'oklch(15% 0.01 270)',
    '--ink-2': 'oklch(38% 0.01 270)',
    '--ink-3': 'oklch(60% 0.008 270)',
    '--rule': 'oklch(87% 0.005 270)',
    '--accent': 'oklch(45% 0.18 260)',
    '--accent-ink': 'oklch(99% 0 0)',
  },
  'sage-forest': {
    '--bg': 'oklch(96% 0.012 130)',
    '--bg-2': 'oklch(93% 0.018 130)',
    '--surface': 'oklch(99% 0.006 130)',
    '--ink': 'oklch(18% 0.02 150)',
    '--ink-2': 'oklch(38% 0.02 150)',
    '--ink-3': 'oklch(58% 0.015 145)',
    '--rule': 'oklch(85% 0.018 140)',
    '--accent': 'oklch(48% 0.13 155)',
    '--accent-ink': 'oklch(98% 0 0)',
  },
  'noir-amber': {
    '--bg': 'oklch(15% 0.012 60)',
    '--bg-2': 'oklch(20% 0.014 60)',
    '--surface': 'oklch(20% 0.012 60)',
    '--ink': 'oklch(95% 0.008 70)',
    '--ink-2': 'oklch(78% 0.008 70)',
    '--ink-3': 'oklch(58% 0.008 70)',
    '--rule': 'oklch(30% 0.012 60)',
    '--accent': 'oklch(78% 0.16 75)',
    '--accent-ink': 'oklch(18% 0.012 60)',
  },
};

const FONT_PAIRS = {
  'geist-newsreader': {
    '--font-display': '"Geist", "Inter", system-ui, sans-serif',
    '--font-body': '"Geist", "Inter", system-ui, sans-serif',
    '--font-mono': '"Geist Mono", ui-monospace, monospace',
    '--font-accent': '"Newsreader", Georgia, serif',
  },
  'newsreader-geist': {
    '--font-display': '"Newsreader", Georgia, serif',
    '--font-body': '"Geist", "Inter", system-ui, sans-serif',
    '--font-mono': '"Geist Mono", ui-monospace, monospace',
    '--font-accent': '"Newsreader", Georgia, serif',
  },
  'instrument-geist': {
    '--font-display': '"Instrument Serif", Georgia, serif',
    '--font-body': '"Geist", "Inter", system-ui, sans-serif',
    '--font-mono': '"Geist Mono", ui-monospace, monospace',
    '--font-accent': '"Instrument Serif", Georgia, serif',
  },
  'all-geist': {
    '--font-display': '"Geist", system-ui, sans-serif',
    '--font-body': '"Geist", system-ui, sans-serif',
    '--font-mono': '"Geist Mono", ui-monospace, monospace',
    '--font-accent': '"Newsreader", Georgia, serif',
  },
  'all-mono': {
    '--font-display': '"Geist Mono", ui-monospace, monospace',
    '--font-body': '"Geist Mono", ui-monospace, monospace',
    '--font-mono': '"Geist Mono", ui-monospace, monospace',
    '--font-accent': '"Newsreader", Georgia, serif',
  },
};

const applyTokens = (paletteKey, fontKey) => {
  const root = document.documentElement;
  const palette = PALETTES[paletteKey] || PALETTES['editorial-earth'];
  const font = FONT_PAIRS[fontKey] || FONT_PAIRS['geist-newsreader'];
  Object.entries(palette).forEach(([k, v]) => root.style.setProperty(k, v));
  Object.entries(font).forEach(([k, v]) => root.style.setProperty(k, v));
  root.setAttribute('data-mode', paletteKey === 'noir-amber' ? 'dark' : 'light');
};

// ─────────────────────────────────────────────────────────────
// App
// ─────────────────────────────────────────────────────────────
const App = () => {
  const route = useRoute();
  const [lang, setLang] = useState(() => {
    try {
      return window.localStorage.getItem('jab-portfolio-language') === 'th' ? 'th' : 'en';
    } catch (error) {
      return 'en';
    }
  });
  const [t, setTweak] = window.useTweaks ? window.useTweaks(TWEAK_DEFAULTS) : [TWEAK_DEFAULTS, () => {}];

  useEffect(() => { applyTokens(t.palette, t.fontPair); }, [t.palette, t.fontPair]);
  useEffect(() => {
    document.documentElement.lang = lang;
    const titles = lang === 'th' ? {
      home: 'Jab Tawanrat — ที่ปรึกษาด้านระบบการเติบโต',
      work: 'ผลงาน — Jab Tawanrat',
      about: 'เกี่ยวกับ — Jab Tawanrat',
    } : {
      home: 'Jab Tawanrat — Growth Systems Consultant',
      work: 'Selected Work — Jab Tawanrat',
      about: 'About — Jab Tawanrat',
    };
    document.title = titles[route];
    const description = document.querySelector('meta[name="description"]');
    if (description) {
      description.setAttribute(
        'content',
        lang === 'th'
          ? 'Jab Tawanrat ออกแบบและสร้างระบบ CRM, lifecycle, sales operations, AI automation และผลิตภัณฑ์ดิจิทัลสำหรับทีมที่กำลังเติบโต'
          : 'Jab Tawanrat designs and builds practical CRM, lifecycle, sales operations, AI automation, and digital products for growing teams.'
      );
    }
    try {
      window.localStorage.setItem('jab-portfolio-language', lang);
    } catch (error) {
      // The language still works when storage is unavailable.
    }
  }, [lang, route]);

  return (
    <LocaleContext.Provider value={{ lang }}>
    <div style={{ display: 'contents' }} className={lang === 'th' ? 'locale-th' : 'locale-en'}>
      <Nav route={route} onLanguageChange={setLang} />
      <main id="main-content" className={`route-view route-${route}`}>
        {route === 'home' && (
          <>
            <Hero />
            <Now />
            <SystemLoop />
            <HomeWorkPreview />
            <IndependentBuilds compact />
            <Services />
          </>
        )}
        {route === 'work' && (
          <>
            <PageIntro
              index="01"
              eyebrow={lang === 'th' ? 'ผลงานที่เลือก' : 'Selected work'}
              title={lang === 'th' ? 'ระบบที่เริ่มจากปัญหาในการทำงานจริง' : 'Systems built around real operational friction.'}
              body={lang === 'th' ? '3 ระบบหลักที่สร้างผลลัพธ์ระดับองค์กร และ 4 ผลิตภัณฑ์หรืองานลูกค้าที่แสดงความสามารถตั้งแต่หาโจทย์ ออกแบบ ไปจนถึงส่งมอบ' : 'Three core systems with measurable operating impact, plus four product and client builds that show the path from problem definition to delivery.'}
              visual="work"
            />
            <Work />
            <IndependentBuilds />
          </>
        )}
        {route === 'about' && (
          <>
            <PageIntro
              index="02"
              eyebrow={lang === 'th' ? 'เกี่ยวกับ' : 'About'}
              title={lang === 'th' ? 'นักวางระบบการเติบโตที่ลงมือสร้างเอง' : 'A growth operator who builds.'}
              body={lang === 'th' ? 'ประสบการณ์ 7 ปีด้าน CRM, lifecycle, product operations และ automation ผมเชื่อมกลยุทธ์ธุรกิจกับการลงมือสร้าง เพื่อเปลี่ยนปัญหาในการทำงานให้เป็นระบบที่ทีมดูแลต่อเองได้' : 'Seven years across CRM, lifecycle, product operations, and automation. I work between business strategy and implementation — turning operational friction into systems teams can actually own.'}
              visual="about"
            />
            <How />
            <Experience />
            <Skills />
          </>
        )}
      </main>
      <Contact />

      {window.TweaksPanel && (
        <window.TweaksPanel>
          <window.TweakSection label="Palette" />
          <window.TweakRadio
            label="Tone"
            value={t.palette}
            onChange={(v) => setTweak('palette', v)}
            options={[
              { value: 'editorial-earth', label: 'Editorial · earth' },
              { value: 'studio-olive', label: 'Studio · olive' },
              { value: 'cream-coral', label: 'Cream · coral' },
              { value: 'paper-ink', label: 'Paper · ink' },
              { value: 'sage-forest', label: 'Sage · forest' },
              { value: 'noir-amber', label: 'Noir · amber' },
            ]}
          />
          <window.TweakSection label="Typography" />
          <window.TweakRadio
            label="Font pair"
            value={t.fontPair}
            onChange={(v) => setTweak('fontPair', v)}
            options={[
              { value: 'geist-newsreader', label: 'Geist · Newsreader' },
              { value: 'newsreader-geist', label: 'Newsreader · Geist' },
              { value: 'instrument-geist', label: 'Instrument · Geist' },
              { value: 'all-geist', label: 'All Geist (sans)' },
              { value: 'all-mono', label: 'All mono' },
            ]}
          />
          <window.TweakSection label="Display" />
          <window.TweakToggle
            label="Marquee strip"
            value={t.showMarquee}
            onChange={(v) => setTweak('showMarquee', v)}
          />
        </window.TweaksPanel>
      )}
      <style>{`.marquee { display: ${t.showMarquee ? 'block' : 'none'}; }`}</style>
    </div>
    </LocaleContext.Provider>
  );
};

window.PortfolioApp = App;
