// Maple Pavers — DESKTOP sections, part 1: Header, Hero, Quote, Process, Services.
(function () {
  const DS = window.MaplePaversDesignSystem_8de4d8;
  const { Button, Badge, ServiceCard } = DS;
  const { Icon, Overline, Stars, PHOTO, ASSET, PHONE, startQuote } = window.MP;
  const D = window.MP.data;
  const MPD = window.MPD = window.MPD || {};

  const Container = ({ children, style }) => (
    <div className="d-wrap" style={style}>{children}</div>
  );
  MPD.Container = Container;

  function SecHead({ over, title, desc, onDark, align = 'center' }) {
    return (
      <div style={{ textAlign: align, maxWidth: desc ? 640 : 'none', margin: align === 'center' ? '0 auto' : 0 }}>
        <Overline onDark>{over}</Overline>
        <h2 style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 'clamp(30px,3.2vw,40px)', lineHeight: 1.12, color: onDark ? 'var(--beige-150)' : 'var(--text-strong)', margin: '12px 0 0' }}>{title}</h2>
        {desc && <p style={{ fontFamily: 'var(--font-body)', fontSize: 17, lineHeight: '27px', color: onDark ? 'var(--text-on-dark-muted)' : 'var(--text-muted)', margin: '14px auto 0' }}>{desc}</p>}
      </div>
    );
  }
  MPD.SecHead = SecHead;

  // ───────────────────────── Header ─────────────────────────
  function Header() {
    const links = [['process', 'Process'], ['services', 'Services'], ['gallery', 'Gallery'], ['why', 'Why Us'], ['reviews', 'Reviews']];
    return (
      <header style={{ position: 'sticky', top: 0, zIndex: 100 }}>
        <div className="d-nav" style={{ background: 'var(--color-surface)', borderBottom: '1px solid var(--border-subtle)' }}>
          <div className="d-wrap" style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 48px', height: 84 }}>
            <a href="#top" style={{ display: 'flex', alignItems: 'center' }}><img src={ASSET + 'logo-horizontal.png'} alt="Maple Pavers" style={{ height: 40 }} /></a>
            <nav style={{ display: 'flex', alignItems: 'center', gap: 28 }}>
              {links.map(([id, label]) => (
                <a key={id} href={'#' + id} className="lnk" style={{ fontFamily: 'var(--font-body)', fontSize: 13, fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--text-strong)', textDecoration: 'none', whiteSpace: 'nowrap' }}>{label}</a>
              ))}
            </nav>
            <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
              <Button variant="primary" size="md" withArrow onClick={startQuote}>Free Quote</Button>
            </div>
          </div>
        </div>
      </header>
    );
  }
  MPD.Header = Header;

  // ───────────────────────── Hero (image + thumbnail rail) ─────────────────────────
  // Desktop port of the mobile HeroRail (src/hero.jsx). The right column is a
  // crossfading image with an overlaid step caption, a thumbnail filmstrip, and
  // one CTA. No address field / upload / "90 seconds" — by design.
  const HERO_STEPS = [
    { img: 't-address.jpg', title: 'Add Your Driveway', long: 'Type in your address or snap a photo of your driveway to get started.' },
    { img: 't-style.jpg', title: 'Pick Materials & Style', long: 'Select from premium styles and materials and see your finished driveway with a real estimate automatically.' },
    { img: 't-render.jpg', title: 'See Your New Driveway', long: 'A realistic preview of your driveway with a real estimate in under 90 seconds — for free.' },
  ];
  const HERO_DWELL = 3200;

  // Auto-advancing cycle with manual override (adapted from mobile useCycle).
  function useHeroCycle(n, dwell) {
    const [active, setActive] = React.useState(0);
    const [tick, setTick] = React.useState(0);
    const ref = React.useRef();
    React.useEffect(() => {
      ref.current = setTimeout(() => { setActive((a) => (a + 1) % n); setTick((t) => t + 1); }, dwell);
      return () => clearTimeout(ref.current);
    }, [active, tick, n, dwell]);
    const go = (i) => { clearTimeout(ref.current); setActive(i); setTick((t) => t + 1); };
    return [active, go];
  }

  function Hero() {
    const [active, go] = useHeroCycle(HERO_STEPS.length, HERO_DWELL);
    return (
      <section id="top" style={{ position: 'relative', overflow: 'hidden' }}>
        <div style={{ position: 'absolute', inset: 0, backgroundImage: `url(${PHOTO}hero-driveway.png)`, backgroundSize: 'cover', backgroundPosition: 'center' }} />
        <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(90deg, rgba(20,18,16,0.95) 0%, rgba(20,18,16,0.82) 40%, rgba(20,18,16,0.55) 100%)' }} />
        <div className="d-wrap" style={{ position: 'relative', padding: '76px 48px' }}>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1.04fr', gap: 56, alignItems: 'center' }}>
            <div>
              {/* Credential chips — mirrors the mobile hero (4.9 Google · HomeStars Best 2025 · Family-Owned Since 1992) */}
              <div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: 8, marginBottom: 4, textShadow: '0 1px 6px rgba(0,0,0,0.55)' }}>
                <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, padding: '4px 11px', borderRadius: 999, fontFamily: 'var(--font-body)', fontSize: 12, fontWeight: 700, background: 'rgba(255,255,255,0.1)', border: '1px solid rgba(255,255,255,0.2)', color: 'var(--beige-150)', whiteSpace: 'nowrap' }}>
                  <span style={{ color: '#f4c542', fontSize: 11 }}>★</span> 4.9 Google
                </span>
                <span style={{ display: 'inline-flex', alignItems: 'center', padding: '4px 11px', borderRadius: 999, fontFamily: 'var(--font-body)', fontSize: 12, fontWeight: 700, background: 'var(--terracotta)', border: '1px solid var(--terracotta)', color: '#fff', whiteSpace: 'nowrap' }}>HomeStars Best 2025</span>
                <span style={{ display: 'inline-flex', flexDirection: 'column', alignItems: 'flex-start', gap: 0, padding: '3px 11px', borderRadius: 999, fontFamily: 'var(--font-body)', fontSize: 9.5, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', lineHeight: 1.15, background: 'rgba(255,255,255,0.1)', border: '1px solid rgba(255,255,255,0.2)', color: 'var(--beige-150)' }}>
                  <span>Family-Owned</span><span>Since 1992</span>
                </span>
              </div>
              <h1 style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 'clamp(34px,3.4vw,50px)', lineHeight: 1.05, letterSpacing: '-0.02em', color: 'var(--beige-150)', margin: '14px 0 0' }}>
                Get the driveway<br />your home deserves.
              </h1>
              <p style={{ fontFamily: 'var(--font-body)', fontSize: 17, lineHeight: '26px', color: 'rgba(248,240,229,0.84)', margin: '16px 0 0', maxWidth: 440 }}>
                Design yours and get a free estimate automatically.
              </p>
            </div>
            <div className="d-rise" style={{ background: 'var(--color-surface)', borderRadius: 'var(--radius-xl)', boxShadow: 'var(--shadow-lg)', border: '1px solid var(--border-subtle)', padding: 18 }}>
              {/* Crossfading hero image with overlaid step caption */}
              <div style={{ position: 'relative', height: 340, borderRadius: 'var(--radius-lg)', overflow: 'hidden' }}>
                {HERO_STEPS.map((s, i) => (
                  <img key={i} className="mp-step-img" src={PHOTO + s.img} alt={s.title} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', opacity: i === active ? 1 : 0 }} />
                ))}
                {/* Whole-image tint for caption legibility without killing the photo */}
                <div style={{ position: 'absolute', inset: 0, background: 'rgba(20,18,16,0.18)' }} />
                {/* Bottom gradient — caption block sits on solid dark */}
                <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(0deg, rgba(20,18,16,0.92) 18%, rgba(20,18,16,0.45) 48%, transparent 75%)' }} />
                <div className="mp-cap-in" key={'cap' + active} style={{ position: 'absolute', left: 22, right: 22, bottom: 20 }}>
                  <span style={{ fontFamily: 'var(--font-body)', fontWeight: 800, fontSize: 12, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--terracotta)', textShadow: '0 1px 6px rgba(0,0,0,0.6)' }}>Step {active + 1}</span>
                  <h3 style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 30, lineHeight: 1.08, color: 'var(--beige-150)', margin: '5px 0 0' }}>{HERO_STEPS[active].title}</h3>
                  <p style={{ fontFamily: 'var(--font-body)', fontSize: 15, lineHeight: '22px', color: 'rgba(248,240,229,0.86)', margin: '8px 0 0', maxWidth: 480 }}>{HERO_STEPS[active].long}</p>
                </div>
              </div>
              {/* Thumbnail filmstrip — all steps, active enlarged */}
              <div style={{ display: 'flex', gap: 10, marginTop: 12, alignItems: 'stretch' }}>
                {HERO_STEPS.map((s, i) => {
                  const on = i === active;
                  return (
                    <button key={i} onClick={() => go(i)} aria-label={s.title} className="mp-press" style={{ flex: '0 0 auto', width: on ? '54%' : '21%', boxSizing: 'border-box', minWidth: 0, padding: 0, border: '2px solid', borderColor: on ? 'var(--terracotta)' : 'transparent', borderRadius: 'var(--radius-md)', overflow: 'hidden', cursor: 'pointer', height: on ? 76 : 64, alignSelf: 'center', position: 'relative', transition: 'width 0.45s var(--ease-standard), height 0.45s var(--ease-standard), border-color 0.3s' }}>
                      <div style={{ position: 'absolute', inset: 0, backgroundImage: `url(${PHOTO}${s.img})`, backgroundSize: 'cover', backgroundPosition: 'center', opacity: on ? 1 : 0.6 }} />
                      <span style={{ position: 'absolute', top: 5, left: 7, fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 13, color: '#fff', textShadow: '0 1px 3px rgba(0,0,0,0.7)' }}>{i + 1}</span>
                    </button>
                  );
                })}
              </div>
              {/* Full-width CTA — matches the desktop primary buttons (sparkles + arrow) */}
              <button onClick={startQuote} className="mp-press" style={{ width: '100%', marginTop: 16, border: 0, cursor: 'pointer', background: 'var(--terracotta)', color: '#fff', borderRadius: 'var(--radius)', padding: '17px', fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 15, letterSpacing: '0.1em', textTransform: 'uppercase', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 10 }}>
                <Icon name="sparkles" size={18} /> Design My Driveway <Icon name="arrow" size={18} />
              </button>
            </div>
          </div>
        </div>
      </section>
    );
  }
  MPD.Hero = Hero;

  // ───────────────────────── Quote (full phone flow, desktop port) ─────────────────────────
  // Desktop port of the mobile QuotePhone sequence (src/quote.jsx), rebuilt as
  // inline-styled React for the dark chat card: greet → address → street view →
  // analysis → render + material swatches → estimate → lead toast, then loop.
  // No light phone CSS is imported; everything reads on the graphite-800 card.
  const QUOTE_FLOW = {
    greet: "👋 Hi! I'm Maple Pavers' quote assistant. Want to see your new driveway before you spend a dollar? Just drop in your address.",
    addr: '88 Forest Hill Rd, Toronto',
    found: "Found it. Here's your place from the street.",
    streetView: 'quote-phone-before.jpg',
    analyze: 'Give me a sec to size it up…',
    rows: [
      ['Current surface', 'Aging asphalt'],
      ['Driveway size', '~820 sq ft'],
      ['Best upgrade', 'Premium pavers'],
    ],
    renderMsg: "Here's your home with fresh new pavers ✨",
    materials: [
      { n: 'Stamped Concrete', img: 'quote-phone-stamped.jpg', c1: '#C3B8AB', c2: '#A89C8C', p: '$6,200 – $7,800' },
      { n: 'Poured Concrete', img: 'quote-phone-concrete.jpg', c1: '#cfd3d8', c2: '#9aa0a8', p: '$7,200 – $9,400' },
      { n: 'Charcoal Pavers', img: 'quote-phone-pavers.jpg', c1: '#4A505A', c2: '#2C313A', p: '$8,450 – $10,250' },
    ],
    active: 2, // Charcoal Pavers — the render/estimate subject
    incs: [
      'Premium charcoal pavers',
      'Base prep + compaction',
      '~2-week install',
      '10-year workmanship warranty',
    ],
    lead: { nm: 'Sarah Johnson', mt: 'Charcoal Pavers driveway · Toronto, ON', pr: '$8,450–$10,250', initial: 'SJ' },
  };

  // AI / user text bubble on the dark card.
  function QBubble({ ai, children }) {
    return (
      <div className="mp-msg-in" style={{ display: 'flex', gap: 10, justifyContent: ai ? 'flex-start' : 'flex-end' }}>
        {ai && <span style={{ width: 32, height: 32, borderRadius: 'var(--radius)', background: 'var(--terracotta)', display: 'flex', alignItems: 'center', justifyContent: 'center', flex: 'none', alignSelf: 'flex-end' }}><img src={ASSET + 'mark-solid.png'} alt="" style={{ width: 18, filter: 'brightness(0) invert(1)' }} /></span>}
        <div style={{ maxWidth: '76%' }}>
          <div style={{ background: ai ? 'rgba(248,240,229,0.09)' : 'var(--clay)', color: ai ? 'var(--beige-150)' : '#fff', borderRadius: ai ? '4px 16px 16px 16px' : '16px 4px 16px 16px', padding: '13px 16px', fontFamily: 'var(--font-body)', fontSize: 15, lineHeight: '22px' }}>{children}</div>
        </div>
      </div>
    );
  }

  // A rounded image block in the chat (street view / render), with a caption pill.
  function QImage({ src, label }) {
    return (
      <div className="mp-msg-in" style={{ alignSelf: 'flex-start', width: '88%', borderRadius: 'var(--radius-lg)', overflow: 'hidden', position: 'relative', height: 168 }}>
        <img src={PHOTO + src} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
        <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(to top, rgba(0,0,0,0.55), transparent 50%)' }} />
        <span style={{ position: 'absolute', left: 12, bottom: 11, fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 12, color: '#fff', background: 'rgba(0,0,0,0.5)', backdropFilter: 'blur(4px)', padding: '4px 10px', borderRadius: 'var(--radius-md)' }}>{label}</span>
      </div>
    );
  }

  // "Analyzing project…" card — rows reveal one by one (self-staggering).
  function QAnalysis({ rows }) {
    const [n, setN] = React.useState(0);
    React.useEffect(() => {
      let cancelled = false; const timers = [];
      rows.forEach((_, i) => { timers.push(setTimeout(() => { if (!cancelled) setN(i + 1); }, 360 + i * 460)); });
      return () => { cancelled = true; timers.forEach(clearTimeout); };
    }, []);
    return (
      <div className="mp-msg-in" style={{ alignSelf: 'flex-start', width: '90%', background: 'rgba(248,240,229,0.06)', border: '1px solid var(--border-on-dark)', borderRadius: 'var(--radius-lg)', padding: '13px 15px' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10, fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 11, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--beige-150)' }}>
          <span style={{ width: 8, height: 8, borderRadius: '50%', background: 'var(--terracotta)', flex: 'none' }} /> Analyzing project…
        </div>
        {rows.map((r, i) => (
          <div key={r[0]} style={{ display: 'flex', alignItems: 'center', gap: 9, padding: '5px 0', fontFamily: 'var(--font-body)', fontSize: 13.5, opacity: i < n ? 1 : 0, transform: i < n ? 'none' : 'translateX(-6px)', transition: 'opacity 0.3s, transform 0.3s' }}>
            <span style={{ width: 16, height: 16, borderRadius: '50%', background: 'var(--success)', color: '#fff', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flex: 'none' }}><Icon name="check" size={10} stroke={3} color="#fff" /></span>
            <span style={{ color: 'var(--text-on-dark-muted)' }}>{r[0]}</span>
            <span style={{ marginLeft: 'auto', fontWeight: 700, color: 'var(--beige-150)' }}>{r[1]}</span>
          </div>
        ))}
      </div>
    );
  }

  // Render image + 3 material swatch chips, with a subtle auto-tap to Charcoal.
  function QRender({ materials, target }) {
    const [sel, setSel] = React.useState(0);
    React.useEffect(() => {
      const t = setTimeout(() => setSel(target), 1100);
      return () => clearTimeout(t);
    }, [target]);
    const mat = materials[sel];
    return (
      <div className="mp-msg-in" style={{ alignSelf: 'flex-start', width: '92%', display: 'flex', flexDirection: 'column', gap: 10 }}>
        <div style={{ borderRadius: 'var(--radius-lg)', overflow: 'hidden', position: 'relative', height: 168 }}>
          <img src={PHOTO + mat.img} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover', transition: 'opacity 0.3s' }} />
          <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(to top, rgba(0,0,0,0.55), transparent 50%)' }} />
          <span style={{ position: 'absolute', left: 12, bottom: 11, fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 12, color: '#fff', background: 'rgba(0,0,0,0.5)', backdropFilter: 'blur(4px)', padding: '4px 10px', borderRadius: 'var(--radius-md)' }}>{mat.n} · {mat.p}</span>
        </div>
        <div style={{ display: 'flex', gap: 7, flexWrap: 'wrap' }}>
          {materials.map((m, i) => {
            const on = i === sel;
            return (
              <button key={m.n} onClick={() => setSel(i)} className="mp-press" style={{ display: 'flex', alignItems: 'center', gap: 7, border: '1.5px solid', borderColor: on ? 'var(--terracotta)' : 'var(--border-on-dark)', background: on ? 'rgba(176,79,36,0.18)' : 'rgba(248,240,229,0.05)', borderRadius: 999, padding: '5px 11px 5px 6px', cursor: 'pointer', fontFamily: 'var(--font-body)', fontSize: 11.5, fontWeight: 700, color: on ? 'var(--clay)' : 'var(--text-on-dark-muted)' }}>
                <span style={{ width: 14, height: 14, borderRadius: '50%', border: '1px solid rgba(255,255,255,0.2)', background: `linear-gradient(135deg, ${m.c1}, ${m.c2})`, flex: 'none' }} />
                {m.n} · {m.p.split('–')[0].trim()}
              </button>
            );
          })}
        </div>
      </div>
    );
  }

  // Instant-estimate card: price range, material, inclusions list.
  function QEstimate({ mat, incs }) {
    return (
      <div className="mp-msg-in" style={{ alignSelf: 'flex-start', width: '92%', background: 'rgba(248,240,229,0.06)', border: '1px solid var(--border-on-dark)', borderRadius: 'var(--radius-lg)', overflow: 'hidden' }}>
        <div style={{ padding: '14px 16px 13px', borderBottom: '1px solid rgba(255,255,255,0.08)' }}>
          <div style={{ fontFamily: 'var(--font-body)', fontSize: 10.5, fontWeight: 700, letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--text-on-dark-muted)' }}>Instant estimate</div>
          <div style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 28, lineHeight: 1.05, letterSpacing: '-0.01em', color: 'var(--clay)', marginTop: 5 }}>{mat.p}</div>
          <div style={{ fontFamily: 'var(--font-body)', fontSize: 11.5, color: 'var(--text-on-dark-muted)', marginTop: 4 }}>{mat.n} · all-in</div>
        </div>
        <div style={{ padding: '11px 16px 14px', display: 'flex', flexDirection: 'column', gap: 2 }}>
          {incs.map((tx) => (
            <div key={tx} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '4px 0', fontFamily: 'var(--font-body)', fontSize: 13, color: 'var(--beige-150)' }}>
              <span style={{ width: 18, height: 18, borderRadius: '50%', background: 'rgba(176,79,36,0.22)', color: 'var(--terracotta)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flex: 'none' }}><Icon name="check" size={11} stroke={3} color="var(--clay)" /></span>
              {tx}
            </div>
          ))}
        </div>
      </div>
    );
  }

  // "New lead" notification toast (as in mobile).
  function QLead({ lead }) {
    return (
      <div className="mp-msg-in" style={{ alignSelf: 'stretch', display: 'flex', flexDirection: 'column', gap: 8 }}>
        <div style={{ fontFamily: 'var(--font-body)', fontSize: 10, fontWeight: 700, letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--text-on-dark-muted)', alignSelf: 'center' }}>Meanwhile, at the shop</div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 11, background: 'var(--graphite)', border: '1px solid var(--border-on-dark)', borderRadius: 'var(--radius-lg)', padding: '11px 13px' }}>
          <span style={{ width: 38, height: 38, borderRadius: 'var(--radius-md)', background: 'rgba(176,79,36,0.22)', color: 'var(--clay)', display: 'flex', alignItems: 'center', justifyContent: 'center', flex: 'none', fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 14 }}>{lead.initial}</span>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontFamily: 'var(--font-body)', fontWeight: 700, fontSize: 13, color: 'var(--beige-150)', lineHeight: 1.2 }}>{lead.nm}</div>
            <div style={{ fontFamily: 'var(--font-body)', fontSize: 11, color: 'var(--text-on-dark-muted)', marginTop: 2 }}>{lead.mt}</div>
          </div>
          <span style={{ marginLeft: 'auto', fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 13, color: 'var(--clay)', whiteSpace: 'nowrap' }}>{lead.pr}</span>
        </div>
      </div>
    );
  }

  function Quote() {
    const T = QUOTE_FLOW;
    const mat = T.materials[T.active];
    // Timeline of items appended to the chat; each entry is a typed step.
    // think = AI typing pause before the item; pause = settle time after it.
    const STEPS = React.useMemo(() => [
      { kind: 'ai', think: 1000, pause: 420, content: T.greet },
      { kind: 'user', think: 720, pause: 480, content: '📍 ' + T.addr },
      { kind: 'ai', think: 1000, pause: 360, content: T.found },
      { kind: 'image', think: 0, pause: 900, src: T.streetView, label: 'Your home · Street View' },
      { kind: 'ai', think: 950, pause: 300, content: T.analyze },
      { kind: 'analysis', think: 0, pause: 1900, rows: T.rows },
      { kind: 'ai', think: 1100, pause: 360, content: T.renderMsg },
      { kind: 'render', think: 0, pause: 2400, materials: T.materials, target: T.active },
      { kind: 'ai', think: 850, pause: 320, content: 'Here is your instant estimate:' },
      { kind: 'estimate', think: 0, pause: 2200, mat, incs: T.incs },
      { kind: 'lead', think: 0, pause: 3200, lead: T.lead },
    ], []);

    const [shown, setShown] = React.useState([]);
    const [typing, setTyping] = React.useState(false);
    const bodyRef = React.useRef(null);
    React.useEffect(() => {
      let cancelled = false; const timers = [];
      const wait = (ms) => new Promise((r) => timers.push(setTimeout(r, ms)));
      (async function run() {
        while (!cancelled) {
          setShown([]); setTyping(false); await wait(700);
          for (let i = 0; i < STEPS.length; i++) {
            const s = STEPS[i];
            if (cancelled) return;
            if (s.kind === 'ai') { setTyping(true); await wait(s.think); if (cancelled) return; setTyping(false); }
            else if (s.think) { await wait(s.think); }
            if (cancelled) return;
            setShown((prev) => [...prev, s]);
            await wait(s.pause || 380);
          }
          if (cancelled) return;
          await wait(3600); // hold on the finished flow, then loop
        }
      })();
      return () => { cancelled = true; timers.forEach(clearTimeout); };
    }, [STEPS]);
    React.useEffect(() => { const el = bodyRef.current; if (el) el.scrollTop = el.scrollHeight; }, [shown, typing]);

    function renderItem(s, i) {
      switch (s.kind) {
        case 'ai': return <QBubble key={i} ai>{s.content}</QBubble>;
        case 'user': return <QBubble key={i}>{s.content}</QBubble>;
        case 'image': return <QImage key={i} src={s.src} label={s.label} />;
        case 'analysis': return <QAnalysis key={i} rows={s.rows} />;
        case 'render': return <QRender key={i} materials={s.materials} target={s.target} />;
        case 'estimate': return <QEstimate key={i} mat={s.mat} incs={s.incs} />;
        case 'lead': return <QLead key={i} lead={s.lead} />;
        default: return null;
      }
    }
    return (
      <section id="maple-ai" style={{ background: 'var(--graphite)', padding: '96px 0' }}>
        <Container>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 64, alignItems: 'center' }}>
            <div>
              <SecHead align="left" onDark over="Your Free Driveway Preview" title="Real renders. Real prices. Zero pressure." />
              <p style={{ fontFamily: 'var(--font-body)', fontSize: 17, lineHeight: '27px', color: 'var(--text-on-dark-muted)', margin: '18px 0 26px', maxWidth: 460 }}>
                Drop your address and a photo. Maple AI redesigns your driveway and hands you a real price range — in about 90 seconds. No salesperson, no waiting.
              </p>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 12, marginBottom: 30 }}>
                {[['sparkles', 'Photorealistic AI render of your home'], ['tag', 'Instant ballpark estimate'], ['badge-check', 'No obligation, no pushy follow-ups']].map(([ic, tx]) => (
                  <div key={tx} style={{ display: 'flex', alignItems: 'center', gap: 12, fontFamily: 'var(--font-body)', fontSize: 15, color: 'var(--beige-150)' }}>
                    <Icon name={ic} size={18} color="var(--clay)" /> {tx}
                  </div>
                ))}
              </div>
              <Button variant="primary" size="lg" withArrow onClick={startQuote}>Start My Driveway Design</Button>
            </div>
            <div style={{ background: 'var(--graphite-800)', border: '1px solid var(--border-on-dark)', borderRadius: 'var(--radius-xl)', overflow: 'hidden', boxShadow: 'var(--shadow-lg)' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 11, padding: '14px 18px', borderBottom: '1px solid rgba(255,255,255,0.08)' }}>
                <span style={{ width: 34, height: 34, borderRadius: 'var(--radius)', background: 'var(--terracotta)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><img src={ASSET + 'mark-solid.png'} alt="" style={{ width: 19, filter: 'brightness(0) invert(1)' }} /></span>
                <div style={{ flex: 1 }}>
                  <div style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 16, color: 'var(--beige-150)' }}>Maple Pavers</div>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 3 }}><span className="mp-online" /><span style={{ fontFamily: 'var(--font-body)', fontSize: 11.5, color: 'var(--text-on-dark-muted)' }}>Online</span></div>
                </div>
                <Badge variant="soft" size="sm">Free</Badge>
              </div>
              <div ref={bodyRef} style={{ height: 440, overflowY: 'auto', overflowX: 'hidden', padding: 20, display: 'flex', flexDirection: 'column', gap: 12 }} className="mp-hide-sb">
                <div style={{ flex: 1 }} />
                {shown.map((s, i) => renderItem(s, i))}
                {typing && (
                  <div className="mp-msg-in" style={{ display: 'flex', gap: 10 }}>
                    <span style={{ width: 32, height: 32, borderRadius: 'var(--radius)', background: 'var(--terracotta)', display: 'flex', alignItems: 'center', justifyContent: 'center', alignSelf: 'flex-end' }}><img src={ASSET + 'mark-solid.png'} alt="" style={{ width: 18, filter: 'brightness(0) invert(1)' }} /></span>
                    <div className="mp-typing" style={{ background: 'rgba(248,240,229,0.09)', color: 'var(--text-on-dark-muted)', borderRadius: '4px 16px 16px 16px', padding: '14px 16px' }}><i /><i /><i /></div>
                  </div>
                )}
              </div>
              <div style={{ padding: '0 18px 18px' }}>
                <button onClick={startQuote} className="mp-press" style={{ width: '100%', display: 'flex', alignItems: 'center', gap: 10, border: '1px solid var(--border-on-dark)', borderRadius: 'var(--radius)', padding: '8px 8px 8px 16px', background: 'rgba(248,240,229,0.05)', cursor: 'pointer' }}>
                  <span style={{ flex: 1, textAlign: 'left', fontFamily: 'var(--font-body)', fontSize: 15, color: 'var(--text-on-dark-muted)' }}>Type your address to start…</span>
                  <span style={{ width: 40, height: 40, borderRadius: 'var(--radius-sm)', background: 'var(--terracotta)', color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="arrow" size={18} /></span>
                </button>
              </div>
            </div>
          </div>
        </Container>
      </section>
    );
  }
  MPD.Quote = Quote;

  // ───────────────────────── Process (grid) ─────────────────────────
  function Process() {
    return (
      <section id="process" style={{ background: 'var(--color-bg)', padding: '96px 0' }}>
        <Container>
          <SecHead over="How It Works" title="Four steps from idea to driveway." />
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 32, marginTop: 56 }}>
            {D.process.map((p, i) => (
              <div key={p.t} style={{ textAlign: 'center', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 14 }}>
                <div style={{ position: 'relative', width: 76, height: 76, borderRadius: 'var(--radius-full)', background: 'var(--terracotta-100)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                  <Icon name={p.icon} size={30} color="var(--terracotta)" />
                  <span style={{ position: 'absolute', top: -6, right: -6, width: 28, height: 28, borderRadius: 'var(--radius-full)', background: 'var(--terracotta)', color: '#fff', fontFamily: 'var(--font-body)', fontSize: 13, fontWeight: 700, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>{i + 1}</span>
                </div>
                <h3 style={{ fontFamily: 'var(--font-display)', fontWeight: 600, fontSize: 21, color: 'var(--text-strong)', margin: 0 }}>{p.t}</h3>
                <p style={{ fontFamily: 'var(--font-body)', fontSize: 14.5, lineHeight: '22px', color: 'var(--text-muted)', margin: 0, maxWidth: 230 }}>{p.d}</p>
              </div>
            ))}
          </div>
        </Container>
      </section>
    );
  }
  MPD.Process = Process;

  // ───────────────────────── Services (grid of cards) ─────────────────────────
  function Services() {
    return (
      <section id="services" style={{ background: 'var(--beige-300)', padding: '96px 0' }}>
        <Container>
          <SecHead over="Our Work" title="Pavers. Patios. Walls. Done right." />
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 22, marginTop: 52 }}>
            {D.services.map((s) => (
              <ServiceCard key={s.t} title={s.t} description={s.d} image={PHOTO + s.img} height={280} onClick={startQuote} />
            ))}
          </div>
        </Container>
      </section>
    );
  }
  MPD.Services = Services;
})();
