// Inquiry Wizard (8-step), Footer, FAQ, Tweaks panel

// ─────────────────────────────────────────────────────────────────────────
// Validation helpers
// ─────────────────────────────────────────────────────────────────────────
const digits = (s) => (s || "").replace(/\D/g, "");
const isValidEmail = (s) => /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test((s || "").trim());
const isValidPhone = (s) => {
  const d = digits(s);
  return d.length === 10 || (d.length === 11 && d[0] === "1");
};
const formatPhone = (s) => {
  let d = digits(s);
  if (d.length === 11 && d[0] === "1") d = d.slice(1);
  d = d.slice(0, 10);
  if (d.length === 0) return "";
  if (d.length < 4) return "(" + d;
  if (d.length < 7) return `(${d.slice(0, 3)}) ${d.slice(3)}`;
  return `(${d.slice(0, 3)}) ${d.slice(3, 6)}-${d.slice(6)}`;
};

// File → base64 data URL
const fileToDataURL = (file) => new Promise((res, rej) => {
  const fr = new FileReader();
  fr.onload = () => res(fr.result);
  fr.onerror = rej;
  fr.readAsDataURL(file);
});

// ─────────────────────────────────────────────────────────────────────────
// Main wizard
// ─────────────────────────────────────────────────────────────────────────
// ── Address autocomplete ─────────────────────────────────────────────
// Uses Places API (New) REST endpoints directly. No Google JS SDK; we render
// our own dropdown matching the brand. Falls back to a plain input when no
// key is configured.
function parseAddressComponents(components) {
  let streetNumber = "", route = "", subpremise = "";
  let city = "", state = "", zip = "", zipExt = "";
  for (const c of components) {
    const t = c.types || [];
    if (t.includes("street_number")) streetNumber = c.long_name;
    else if (t.includes("route")) route = c.long_name;
    else if (t.includes("subpremise")) subpremise = c.long_name;
    else if (t.includes("locality")) city = c.long_name;
    else if (!city && (t.includes("sublocality") || t.includes("sublocality_level_1") || t.includes("neighborhood"))) city = c.long_name;
    else if (!city && t.includes("postal_town")) city = c.long_name;
    else if (!city && t.includes("administrative_area_level_3")) city = c.long_name;
    else if (t.includes("administrative_area_level_1")) state = c.short_name;
    else if (t.includes("postal_code")) zip = c.long_name;
    else if (t.includes("postal_code_suffix")) zipExt = c.long_name;
  }
  return {
    line1: [streetNumber, route].filter(Boolean).join(" "),
    line2: subpremise,
    city,
    state,
    zip: zipExt && zip ? `${zip}-${zipExt}` : zip,
  };
}

function AddressAutocomplete({ value, onChange, onPlace, error, placeholder, autoFocus }) {
  const [suggestions, setSuggestions] = useState([]);
  const [open, setOpen] = useState(false);
  const [highlight, setHighlight] = useState(-1);
  const wrapRef = useRef(null);
  const inputRef = useRef(null);
  const debounceRef = useRef(null);
  const sessionTokenRef = useRef(null);

  const getSessionToken = () => {
    if (!sessionTokenRef.current) {
      sessionTokenRef.current = (window.crypto && crypto.randomUUID && crypto.randomUUID()) || String(Math.random()).slice(2);
    }
    return sessionTokenRef.current;
  };

  const fetchSuggestions = async (input) => {
    if (!input || input.trim().length < 3) {
      setSuggestions([]); setOpen(false); return;
    }
    const key = window.GOOGLE_PLACES_KEY;
    if (!key) return;
    try {
      const res = await fetch("https://places.googleapis.com/v1/places:autocomplete", {
        method: "POST",
        headers: { "Content-Type": "application/json", "X-Goog-Api-Key": key },
        body: JSON.stringify({
          input,
          sessionToken: getSessionToken(),
          includedRegionCodes: ["us"],
        }),
      });
      if (!res.ok) {
        console.warn("[places] autocomplete", res.status, await res.text().catch(() => ""));
        return;
      }
      const data = await res.json();
      setSuggestions(data.suggestions || []);
      setOpen(true);
      setHighlight(-1);
    } catch (err) {
      console.warn("[places] autocomplete error", err);
    }
  };

  const handleChange = (v) => {
    onChange(v);
    clearTimeout(debounceRef.current);
    debounceRef.current = setTimeout(() => fetchSuggestions(v), 220);
  };

  const handleSelect = async (sug) => {
    const pred = sug.placePrediction;
    if (!pred) return;
    setOpen(false);
    setSuggestions([]);
    const key = window.GOOGLE_PLACES_KEY;
    try {
      const url = `https://places.googleapis.com/v1/places/${encodeURIComponent(pred.placeId)}?sessionToken=${encodeURIComponent(getSessionToken())}`;
      const res = await fetch(url, {
        headers: { "X-Goog-Api-Key": key, "X-Goog-FieldMask": "addressComponents,formattedAddress" },
      });
      if (!res.ok) {
        console.warn("[places] details", res.status);
        onChange(pred.text?.text || "");
        return;
      }
      const place = await res.json();
      sessionTokenRef.current = null; // new session for next lookup
      const components = (place.addressComponents || []).map(c => ({
        long_name: c.longText, short_name: c.shortText, types: c.types,
      }));
      const parts = parseAddressComponents(components);
      onPlace({ ...parts, formatted: place.formattedAddress || pred.text?.text || "" });
    } catch (err) {
      console.warn("[places] details error", err);
      onChange(pred.text?.text || "");
    }
  };

  useEffect(() => {
    const onDown = (e) => {
      if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
    };
    document.addEventListener("mousedown", onDown);
    return () => document.removeEventListener("mousedown", onDown);
  }, []);

  const onKeyDown = (e) => {
    if (!open || suggestions.length === 0) {
      if (e.key === "ArrowDown" && value && value.length >= 3) fetchSuggestions(value);
      return;
    }
    if (e.key === "ArrowDown") {
      e.preventDefault();
      setHighlight(h => Math.min(h + 1, suggestions.length - 1));
    } else if (e.key === "ArrowUp") {
      e.preventDefault();
      setHighlight(h => Math.max(h - 1, 0));
    } else if (e.key === "Enter") {
      if (highlight >= 0 && highlight < suggestions.length) {
        e.preventDefault();
        handleSelect(suggestions[highlight]);
      }
    } else if (e.key === "Escape") {
      setOpen(false);
    }
  };

  const fStyle = {
    ...fieldStyle,
    borderColor: error ? "var(--maroon)" : "var(--line)",
    background: error ? "rgba(107,20,22,0.04)" : "var(--cream)",
  };

  return (
    <div ref={wrapRef} style={{ position: "relative" }}>
      <input
        ref={inputRef}
        type="text"
        value={value}
        onChange={(e) => handleChange(e.target.value)}
        onFocus={() => { if (suggestions.length > 0) setOpen(true); }}
        onKeyDown={onKeyDown}
        placeholder={placeholder}
        autoComplete="off"
        autoFocus={autoFocus}
        style={fStyle}
      />
      {open && suggestions.length > 0 && (
        <div role="listbox" style={{
          position: "absolute",
          top: "calc(100% + 4px)",
          left: 0, right: 0,
          background: "var(--bone)",
          border: "1px solid var(--line)",
          boxShadow: "0 16px 40px rgba(10,9,8,0.22)",
          zIndex: 10000,
          maxHeight: 340,
          overflowY: "auto",
        }}>
          {suggestions.map((sug, i) => {
            const pred = sug.placePrediction;
            if (!pred) return null;
            const main = pred.structuredFormat?.mainText?.text || pred.text?.text || "";
            const secondary = pred.structuredFormat?.secondaryText?.text || "";
            const active = highlight === i;
            return (
              <div
                key={pred.placeId || i}
                role="option"
                aria-selected={active}
                onMouseDown={(e) => { e.preventDefault(); handleSelect(sug); }}
                onMouseEnter={() => setHighlight(i)}
                style={{
                  padding: "12px 16px",
                  fontSize: 14,
                  lineHeight: 1.4,
                  cursor: "pointer",
                  borderBottom: i < suggestions.length - 1 ? "1px solid rgba(217,210,198,0.5)" : "none",
                  background: active ? "rgba(232,212,168,0.18)" : "transparent",
                }}
              >
                <div style={{ fontWeight: 500, color: "var(--ink)" }}>{main}</div>
                {secondary && (
                  <div style={{ fontSize: 12, color: "var(--mute)", marginTop: 2 }}>{secondary}</div>
                )}
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

// US states for dropdown
const US_STATES = [
  ["AL","Alabama"],["AK","Alaska"],["AZ","Arizona"],["AR","Arkansas"],["CA","California"],
  ["CO","Colorado"],["CT","Connecticut"],["DE","Delaware"],["DC","District of Columbia"],
  ["FL","Florida"],["GA","Georgia"],["HI","Hawaii"],["ID","Idaho"],["IL","Illinois"],
  ["IN","Indiana"],["IA","Iowa"],["KS","Kansas"],["KY","Kentucky"],["LA","Louisiana"],
  ["ME","Maine"],["MD","Maryland"],["MA","Massachusetts"],["MI","Michigan"],
  ["MN","Minnesota"],["MS","Mississippi"],["MO","Missouri"],["MT","Montana"],
  ["NE","Nebraska"],["NV","Nevada"],["NH","New Hampshire"],["NJ","New Jersey"],
  ["NM","New Mexico"],["NY","New York"],["NC","North Carolina"],["ND","North Dakota"],
  ["OH","Ohio"],["OK","Oklahoma"],["OR","Oregon"],["PA","Pennsylvania"],
  ["RI","Rhode Island"],["SC","South Carolina"],["SD","South Dakota"],["TN","Tennessee"],
  ["TX","Texas"],["UT","Utah"],["VT","Vermont"],["VA","Virginia"],["WA","Washington"],
  ["WV","West Virginia"],["WI","Wisconsin"],["WY","Wyoming"]
];
const US_STATE_CODES = new Set(US_STATES.map(([c]) => c));
const isValidZip = (s) => /^\d{5}(-\d{4})?$/.test((s || "").trim());
const isValidState = (s) => US_STATE_CODES.has((s || "").trim().toUpperCase());

const STEP_TITLES = [
  { eyebrow: "Location",      title: "Where are you located?",            sub: "We service NY, NJ, and PA directly. Anywhere else, we'll route you to StoneGuard, who connects you with your nearest installer." },
  { eyebrow: "Your stone",    title: "What type of stone?",                sub: "Don't worry if you're not sure — pick \"Other\" and tell us in the box." },
  { eyebrow: "Project scope", title: "Which surfaces, and how big?",       sub: "Select everything that needs protection. Square footage is a ballpark." },
  { eyebrow: "Situation",     title: "What best describes your situation right now?", sub: "Helps us know if we're protecting fresh stone or fixing trouble first." },
  { eyebrow: "Timeline",      title: "When would you like this done?",     sub: "We're currently booking about a month out for most projects." },
  { eyebrow: "Discovery",     title: "How did you find us?",               sub: "Helps us understand what's working — and what isn't." },
  { eyebrow: "Details",       title: "Anything else? Photos, message, both.", sub: "Optional, but a single photo can change our quote dramatically." },
  { eyebrow: "Contact",       title: "Where should we send your plan?",    sub: "You'll get a written protection plan and quote within 24 hours." },
];

function InquiryWizard({ open, onClose, ctaPromise }) {
  const [step, setStep] = useState(0);
  const [data, setData] = useState(initialData());
  const [touched, setTouched] = useState({});
  const [submitting, setSubmitting] = useState(false);
  const [serverError, setServerError] = useState(null);
  const [submitted, setSubmitted] = useState(false);
  const startedAtRef = useRef(null);

  useEffect(() => {
    if (open) {
      setStep(0);
      setData(initialData());
      setTouched({});
      setSubmitted(false);
      setServerError(null);
      startedAtRef.current = Date.now();
      if (typeof window !== "undefined" && window.mtTrack) {
        window.mtTrack("StartInquiry", { source: "desktop" }, null, true);
      }
      document.body.style.overflow = "hidden";
    } else {
      document.body.style.overflow = "";
    }
  }, [open]);

  if (!open) return null;

  const total = STEP_TITLES.length;
  const update = (k, v) => setData(d => ({ ...d, [k]: v }));
  const toggleArr = (k, v) => setData(d => ({
    ...d,
    [k]: d[k].includes(v) ? d[k].filter(x => x !== v) : [...d[k], v]
  }));
  const onBlur = (k) => setTouched(t => ({ ...t, [k]: true }));

  // Per-field errors for contact step
  const errors = {
    name:  data.name.trim() ? null : "Please enter your name.",
    email: isValidEmail(data.email) ? null : "Please enter a valid email.",
    phone: isValidPhone(data.phone) ? null : "Please enter a valid US phone number.",
    addressLine1: data.addressLine1.trim() ? null : "Please enter your street address.",
    addressCity:  data.addressCity.trim()  ? null : "Please enter a city.",
    addressState: isValidState(data.addressState) ? null : "Please pick a state.",
    addressZip:   isValidZip(data.addressZip)     ? null : "Please enter a valid ZIP.",
  };
  const contactValid = !errors.name && !errors.email && !errors.phone
    && !errors.addressLine1 && !errors.addressCity && !errors.addressState && !errors.addressZip;

  const canNext = () => {
    switch (step) {
      case 0: return !!data.location;
      case 1: return !!data.stone && (data.stone !== "Other" || data.stoneOther.trim().length > 0);
      case 2: return data.surfaces.length > 0 && (!data.surfaces.includes("Other") || data.surfacesOther.trim().length > 0);
      case 3: return !!data.situation;
      case 4: return !!data.timeline;
      case 5: return !!data.howHeard && (data.howHeard !== "Other" || data.howHeardOther.trim().length > 0);
      case 6: return true; // photos/message optional
      case 7: return contactValid;
      default: return false;
    }
  };

  const handleSubmit = async () => {
    setTouched({
      name: true, email: true, phone: true,
      addressLine1: true, addressCity: true, addressState: true, addressZip: true,
    });
    if (!contactValid) return;

    // Silent bot filter
    const tooFast = Date.now() - (startedAtRef.current || 0) < 3000;
    if (data.website || tooFast) {
      setSubmitted(true);
      return;
    }

    setSubmitting(true);
    setServerError(null);

    // Meta Pixel/CAPI dedup: one event_id shared by the browser Lead event
    // (fired below on success) and the server CAPI event (api/inquiry.js).
    const eventId = (window.crypto && window.crypto.randomUUID)
      ? window.crypto.randomUUID()
      : String(Date.now()) + Math.random();
    const fbCookies = (window.mtFbCookies && window.mtFbCookies()) || {};

    const payload = {
      // location → routing
      location: data.location,
      route: data.location === "Other" ? "stoneguard" : "mt",

      // Meta Conversions API dedup + match keys
      event_id: eventId,
      fbp: fbCookies.fbp || null,
      fbc: fbCookies.fbc || null,

      // stone
      stone: data.stone,
      stone_other: data.stone === "Other" ? data.stoneOther.trim() : null,

      // surfaces
      surfaces: data.surfaces.filter(s => s !== "Other"),
      surfaces_other: data.surfaces.includes("Other") ? data.surfacesOther.trim() : null,
      sqft: data.sqftKnown ? data.sqft : null,
      sqft_known: !!data.sqftKnown,

      // qualifiers
      situation: data.situation,
      timeline: data.timeline,
      how_heard: data.howHeard,
      how_heard_other: data.howHeard === "Other" ? data.howHeardOther.trim() : null,

      // optional message + photos (base64 data URLs)
      message: data.message.trim(),
      photos: data.photos.map(p => ({
        name: p.name, size: p.size, type: p.type, data_url: p.dataUrl,
      })),

      // contact
      name: data.name.trim(),
      email: data.email.trim(),
      phone: digits(data.phone),
      phone_formatted: data.phone.trim(),
      address_line1: data.addressLine1.trim(),
      address_line2: data.addressLine2.trim(),
      address_city:  data.addressCity.trim(),
      address_state: data.addressState.trim().toUpperCase(),
      address_zip:   data.addressZip.trim(),
      address_formatted: data.addressFormatted ||
        [
          [data.addressLine1, data.addressLine2].filter(Boolean).join(" "),
          data.addressCity,
          [data.addressState, data.addressZip].filter(Boolean).join(" "),
        ].filter(Boolean).join(", "),
      sms_consent: !!data.smsConsent,

      // context
      source: "desktop",
      page: typeof window !== "undefined" ? window.location.pathname : "",
      referrer: typeof document !== "undefined" ? document.referrer : "",
      submitted_at: new Date().toISOString(),
    };

    try {
      const res = await fetch("/api/inquiry", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      // Fire the browser Lead event with the shared event_id (the server
      // mirrors it via CAPI). Serviceable area = standard "Lead"; out-of-area
      // StoneGuard handoffs get a distinct custom event so ad optimization
      // only chases leads Michael can actually service.
      if (window.mtTrack) {
        if (data.location === "Other") {
          window.mtTrack("LeadOutOfArea", { content_category: "stoneguard_handoff" }, eventId, true);
        } else {
          window.mtTrack("Lead", {
            value: window.MT_LEAD_VALUE || 0,
            currency: "USD",
            content_category: "stone_protection",
            content_name: data.location || "",
          }, eventId);
        }
      }
      setSubmitted(true);
    } catch (err) {
      setServerError("Something went wrong sending your inquiry. Please try again, or call Michael directly at (908) 866-1919.");
    } finally {
      setSubmitting(false);
    }
  };

  const meta = STEP_TITLES[step];
  const isOutOfArea = data.location === "Other";

  return (
    <div style={{
      position: "fixed", inset: 0, zIndex: 100,
      display: "flex", alignItems: "stretch", justifyContent: "flex-end",
      animation: "fadein .25s ease",
    }}>
      <div onClick={onClose} style={{
        position: "absolute", inset: 0, background: "rgba(10,9,8,0.55)",
        backdropFilter: "blur(4px)",
      }}/>
      <aside style={{
        position: "relative", zIndex: 1,
        width: "min(660px, 100%)", height: "100%", overflowY: "auto",
        background: "var(--bone)",
        display: "flex", flexDirection: "column",
        animation: "slideIn .5s cubic-bezier(.2,.7,.2,1)",
      }}>
        <style>{`
          @keyframes slideIn { from{ transform: translateX(40px); opacity:0;} to{transform:none; opacity:1;} }
        `}</style>

        {/* Header */}
        <header style={{
          padding: "24px 40px", borderBottom: "1px solid var(--line)",
          display: "flex", justifyContent: "space-between", alignItems: "center",
          position: "sticky", top: 0, background: "var(--bone)", zIndex: 2,
        }}>
          <div className="mono" style={{ fontSize: 11, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--mute)" }}>
            {submitted ? "Plan requested" : `Step ${step + 1} of ${total}`}
          </div>
          <button onClick={onClose} aria-label="Close" style={{
            width: 32, height: 32, display: "grid", placeItems: "center",
            borderRadius: 2, border: "1px solid var(--line)",
          }}>
            <svg width="12" height="12" viewBox="0 0 12 12"><path d="M1 1l10 10M11 1L1 11" stroke="currentColor" strokeWidth="1.2"/></svg>
          </button>
        </header>

        {/* Progress */}
        {!submitted && (
          <div style={{ height: 2, background: "var(--line)" }}>
            <div style={{
              height: "100%", background: "var(--ink)",
              width: `${((step + 1) / total) * 100}%`,
              transition: "width .4s ease",
            }}/>
          </div>
        )}

        {/* Body */}
        <div style={{ flex: 1, padding: "48px 40px" }}>
          {submitted ? (
            <SubmittedView data={data} onClose={onClose} />
          ) : (
            <>
              <div className="eyebrow" style={{ marginBottom: 16 }}>{meta.eyebrow}</div>
              <h2 className="serif" style={{ fontSize: 36, lineHeight: 1.1, letterSpacing: "-0.02em", marginBottom: 12, textWrap: "balance" }}>
                {meta.title}
              </h2>
              <p style={{ fontSize: 15, color: "var(--mute)", lineHeight: 1.55, marginBottom: 36, maxWidth: 500 }}>
                {meta.sub}
              </p>

              {/* Step content */}
              {step === 0 && (
                <>
                  <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
                    {["NY", "NJ", "PA", "Other"].map(s => (
                      <OptionTile key={s} selected={data.location === s} onClick={() => update("location", s)}>
                        <span className="serif" style={{ fontSize: 22 }}>{s === "NY" ? "New York" : s === "NJ" ? "New Jersey" : s === "PA" ? "Pennsylvania" : "Somewhere else"}</span>
                      </OptionTile>
                    ))}
                  </div>
                  {isOutOfArea && (
                    <OutOfAreaNote />
                  )}
                </>
              )}

              {step === 1 && (
                <>
                  <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
                    {["Marble", "Quartzite", "Quartz", "Travertine", "Porcelain", "Granite", "Other"].map(s => (
                      <OptionTile key={s} selected={data.stone === s} onClick={() => update("stone", s)} wide={s === "Other"}>
                        {s}
                      </OptionTile>
                    ))}
                  </div>
                  {data.stone === "Other" && (
                    <input
                      type="text"
                      value={data.stoneOther}
                      onChange={e => update("stoneOther", e.target.value)}
                      placeholder="Tell us what kind of stone"
                      autoFocus
                      style={{ ...fieldStyle, marginTop: 12 }}
                    />
                  )}
                </>
              )}

              {step === 2 && (
                <>
                  <div className="mono" style={{ fontSize: 11, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--mute)", marginBottom: 12 }}>
                    Select all that apply
                  </div>
                  <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 24 }}>
                    {[
                      "Kitchen Countertop",
                      "Kitchen Island",
                      "Kitchen Backsplash / Waterfall",
                      "Bathroom Vanity",
                      "Table",
                      "Other",
                    ].map(s => (
                      <OptionTile key={s} selected={data.surfaces.includes(s)} onClick={() => toggleArr("surfaces", s)} check>
                        {s}
                      </OptionTile>
                    ))}
                  </div>
                  {data.surfaces.includes("Other") && (
                    <input
                      type="text"
                      value={data.surfacesOther}
                      onChange={e => update("surfacesOther", e.target.value)}
                      placeholder="Tell us what other surfaces"
                      style={{ ...fieldStyle, marginBottom: 24 }}
                    />
                  )}
                  <SqftField data={data} update={update} />
                </>
              )}

              {step === 3 && (
                <div style={{ display: "grid", gap: 12 }}>
                  {[
                    { v: "Proactive",       d: "We want peace of mind." },
                    { v: "Staining",        d: "We've had staining." },
                    { v: "Etching",         d: "We've had etching, dull spots, or rings." },
                    { v: "Newly installed", d: "We're moving in / newly installed stone." },
                    { v: "Exploring",       d: "Just exploring options / getting a quote." },
                  ].map(o => (
                    <OptionTile key={o.v} selected={data.situation === o.v} onClick={() => update("situation", o.v)} wide>
                      <span style={{ display: "block" }}>
                        <span style={{ fontWeight: 500 }}>{o.v}</span>
                        <span style={{ display: "block", fontSize: 13, color: data.situation === o.v ? "rgba(245,242,237,0.7)" : "var(--mute)", marginTop: 3 }}>{o.d}</span>
                      </span>
                    </OptionTile>
                  ))}
                </div>
              )}

              {step === 4 && (
                <div style={{ display: "grid", gap: 12 }}>
                  {[
                    { k: "ASAP",       v: "As soon as possible" },
                    { k: "1–3 months", v: "In the next 1–3 months" },
                    { k: "3–6 months", v: "In 3–6 months" },
                    { k: "6 months+",  v: "Six months out or more" },
                    { k: "Planning",   v: "Just planning ahead" },
                  ].map(t => (
                    <OptionTile key={t.k} selected={data.timeline === t.k} onClick={() => update("timeline", t.k)} wide>
                      <span className="serif" style={{ fontSize: 20, marginRight: 14 }}>{t.k}</span>
                      <span style={{ color: data.timeline === t.k ? "rgba(245,242,237,0.7)" : "var(--mute)", fontSize: 14 }}>{t.v}</span>
                    </OptionTile>
                  ))}
                </div>
              )}

              {step === 5 && (
                <>
                  <div style={{ display: "grid", gap: 12 }}>
                    {[
                      "Instagram / Facebook video",
                      "Google",
                      "Referred by a friend we serviced",
                      "Designer / fabricator referral",
                      "Other",
                    ].map(s => (
                      <OptionTile key={s} selected={data.howHeard === s} onClick={() => update("howHeard", s)} wide>
                        {s}
                      </OptionTile>
                    ))}
                  </div>
                  {data.howHeard === "Other" && (
                    <input
                      type="text"
                      value={data.howHeardOther}
                      onChange={e => update("howHeardOther", e.target.value)}
                      placeholder="How did you hear about us?"
                      autoFocus
                      style={{ ...fieldStyle, marginTop: 12 }}
                    />
                  )}
                </>
              )}

              {step === 6 && (
                <PhotosAndMessage data={data} update={update} />
              )}

              {step === 7 && (
                <div style={{ display: "grid", gap: 18 }}>
                  <FormField
                    label="Full name" value={data.name}
                    onChange={v => update("name", v)} onBlur={() => onBlur("name")}
                    placeholder="Jane Doe" autoComplete="name"
                    error={touched.name && errors.name}
                  />
                  <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }}>
                    <FormField
                      label="Phone" value={data.phone}
                      onChange={v => update("phone", formatPhone(v))} onBlur={() => onBlur("phone")}
                      placeholder="(908) 555-0100"
                      type="tel" inputMode="tel" autoComplete="tel"
                      error={touched.phone && errors.phone}
                    />
                    <FormField
                      label="Email" value={data.email}
                      onChange={v => update("email", v)} onBlur={() => onBlur("email")}
                      placeholder="jane@email.com"
                      type="email" inputMode="email" autoComplete="email"
                      error={touched.email && errors.email}
                    />
                  </div>

                  <ConsentCheckbox
                    checked={data.smsConsent}
                    onChange={v => update("smsConsent", v)}
                  />

                  {/* Project address — split fields, all required */}
                  <div>
                    <div className="mono" style={{ fontSize: 10, letterSpacing: "0.16em", textTransform: "uppercase", color: "var(--mute)", marginBottom: 8, display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
                      <span>Project address</span>
                      <span style={{ color: "var(--maroon)", letterSpacing: "0.1em" }}>Required</span>
                    </div>

                    <AddressAutocomplete
                      value={data.addressLine1}
                      onChange={(v) => {
                        update("addressLine1", v);
                        // Clear formatted if user is editing manually after picking
                        if (data.addressFormatted) update("addressFormatted", "");
                      }}
                      onPlace={(p) => {
                        setData(d => ({
                          ...d,
                          addressLine1: p.line1 || d.addressLine1,
                          addressLine2: p.line2 || d.addressLine2,
                          addressCity:  p.city  || d.addressCity,
                          addressState: p.state || d.addressState,
                          addressZip:   p.zip   || d.addressZip,
                          addressFormatted: p.formatted || "",
                        }));
                        setTouched(t => ({ ...t, addressLine1: true, addressCity: true, addressState: true, addressZip: true }));
                      }}
                      placeholder="Start typing your address…"
                      error={touched.addressLine1 && errors.addressLine1}
                    />
                    {touched.addressLine1 && errors.addressLine1 && (
                      <div className="mono" style={{ fontSize: 11, color: "var(--maroon)", marginTop: 6, letterSpacing: "0.06em" }}>
                        {errors.addressLine1}
                      </div>
                    )}

                    <input
                      type="text" value={data.addressLine2}
                      onChange={e => update("addressLine2", e.target.value)}
                      placeholder="Apartment, suite, floor (optional)"
                      autoComplete="address-line2"
                      style={{ ...fieldStyle, marginTop: 10 }}
                    />

                    <div style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr 1fr", gap: 10, marginTop: 10 }}>
                      <div>
                        <input
                          type="text" value={data.addressCity}
                          onChange={e => update("addressCity", e.target.value)}
                          onBlur={() => onBlur("addressCity")}
                          placeholder="City"
                          autoComplete="address-level2"
                          style={{
                            ...fieldStyle,
                            borderColor: (touched.addressCity && errors.addressCity) ? "var(--maroon)" : "var(--line)",
                            background: (touched.addressCity && errors.addressCity) ? "rgba(107,20,22,0.04)" : "var(--cream)",
                          }}
                        />
                        {touched.addressCity && errors.addressCity && (
                          <div className="mono" style={{ fontSize: 10.5, color: "var(--maroon)", marginTop: 4, letterSpacing: "0.06em" }}>
                            City required
                          </div>
                        )}
                      </div>
                      <div>
                        <select
                          value={data.addressState}
                          onChange={e => update("addressState", e.target.value)}
                          onBlur={() => onBlur("addressState")}
                          autoComplete="address-level1"
                          style={{
                            ...fieldStyle,
                            appearance: "none",
                            backgroundImage:
                              "url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' stroke='%236B645B' stroke-width='1.2' fill='none'/></svg>\")",
                            backgroundRepeat: "no-repeat",
                            backgroundPosition: "right 12px center",
                            paddingRight: 32,
                            borderColor: (touched.addressState && errors.addressState) ? "var(--maroon)" : "var(--line)",
                            background: (touched.addressState && errors.addressState) ? "rgba(107,20,22,0.04)" : "var(--cream)",
                            color: data.addressState ? "var(--ink)" : "var(--mute)",
                          }}
                        >
                          <option value="">State</option>
                          {US_STATES.map(([code, name]) => (
                            <option key={code} value={code}>{code} — {name}</option>
                          ))}
                        </select>
                        {touched.addressState && errors.addressState && (
                          <div className="mono" style={{ fontSize: 10.5, color: "var(--maroon)", marginTop: 4, letterSpacing: "0.06em" }}>
                            State required
                          </div>
                        )}
                      </div>
                      <div>
                        <input
                          type="text" value={data.addressZip}
                          onChange={e => update("addressZip", e.target.value.replace(/[^\d-]/g, "").slice(0, 10))}
                          onBlur={() => onBlur("addressZip")}
                          placeholder="ZIP"
                          inputMode="numeric"
                          autoComplete="postal-code"
                          style={{
                            ...fieldStyle,
                            borderColor: (touched.addressZip && errors.addressZip) ? "var(--maroon)" : "var(--line)",
                            background: (touched.addressZip && errors.addressZip) ? "rgba(107,20,22,0.04)" : "var(--cream)",
                          }}
                        />
                        {touched.addressZip && errors.addressZip && (
                          <div className="mono" style={{ fontSize: 10.5, color: "var(--maroon)", marginTop: 4, letterSpacing: "0.06em" }}>
                            ZIP required
                          </div>
                        )}
                      </div>
                    </div>
                  </div>

                  {/* Honeypot */}
                  <label aria-hidden="true" style={{
                    position: "absolute", left: "-10000px", top: "auto",
                    width: 1, height: 1, overflow: "hidden",
                  }}>
                    Website (leave blank)
                    <input
                      type="text" tabIndex={-1} autoComplete="off"
                      value={data.website}
                      onChange={e => update("website", e.target.value)}
                    />
                  </label>

                  {serverError && (
                    <div role="alert" style={{
                      padding: "14px 16px",
                      background: "rgba(107,20,22,0.08)",
                      border: "1px solid rgba(107,20,22,0.3)",
                      color: "var(--maroon)",
                      fontSize: 13, lineHeight: 1.5,
                    }}>
                      {serverError}
                    </div>
                  )}
                </div>
              )}
            </>
          )}
        </div>

        {/* Footer */}
        {!submitted && (
          <footer style={{
            padding: "20px 40px", borderTop: "1px solid var(--line)",
            display: "flex", justifyContent: "space-between", alignItems: "center",
            background: "var(--cream)", position: "sticky", bottom: 0,
          }}>
            <button
              onClick={() => setStep(s => Math.max(0, s - 1))}
              disabled={step === 0}
              style={{ fontSize: 13, color: step === 0 ? "var(--line)" : "var(--mute)", padding: "10px 0", cursor: step === 0 ? "default" : "pointer" }}
            >
              ← Back
            </button>
            {step < total - 1 ? (
              <button
                onClick={() => canNext() && setStep(s => s + 1)}
                disabled={!canNext()}
                className="btn btn-primary"
                style={{ opacity: canNext() ? 1 : 0.35, cursor: canNext() ? "pointer" : "default" }}
              >
                Continue
                <svg width="12" height="12" viewBox="0 0 12 12"><path d="M1 6h10m0 0L6 1m5 5L6 11" stroke="currentColor" strokeWidth="1.2"/></svg>
              </button>
            ) : (
              <button
                onClick={() => !submitting && handleSubmit()}
                disabled={submitting || !canNext()}
                className="btn btn-primary"
                style={{ opacity: (submitting || !canNext()) ? 0.55 : 1, cursor: (submitting || !canNext()) ? "default" : "pointer" }}
              >
                {submitting ? "Sending…" : (isOutOfArea ? "Forward to StoneGuard" : "Send my protection plan")}
                {!submitting && (
                  <svg width="12" height="12" viewBox="0 0 12 12"><path d="M1 6h10m0 0L6 1m5 5L6 11" stroke="currentColor" strokeWidth="1.2"/></svg>
                )}
              </button>
            )}
          </footer>
        )}
      </aside>
    </div>
  );
}

function initialData() {
  return {
    location: null,
    stone: null,
    stoneOther: "",
    surfaces: [],
    surfacesOther: "",
    sqft: 25,
    sqftKnown: false,
    situation: null,
    timeline: null,
    howHeard: null,
    howHeardOther: "",
    photos: [],
    message: "",
    name: "",
    email: "",
    phone: "",
    // address — split fields, all required (state + zip are critical for routing)
    addressLine1: "",
    addressLine2: "",
    addressCity: "",
    addressState: "",
    addressZip: "",
    addressFormatted: "",
    smsConsent: false,
    website: "",
  };
}

// ─────────────────────────────────────────────────────────────────────────
// Step content fragments
// ─────────────────────────────────────────────────────────────────────────

function OutOfAreaNote() {
  return (
    <div style={{
      marginTop: 24,
      padding: "20px 22px",
      borderLeft: "2px solid var(--maroon)",
      background: "var(--cream)",
    }}>
      <div className="mono" style={{ fontSize: 10, letterSpacing: "0.18em", textTransform: "uppercase", color: "var(--maroon)", marginBottom: 8 }}>
        Out of service area
      </div>
      <p style={{ fontSize: 14, lineHeight: 1.6, color: "var(--ink-2)", margin: 0 }}>
        We don't directly service this region. Continue through the form anyway — we'll forward your inquiry to <strong>StoneGuard</strong> (our parent company), who will connect you with your nearest certified installer.
      </p>
    </div>
  );
}

function SqftField({ data, update }) {
  return (
    <div style={{ borderTop: "1px solid var(--line)", paddingTop: 24 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 14 }}>
        <label className="mono" style={{ fontSize: 11, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--mute)" }}>
          Approximate square footage
        </label>
        <span className="serif" style={{ fontSize: 24 }}>
          {data.sqftKnown ? (
            <>
              {data.sqft >= 200 ? "200+" : data.sqft}
              <span style={{ fontSize: 14, color: "var(--mute)" }}> sq ft</span>
            </>
          ) : (
            <span style={{ color: "var(--mute)", fontStyle: "italic", fontSize: 20 }}>Unknown</span>
          )}
        </span>
      </div>
      <input
        type="range" min="5" max="200" step="5"
        value={data.sqft}
        onChange={e => {
          update("sqft", +e.target.value);
          if (!data.sqftKnown) update("sqftKnown", true);
        }}
        style={{ width: "100%", accentColor: "var(--ink)", opacity: data.sqftKnown ? 1 : 0.4 }}
      />
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 8 }}>
        <span className="mono" style={{ fontSize: 10, color: "var(--mute)" }}>
          {data.sqftKnown ? "5 sq ft" : "Drag to set, or leave as Unknown"}
        </span>
        {data.sqftKnown && (
          <button
            type="button"
            onClick={() => update("sqftKnown", false)}
            className="mono"
            style={{
              fontSize: 10, letterSpacing: "0.12em", textTransform: "uppercase",
              color: "var(--maroon)", padding: 0,
            }}
          >
            Reset to unknown
          </button>
        )}
      </div>
    </div>
  );
}

function PhotosAndMessage({ data, update }) {
  const fileRef = useRef(null);
  const MAX_PHOTOS = 4;
  const MAX_SIZE_MB = 8;

  const handleFiles = async (files) => {
    const arr = Array.from(files);
    const remaining = MAX_PHOTOS - data.photos.length;
    const slice = arr.slice(0, remaining);
    const added = [];
    for (const f of slice) {
      if (!f.type.startsWith("image/")) continue;
      if (f.size > MAX_SIZE_MB * 1024 * 1024) continue;
      try {
        const dataUrl = await fileToDataURL(f);
        added.push({ name: f.name, size: f.size, type: f.type, dataUrl });
      } catch {}
    }
    update("photos", [...data.photos, ...added]);
  };

  const removePhoto = (i) => {
    update("photos", data.photos.filter((_, idx) => idx !== i));
  };

  const onDrop = (e) => {
    e.preventDefault();
    if (e.dataTransfer?.files?.length) handleFiles(e.dataTransfer.files);
  };

  return (
    <div style={{ display: "grid", gap: 24 }}>
      {/* Photo upload */}
      <div>
        <label className="mono" style={{ fontSize: 10, letterSpacing: "0.16em", textTransform: "uppercase", color: "var(--mute)", marginBottom: 10, display: "block" }}>
          Photos {data.photos.length > 0 && `· ${data.photos.length} / ${MAX_PHOTOS}`}
        </label>

        {data.photos.length > 0 && (
          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(120px, 1fr))", gap: 10, marginBottom: 12 }}>
            {data.photos.map((p, i) => (
              <div key={i} style={{ position: "relative", aspectRatio: "1/1", overflow: "hidden", border: "1px solid var(--line)" }}>
                <img src={p.dataUrl} alt={p.name} style={{ width: "100%", height: "100%", objectFit: "cover" }}/>
                <button
                  type="button"
                  onClick={() => removePhoto(i)}
                  aria-label={`Remove ${p.name}`}
                  style={{
                    position: "absolute", top: 6, right: 6,
                    width: 24, height: 24, borderRadius: 99,
                    background: "rgba(10,9,8,0.75)", color: "var(--bone)",
                    display: "grid", placeItems: "center",
                    cursor: "pointer",
                  }}
                >
                  <svg width="10" height="10" viewBox="0 0 12 12"><path d="M2 2l8 8M10 2L2 10" stroke="currentColor" strokeWidth="1.4"/></svg>
                </button>
              </div>
            ))}
          </div>
        )}

        {data.photos.length < MAX_PHOTOS && (
          <div
            onClick={() => fileRef.current?.click()}
            onDragOver={(e) => e.preventDefault()}
            onDrop={onDrop}
            style={{
              padding: "32px 20px",
              border: "1px dashed var(--line)",
              background: "var(--cream)",
              textAlign: "center",
              cursor: "pointer",
              transition: "border-color .2s, background .2s",
            }}
            onMouseEnter={e => { e.currentTarget.style.borderColor = "var(--ink)"; }}
            onMouseLeave={e => { e.currentTarget.style.borderColor = "var(--line)"; }}
          >
            <div className="serif" style={{ fontSize: 18, marginBottom: 6, color: "var(--ink)" }}>
              Drop photos here, or <span style={{ borderBottom: "1px solid var(--maroon)", color: "var(--maroon)" }}>browse</span>
            </div>
            <div className="mono" style={{ fontSize: 10, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--mute)" }}>
              Up to {MAX_PHOTOS} images · {MAX_SIZE_MB}MB each
            </div>
            <input
              ref={fileRef}
              type="file"
              accept="image/*"
              multiple
              onChange={(e) => handleFiles(e.target.files)}
              style={{ display: "none" }}
            />
          </div>
        )}
      </div>

      {/* Message */}
      <div>
        <label className="mono" style={{ fontSize: 10, letterSpacing: "0.16em", textTransform: "uppercase", color: "var(--mute)", marginBottom: 10, display: "block" }}>
          Message (optional)
        </label>
        <textarea
          value={data.message}
          onChange={e => update("message", e.target.value)}
          placeholder="Anything you'd like us to know — designer or fabricator name, specific stain or etch, existing damage, scheduling constraints…"
          rows={4}
          style={fieldStyle}
        />
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// Option tile (radio or checkbox)
// ─────────────────────────────────────────────────────────────────────────
function OptionTile({ children, selected, onClick, check = false, wide = false }) {
  return (
    <button onClick={onClick} style={{
      padding: wide ? "18px 22px" : "20px 18px",
      background: selected ? "var(--ink)" : "var(--cream)",
      color: selected ? "var(--bone)" : "var(--ink)",
      border: `1px solid ${selected ? "var(--ink)" : "var(--line)"}`,
      textAlign: "left",
      fontSize: 15,
      display: "flex", alignItems: "center", gap: 10,
      transition: "all .2s",
      width: "100%",
    }}>
      {check && (
        <span style={{
          width: 16, height: 16, borderRadius: 2,
          border: `1px solid ${selected ? "var(--bone)" : "var(--line)"}`,
          display: "grid", placeItems: "center",
          background: selected ? "var(--bone)" : "transparent",
          flexShrink: 0,
        }}>
          {selected && <svg width="10" height="10" viewBox="0 0 10 10"><path d="M1 5l3 3 5-7" stroke="var(--ink)" strokeWidth="1.5" fill="none"/></svg>}
        </span>
      )}
      <span style={{ flex: 1 }}>{children}</span>
    </button>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// FormField + ConsentCheckbox
// ─────────────────────────────────────────────────────────────────────────
function FormField({ label, value, onChange, onBlur, placeholder, multiline, error, type = "text", inputMode, autoComplete }) {
  const fStyle = {
    ...fieldStyle,
    borderColor: error ? "var(--maroon)" : "var(--line)",
    background: error ? "rgba(107,20,22,0.04)" : "var(--cream)",
  };
  return (
    <label style={{ display: "block" }}>
      <div className="mono" style={{ fontSize: 10, letterSpacing: "0.16em", textTransform: "uppercase", color: "var(--mute)", marginBottom: 8 }}>
        {label}
      </div>
      {multiline ? (
        <textarea value={value} onChange={e => onChange(e.target.value)} onBlur={onBlur} placeholder={placeholder} rows={3} style={fStyle} />
      ) : (
        <input
          type={type} value={value}
          onChange={e => onChange(e.target.value)}
          onBlur={onBlur}
          placeholder={placeholder}
          inputMode={inputMode}
          autoComplete={autoComplete}
          style={fStyle}
        />
      )}
      {error && (
        <div className="mono" style={{ fontSize: 11, color: "var(--maroon)", marginTop: 6, letterSpacing: "0.06em" }}>
          {error}
        </div>
      )}
    </label>
  );
}
const fieldStyle = {
  width: "100%",
  padding: "14px 16px",
  background: "var(--cream)",
  border: "1px solid var(--line)",
  borderRadius: 2,
  fontSize: 15,
  fontFamily: "'Inter', sans-serif",
  outline: "none",
  resize: "vertical",
  transition: "border-color .2s ease, background .2s ease",
};

function ConsentCheckbox({ checked, onChange }) {
  return (
    <label style={{
      display: "grid", gridTemplateColumns: "22px 1fr", gap: 12,
      padding: "14px 16px",
      background: "var(--cream)",
      border: "1px solid var(--line)",
      cursor: "pointer",
      alignItems: "start",
    }}>
      <span style={{
        width: 18, height: 18, marginTop: 2,
        borderRadius: 3,
        border: "1px solid " + (checked ? "var(--ink)" : "var(--mute)"),
        background: checked ? "var(--ink)" : "transparent",
        display: "grid", placeItems: "center", transition: "all .2s",
      }}>
        {checked && (
          <svg width="11" height="11" viewBox="0 0 12 12"><path d="M2 6l3 3 5-7" stroke="var(--bone)" strokeWidth="1.6" fill="none"/></svg>
        )}
      </span>
      <input
        type="checkbox" checked={checked} onChange={e => onChange(e.target.checked)}
        style={{ position: "absolute", opacity: 0, width: 0, height: 0 }}
      />
      <span style={{ fontSize: 13, lineHeight: 1.5, color: "var(--ink-2)" }}>
        It's okay to text me about my project. Reply STOP to opt out, HELP for help. Message and data rates may apply. See our <a href="sms-terms.html" target="_blank" rel="noopener" style={{ color: "var(--maroon)", borderBottom: "1px solid var(--maroon)" }}>SMS Terms</a> and <a href="privacy.html" target="_blank" rel="noopener" style={{ color: "var(--maroon)", borderBottom: "1px solid var(--maroon)" }}>Privacy Policy</a>.
      </span>
    </label>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// SubmittedView — context-aware (in-area vs. forwarded to StoneGuard)
// ─────────────────────────────────────────────────────────────────────────
function SubmittedView({ data, onClose }) {
  const outOfArea = data.location === "Other";
  return (
    <div style={{ textAlign: "center", padding: "20px 0" }}>
      <div style={{
        width: 64, height: 64, borderRadius: 99,
        background: "var(--ink)", color: "var(--bone)",
        margin: "0 auto 32px",
        display: "grid", placeItems: "center",
      }}>
        <svg width="24" height="24" viewBox="0 0 24 24"><path d="M4 12l5 5L20 6" stroke="currentColor" strokeWidth="1.5" fill="none"/></svg>
      </div>
      <h2 className="serif" style={{ fontSize: 40, letterSpacing: "-0.02em", lineHeight: 1.05, marginBottom: 18 }}>
        Thank you, {data.name.split(" ")[0] || "friend"}.
      </h2>
      <p style={{ fontSize: 16, color: "var(--ink-2)", lineHeight: 1.6, maxWidth: 440, margin: "0 auto 32px" }}>
        {outOfArea ? (
          <>Your inquiry is being forwarded to <strong>StoneGuard</strong>, who will connect you with your nearest certified installer. Expect to hear from them within a couple of business days.</>
        ) : (
          <>Your written protection plan and quote will land in your inbox within 24 hours. If you'd like to move faster, Michael is reachable directly below.</>
        )}
      </p>
      {!outOfArea && (
        <div style={{ borderTop: "1px solid var(--line)", borderBottom: "1px solid var(--line)", padding: "20px 0", margin: "0 auto 32px", maxWidth: 360 }}>
          <div className="mono" style={{ fontSize: 10, letterSpacing: "0.16em", textTransform: "uppercase", color: "var(--mute)", marginBottom: 8 }}>Direct Line</div>
          <a href="tel:+19088661919" className="serif" style={{ fontSize: 28, letterSpacing: "-0.01em" }}>
            (908) 866-1919
          </a>
          <div style={{ marginTop: 20 }}>
            <a
              href="/michael-mt-surface-protectors.vcf"
              className="btn"
              style={{ display: "inline-flex", alignItems: "center", gap: 10 }}
            >
              <svg width="15" height="15" viewBox="0 0 24 24" fill="none" aria-hidden="true">
                <path d="M12 12a4 4 0 100-8 4 4 0 000 8z" stroke="currentColor" strokeWidth="1.5"/>
                <path d="M4 20c0-3.3 3.6-6 8-6s8 2.7 8 6" stroke="currentColor" strokeWidth="1.5"/>
                <path d="M19 3v6M22 6h-6" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
              </svg>
              Save Michael to Contacts
            </a>
            <div className="mono" style={{ fontSize: 10, letterSpacing: "0.12em", textTransform: "uppercase", color: "var(--mute)", marginTop: 10 }}>
              Tap to add on iPhone
            </div>
          </div>
        </div>
      )}
      <button onClick={onClose} className="btn btn-ghost">Close</button>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// CTA block (above footer)
// ─────────────────────────────────────────────────────────────────────────
function FinalCTA({ onInquire, ctaPrimary, ctaPromise }) {
  return (
    <section style={{ background: "var(--ink)", color: "var(--bone)", padding: "140px 0" }}>
      <div className="container" style={{ textAlign: "center" }}>
        <div className="eyebrow" style={{ color: "rgba(245,242,237,0.45)", marginBottom: 28 }}>
          04 · Your next step
        </div>
        <h2 className="serif" style={{
          fontSize: "clamp(48px, 7vw, 104px)", lineHeight: 0.98, letterSpacing: "-0.02em",
          maxWidth: 1100, margin: "0 auto 40px",
        }}>
          You chose the stone.<br/>
          <span style={{ color: "var(--bronze)", fontStyle: "italic", whiteSpace: "nowrap" }}>
            We make sure you can{" "}
            <Typewriter
              words={["use it.", "keep it.", "love it."]}
              typeSpeed={95}
              deleteSpeed={50}
              holdMs={1800}
              startDelay={400}
            />
          </span>
        </h2>
        <p style={{ fontSize: 18, lineHeight: 1.55, color: "rgba(245,242,237,0.7)", maxWidth: 560, margin: "0 auto 48px" }}>
          {ctaPromise}
        </p>
        <div style={{ display: "flex", gap: 16, justifyContent: "center", flexWrap: "wrap" }}>
          <button onClick={onInquire} className="btn" style={{ background: "var(--bone)", color: "var(--ink)", padding: "20px 32px", fontSize: 15 }}>
            {ctaPrimary}
            <svg width="14" height="14" viewBox="0 0 14 14"><path d="M1 7h12m0 0L7 1m6 6L7 13" stroke="currentColor" strokeWidth="1.3"/></svg>
          </button>
          <a href="tel:+19088661919" className="btn" style={{ border: "1px solid rgba(245,242,237,0.25)", color: "var(--bone)", padding: "20px 32px", fontSize: 15 }}>
            Or call Michael, (908) 866-1919
          </a>
        </div>
        <div style={{ marginTop: 56, display: "flex", gap: 40, justifyContent: "center", flexWrap: "wrap", color: "rgba(245,242,237,0.55)", fontSize: 13 }}>
          <span>✓ Free written quote</span>
          <span>✓ No obligation</span>
          <span>✓ Lifetime StoneGuard® warranty</span>
        </div>
      </div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// Footer
// ─────────────────────────────────────────────────────────────────────────
function Footer() {
  return (
    <footer style={{ background: "var(--black)", color: "rgba(245,242,237,0.7)", padding: "80px 0 40px" }}>
      <div className="container">
        <div style={{ display: "grid", gridTemplateColumns: "2fr 1fr 1fr 1fr", gap: 60, marginBottom: 80 }} className="footer-grid">
          <div>
            <div className="serif" style={{ fontSize: 32, color: "var(--bone)", letterSpacing: "-0.01em", marginBottom: 20 }}>
              M<span style={{ fontSize: 18, verticalAlign: "super", margin: "0 2px" }}>&amp;</span>T Surface Protectors
            </div>
            <p style={{ fontSize: 14, lineHeight: 1.6, maxWidth: 340 }}>
              Certified StoneGuard® specialists, serving fine homes across NY, NJ, and PA since 2020.
            </p>
          </div>
          {[
            { t: "Services", l: [
              { label: "StoneGuard® Clear",   href: "services.html#clear" },
              { label: "StoneGuard® Satin",   href: "services.html#satin" },
              { label: "Stain & Etch Removal", href: "services.html" },
              { label: "Stone Restoration",   href: "services.html" },
            ]},
            { t: "Company", l: [
              { label: "About",     href: "about.html" },
              { label: "Our Work",  href: "work.html" },
              { label: "Reviews",   href: "index.html#reviews" },
              { label: "FAQ",       href: "faq.html" },
            ]},
            { t: "Connect", l: [
              { label: "Instagram", href: "https://www.instagram.com/mt_surfaceprotectors/" },
              { label: "TikTok",    href: "https://www.tiktok.com/@mt_surfaceprotectors" },
              { label: "Facebook",  href: "https://www.facebook.com/mtsurfaceprotectors/" },
              { label: "YouTube",   href: "https://www.youtube.com/@mt_surfaceprotectors" },
            ]},
          ].map(col => (
            <div key={col.t}>
              <div className="mono" style={{ fontSize: 10, letterSpacing: "0.18em", textTransform: "uppercase", color: "rgba(245,242,237,0.45)", marginBottom: 20 }}>{col.t}</div>
              <ul style={{ listStyle: "none", display: "grid", gap: 12 }}>
                {col.l.map(i => (
                  <li key={i.label}>
                    <a
                      href={i.href}
                      target={i.href.startsWith("http") ? "_blank" : undefined}
                      rel={i.href.startsWith("http") ? "noopener noreferrer" : undefined}
                      style={{ fontSize: 14 }}
                    >{i.label}</a>
                  </li>
                ))}
              </ul>
            </div>
          ))}
        </div>
        <div style={{ borderTop: "1px solid rgba(245,242,237,0.12)", paddingTop: 32, display: "flex", justifyContent: "space-between", alignItems: "center", flexWrap: "wrap", gap: 20 }}>
          <div className="mono" style={{ fontSize: 11, letterSpacing: "0.12em" }}>
            © 2026 M&amp;T Surface Protectors LLC
          </div>
          <div style={{ display: "flex", gap: 28, fontSize: 12 }}>
            <a href="tel:+19088661919">(908) 866-1919</a>
            <a href="mailto:sales@mtsurfaceprotectors.com">sales@mtsurfaceprotectors.com</a>
            <a href="privacy.html">Privacy</a>
            <a href="sms-terms.html">SMS Terms</a>
          </div>
        </div>
      </div>
      <style>{`
        @media (max-width: 860px){
          .footer-grid{ grid-template-columns: 1fr 1fr !important; }
        }
      `}</style>
    </footer>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// Tweaks panel
// ─────────────────────────────────────────────────────────────────────────
function TweaksPanel({ tweaks, setTweaks, visible }) {
  if (!visible) return null;
  const setKey = (k, v) => {
    const next = { ...tweaks, [k]: v };
    setTweaks(next);
    window.parent.postMessage({ type: "__edit_mode_set_keys", edits: { [k]: v } }, "*");
  };
  return (
    <div style={{
      position: "fixed", bottom: 24, right: 24, zIndex: 200,
      width: 320, background: "var(--bone)", border: "1px solid var(--ink)",
      padding: 24, fontFamily: "'Inter', sans-serif",
      boxShadow: "0 30px 60px rgba(0,0,0,0.2)",
    }}>
      <div className="mono" style={{ fontSize: 11, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--mute)", marginBottom: 20 }}>
        Tweaks
      </div>

      <div style={{ marginBottom: 20 }}>
        <label style={{ fontSize: 12, fontWeight: 500, display: "block", marginBottom: 8 }}>Primary CTA copy</label>
        <select value={tweaks.ctaPrimary} onChange={e => setKey("ctaPrimary", e.target.value)} style={tweakSelectStyle}>
          <option>Get My Stone Protected</option>
          <option>Lock In My Protection Plan</option>
          <option>Protect My Counters For Life</option>
          <option>Claim My Free Protection Plan</option>
          <option>Start My Stone's Protection</option>
        </select>
      </div>

      <div style={{ marginBottom: 20 }}>
        <label style={{ fontSize: 12, fontWeight: 500, display: "block", marginBottom: 8 }}>CTA promise (value stack)</label>
        <select value={tweaks.ctaPromise} onChange={e => setKey("ctaPromise", e.target.value)} style={tweakSelectStyle}>
          <option>Tell us about your stone in 60 seconds and we'll send back a custom protection plan, what it costs, and exactly what we'd do. Free, in 24 hours, no visit required.</option>
          <option>Answer a few quick questions about your stone and we'll send you a tailored plan to keep it flawless for life. Free, within 24 hours, no site visit needed.</option>
          <option>Share a couple details about your countertops. We'll reply within a day with a written plan, a price, and clear next steps. Free. No pressure. No visit.</option>
          <option>Free, no-obligation protection plan for your stone, delivered in 24 hours. No site visit required.</option>
        </select>
      </div>

      <div style={{ marginBottom: 4 }}>
        <label style={{ fontSize: 12, fontWeight: 500, display: "block", marginBottom: 8 }}>Hero variant</label>
        <div style={{ display: "flex", gap: 6 }}>
          {["type-driven", "split", "editorial"].map(v => (
            <button key={v} onClick={() => setKey("heroVariant", v)} style={{
              flex: 1, padding: "8px 6px", fontSize: 11,
              border: `1px solid ${tweaks.heroVariant === v ? "var(--ink)" : "var(--line)"}`,
              background: tweaks.heroVariant === v ? "var(--ink)" : "transparent",
              color: tweaks.heroVariant === v ? "var(--bone)" : "var(--ink)",
            }}>{v}</button>
          ))}
        </div>
      </div>
    </div>
  );
}
const tweakSelectStyle = {
  width: "100%", padding: "10px 12px", fontSize: 12,
  background: "var(--cream)", border: "1px solid var(--line)", fontFamily: "inherit",
};

Object.assign(window, { InquiryWizard, FinalCTA, Footer, TweaksPanel, ConsentCheckbox, isValidEmail, isValidPhone, formatPhone, digits });
