// Permit Nav — reusable section primitives that break the repeated-card rhythm.
// SectionHead, StatBand, JourneyTimeline, CompareOldWay, SplitEditorial, QuoteBand.
(function () {
  const S = window.PermitNavDesignSystem_779430;
  const { Eyebrow, Badge, Button, IconTile } = S;
  const { Icon, Reveal, Photo, pnImg } = window;

  // Eyebrow + headline + optional sub, used everywhere so headers stay consistent.
  function SectionHead({ eyebrow, eyebrowTone, title, sub, align = 'left', maxWidth = 640, light, style }) {
    return (
      <div style={{ textAlign: align, maxWidth, margin: align === 'center' ? '0 auto' : 0, ...style }}>
      {eyebrow ? <Eyebrow tone={eyebrowTone}>{eyebrow}</Eyebrow> : null}
      <h2 className="pn-h2" style={{ fontSize: 'clamp(28px,3.3vw,44px)', margin: '14px 0 0', color: light ? '#fff' : 'var(--ink-900)' }}>{title}</h2>
      {sub ? <p className="pn-sub" style={{ marginTop: 14, marginLeft: align === 'center' ? 'auto' : 0, marginRight: align === 'center' ? 'auto' : 0, color: light ? 'var(--text-on-dark-muted)' : 'var(--ink-500)' }}>{sub}</p> : null}
    </div>);

  }

  // Big-number stat callouts on a dark band — large type, no cards.
  function StatBand({ eyebrow, title, stats, dark = true }) {
    return (
      <section style={{ background: dark ? 'var(--surface-dark)' : 'var(--surface-muted)' }}>
      <div className="pn-container" style={{ padding: '72px 32px' }}>
        {eyebrow || title ?
          <Reveal style={{ marginBottom: 44, maxWidth: 620 }}>
            {eyebrow ? <Eyebrow tone={dark ? 'blue' : undefined}>{eyebrow}</Eyebrow> : null}
            {title ? <h2 className="pn-h2" style={{ fontSize: 'clamp(26px,3vw,40px)', marginTop: 12, color: dark ? '#fff' : 'var(--ink-900)', fontWeight: "800" }}>{title}</h2> : null}
          </Reveal> :
          null}
        <div className="pn-grid-4" style={{ display: 'grid', gridTemplateColumns: `repeat(${stats.length}, 1fr)`, gap: 0 }}>
          {stats.map((s, i) =>
            <Reveal key={s.label} delay={i % 4 + 1} style={{ padding: '6px 30px', borderLeft: i ? `1px solid ${dark ? 'rgba(255,255,255,0.12)' : 'var(--border)'}` : 'none' }}>
              <div style={{ fontFamily: 'var(--font-display)', fontSize: 'clamp(34px,3.6vw,50px)', lineHeight: 1, letterSpacing: '-.02em', color: dark ? '#fff' : 'var(--ink-900)', fontWeight: "500" }}>{s.big}</div>
              <div style={{ fontSize: 14.5, lineHeight: 1.45, marginTop: 12, color: dark ? 'var(--text-on-dark-muted)' : 'var(--ink-500)' }}>{s.label}</div>
            </Reveal>
            )}
        </div>
      </div>
    </section>);

  }

  // Horizontal permit-journey timeline: describe -> validate -> submit -> track -> approved.
  function JourneyTimeline({ steps, active = -1 }) {
    return (
      <div className="pn-timeline">
      {steps.map((st, i) =>
        <Reveal key={st.label} delay={i % 4 + 1} className="pn-timeline-step">
          <div className="pn-timeline-rail">
            {i !== 0 ? <span className="pn-timeline-line pn-timeline-line--l"></span> : null}
            <span className={`pn-timeline-dot${st.done ? ' is-done' : ''}`} style={{ background: st.tone === 'green' ? 'var(--green-500)' : 'var(--blue-600)' }}>
              <Icon n={st.icon} size={20} color="#fff" />
            </span>
            {i !== steps.length - 1 ? <span className="pn-timeline-line pn-timeline-line--r"></span> : null}
          </div>
          <div className="pn-timeline-num">{String(i + 1).padStart(2, '0')}</div>
          <div className="pn-timeline-label">{st.label}</div>
          <div className="pn-timeline-desc">{st.desc}</div>
        </Reveal>
        )}
    </div>);

  }

  // Permit Nav vs the old way — two bold contrast cards, not a dense table.
  function CompareOldWay({ rows }) {
    const items = rows.slice(0, 3);
    return (
      <Reveal>
      <div className="pn-versus">
        <div className="pn-versus-card pn-versus-card--old">
          <div className="pn-versus-head">
            <span className="pn-versus-badge"><Icon n="x" size={20} /></span>
            <div>
              <div className="pn-versus-title" style={{ color: "rgb(135, 5, 5)" }}>Without Permit Nav</div>
              <div className="pn-versus-sub">Guesswork, expediters, rejections</div>
            </div>
          </div>
          <ul className="pn-versus-list">
            {items.map((r) =>
              <li key={r.label}>
                <span className="pn-versus-ic pn-versus-ic--old"><Icon n={r.icon} size={18} /></span>
                <span>{r.old}</span>
              </li>
              )}
          </ul>
        </div>
        <div className="pn-versus-card pn-versus-card--new">
          <div className="pn-versus-head">
            <span className="pn-versus-badge pn-versus-badge--new"><Icon n="check" size={20} /></span>
            <div>
              <div className="pn-versus-title">With Permit Nav</div>
              <div className="pn-versus-sub">One certain answer, up front</div>
            </div>
          </div>
          <ul className="pn-versus-list">
            {items.map((r) =>
              <li key={r.label}>
                <span className="pn-versus-ic pn-versus-ic--new"><Icon n={r.icon} size={18} /></span>
                <span>{r.neu}</span>
              </li>
              )}
          </ul>
        </div>
      </div>
    </Reveal>);

  }

  // Split editorial: photo (or product screenshot) one side, content the other.
  function SplitEditorial({ photo, photoAlt, shot, eyebrow, eyebrowTone, title, children, flip, badge, floatStat, muted }) {
    const [zoom, setZoom] = React.useState(false);
    React.useEffect(() => {
      if (!zoom) return undefined;
      if (window.lucide) window.lucide.createIcons();
      const onKey = (e) => {if (e.key === 'Escape') setZoom(false);};
      window.addEventListener('keydown', onKey);
      return () => window.removeEventListener('keydown', onKey);
    }, [zoom]);
    return (
      <section className={`pn-section${muted ? ' pn-muted' : ''}`}>
      <div className="pn-container pn-split" style={{ display: 'grid', gridTemplateColumns: flip ? '0.82fr 1.18fr' : '1.18fr 0.82fr', gap: 56, alignItems: 'center' }}>
        <Reveal style={{ order: flip ? 2 : 1, position: 'relative' }}>
          {shot ?
            <div className={`pn-shot${shot.tall ? ' pn-shot--tall' : ''}`}><img src={shot.src} alt={shot.alt} loading="lazy" onClick={() => setZoom(true)} style={{ cursor: 'zoom-in' }} /></div> :

            <Photo id={photo} alt={photoAlt} ratio="4 / 3.2" style={{ boxShadow: 'var(--shadow-lg)' }} />
            }
          {floatStat ?
            <div className={`pn-float-stat${flip ? '' : ' pn-float-stat--left'}`}>
              <div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 30, color: 'var(--ink-900)', lineHeight: 1 }}>{floatStat.big}</div>
              <div style={{ fontSize: 13, color: 'var(--ink-500)', marginTop: 5 }}>{floatStat.label}</div>
            </div> :
            null}
        </Reveal>
        <Reveal delay={1} style={{ order: flip ? 1 : 2 }}>
          {badge ? <div style={{ marginBottom: 14 }}><Badge tone="tint" icon={<Icon n={badge.icon} size={14} />}>{badge.label}</Badge></div> : null}
          {eyebrow ? <Eyebrow tone={eyebrowTone}>{eyebrow}</Eyebrow> : null}
          <h2 className="pn-h2" style={{ fontSize: 'clamp(28px,3.2vw,42px)', margin: '14px 0 16px' }}>{title}</h2>
          {children}
        </Reveal>
      </div>
      {zoom && shot ? ReactDOM.createPortal(
          <div className="pn-lightbox" onClick={() => setZoom(false)} role="dialog" aria-modal="true">
          <button className="pn-lightbox__close" onClick={() => setZoom(false)} aria-label="Close"><Icon n="x" size={24} /></button>
          <figure className="pn-lightbox__figure" onClick={(e) => e.stopPropagation()}>
            <img src={shot.src} alt={shot.alt} />
          </figure>
        </div>, document.body) : null}
    </section>);

  }

  // A single featured quote on a dark band with a portrait-free monogram.
  function QuoteBand({ quote, name, meta, icon = 'home' }) {
    return (
      <section style={{ background: 'var(--surface-dark)' }}>
      <div className="pn-container" style={{ padding: '80px 32px', maxWidth: 920, textAlign: 'center' }}>
        <Reveal>
          <span style={{ color: 'var(--blue-400)' }}><Icon n="quote" size={36} /></span>
          <p style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 'clamp(24px,2.8vw,36px)', lineHeight: 1.32, letterSpacing: '-.015em', color: '#fff', margin: '18px auto 26px', textWrap: 'balance' }}>{quote}</p>
          <div style={{ display: 'inline-flex', alignItems: 'center', gap: 12 }}>
            <span style={{ width: 42, height: 42, borderRadius: '50%', background: 'rgba(127,176,236,0.16)', border: '1px solid rgba(127,176,236,0.35)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', color: 'var(--blue-300)' }}><Icon n={icon} size={20} /></span>
            <div style={{ textAlign: 'left' }}>
              <div style={{ color: '#fff', fontWeight: 700, fontSize: 15 }}>{name}</div>
              <div style={{ color: 'var(--text-on-dark-muted)', fontSize: 13 }}>{meta}</div>
            </div>
          </div>
        </Reveal>
      </div>
    </section>);

  }

  // Coverage: real label-free map of the Vancouver region + the five municipality chips.
  function CoverageSection() {
    const munis = window.PN_MUNICIPALITIES;
    const mapRef = React.useRef(null);
    React.useEffect(() => {
      const L = window.L;
      if (!L || !mapRef.current || mapRef.current._leaflet_id) return;
      const pts = [
      [49.262, -123.114], // City of Vancouver
      [49.320, -123.073], // City of North Vancouver
      [49.345, -122.990], // District of North Vancouver
      [49.330, -123.160], // District of West Vancouver
      [49.246, -122.980] // City of Burnaby
      ];
      const map = L.map(mapRef.current, {
        zoomControl: false, scrollWheelZoom: false, attributionControl: false,
        dragging: true, doubleClickZoom: false, keyboard: false
      });
      L.tileLayer('https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png', {
        subdomains: 'abcd', maxZoom: 19
      }).addTo(map);
      const group = L.featureGroup(
        pts.map((p) => L.circleMarker(p, { radius: 9, color: '#fff', weight: 3, fillColor: '#138A4E', fillOpacity: 1 }))
      ).addTo(map);
      map.fitBounds(group.getBounds().pad(0.5));
      const t = setTimeout(() => map.invalidateSize(), 250);
      return () => {clearTimeout(t);map.remove();};
    }, []);
    return (
      <section className="pn-coverage">
      <div className="pn-container" style={{ padding: '82px 32px' }}>
        <div className="pn-split" style={{ display: 'grid', gridTemplateColumns: '0.96fr 1.04fr', gap: 56, alignItems: 'center' }}>
          <Reveal>
            <SectionHead eyebrow="Coverage" title="Coming soon across Metro Vancouver." sub="We make permit navigation easier. Starting where we live: right here in Vancouver." />
            <div style={{ marginTop: 26 }}>
              <Button className="pn-sweep" variant="primary" onClick={() => window.openBetaModal()} iconRight={<Icon n="arrow-right" size={17} />}>Join the beta</Button>
            </div>
          </Reveal>
          <Reveal delay={1}>
            <div className="pn-map-canvas" ref={mapRef} aria-label="Map of the Metro Vancouver service area"></div>
          </Reveal>
        </div>
        <Reveal style={{ marginTop: 54, textAlign: 'center' }}>
          <div className="pn-support-head">Support for</div>
          <div className="pn-logo-row">
            {munis.map((m) =>
              <div className="pn-logo-slot" key={m.name}>
                <img src={`assets/muni-logo-${m.mark}.webp`} alt={m.name} loading="lazy" />
              </div>
              )}
          </div>
        </Reveal>
      </div>
    </section>);

  }

  // The data engine: four sources + the AI data-flow diagram.
  function DataEngine() {
    const sources = [
    { n: '01', icon: 'database', t: 'AI permit requirements database', s: 'Every permit, form and condition across covered municipalities, structured and kept current.' },
    { n: '02', icon: 'landmark', t: 'Municipality processing insights', s: 'How each city actually reviews and moves a file, not just what the bylaws say on paper.' },
    { n: '03', icon: 'hard-hat', t: 'Contractor & trades interviews', s: 'Hard-won field knowledge from the people who pull permits every single week.' },
    { n: '04', icon: 'message-circle', t: 'Homeowner feedback', s: 'Real projects and real outcomes, feeding back to sharpen every estimate we give.' }];

    return (
      <section className="pn-section">
      <div className="pn-container">
        <Reveal style={{ marginBottom: 40, maxWidth: 640 }}>
          <SectionHead eyebrow="The data engine" title="Multiple sources behind every answer." sub="Permit Nav blends official rules with lived community experience so what you see reflects how permitting really works, municipality by municipality." />
        </Reveal>
        <Reveal>
          <div className="pn-source-grid">
            {sources.map((s) =>
              <div className="pn-source" key={s.n}>
                <div className="pn-source-num">{s.n}</div>
                <IconTile tone="blue" size={42}><Icon n={s.icon} size={21} /></IconTile>
                <div className="pn-source-t">{s.t}</div>
                <p className="pn-source-s">{s.s}</p>
              </div>
              )}
          </div>
        </Reveal>
      </div>
    </section>);

  }

  // Shared auto-advancing product-shot carousel (used on Home + Our Story).
  function ProductCarousel() {
    const shots = [
    { src: 'assets/shot-result.png', cap: 'Based on your answers, see exactly what your project needs.' },
    { src: 'assets/shot-arborist.png', cap: 'Replacement-tree and arborist requirements, mapped to your city.' },
    { src: 'assets/shot-summary.png', cap: 'Describe your project, see exactly what it needs.' },
    { src: 'assets/shot-application.png', cap: 'Track every document and requirement in one place.' }];

    const [i, setI] = React.useState(0);
    const [paused, setPaused] = React.useState(false);
    const [zoom, setZoom] = React.useState(false);
    const touchX = React.useRef(null);
    React.useEffect(() => {
      if (!zoom) return undefined;
      const onKey = (e) => {
        if (e.key === 'Escape') setZoom(false);else
        if (e.key === 'ArrowRight') setI((p) => (p + 1) % shots.length);else
        if (e.key === 'ArrowLeft') setI((p) => (p - 1 + shots.length) % shots.length);
      };
      window.addEventListener('keydown', onKey);
      return () => window.removeEventListener('keydown', onKey);
    }, [zoom, shots.length]);
    React.useEffect(() => {
      const reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
      if (paused || zoom || reduce) return undefined;
      const t = setInterval(() => setI((p) => (p + 1) % shots.length), 4500);
      return () => clearInterval(t);
    }, [paused, zoom, shots.length]);
    React.useEffect(() => {if (window.lucide) window.lucide.createIcons();});
    const go = (n) => setI((n + shots.length) % shots.length);
    const onTouchStart = (e) => {touchX.current = e.touches[0].clientX;setPaused(true);};
    const onTouchEnd = (e) => {
      if (touchX.current == null) return;
      const dx = e.changedTouches[0].clientX - touchX.current;
      if (Math.abs(dx) > 40) go(dx < 0 ? i + 1 : i - 1);
      touchX.current = null;
    };
    return (
      <div className="pn-carousel" onMouseEnter={() => setPaused(true)} onMouseLeave={() => setPaused(false)}>
      <div className="pn-carousel__stage">
        <button className="pn-carousel__arrow pn-carousel__arrow--prev" onClick={() => go(i - 1)} aria-label="Previous"><Icon n="chevron-left" size={20} /></button>
        <div className="pn-carousel__frame">
          <div className="pn-carousel__viewport" onTouchStart={onTouchStart} onTouchEnd={onTouchEnd}>
            {shots.map((s, idx) =>
              <div key={s.src} className={`pn-carousel__slide${idx === i ? ' is-active' : ''}`}>
                <img src={s.src} alt={s.cap} loading={idx === 0 ? 'eager' : 'lazy'} onClick={() => setZoom(true)} style={{ cursor: 'zoom-in' }} />
              </div>
              )}
          </div>
        </div>
        <button className="pn-carousel__arrow pn-carousel__arrow--next" onClick={() => go(i + 1)} aria-label="Next"><Icon n="chevron-right" size={20} /></button>
      </div>
      <div className="pn-carousel__cap">{shots[i].cap}</div>
      <div className="pn-carousel__controls">
        <button className="pn-carousel__arrow pn-carousel__arrow--m pn-carousel__arrow--prev" onClick={() => go(i - 1)} aria-label="Previous"><Icon n="chevron-left" size={18} /></button>
        <div className="pn-carousel__dots">
          {shots.map((s, idx) =>
            <button key={s.src} className={`pn-carousel__dot${idx === i ? ' is-active' : ''}`} onClick={() => go(idx)} aria-label={`Go to slide ${idx + 1}`}></button>
            )}
        </div>
        <button className="pn-carousel__arrow pn-carousel__arrow--m pn-carousel__arrow--next" onClick={() => go(i + 1)} aria-label="Next"><Icon n="chevron-right" size={18} /></button>
      </div>
      {zoom ? ReactDOM.createPortal(
          <div className="pn-lightbox" onClick={() => setZoom(false)} role="dialog" aria-modal="true">
          <button className="pn-lightbox__close" onClick={() => setZoom(false)} aria-label="Close"><Icon n="x" size={24} /></button>
          <button className="pn-lightbox__arrow pn-lightbox__arrow--prev" onClick={(e) => {e.stopPropagation();go(i - 1);}} aria-label="Previous"><Icon n="chevron-left" size={28} /></button>
          <figure className="pn-lightbox__figure" onClick={(e) => e.stopPropagation()}>
            <img src={shots[i].src} alt={shots[i].cap} />
            <figcaption>{shots[i].cap}</figcaption>
          </figure>
          <button className="pn-lightbox__arrow pn-lightbox__arrow--next" onClick={(e) => {e.stopPropagation();go(i + 1);}} aria-label="Next"><Icon n="chevron-right" size={28} /></button>
          <div className="pn-lightbox__dots">
            {shots.map((s, idx) =>
              <button key={s.src} className={`pn-carousel__dot${idx === i ? ' is-active' : ''}`} onClick={(e) => {e.stopPropagation();go(idx);}} aria-label={`Go to slide ${idx + 1}`}></button>
              )}
          </div>
        </div>, document.body) : null}
    </div>);

  }

  Object.assign(window, { SectionHead, StatBand, JourneyTimeline, CompareOldWay, SplitEditorial, QuoteBand, CoverageSection, DataEngine, ProductCarousel });
})();