// Kahla Labs — Homepage React shell

const { useState, useEffect, useRef } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "gold",
  "density": "airy",
  "headlineVariant": "bookings",
  "compassStyle": "full"
}/*EDITMODE-END*/;

const HEADLINES = {
  bookings: {
    line1: 'Websites, booking systems, and AI receptionists',
    line2: 'for businesses that can’t miss a lead.',
    lede: 'Kahla Labs builds lean digital operating systems for service businesses — so calls get answered, appointments get booked, and follow-up happens before leads go cold.'
  },
  opportune: {
    line1: 'The opportune',
    line2: 'moment, engineered.',
    lede: 'Service businesses on Kahla-managed infrastructure book 3× more calls and recover 70% of leaked leads. We host and operate the whole stack — you stop touching it. SOW after a free Systems Audit.'
  },
  compound: {
    line1: 'Systems that compound.',
    line2: 'Campaigns that don’t.',
    lede: 'Booking engine, AI concierge, SEO pipeline — built once, operated forever by us. You get an embedded team, not a deliverable. Free Systems Audit.'
  }
};

const HERO_TAGLINE = 'The opportune moment, engineered.';

// Pinned scrollytelling steps — each maps to a node in <SystemDiagram focus={n} />.
const SYS_STEPS = [
  { num: '01', title: 'Booking that never sleeps',
    body: 'Self-serve scheduling synced to your calendar. Customers pick a slot, get a reminder, and leave a deposit — no phone tag, no double-bookings, no half-empty week.' },
  { num: '02', title: 'An AI receptionist on every channel',
    body: 'Chat and voice agents answer in seconds, qualify the lead, and drop it straight onto the calendar. After hours, mid-job, weekends — nothing goes to voicemail.' },
  { num: '03', title: 'SEO that compounds',
    body: 'A local-SEO pipeline that keeps you ranking for the searches buyers actually type, so new demand shows up month over month without paying for every click.' }
];

// Local placeholder until a real number is connected.
// IANA-reserved fictional range (555-0100..0199). Search for KAHLA_PHONE to replace.
const KAHLA_PHONE = '(626) 555-0118';
const KAHLA_PHONE_TEL = '+16265550118';

const PROBLEMS = [
  { num: '·01', title: 'Calls go to voicemail',
    body: 'Every missed ring is a lead a competitor catches first. After hours, weekends, mid-job — the phone keeps ringing whether you can answer or not.' },
  { num: '·02', title: 'Follow-up is days late',
    body: 'A quote not sent the same day is a quote that loses. Manual follow-up gets crowded out by everything else the operator is doing.' },
  { num: '·03', title: 'Booking is a back-and-forth mess',
    body: 'Three SMS threads, two phone calls, a confused customer and a half-empty calendar. Self-serve booking with reminders and deposits ends this.' },
  { num: '·04', title: 'No one finds you on Google',
    body: 'A site that doesn’t rank for "<service> near me" is invisible to the half of buyers who never call until they’ve typed those words.' }
];

const PACKAGES = [
  { name: 'Launch', sub: 'New site + booking',
    outcome: 'A site that books appointments while you sleep.',
    items: [
      'Custom-designed marketing site (5–7 pages)',
      'Self-serve booking + calendar sync',
      'Mobile + speed optimized',
      'On-page local SEO',
      'Google Business Profile setup'
    ] },
  { name: 'Automate', sub: 'Add the AI receptionist', featured: true,
    outcome: 'Every inbound captured, qualified, and routed — 24/7.',
    items: [
      'Everything in Launch',
      'AI chat concierge trained on your business',
      'AI voice receptionist for after-hours calls',
      'SMS reminders + deposit collection',
      'Lead capture + auto follow-up sequences',
      'Monthly performance dashboard'
    ] },
  { name: 'Scale', sub: 'Multi-location + custom AI',
    outcome: 'A digital operating system across every location and service line.',
    items: [
      'Everything in Automate',
      'Multi-location SEO + Google Business Profiles',
      'Custom AI workflows for ops + sales',
      'Lead nurture + reactivation automation',
      'Quarterly re-architect on the system',
      'Embedded engineer on a private channel'
    ] }
];

function App() {
  const [tweaks, setTweaks] = useState(TWEAK_DEFAULTS);
  const [activeSection, setActiveSection] = useState('hero');
  const [mobileNavOpen, setMobileNavOpen] = useState(false);
  const [cms, setCms] = useState(null);
  const [sysStep, setSysStep] = useState(0);
  const heroCenterRef = useRef(null);
  const sysScrollRef = useRef(null);

  // Hero email capture → start the lead funnel with the address prefilled.
  const onHeroSubmit = (e) => {
    e.preventDefault();
    const email = (new FormData(e.currentTarget).get('email') || '').toString().trim();
    window.location.href = email ? `contact.html?email=${encodeURIComponent(email)}` : 'contact.html';
  };

  // Pull homepage content from Sanity if a project is configured (kahla/cms-config.js).
  // Fallback-first: until then, or on any failure, the hardcoded constants below render.
  useEffect(() => {
    if (!window.KahlaCMS || !window.KahlaCMS.configured) return;
    const groq = `*[_type == "homepage"][0]{
      hero{ line1, line2, lede, tagline },
      problems[]{ num, title, body },
      packages[]{ name, sub, outcome, featured, items },
      process[]{ title, desc },
      faqs[]{ "q": question, "a": answer }
    }`;
    window.KahlaCMS.query(groq).then((doc) => { if (doc) setCms(doc); }).catch(() => {});
  }, []);

  // Admin postMessage protocol:
  //   parent → iframe : { type: '__set_tweak', key, value }     (single update)
  //   parent → iframe : { type: '__set_tweaks', edits: {...} }  (bulk)
  //   iframe → parent : { type: '__edit_mode_available', tweaks } (handshake on mount)
  // /admin.html drives this; the consumer site never sees a UI for tweaks.
  useEffect(() => {
    const onMsg = (e) => {
      if (!e.data || typeof e.data !== 'object') return;
      if (e.data.type === '__set_tweak' && typeof e.data.key === 'string') {
        setTweaks((t) => ({ ...t, [e.data.key]: e.data.value }));
      }
      if (e.data.type === '__set_tweaks' && e.data.edits && typeof e.data.edits === 'object') {
        setTweaks((t) => ({ ...t, ...e.data.edits }));
      }
    };
    window.addEventListener('message', onMsg);
    if (window.parent && window.parent !== window) {
      window.parent.postMessage({ type: '__edit_mode_available', tweaks }, '*');
    }
    return () => window.removeEventListener('message', onMsg);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Scroll reveal
  useEffect(() => {
    const obs = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) e.target.classList.add('is-visible');
      });
    }, { threshold: 0.12 });
    document.querySelectorAll('[data-reveal]').forEach((el) => obs.observe(el));
    return () => obs.disconnect();
  }, []);

  // Hero parallax + cinematic fade-on-scroll (skips entirely under reduced-motion).
  useEffect(() => {
    if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
    const layers = Array.from(document.querySelectorAll('[data-parallax]'));
    const center = heroCenterRef.current;
    let raf = 0;
    const apply = () => {
      raf = 0;
      const y = window.scrollY || 0;
      const vh = window.innerHeight || 800;
      layers.forEach((el) => {
        const rate = el.getAttribute('data-parallax') === 'mid' ? 0.32 : 0.16;
        el.style.setProperty('--py', `${y * rate}px`);
      });
      if (center) {
        const p = Math.min(1, y / (vh * 0.85));
        center.style.opacity = String(1 - p);
        center.style.transform = `translateY(${y * 0.12}px)`;
      }
    };
    const onScroll = () => { if (!raf) raf = requestAnimationFrame(apply); };
    window.addEventListener('scroll', onScroll, { passive: true });
    apply();
    return () => { window.removeEventListener('scroll', onScroll); if (raf) cancelAnimationFrame(raf); };
  }, []);

  // Pinned systems scrollytelling — derive the active step from scroll progress
  // through the tall container. Desktop only; on mobile every step shows at once.
  useEffect(() => {
    const el = sysScrollRef.current;
    if (!el) return;
    let raf = 0;
    const compute = () => {
      raf = 0;
      if (window.innerWidth < 901) { setSysStep((s) => (s === 0 ? s : 0)); return; }
      const vh = window.innerHeight || 800;
      const total = el.offsetHeight - vh;
      const scrolled = Math.min(Math.max(-el.getBoundingClientRect().top, 0), Math.max(total, 1));
      const p = total > 0 ? scrolled / total : 0;
      const step = Math.min(SYS_STEPS.length - 1, Math.floor(p * SYS_STEPS.length));
      setSysStep((s) => (s === step ? s : step));
    };
    const onScroll = () => { if (!raf) raf = requestAnimationFrame(compute); };
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    compute();
    return () => { window.removeEventListener('scroll', onScroll); window.removeEventListener('resize', onScroll); if (raf) cancelAnimationFrame(raf); };
  }, []);

  // Scrollspy
  useEffect(() => {
    const sections = ['hero','problem','systems','services','work','pricing','contact'];
    const obs = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) setActiveSection(e.target.id);
      });
    }, { threshold: 0.45 });
    sections.forEach((id) => {
      const el = document.getElementById(id);
      if (el) obs.observe(el);
    });
    return () => obs.disconnect();
  }, []);

  // CMS-or-fallback resolution. Each value prefers Sanity content when present,
  // otherwise the hardcoded constant renders — so the page is identical with or
  // without a configured project.
  const base = HEADLINES[tweaks.headlineVariant] || HEADLINES.bookings;
  const h = cms && cms.hero && cms.hero.line1 ? cms.hero : base;
  const heroTagline = (cms && cms.hero && cms.hero.tagline) || HERO_TAGLINE;
  const problems = cms && cms.problems && cms.problems.length ? cms.problems : PROBLEMS;
  const packages = cms && cms.packages && cms.packages.length ? cms.packages : PACKAGES;
  const process = cms && cms.process && cms.process.length ? cms.process : PROCESS;
  const faqs = cms && cms.faqs && cms.faqs.length ? cms.faqs : FAQS;
  const accentVar = tweaks.accent === 'terra' ? '#9B4E30' : '#C9A34F';
  const densityPad = tweaks.density === 'tight' ? '96px 0' : '128px 0';

  return (
    <div style={{ '--k-gold': accentVar }}>
      {/* Atmospheric orbs */}
      <div className="k-atmos k-atmos-gold" />
      <div className="k-atmos k-atmos-terra" />

      <Nav active={activeSection} mobileOpen={mobileNavOpen} setMobileOpen={setMobileNavOpen} />
      <Scrollspy active={activeSection} />

      {/* ── HERO ──────────────────────────────────────────────── */}
      <section id="hero" className="hero" data-screen-label="Home / Hero">
        {/* Cinematic atmosphere — dawn light over the void, compass rising on the horizon */}
        <div className="hero-atmos" aria-hidden="true">
          <div className="hero-sky" data-parallax="slow" />
          <div className="hero-sun" data-parallax="mid">
            <CompassMark size={520} animate />
          </div>
          <div className="hero-horizon" />
          <div className="hero-floor" />
          <div className="hero-grain" />
        </div>

        <div className="hero-center" ref={heroCenterRef}>
          <div className="hero-eyebrow" data-reveal>
            <span className="hero-eyebrow-dot" />
            Built for service businesses that can’t afford to miss a lead
          </div>
          <h1 className="k-hero hero-title" data-reveal data-reveal-delay="1">
            <span className="hero-title-line">{h.line1}</span>
            <span className="hero-title-line k-hero--italic">{h.line2}</span>
          </h1>
          <p className="hero-sub" data-reveal data-reveal-delay="2">{h.lede}</p>
          <p className="hero-tagline" data-reveal data-reveal-delay="2">{heroTagline}</p>

          <form className="hero-capture" data-reveal data-reveal-delay="3" onSubmit={onHeroSubmit}>
            <input
              type="email"
              name="email"
              className="hero-capture-input"
              placeholder="Enter your email"
              aria-label="Your email"
              autoComplete="email"
            />
            <button type="submit" className="k-btn k-btn--primary hero-capture-btn">
              Book a free Systems Audit <Arrow />
            </button>
          </form>
          <div className="hero-capture-alt" data-reveal data-reveal-delay="3">
            <span className="hero-capture-note">
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none"><path d="M5 12l5 5 9-11" stroke="currentColor" strokeWidth="1.8" strokeLinecap="square"/></svg>
              Free 30-min Audit · Leak Map in 24 hours · no obligation
            </span>
            <a href={`tel:${KAHLA_PHONE_TEL}`} className="hero-capture-call" data-phone-placeholder>
              <PhoneIcon /> or call {KAHLA_PHONE}
            </a>
          </div>

          <div className="hero-meta" data-reveal data-reveal-delay="4">
            <div className="hero-meta-item">
              <div className="hero-meta-num">3.2<span style={{fontSize:'20px',color:'var(--k-muted)'}}>×</span></div>
              <span className="hero-meta-label">Avg booking lift</span>
            </div>
            <div className="hero-meta-item">
              <div className="hero-meta-num">12<span style={{fontSize:'18px',color:'var(--k-muted)'}}>h</span></div>
              <span className="hero-meta-label">Saved/wk per client</span>
            </div>
            <div className="hero-meta-item">
              <div className="hero-meta-num">12<span style={{fontSize:'18px',color:'var(--k-muted)'}}>mo</span></div>
              <span className="hero-meta-label">Min engagement</span>
            </div>
          </div>
        </div>

        <a href="#problem" className="hero-scroll-cue" aria-label="Scroll to see where leads leak">
          <span>Where it leaks</span>
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none"><path d="M7 10l5 5 5-5" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round"/></svg>
        </a>
      </section>

      {/* ── TRUST STRIP ──────────────────────────────────────── */}
      <section className="trust-strip" data-screen-label="Home / Trust">
        <div className="k-container trust-inner">
          <div className="trust-label">Selected work</div>
          <div className="trust-logos">
            <div className="trust-logo"><span className="trust-mark">◐</span> Measure Joy</div>
            <div className="trust-stat">
              <strong>0%</strong>
              <span>marketplace commission after migrating Measure Joy off Shopify + BigCommerce</span>
            </div>
          </div>
        </div>
      </section>

      {/* ── PROBLEM — "Where it leaks" ────────────────────────── */}
      <section id="problem" className="k-section problem-section" data-screen-label="Home / Problem">
        <div className="k-container">
          <div className="sec-head">
            <div data-reveal>
              <div className="sec-head-num">I · Where it leaks</div>
              <h2 className="sec-head-title">
                The four things <em>bleeding leads</em> from a service business right now.
              </h2>
            </div>
            <p className="sec-head-lede" data-reveal data-reveal-delay="1">
              You already know the symptoms. The point of the audit is naming them in order of cost — and pointing at the system that closes each one.
            </p>
          </div>
          <div className="problems-grid">
            {problems.map((p, i) => (
              <div key={p.num} className="problem-card" data-reveal data-reveal-delay={(i%4)+1}>
                <div className="problem-num">{p.num}</div>
                <h3 className="problem-title">{p.title}</h3>
                <p className="problem-body">{p.body}</p>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* ── LIVE SYSTEMS ──────────────────────────────────────── */}
      <section data-screen-label="Home / Systems">
        <div className="systems-scroll" ref={sysScrollRef}>
          <div className="systems-pin" id="systems">
            <div className="systems-steps">
              <div className="sec-head-num">II · The system</div>
              <h2 className="sec-head-title">
                Built like a system, <em>not a stack of tools.</em>
              </h2>
              <p className="systems-intro">
                Your booking engine talks to your AI receptionist talks to your SEO pipeline.
                Every enquiry is captured, qualified, booked, and indexed. Nothing falls through.
              </p>
              <div className="systems-step-list">
                {SYS_STEPS.map((s, i) => (
                  <div
                    key={s.num}
                    className={`systems-step ${i === sysStep ? 'is-active' : ''}`}
                  >
                    <div className="systems-step-num">{s.num}</div>
                    <h3 className="systems-step-title">{s.title}</h3>
                    <p className="systems-step-body">{s.body}</p>
                  </div>
                ))}
              </div>
            </div>
            <div className="systems-stage">
              <SystemDiagram focus={sysStep} />
            </div>
          </div>
        </div>
      </section>

      {/* ── SERVICES ──────────────────────────────────────────── */}
      <section id="services" className="k-section" data-screen-label="Home / Services">
        <div className="k-container">
          <div className="sec-head">
            <div data-reveal>
              <div className="sec-head-num">III · What we build</div>
              <h2 className="sec-head-title">
                Four surfaces. <em>One operating system.</em>
              </h2>
            </div>
            <p className="sec-head-lede" data-reveal data-reveal-delay="1">
              Every Kahla build ships with these pieces. Choose the mix.
              Every piece is engineered to talk to the others.
            </p>
          </div>

          <div className="services-grid">
            {SERVICES.map((s, i) => (
              <a key={s.slug} href={s.href} className="service-card" data-reveal data-reveal-delay={(i%4)+1}>
                <div className="service-idx">{String(i+1).padStart(2,'0')}</div>
                <h3 className="service-title">{s.title}</h3>
                <p className="service-desc">{s.desc}</p>
                <div className="service-stack">
                  {s.stack.map((t) => <span key={t} className="service-tag">{t}</span>)}
                </div>
                <span className="service-arrow"><Arrow size={20} /></span>
              </a>
            ))}
          </div>
        </div>
      </section>

      {/* ── CASE STUDY ────────────────────────────────────────── */}
      <section id="work" className="k-section" data-screen-label="Home / Work">
        <div className="k-container">
          <div className="sec-head">
            <div data-reveal>
              <div className="sec-head-num">IV · Selected work</div>
              <h2 className="sec-head-title">
                The first case <em>compounds.</em>
              </h2>
            </div>
            <p className="sec-head-lede" data-reveal data-reveal-delay="1">
              Measure Joy — restored Y2K-era digital cameras. We moved Christian off Shopify and
              BigCommerce onto a storefront he owns, with payments on his own Stripe account, so the
              margin and the customer stay his.
            </p>
          </div>

          <div className="casestudy" data-reveal>
            <div className="cs-copy">
              <div className="k-caption">Client · Measure Joy</div>
              <h3 className="cs-title">
                Off the marketplaces, <span className="cs-italic">onto his own storefront.</span>
              </h3>
              <p className="k-body-muted">
                Christian sells restored, tested Y2K digital cameras — and was handing a cut of every
                sale to Shopify and BigCommerce. We migrated Measure Joy onto an independent storefront
                with checkout on his own Stripe account and BNPL built in. No marketplace commission,
                no platform holding his payouts.
              </p>
              <div className="cs-stats">
                <div>
                  <div className="cs-stat-num">0%</div>
                  <span className="cs-stat-label">Marketplace commission</span>
                </div>
                <div>
                  <div className="cs-stat-num">100%</div>
                  <span className="cs-stat-label">Owned sales channel</span>
                </div>
                <div>
                  <div className="cs-stat-num">Own</div>
                  <span className="cs-stat-label">Stripe account · BNPL</span>
                </div>
              </div>
              <div style={{ marginTop: 'var(--k-8)' }}>
                <a href="case-study-measurejoy.html" className="k-btn k-btn--ghost">
                  Read the full case <Arrow />
                </a>
              </div>
            </div>

            <div className="cs-visual">
              <div className="cs-visual-inner">
                <div className="cs-visual-brand">Measure Joy</div>
                <div className="cs-visual-placeholder">[ owned storefront · reviving Y2K tech ]</div>
              </div>
            </div>
          </div>

          <div className="testimonial" data-reveal>
            <div className="testimonial-quote-mark">“</div>
            <div>
              <div className="testimonial-body">
                Kahla moved my whole shop off the platforms I was renting. I own the storefront, payments
                run through my own Stripe, and I keep the margin I was handing to Shopify on every sale.
              </div>
              <div className="testimonial-attrib">
                <div className="testimonial-avatar">C</div>
                <div>
                  <div className="testimonial-name">Christian Velasquez</div>
                  <div className="testimonial-role">Founder, Measure Joy</div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </section>

      {/* ── PACKAGES ──────────────────────────────────────────── */}
      <section id="pricing" className="k-section" data-screen-label="Home / Packages">
        <div className="k-container">
          <div className="sec-head">
            <div data-reveal>
              <div className="sec-head-num">V · Three ways to engage</div>
              <h2 className="sec-head-title">
                Launch. Automate. <em>Scale.</em>
              </h2>
            </div>
            <p className="sec-head-lede" data-reveal data-reveal-delay="1">
              Three named shells, sized to where the business actually is today. Pick the one that matches the leak you want to close first. The exact dollar figure lives in a written SOW after your free Systems Audit — no two engagements are priced the same.
            </p>
          </div>

          <div className="package-grid">
            {packages.map((pkg, i) => (
              <div key={pkg.name} className={`package-card ${pkg.featured ? 'is-featured' : ''}`} data-reveal data-reveal-delay={i+1}>
                {pkg.featured && <div className="package-badge">Most chosen</div>}
                <div className="package-name">{pkg.name}</div>
                <div className="package-sub">{pkg.sub}</div>
                <p className="package-outcome">{pkg.outcome}</p>
                <ul className="package-list">
                  {pkg.items.map((it) => <li key={it}>{it}</li>)}
                </ul>
                <a href="book.html" className={`k-btn ${pkg.featured ? 'k-btn--primary' : 'k-btn--ghost'} package-cta`}>
                  Book a Systems Audit <Arrow />
                </a>
              </div>
            ))}
          </div>

          <div className="sow-footnote" data-reveal>
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
              <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" stroke="currentColor" strokeWidth="1.5"/>
              <path d="M14 2v6h6M9 13h6M9 17h4" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
            </svg>
            <span>
              <strong>Every engagement is custom-scoped.</strong> After the free Systems Audit you receive a written SOW within 24 hours — fixed scope, fixed price, every integration spelled out. Nothing is billable until you sign.
            </span>
          </div>
        </div>
      </section>

      {/* ── PROCESS ───────────────────────────────────────────── */}
      <section id="process" className="k-section" data-screen-label="Home / Process">
        <div className="k-container">
          <div className="sec-head">
            <div data-reveal>
              <div className="sec-head-num">VI · How it goes</div>
              <h2 className="sec-head-title">
                Audit. Build. Launch. <em>Optimize.</em>
              </h2>
            </div>
            <p className="sec-head-lede" data-reveal data-reveal-delay="1">
              Four movements. You always know what is happening this week and what is happening next.
            </p>
          </div>
          <div className="process-list">
            {process.map((p, i) => (
              <div key={i} className="process-step" data-reveal data-reveal-delay={(i%4)+1}>
                <div className="process-num">M.{String(i+1).padStart(2,'0')}</div>
                <h4 className="process-title">{p.title}</h4>
                <p className="process-desc">{p.desc}</p>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* ── FAQ / OBJECTION HANDLING ──────────────────────────── */}
      <section id="faq" className="k-section" data-screen-label="Home / FAQ">
        <div className="k-container">
          <div className="sec-head">
            <div data-reveal>
              <div className="sec-head-num">VII · Before you ask</div>
              <h2 className="sec-head-title">
                The four things <em>everyone asks.</em>
              </h2>
            </div>
            <p className="sec-head-lede" data-reveal data-reveal-delay="1">
              Straight answers. If you have a fifth, ask it on the free Systems Audit.
            </p>
          </div>
          <div className="faq-list">
            {faqs.map((f, i) => (
              <details key={i} className="faq-item" data-reveal data-reveal-delay={(i%4)+1}>
                <summary>
                  <span className="faq-q-num">Q.{String(i+1).padStart(2,'0')}</span>
                  <span className="faq-q-text">{f.q}</span>
                  <span className="faq-q-toggle">+</span>
                </summary>
                <div className="faq-a">{f.a}</div>
              </details>
            ))}
          </div>
        </div>
      </section>

      {/* ── CTA ──────────────────────────────────────────────── */}
      <section id="contact" className="cta-band" data-screen-label="Home / CTA">
        <div data-reveal>
          <h2 className="cta-title">
            Find the leaks. <em>Fix the system.</em>
          </h2>
          <p className="cta-sub">
            Thirty minutes on the phone or video. We send a Leak Map and, if it is a fit, a written SOW the next business day. Yours to keep whether you hire us or not.
          </p>
          <div>
            <a href="book.html" className="k-btn k-btn--primary">
              Book your free Systems Audit <Arrow />
            </a>
            <a href={`tel:${KAHLA_PHONE_TEL}`} className="k-btn k-btn--ghost" data-phone-placeholder>
              <PhoneIcon /> Call {KAHLA_PHONE}
            </a>
            <a href="voice-agent.html" className="k-btn k-btn--ghost">
              Try our AI concierge
            </a>
          </div>
          <div className="cta-coords">
            <span>Mon–Fri · 9am–6pm PT</span>
            <span>hi@kahlalabs.com</span>
            <span>Response within 24h</span>
          </div>
        </div>
      </section>

      <StickyQuoteBar />

      <Footer />
    </div>
  );
}

// ── Shared data ─────────────────────────────────────────────
const SERVICES = [
  { slug: 'booking', href: 'services-local.html', title: 'Booking engines',
    desc: 'Self-serve calendar, CRM sync, SMS reminders, deposit capture. Plugs into the calendars your team already uses. Lives inside your site, runs on our infrastructure.',
    stack: ['calendar', 'payments', 'sms', 'automation'] },
  { slug: 'ai', href: 'services-local.html', title: 'AI receptionists',
    desc: 'Always-on chat and voice that answers FAQ, qualifies leads, books appointments, and escalates to a human when it should. Trained on your business. Operated by us.',
    stack: ['chat', 'voice', 'qualification', 'escalation'] },
  { slug: 'seo', href: 'services-local.html', title: 'Local SEO pipelines',
    desc: 'Map presence, schema, monthly content programs, and review automation. Optimized for local service queries. Compounds month over month while you do the work you actually want to do.',
    stack: ['gbp', 'schema', 'content', 'reporting'] },
  { slug: 'web', href: 'services-commerce.html', title: 'Custom websites',
    desc: 'Hand-built, fast, accessible, scoped to do one job well. No template sludge. No page-builder tax. Hosted and monitored by us so it stays fast.',
    stack: ['custom', 'fast', 'monitored', 'evolving'] },
];

const FAQS = [
  { q: 'How does pricing actually work?',
    a: 'Every engagement falls into one of three named shells — Launch, Automate, or Scale — sized to where your business actually is. The exact dollar figure is custom-scoped against a written SOW after your free Systems Audit. Integrations, deliverables, and monthly operator hours are spelled out line by line before any work begins. Nothing is billable until you sign. If the SOW isn’t right, you walk — no charge for the Audit.' },
  { q: 'What does "infrastructure on us" actually mean?',
    a: 'Kahla hosts and operates the entire stack. Booking engine, AI agents, monitoring, content updates, vendor relationships — we run all of it. You get an embedded team, not a deliverable. The whole point is that you stop touching the system. Most of our clients haven’t logged into a CMS or Stripe dashboard since month two.' },
  { q: 'Who actually does the work?',
    a: 'The same senior team that scopes your build operates it after launch. No account-manager layer, no offshore handoff. We keep the engagement small enough that the people on the calls are the people writing the code, tuning the AI, and watching the dashboards. You always know who is doing what, and they always know the full shape of your business.' },
  { q: 'What if I want to leave?',
    a: 'Twelve-month minimum. After that, the engagement continues quarter to quarter — cancel anytime with 30 days notice. There’s no exit fee, but moving the infrastructure off Kahla means rebuilding the operator role on your end (hosting, monitoring, integrations, on-call). We’ll help you transition over a 90-day window if you want to. Most clients renew because the math doesn’t work to bring it in-house.' },
];

const PROCESS = [
  { title: 'Audit',    desc: 'A free 30-minute call. We map your funnel, your stack, and the places leads are leaking. You leave with a written Leak Map — yours to keep whether you hire us or not.' },
  { title: 'Build',    desc: 'Weeks 1–4 typically. We run the build against the signed SOW with async video updates every working day. Every integration is spelled out before any code is written.' },
  { title: 'Launch',   desc: 'Site goes live, monitored, and instrumented. Booking, AI agents, SEO pipeline — all running. We watch the dashboard for the first two weeks so nothing breaks unseen.' },
  { title: 'Optimize', desc: 'Monthly retainer covers operator time, content updates, monitoring, and a quarterly re-architect when the business shape changes. You stop touching infrastructure.' },
];

// ── Nav, Footer, Scrollspy ──────────────────────────────────
function Nav({ active, mobileOpen, setMobileOpen }) {
  const close = () => setMobileOpen(false);
  return (
    <nav className={`k-nav ${mobileOpen ? 'is-mobile-open' : ''}`}>
      <a href="index.html" className="k-nav-wordmark" onClick={close}>
        <CompassBug size={24} />
        <span>KAHLA</span>
      </a>
      <div className="k-nav-links">
        <a href="services-local.html" onClick={close}>Services</a>
        <a href="case-study-measurejoy.html" onClick={close}>Work</a>
        <a href="#pricing" className={active==='pricing'?'is-active':''} onClick={close}>How we price</a>
        <a href="about.html" onClick={close}>About</a>
      </div>
      <div className="k-nav-actions">
        <a href={`tel:${KAHLA_PHONE_TEL}`} className="k-nav-phone" data-phone-placeholder>
          <PhoneIcon /> {KAHLA_PHONE}
        </a>
        <a href="book.html" className="k-btn k-btn--primary k-nav-cta" style={{padding:'10px 18px',fontSize:'11px'}}>
          Free Audit
        </a>
        <button
          className="k-nav-hamburger"
          aria-label={mobileOpen ? 'Close menu' : 'Open menu'}
          aria-expanded={mobileOpen}
          onClick={() => setMobileOpen(!mobileOpen)}
        >
          <span /><span /><span />
        </button>
      </div>
    </nav>
  );
}

function StickyQuoteBar() {
  return (
    <div className="sticky-quote">
      <a href={`tel:${KAHLA_PHONE_TEL}`} className="sticky-quote-call" data-phone-placeholder>
        <PhoneIcon /> <span className="sticky-quote-call-label">Call</span>
        <span className="sticky-quote-call-num">{KAHLA_PHONE}</span>
      </a>
      <a href="book.html" className="sticky-quote-cta">
        Free Systems Audit <Arrow />
      </a>
    </div>
  );
}

function PhoneIcon() {
  return (
    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.9.34 1.77.63 2.6a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.48-1.48a2 2 0 0 1 2.11-.45c.83.29 1.7.5 2.6.63A2 2 0 0 1 22 16.92z"/>
    </svg>
  );
}

function Scrollspy({ active }) {
  const items = [
    { id: 'hero',     label: 'Top' },
    { id: 'problem',  label: 'Problem' },
    { id: 'systems',  label: 'System' },
    { id: 'services', label: 'Services' },
    { id: 'work',     label: 'Work' },
    { id: 'pricing',  label: 'Packages' },
    { id: 'contact',  label: 'Audit' },
  ];
  return (
    <div className="k-scrollnav">
      {items.map((it) => (
        <a key={it.id} href={`#${it.id}`}
           className={`k-scrollnav-tick ${active===it.id?'is-active':''}`}
           data-label={it.label} />
      ))}
    </div>
  );
}

function Footer() {
  return (
    <footer className="k-footer">
      <div className="k-container">
        <div className="k-footer-grid">
          <div className="k-footer-col">
            <div style={{display:'flex', alignItems:'center', gap:12, marginBottom:20}}>
              <CompassBug size={28} />
              <span style={{fontFamily:'var(--k-display)', letterSpacing:'0.32em', fontSize:18}}>KAHLA</span>
            </div>
            <p className="k-body-muted" style={{maxWidth:320}}>
              A digital studio for service businesses. Booking, AI chat, SEO — built, hosted, and operated by us.
            </p>
            <div className="k-footer-contact">
              <a href={`tel:${KAHLA_PHONE_TEL}`} data-phone-placeholder><PhoneIcon /> {KAHLA_PHONE}</a>
              <a href="mailto:hi@kahlalabs.com">hi@kahlalabs.com</a>
              <div className="k-footer-hours">Mon–Fri · 9am–6pm Pacific</div>
            </div>
          </div>
          <div className="k-footer-col">
            <h4>Services</h4>
            <a href="services-local.html">Local services</a>
            <a href="services-commerce.html">E-commerce</a>
            <a href="services-local.html#booking">Booking engine</a>
            <a href="services-local.html#seo">Local SEO</a>
            <a href="voice-agent.html">AI receptionist</a>
          </div>
          <div className="k-footer-col">
            <h4>Studio</h4>
            <a href="about.html">About</a>
            <a href="case-study-measurejoy.html">Case studies</a>
            <a href="#pricing">Packages</a>
            <a href="book.html">Book a Systems Audit</a>
          </div>
        </div>
        <div className="k-footer-base">
          <span>© 2026 Kahla Labs LLC · kahlalabs.com</span>
          <span className="k-footer-legal">
            <a href="privacy.html">Privacy</a>
            <a href="terms.html">Terms</a>
            <a href="accessibility.html">Accessibility</a>
          </span>
        </div>
      </div>
    </footer>
  );
}

function Arrow({ size = 14 }) {
  return (
    <svg className="arrow" width={size} height={size} viewBox="0 0 24 24" fill="none">
      <path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" strokeWidth="1.5" strokeLinecap="square" strokeLinejoin="miter" />
    </svg>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
