// Shared components used across all three directions.
// Exposes: PolarisLogo, ChicagoMap, ContactFlow, Icon

// ─────────────────────────────────────────────────────────────
// Logo — recreates the user's logo (P-leaf mark + wordmark)
// Colors via props so each direction can recolor.
// ─────────────────────────────────────────────────────────────
function PolarisLogo({ markColor = "#2C5249", textColor = "#2A2A2A", showWordmark = true, size = 36, invert = false }) {
  // Aspect of original 1000x209 ≈ 4.78
  const w = showWordmark ? size * 4.78 : size * 1.0;
  const h = size;
  // Use real logo PNG. Recolor via CSS filter only when invert (white on dark).
  // For dark-on-light usage, render the natural logo unmodified.
  const filter = invert ? 'brightness(0) invert(1)' : 'none';
  return (
    <img
      src="assets/polaris-logo.png"
      alt="Polaris Landscape"
      width={w}
      height={h}
      style={{ display: 'block', height: h, width: 'auto', filter, objectFit: 'contain' }}
    />
  );
}

// ─────────────────────────────────────────────────────────────
// Icon set — minimal stroke icons
// ─────────────────────────────────────────────────────────────
function Icon({ name, size = 20, stroke = "currentColor", strokeWidth = 1.5 }) {
  const props = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke, strokeWidth, strokeLinecap: "round", strokeLinejoin: "round" };
  switch (name) {
    case 'leaf': return <svg {...props}><path d="M11 20A7 7 0 0 1 4 13c0-6 9-11 17-11 0 8-5 17-11 17a7 7 0 0 1-7-7"/><path d="M2 22 17 7"/></svg>;
    case 'snow': return <svg {...props}><path d="M12 2v20M2 12h20M4.93 4.93l14.14 14.14M19.07 4.93 4.93 19.07"/></svg>;
    case 'sparkle': return <svg {...props}><path d="M12 3v4M12 17v4M3 12h4M17 12h4M5.6 5.6l2.8 2.8M15.6 15.6l2.8 2.8M5.6 18.4l2.8-2.8M15.6 8.4l2.8-2.8"/></svg>;
    case 'arrow-right': return <svg {...props}><path d="M5 12h14M13 5l7 7-7 7"/></svg>;
    case 'arrow-down': return <svg {...props}><path d="M12 5v14M5 12l7 7 7-7"/></svg>;
    case 'check': return <svg {...props}><path d="M20 6 9 17l-5-5"/></svg>;
    case 'pin': return <svg {...props}><path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z"/><circle cx="12" cy="10" r="3"/></svg>;
    case 'star': return <svg {...props}><path d="m12 2 3 7 7 .5-5.5 4.5L18 21l-6-4-6 4 1.5-7L2 9.5 9 9z"/></svg>;
    case 'menu': return <svg {...props}><path d="M3 6h18M3 12h18M3 18h18"/></svg>;
    case 'close': return <svg {...props}><path d="M18 6 6 18M6 6l12 12"/></svg>;
    case 'plus': return <svg {...props}><path d="M12 5v14M5 12h14"/></svg>;
    default: return null;
  }
}

// ─────────────────────────────────────────────────────────────
// Chicagoland Map — stylized SVG, dark mode by default but
// can be themed via props.
// Pins glow + pulse. Hover shows site card.
// ─────────────────────────────────────────────────────────────
function ChicagoMap({ theme = "dark", height = 560, accentColor = "#7BD389", showStats = true }) {
  const sites = window.POLARIS_SITES;
  const [hovered, setHovered] = React.useState(null);
  const [filter, setFilter] = React.useState("All");

  // Bounding box calibrated to assets/chicagoland-map.png (996x1166).
  const BBOX = { minLat: 41.24, maxLat: 42.47, minLng: -88.50, maxLng: -87.01 };
  // Project lat/lng to PERCENT (0-100) of the map image.
  const project = (lat, lng) => {
    const xPct = ((lng - BBOX.minLng) / (BBOX.maxLng - BBOX.minLng)) * 100;
    const yPct = ((BBOX.maxLat - lat) / (BBOX.maxLat - BBOX.minLat)) * 100;
    return [xPct, yPct];
  };

  const themes = {
    dark: {
      bg: "#E8EEF0",
      pin: accentColor,
      cardBg: "rgba(15, 26, 22, 0.92)",
      cardBorder: "rgba(123, 211, 137, 0.35)",
      cardText: "#E8F0E8",
      cardSubtext: "rgba(220, 230, 220, 0.7)",
      cityLabel: "#1A2A26",
      tint: "rgba(14, 22, 20, 0.55)",
    },
    light: {
      bg: "#F7F5EE",
      pin: "#2C5249",
      cardBg: "rgba(255, 254, 250, 0.97)",
      cardBorder: "rgba(44, 82, 73, 0.18)",
      cardText: "#1A1F1C",
      cardSubtext: "rgba(44, 50, 45, 0.6)",
      cityLabel: "rgba(44, 50, 45, 0.65)",
      tint: "rgba(247, 245, 238, 0.0)",
    },
  };
  const t = themes[theme];

  const types = ["All", "Commercial", "HOA", "Industrial", "Municipal"];
  const filtered = filter === "All" ? sites : sites.filter(s => s.type === filter);

  return (
    <div style={{
      position: 'relative',
      width: '100%',
      height,
      background: t.bg,
      borderRadius: 6,
      overflow: 'hidden',
      fontFamily: '-apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, sans-serif',
    }}>
      {/* Real map image as background */}
      <div style={{
        position: 'absolute', inset: 0,
        backgroundImage: 'url(assets/chicagoland-map.png)',
        backgroundSize: 'cover',
        backgroundPosition: 'center',
      }} />
      {/* (Showing the map as-is for full color/legibility against the site's dark sections.) */}

      {/* Filter pills */}
      <div style={{
        position: 'absolute', top: 20, left: 20, zIndex: 5,
        display: 'flex', gap: 6, flexWrap: 'wrap', maxWidth: 'calc(100% - 40px)',
      }}>
        {types.map(typ => (
          <button key={typ} onClick={() => setFilter(typ)} style={{
            padding: '7px 14px',
            background: filter === typ ? (theme === 'dark' ? '#0E1614' : '#2C5249') : 'rgba(255,255,255,0.85)',
            color: filter === typ ? '#FFFFFF' : '#1A2A26',
            border: `1px solid ${filter === typ ? 'transparent' : 'rgba(26,42,38,0.18)'}`,
            borderRadius: 100,
            fontSize: 11,
            fontWeight: 500,
            letterSpacing: '0.05em',
            textTransform: 'uppercase',
            cursor: 'pointer',
            backdropFilter: 'blur(10px)',
            WebkitBackdropFilter: 'blur(10px)',
            transition: 'all .2s',
          }}>
            {typ === 'All' ? `All · ${sites.length}` : typ}
          </button>
        ))}
      </div>

      {/* Stats overlay */}
      {showStats && (
        <div style={{
          position: 'absolute', bottom: 20, left: 20, zIndex: 5,
          background: t.cardBg, border: `1px solid ${t.cardBorder}`,
          borderRadius: 4, padding: '14px 18px',
          backdropFilter: 'blur(20px)',
          WebkitBackdropFilter: 'blur(20px)',
        }}>
          <div style={{ fontSize: 10, letterSpacing: '0.15em', textTransform: 'uppercase', color: t.cardSubtext, marginBottom: 4 }}>
            Live Coverage
          </div>
          <div style={{ fontSize: 22, fontWeight: 600, color: t.cardText, letterSpacing: '-0.01em' }}>
            {filtered.length} active sites
          </div>
          <div style={{ fontSize: 12, color: t.cardSubtext, marginTop: 2 }}>
            Across {new Set(filtered.map(s => s.area)).size} Chicagoland communities
          </div>
        </div>
      )}

      {/* Pins, absolutely positioned over the map by lat/lng → percent */}
      {filtered.map((site, i) => {
        const [xPct, yPct] = project(site.lat, site.lng);
        const isHovered = hovered === i;
        const dur = 2.5 + (i % 5) * 0.3;
        return (
          <div key={i}
               onMouseEnter={() => setHovered(i)}
               onMouseLeave={() => setHovered(null)}
               style={{
                 position: 'absolute',
                 left: `${xPct}%`,
                 top: `${yPct}%`,
                 transform: 'translate(-50%, -50%)',
                 width: 28, height: 28,
                 cursor: 'pointer',
                 zIndex: isHovered ? 6 : 3,
               }}>
            {/* glow / pulse */}
            <div style={{
              position: 'absolute', inset: 0,
              borderRadius: '50%',
              background: `radial-gradient(circle, ${t.pin}88 0%, ${t.pin}00 60%)`,
              animation: `polaris-pulse ${dur}s ease-in-out infinite`,
            }} />
            {/* dot */}
            <div style={{
              position: 'absolute',
              left: '50%', top: '50%',
              transform: 'translate(-50%, -50%)',
              width: isHovered ? 14 : 10,
              height: isHovered ? 14 : 10,
              borderRadius: '50%',
              background: t.pin,
              border: `2px solid ${theme === 'dark' ? '#0E1614' : '#fff'}`,
              boxShadow: `0 0 0 1px ${t.pin}55, 0 2px 8px ${t.pin}88`,
              transition: 'width .2s, height .2s',
            }} />
          </div>
        );
      })}

      {/* Hover card */}
      {hovered !== null && (() => {
        const site = filtered[hovered];
        const [xPct, yPct] = project(site.lat, site.lng);
        return (
          <div style={{
            position: 'absolute',
            left: `${xPct}%`, top: `${yPct}%`,
            transform: `translate(${xPct > 70 ? '-110%' : '20px'}, ${yPct > 70 ? '-110%' : '-50%'})`,
            background: t.cardBg, border: `1px solid ${t.cardBorder}`,
            borderRadius: 4, padding: '14px 18px',
            backdropFilter: 'blur(20px)',
            WebkitBackdropFilter: 'blur(20px)',
            minWidth: 220, maxWidth: 280,
            pointerEvents: 'none',
            boxShadow: theme === 'dark' ? '0 8px 32px rgba(0,0,0,0.6)' : '0 8px 32px rgba(0,0,0,0.12)',
            zIndex: 7,
          }}>
            <div style={{ fontSize: 10, letterSpacing: '0.15em', textTransform: 'uppercase', color: accentColor, fontWeight: 600, marginBottom: 6 }}>
              {site.type}
            </div>
            <div style={{ fontSize: 15, fontWeight: 600, color: t.cardText, lineHeight: 1.25, marginBottom: 4 }}>
              {site.name}
            </div>
            <div style={{ fontSize: 12, color: t.cardSubtext }}>
              {site.area}, IL
            </div>
          </div>
        );
      })()}

      {/* Pulse keyframes (one-time injection) */}
      <style dangerouslySetInnerHTML={{ __html: `
        @keyframes polaris-pulse {
          0%   { transform: scale(0.7); opacity: 0.55; }
          50%  { transform: scale(1.5); opacity: 0.10; }
          100% { transform: scale(0.7); opacity: 0.55; }
        }
      ` }} />
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Apple-style Contact Flow — one question per screen
// Crossfades + Y-shift between steps. Theme-able.
// ─────────────────────────────────────────────────────────────
function FormField({ label, optional, error, showErrors, htmlFor, subtleColor, children }) {
  return (
    <div style={{ marginBottom: 22 }}>
      <label htmlFor={htmlFor} style={{
        display: 'block', fontSize: 12, fontWeight: 600, letterSpacing: '0.06em',
        textTransform: 'uppercase', color: subtleColor, marginBottom: 10,
      }}>
        {label}
        {optional && <span style={{ color: subtleColor, fontWeight: 400, textTransform: 'none', letterSpacing: 0, marginLeft: 8 }}>· optional</span>}
      </label>
      {children}
      {showErrors && error && (
        <div style={{ fontSize: 13, color: '#c44', marginTop: 6 }}>{error}</div>
      )}
    </div>
  );
}

function ContactFlow({ theme = "light", accentColor = "#2C5249", onClose }) {
  const [data, setData] = React.useState({
    name: '', email: '', phone: '', address: '', propertyType: '', service: [], notes: '',
    smsConsent: false,
  });
  const [submitted, setSubmitted] = React.useState(false);
  const [submitError, setSubmitError] = React.useState(null);
  const [submitting, setSubmitting] = React.useState(false);
  const [showErrors, setShowErrors] = React.useState(false);
  const [gmapsReady, setGmapsReady] = React.useState(!!(typeof window !== 'undefined' && window.google?.maps?.places));

  const themes = {
    light: { bg: '#FBFAF5', text: '#1A1F1C', subtle: 'rgba(26,31,28,0.55)', border: 'rgba(26,31,28,0.12)', inputBg: 'transparent' },
    dark:  { bg: '#0E1614', text: '#F0F2EE', subtle: 'rgba(240,242,238,0.55)', border: 'rgba(240,242,238,0.15)', inputBg: 'transparent' },
    cream: { bg: '#F4F0E6', text: '#1A1F1C', subtle: 'rgba(26,31,28,0.55)', border: 'rgba(26,31,28,0.12)', inputBg: 'transparent' },
  };
  const t = themes[theme];

  const propertyTypes = ['Commercial', 'Residential', 'HOA', 'Industrial'];
  const serviceOptions = ['Property Maintenance', 'Site Enhancements', 'Snow & Ice Management', "I'm not sure yet"];

  const errors = {
    name: !data.name.trim() ? 'Required' : null,
    email: !data.email ? 'Required' : !/\S+@\S+\.\S+/.test(data.email) ? 'Invalid email' : null,
    phone: !data.phone ? 'Required' : data.phone.replace(/\D/g, '').length < 10 ? 'Invalid phone' : null,
    address: !data.address.trim() ? 'Required' : null,
    propertyType: !data.propertyType ? 'Required' : null,
    service: !data.service.length ? 'Pick at least one' : null,
  };
  const isValid = !Object.values(errors).some(Boolean);

  const set = (key, value) => setData(d => ({ ...d, [key]: value }));
  const toggleService = (opt) => setData(d => {
    const arr = d.service || [];
    return { ...d, service: arr.includes(opt) ? arr.filter(x => x !== opt) : [...arr, opt] };
  });

  const handleSubmit = async (e) => {
    if (e) e.preventDefault();
    if (!isValid) {
      setShowErrors(true);
      return;
    }
    setSubmitting(true);
    setSubmitError(null);
    try {
      // Lead intake migrated from Vercel /api/lead to a Supabase Edge Function.
      // The Supabase function (lead-intake) is the canonical "create new lead"
      // code path — same module as cold inbounds, single Pipedrive sync, single
      // Slack helper, single Lisa first-touch prompt. If anything goes wrong we
      // can flip back to '/api/lead' (Vercel) in one line — that endpoint stays
      // alive as a 308 redirect during the rollout window.
      const res = await fetch('https://vmlzjbwmrtvhogckttmt.supabase.co/functions/v1/lead-intake', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data),
      });
      if (!res.ok) {
        const err = await res.json().catch(() => ({}));
        throw new Error(err.message || 'Submission failed');
      }
      setSubmitted(true);
      if (typeof window.gtag === 'function') {
        window.gtag('event', 'generate_lead', {
          event_category: 'engagement',
          event_label: data.propertyType || 'unknown',
          value: 1,
        });
      }
    } catch (err) {
      setSubmitError(err.message || 'Something went wrong. Please call us at (630) 296-4277.');
    } finally {
      setSubmitting(false);
    }
  };

  // ESC closes
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape' && onClose) onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);

  // Google Maps Places: lazy-load on form mount
  React.useEffect(() => {
    if (window.google?.maps?.places) { setGmapsReady(true); return; }
    let cancelled = false;
    (async () => {
      try {
        if (!window.__gmapsScriptLoading) {
          const cfg = await fetch('/api/config').then(r => r.ok ? r.json() : null).catch(() => null);
          const key = cfg?.googleMapsApiKey;
          if (!key) return;
          window.__gmapsScriptLoading = new Promise((resolve, reject) => {
            const s = document.createElement('script');
            s.src = `https://maps.googleapis.com/maps/api/js?key=${encodeURIComponent(key)}&libraries=places&v=weekly`;
            s.async = true; s.defer = true;
            s.onload = () => resolve();
            s.onerror = () => reject(new Error('Google Maps failed to load'));
            document.head.appendChild(s);
          });
        }
        await window.__gmapsScriptLoading;
        // Belt-and-suspenders: wait until the places library is actually attached.
        // Without this, a race can fire setGmapsReady(true) before window.google.maps.places exists.
        for (let i = 0; i < 50 && !window.google?.maps?.places; i++) {
          await new Promise(r => setTimeout(r, 50));
        }
        if (!cancelled && window.google?.maps?.places) setGmapsReady(true);
      } catch (e) {
        console.warn('Address autocomplete unavailable:', e?.message || e);
      }
    })();
    return () => { cancelled = true; };
  }, []);

  // Refs for inputs we need direct access to
  const nameInputRef = React.useRef(null);
  const addressInputRef = React.useRef(null);

  // Attach Autocomplete to address input once gmaps is ready
  React.useEffect(() => {
    if (!gmapsReady || !addressInputRef.current) return;
    // Extra guard: if places isn't actually loaded yet, bail silently — autocomplete just won't attach this render
    if (!window.google?.maps?.places?.Autocomplete) return;
    const ac = new window.google.maps.places.Autocomplete(addressInputRef.current, {
      bounds: new window.google.maps.LatLngBounds(
        { lat: 41.40, lng: -88.50 },
        { lat: 42.50, lng: -87.30 },
      ),
      strictBounds: false,
      componentRestrictions: { country: 'us' },
      fields: ['formatted_address', 'geometry', 'address_components', 'place_id'],
    });
    const listener = ac.addListener('place_changed', () => {
      const place = ac.getPlace();
      if (!place || !place.formatted_address) return;
      const parts = {};
      (place.address_components || []).forEach(c => {
        if (c.types.includes('locality')) parts.city = c.long_name;
        else if (!parts.city && c.types.includes('sublocality')) parts.city = c.long_name;
        else if (c.types.includes('administrative_area_level_1')) parts.state = c.short_name;
        else if (c.types.includes('postal_code')) parts.zip = c.long_name;
      });
      setData(d => ({
        ...d,
        address: place.formatted_address,
        addressCity: parts.city || null,
        addressState: parts.state || null,
        addressZip: parts.zip || null,
        addressLat: place.geometry?.location?.lat?.() ?? null,
        addressLng: place.geometry?.location?.lng?.() ?? null,
        addressPlaceId: place.place_id || null,
      }));
    });
    return () => {
      window.google?.maps?.event?.removeListener?.(listener);
    };
  }, [gmapsReady]);

  // Auto-focus name input when form opens
  React.useEffect(() => {
    setTimeout(() => nameInputRef.current?.focus(), 350);
  }, []);

  // Success screen
  if (submitted) {
    return (
      <div style={{
        background: t.bg, color: t.text, height: '100%', width: '100%',
        display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
        fontFamily: '-apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, sans-serif',
        padding: 40, textAlign: 'center',
      }}>
        <style>{`@keyframes polarisPop { 0% { transform: scale(0.6); opacity: 0; } 100% { transform: scale(1); opacity: 1; } }`}</style>
        <div style={{
          width: 64, height: 64, borderRadius: '50%',
          background: accentColor, color: theme === 'dark' ? '#0E1614' : '#fff',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          marginBottom: 32,
          animation: 'polarisPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1)',
        }}>
          <Icon name="check" size={28} stroke="currentColor" strokeWidth={2.5} />
        </div>
        <h2 style={{ fontSize: 'clamp(28px, 4vw, 44px)', fontWeight: 500, letterSpacing: '-0.02em', margin: '0 0 16px', lineHeight: 1.1 }}>
          Thank you, {data.name.split(' ')[0]}.
        </h2>
        <p style={{ fontSize: 18, color: t.subtle, maxWidth: 460, lineHeight: 1.5, margin: '0 0 40px' }}>
          Our lead agent will reach out shortly to learn more about your project. A senior team
          member will follow up with your personalized proposal.
        </p>
        {onClose && (
          <button onClick={onClose} style={{
            background: accentColor,
            color: theme === 'dark' ? '#0E1614' : '#fff',
            border: 'none', cursor: 'pointer',
            padding: '14px 36px', borderRadius: 100,
            fontSize: 14, fontWeight: 600, letterSpacing: '0.02em',
            fontFamily: 'inherit',
            transition: 'all .2s',
          }}>
            Done
          </button>
        )}
      </div>
    );
  }

  // Single-page form
  const inputStyle = {
    width: '100%', boxSizing: 'border-box',
    background: 'transparent', border: `1.5px solid ${t.border}`, borderRadius: 10,
    outline: 'none', color: 'inherit',
    fontFamily: 'inherit', fontSize: 16, fontWeight: 400,
    padding: '14px 16px', transition: 'border-color .2s',
  };
  const onFocusInput = (e) => { e.currentTarget.style.borderColor = accentColor; };
  const onBlurInput = (e) => { e.currentTarget.style.borderColor = t.border; };



  return (
    <div style={{
      background: t.bg, color: t.text, height: '100%', width: '100%',
      fontFamily: '-apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, sans-serif',
      display: 'flex', flexDirection: 'column', position: 'relative', overflow: 'auto',
      // Reserve space for the sticky header so iOS autofill doesn't over-scroll past it
      scrollPaddingTop: 80,
      overflowAnchor: 'none',
    }}>
      {/* Sticky header */}
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        padding: '18px 24px', flexShrink: 0, borderBottom: `1px solid ${t.border}`,
        position: 'sticky', top: 0, background: t.bg, zIndex: 2,
      }}>
        <div style={{ fontSize: 11, letterSpacing: '0.18em', textTransform: 'uppercase', color: t.subtle, fontWeight: 600 }}>
          Get in touch
        </div>
        {onClose && (
          <button onClick={onClose} aria-label="Close" style={{
            background: 'transparent', border: 'none', cursor: 'pointer',
            color: t.subtle, padding: 6, display: 'flex',
          }}>
            <Icon name="close" size={20} />
          </button>
        )}
      </div>

      {/* Form */}
      <form onSubmit={handleSubmit} style={{
        flex: 1, padding: 'clamp(24px, 5vw, 40px) clamp(20px, 5vw, 56px) clamp(40px, 8vw, 64px)',
        maxWidth: 640, width: '100%', margin: '0 auto', boxSizing: 'border-box',
      }}>
        <h1 style={{
          fontSize: 'clamp(28px, 5vw, 44px)', fontWeight: 500, letterSpacing: '-0.025em',
          lineHeight: 1.1, margin: '8px 0 12px',
        }}>
          Let's talk about your property.
        </h1>
        <p style={{
          fontSize: 16, color: t.subtle, lineHeight: 1.55, margin: '0 0 32px', maxWidth: 480,
        }}>
          A senior account manager replies within one business day. We'll come prepared.
        </p>

        <FormField label="Your name" error={errors.name} showErrors={showErrors} subtleColor={t.subtle} htmlFor="contact-name">
          <input
            ref={nameInputRef}
            id="contact-name"
            name="name"
            type="text"
            placeholder="Full name"
            value={data.name}
            onChange={(e) => set('name', e.target.value)}
            style={inputStyle}
            onFocus={onFocusInput}
            onBlur={onBlurInput}
            autoComplete="name"
            autoCapitalize="words"
          />
        </FormField>

        <FormField label="Email" error={errors.email} showErrors={showErrors} subtleColor={t.subtle} htmlFor="contact-email">
          <input
            id="contact-email"
            name="email"
            type="email"
            placeholder="you@company.com"
            value={data.email}
            onChange={(e) => set('email', e.target.value)}
            style={inputStyle}
            onFocus={onFocusInput}
            onBlur={onBlurInput}
            autoComplete="email"
            inputMode="email"
            autoCapitalize="off"
            spellCheck={false}
          />
        </FormField>

        <FormField label="Phone" error={errors.phone} showErrors={showErrors} subtleColor={t.subtle} htmlFor="contact-phone">
          <input
            id="contact-phone"
            name="phone"
            type="tel"
            placeholder="(312) 555-0100"
            value={data.phone}
            onChange={(e) => set('phone', e.target.value)}
            style={inputStyle}
            onFocus={onFocusInput}
            onBlur={onBlurInput}
            autoComplete="tel"
            inputMode="tel"
          />
        </FormField>

        <FormField label="Property address" error={errors.address} showErrors={showErrors} subtleColor={t.subtle} htmlFor="contact-address">
          <input
            ref={addressInputRef}
            id="contact-address"
            name="address"
            type="text"
            placeholder="123 N. Wacker Dr., Chicago"
            value={data.address}
            onChange={(e) => set('address', e.target.value)}
            style={inputStyle}
            onFocus={onFocusInput}
            onBlur={onBlurInput}
            autoComplete="off"
          />
        </FormField>

        <FormField label="Property type" error={errors.propertyType} showErrors={showErrors} subtleColor={t.subtle}>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(140px, 1fr))', gap: 8 }}>
            {propertyTypes.map(opt => {
              const sel = data.propertyType === opt;
              return (
                <button
                  type="button"
                  key={opt}
                  onClick={() => set('propertyType', opt)}
                  style={{
                    padding: '14px 16px', borderRadius: 8,
                    background: sel ? accentColor : 'transparent',
                    color: sel ? (theme === 'dark' ? '#0E1614' : '#fff') : 'inherit',
                    border: `1.5px solid ${sel ? accentColor : t.border}`,
                    cursor: 'pointer', fontSize: 15, fontWeight: 500,
                    fontFamily: 'inherit', transition: 'all .15s',
                  }}
                >
                  {opt}
                </button>
              );
            })}
          </div>
        </FormField>

        <FormField label="Services of interest" error={errors.service} showErrors={showErrors} subtleColor={t.subtle}>
          <div style={{ display: 'grid', gap: 8 }}>
            {serviceOptions.map(opt => {
              const sel = data.service.includes(opt);
              return (
                <button
                  type="button"
                  key={opt}
                  onClick={() => toggleService(opt)}
                  style={{
                    display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                    padding: '14px 16px', borderRadius: 8,
                    background: sel ? accentColor : 'transparent',
                    color: sel ? (theme === 'dark' ? '#0E1614' : '#fff') : 'inherit',
                    border: `1.5px solid ${sel ? accentColor : t.border}`,
                    cursor: 'pointer', fontSize: 15, fontWeight: 500,
                    fontFamily: 'inherit', textAlign: 'left', transition: 'all .15s',
                  }}
                >
                  <span>{opt}</span>
                  <span style={{
                    width: 20, height: 20, borderRadius: 4,
                    border: `1.5px solid ${sel ? 'currentColor' : t.border}`,
                    background: sel ? 'currentColor' : 'transparent',
                    display: 'flex', alignItems: 'center', justifyContent: 'center',
                    flexShrink: 0,
                  }}>
                    {sel && (
                      <span style={{ color: accentColor, display: 'flex' }}>
                        <Icon name="check" size={12} stroke="currentColor" strokeWidth={3} />
                      </span>
                    )}
                  </span>
                </button>
              );
            })}
          </div>
        </FormField>

        <FormField label="Anything else we should know?" optional showErrors={showErrors} subtleColor={t.subtle}>
          <textarea
            placeholder="Optional. Share context, timing, scope of work..."
            value={data.notes}
            onChange={(e) => set('notes', e.target.value)}
            style={{ ...inputStyle, minHeight: 110, resize: 'vertical', lineHeight: 1.5 }}
            onFocus={onFocusInput}
            onBlur={onBlurInput}
          />
        </FormField>

        {/* SMS opt-in — benefit-forward framing, but legally optional per TCPA */}
        <div style={{
          marginBottom: 20, padding: 18, borderRadius: 10,
          background: 'rgba(44,82,73,0.04)', border: `1.5px solid ${t.border}`,
        }}>
          <label htmlFor="contact-sms-consent" style={{
            display: 'flex', alignItems: 'flex-start', gap: 12,
            cursor: 'pointer', fontSize: 15, lineHeight: 1.55, color: t.text,
          }}>
            <input
              id="contact-sms-consent"
              name="smsConsent"
              type="checkbox"
              checked={data.smsConsent}
              onChange={(e) => set('smsConsent', e.target.checked)}
              style={{
                marginTop: 4, width: 18, height: 18, flexShrink: 0,
                accentColor: accentColor, cursor: 'pointer',
              }}
            />
            <span>
              <strong>Yes, text me — this is how Polaris delivers our best service.</strong>
              {' '}We use text for project photos from the job site, same-day scheduling,
              weather alerts, and quick questions during your project. Fast, personal,{' '}
              <strong>no spam, ever.</strong>
            </span>
          </label>
          <p style={{
            fontSize: 12, color: t.subtle, lineHeight: 1.6, margin: '12px 0 0 30px',
          }}>
            Message frequency varies — you may receive multiple messages per day during active
            scheduling or project work. Reply <strong>STOP</strong> to opt out anytime,{' '}
            <strong>HELP</strong> for help. Message and data rates may apply. By checking this
            box you agree to our{' '}
            <a href="/terms" style={{ color: accentColor, textDecoration: 'underline' }}>Terms of Service</a>
            {' '}and{' '}
            <a href="/privacy" style={{ color: accentColor, textDecoration: 'underline' }}>Privacy Policy</a>.
            Opt-in is optional — without it, we'll still reach out by email or phone, just less immediately.
          </p>
        </div>

        {submitError && (
          <div style={{
            padding: 14, borderRadius: 8, background: 'rgba(196,68,68,0.08)',
            border: '1px solid rgba(196,68,68,0.2)', color: '#c44',
            fontSize: 14, marginBottom: 20,
          }}>
            {submitError}
          </div>
        )}

        <button
          type="submit"
          disabled={submitting}
          style={{
            width: '100%', padding: '16px 24px', borderRadius: 100,
            background: submitting ? t.border : accentColor,
            color: submitting ? t.subtle : (theme === 'dark' ? '#0E1614' : '#fff'),
            border: 'none', cursor: submitting ? 'default' : 'pointer',
            fontSize: 15, fontWeight: 600, letterSpacing: '0.02em',
            fontFamily: 'inherit',
            display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
            transition: 'all .2s', marginTop: 8,
          }}
        >
          {submitting ? 'Sending…' : 'Send request'}
          {!submitting && <Icon name="arrow-right" size={16} stroke="currentColor" strokeWidth={2} />}
        </button>

        <p style={{ fontSize: 12, color: t.subtle, textAlign: 'center', margin: '16px 0 0', lineHeight: 1.5 }}>
          By submitting, you'll be contacted by Polaris Landscape via email or phone.
        </p>
      </form>
    </div>
  );
}

Object.assign(window, { PolarisLogo, Icon, ChicagoMap, ContactFlow });
