const { useState, useEffect, useMemo, createContext, useContext, useRef } = React;

/* --------------------------------- atoms --------------------------------- */

const Star = ({ filled = true }) => (
  <svg viewBox="0 0 24 24" className="star" aria-hidden="true">
    <path
      d="M12 2.5l2.94 6.35 6.96.74-5.18 4.72 1.47 6.86L12 17.77 5.81 21.17l1.47-6.86L2.1 9.59l6.96-.74L12 2.5z"
      fill={filled ? "currentColor" : "none"}
      stroke="currentColor"
      strokeWidth="1.2"
    />
  </svg>
);

const Rating = ({ value, count }) => {
  const full = Math.floor(value);
  return (
    <span className="inline-flex items-center gap-1.5 text-[#131A24]">
      <span className="inline-flex text-[#E8834B]">
        {[0, 1, 2, 3, 4].map((i) => (
          <Star key={i} filled={i < full} />
        ))}
      </span>
      <span className="tnum text-[12px] text-[#131A24]/70">
        {value.toFixed(1)} · {count} reviews
      </span>
    </span>
  );
};

const Photo = ({ variant = "", children, className = "" }) => (
  <div className={`photo ${variant} ${className}`}>
    {children}
  </div>
);

/* ------------------------------- form context ----------------------------- */

const FormCtx = createContext(null);

function FormProvider({ children }) {
  const [state, setState] = useState({ open: false, mode: "intake", preset: null });
  const open = (mode = "intake", preset = null) => setState({ open: true, mode, preset });
  const close = () => setState((s) => ({ ...s, open: false }));
  /* Expose boolean as isOpen — do not spread state.open then overwrite with open fn */
  return (
    <FormCtx.Provider value={{ isOpen: state.open, mode: state.mode, preset: state.preset, open, close }}>
      {children}
    </FormCtx.Provider>
  );
}
const useForm = () => useContext(FormCtx);

/* --------------------------------- header --------------------------------- */

function Header() {
  const { open } = useForm();
  const scrollTo = (id) => (e) => {
    e.preventDefault();
    const el = document.getElementById(id);
    if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
  };
  return (
    <header className="relative z-30">
      <div className="max-w-[1360px] mx-auto px-10 py-6 flex items-center justify-between">
        <a href="#top" onClick={scrollTo("top")} className="font-display-italic text-[30px] leading-none tracking-tight text-[#131A24]">
          Poolbidder
        </a>
        <nav className="flex items-center gap-10 text-[14px] text-[#131A24]/80">
          <a href="#how" onClick={scrollTo("how")} className="hover:text-[#131A24]">How it works</a>
          <a href="#contractors" onClick={scrollTo("contractors")} className="hover:text-[#131A24]">Contractors</a>
          <a href="#reviews" onClick={scrollTo("reviews")} className="hover:text-[#131A24]">Reviews</a>
        </nav>
        <div className="flex items-center gap-6">
          <button
            onClick={() => open("contractor")}
            className="text-[14px] text-[#131A24]/80 hover:text-[#131A24]"
          >
            For contractors
          </button>
          <button onClick={() => open("intake")} className="btn-blue px-5 py-2.5 text-[14px]">Get my bids</button>
        </div>
      </div>
      <div className="h-px rule" />
    </header>
  );
}

/* ---------------------------------- hero ---------------------------------- */

function Hero() {
  const { open } = useForm();
  const scrollTo = (id) => (e) => {
    e.preventDefault();
    const el = document.getElementById(id);
    if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
  };
  return (
    <section className="relative" id="top">
      <div className="max-w-[1360px] mx-auto px-10 pt-10">
        <div className="relative h-[720px] overflow-hidden grain">
          <Photo variant="warm" className="absolute inset-0">
            <div
              className="absolute inset-x-0 bottom-0 h-[62%]"
              style={{
                background:
                  "linear-gradient(180deg, rgba(10,14,22,0) 0%, rgba(10,14,22,0.55) 55%, rgba(10,14,22,0.88) 100%)",
              }}
            />
            <div className="absolute top-8 left-8 flex items-center gap-4 text-white/85">
              <span className="eyebrow">Bids in 48 hours</span>
              <span className="h-px w-10 bg-white/40" />
              <span className="text-[12px] tracking-wide">Licensed · Insured · Vetted</span>
            </div>
            <div className="absolute top-8 right-8 flex items-center gap-3 text-white/80 text-[12px]">
              <span className="inline-block w-1.5 h-1.5 rounded-full bg-[#E8834B]" />
              <span className="tnum">Serving FL · TX · AZ · CA · NV</span>
            </div>

            <div className="absolute inset-x-0 bottom-0 px-12 pb-14">
              <h1 className="font-display text-white text-[84px] leading-[0.98] max-w-[1000px]">
                Your pool project,<br />priced honestly.
              </h1>
              <p className="mt-7 max-w-[560px] text-[18px] leading-relaxed text-[#F5F1EA]/85">
                Describe your project in 3 minutes. Three vetted local pool contractors bid within 48 hours. You pick. No pressure, no sales calls.
              </p>
              <div className="mt-9 flex items-center gap-8">
                <button onClick={() => open("intake")} className="btn-blue px-7 py-4 text-[15px] inline-flex items-center gap-2">
                  Describe my project <span aria-hidden="true">→</span>
                </button>
                <a href="#how" onClick={scrollTo("how")} className="text-[14px] text-white/90 inline-flex items-center gap-2 hover:text-white">
                  <span className="inline-flex items-center justify-center w-6 h-6 rounded-full border border-white/50">↓</span>
                  See how it works
                </a>
              </div>
            </div>
          </Photo>
        </div>

        {/* stats rail — qualitative, not fabricated */}
        <div className="grid grid-cols-4 border-b hairline border-t border-[#E1DAC9] mt-10">
          {[
            { k: "Bids delivered", v: "48 hrs" },
            { k: "Cost to homeowner", v: "$0" },
            { k: "Bids per project", v: "3" },
            { k: "Obligation to pick", v: "None" },
          ].map((s) => (
            <div key={s.k} className="py-7 px-6 border-r last:border-r-0 hairline">
              <div className="eyebrow text-[#131A24]/60">{s.k}</div>
              <div className="font-display text-[40px] leading-none mt-3 tnum">{s.v}</div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ------------------------------ how it works ------------------------------ */

function HowItWorks() {
  const steps = [
    {
      n: "01",
      h: "Describe your project",
      p: "Fill out a 3-minute form with photos, measurements, and what you want done. Skip anything you don't know — we'll follow up.",
      meta: "≈ 3 min",
    },
    {
      n: "02",
      h: "We get three bids",
      p: "Vetted contractors in your zip code compete within 48 hours. Each bid is itemized, warranty-backed, and time-stamped.",
      meta: "≤ 48 hrs",
    },
    {
      n: "03",
      h: "You compare, you pick",
      p: "Side-by-side bid comparison with materials, timelines, and reviews. No obligation. Pass on all three if you want.",
      meta: "No pressure",
    },
  ];
  return (
    <section id="how" className="py-32">
      <div className="max-w-[1360px] mx-auto px-10">
        <div className="flex items-end justify-between mb-20">
          <div>
            <div className="eyebrow text-[#131A24]/60 mb-5">How it works</div>
            <h2 className="font-display text-[64px] leading-[1.02] max-w-[780px]">
              Three steps. One honest number.
            </h2>
          </div>
          <div className="text-[14px] text-[#131A24]/70 max-w-[260px] text-right">
            Every bid on Poolbidder is backed by a written guarantee and reviewed by our team before it reaches you.
          </div>
        </div>

        <div className="grid grid-cols-3 gap-16">
          {steps.map((s) => (
            <div key={s.n} className="relative">
              <div
                className="font-display text-[#1D6FA3] leading-none"
                style={{ fontSize: "136px", letterSpacing: "-0.04em" }}
              >
                {s.n}
              </div>
              <div className="mt-6 pt-6 border-t hairline">
                <div className="flex items-center justify-between mb-4">
                  <h3 className="font-display text-[30px] leading-tight">{s.h}</h3>
                  <span className="chip tnum text-[#131A24]/70">{s.meta}</span>
                </div>
                <p className="text-[17px] leading-relaxed text-[#131A24]/75 max-w-[360px]">
                  {s.p}
                </p>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ----------------------------- live bid example --------------------------- */

function BidExample() {
  const { open } = useForm();
  const bids = [
    {
      co: "Harborline Aquatics",
      loc: "North metro · 6 mi",
      price: "$14,200",
      timeline: "10 – 14 days",
      start: "Earliest: sample date",
      rating: 4.9,
      reviews: 214,
      materials: "Diamond Brite Super Blue",
      warranty: "10-yr plaster warranty",
      badges: ["Licensed", "Insured"],
      note: "Lowest bid",
      tone: "blue",
    },
    {
      co: "Lowcountry Pool Studio",
      loc: "East county · 9 mi",
      price: "$16,800",
      timeline: "8 – 11 days",
      start: "Earliest: sample date",
      rating: 4.8,
      reviews: 311,
      materials: "Pebble Tec Sandy Beach",
      warranty: "10-yr plaster warranty",
      badges: ["Licensed", "Insured", "BBB A+"],
      note: "Fastest start",
      tone: "neutral",
    },
    {
      co: "Coastal Plasterworks",
      loc: "Westshore · 13 mi",
      price: "$18,500",
      timeline: "12 – 16 days",
      start: "Earliest: sample date",
      rating: 5.0,
      reviews: 88,
      materials: "Pebble Sheen Aqua Blue",
      warranty: "15-yr plaster warranty",
      badges: ["Licensed", "Insured", "Owner on-site"],
      note: "Top rated",
      tone: "neutral",
    },
  ];

  return (
    <section id="reviews" className="py-28" style={{ background: "#ECE4D3" }}>
      <div className="max-w-[1360px] mx-auto px-10">
        <div className="flex items-end justify-between mb-12">
          <div>
            <div className="eyebrow text-[#131A24]/60 mb-5">A sample bid sheet</div>
            <h2 className="font-display text-[56px] leading-[1.02] max-w-[780px]">
              This is what a bid sheet can look like.
            </h2>
            <p className="mt-4 text-[14px] text-[#131A24]/65 max-w-[560px]">
              Illustrative layout and figures for presentation — not a live quote or contractor roster.
            </p>
          </div>
          <button onClick={() => open("intake")} className="text-[14px] text-[#131A24] underline underline-offset-4 decoration-[#131A24]/30">
            Get a bid sheet for my pool →
          </button>
        </div>

        <div className="bg-[#F5F1EA] border hairline">
          <div className="px-8 py-6 border-b hairline flex items-center justify-between">
            <div className="flex items-center gap-6">
              <span className="eyebrow text-[#131A24]/60">Sample project</span>
              <span className="text-[15px]">Replaster a 30,000 gallon pool</span>
            </div>
            <div className="flex items-center gap-6 text-[13px] text-[#131A24]/70 tnum">
              <span>3 of 3 bids received</span>
              <span>·</span>
              <span className="inline-flex items-center gap-1.5">
                <span className="inline-block w-1.5 h-1.5 rounded-full bg-[#1D6FA3]" />
                Bidding closed
              </span>
            </div>
          </div>

          <div className="grid grid-cols-3">
            {bids.map((b, i) => (
              <div
                key={b.co}
                className={`p-8 ${i < 2 ? "border-r hairline" : ""} ${b.tone === "blue" ? "bg-[#F5F1EA]" : ""}`}
              >
                <div className="flex items-center justify-between mb-6">
                  <div className="flex items-center gap-3">
                    <div className="w-10 h-10 rounded-full bg-[#1D6FA3] text-white font-display text-[18px] flex items-center justify-center">
                      {b.co.split(" ").map(w=>w[0]).slice(0,2).join("")}
                    </div>
                    <div>
                      <div className="text-[15px] font-medium leading-tight">{b.co}</div>
                      <div className="text-[12px] text-[#131A24]/60">{b.loc}</div>
                    </div>
                  </div>
                  <span
                    className="eyebrow"
                    style={{
                      color: b.note === "Lowest bid" ? "#1D6FA3" : b.note === "Fastest start" ? "#E8834B" : "#131A24",
                    }}
                  >
                    {b.note}
                  </span>
                </div>

                <div className="font-display tnum text-[64px] leading-none tracking-tight">
                  {b.price}
                </div>
                <div className="mt-2 text-[13px] text-[#131A24]/60">all-in, tax incl.</div>

                <div className="mt-7 space-y-3 text-[14px]">
                  <Row k="Timeline" v={b.timeline} />
                  <Row k="Earliest start" v={b.start} />
                  <Row k="Materials" v={b.materials} />
                  <Row k="Warranty" v={b.warranty} />
                </div>

                <div className="mt-7 pt-5 border-t hairline flex items-center justify-between">
                  <Rating value={b.rating} count={b.reviews} />
                  <div className="flex items-center gap-1.5">
                    {b.badges.map((bd) => (
                      <span key={bd} className="text-[10px] uppercase tracking-wider px-2 py-1 border hairline text-[#131A24]/70">
                        {bd}
                      </span>
                    ))}
                  </div>
                </div>

                <button onClick={() => open("intake")} className="mt-6 w-full btn-blue py-3 text-[14px]">
                  Start my project
                </button>
              </div>
            ))}
          </div>

          <div className="px-8 py-5 border-t hairline flex items-center justify-between text-[12px] text-[#131A24]/60">
            <span>Bid spread: $4,300 · Median: $16,800 · All bids honored for 14 days</span>
            <span className="tnum">Sample bid sheet · 3 contractors</span>
          </div>
        </div>
      </div>
    </section>
  );
}

function Row({ k, v }) {
  return (
    <div className="flex items-baseline justify-between gap-4">
      <span className="text-[13px] text-[#131A24]/55 shrink-0">{k}</span>
      <span className="text-[13px] text-[#131A24] text-right">{v}</span>
    </div>
  );
}

/* ----------------------------- project types ------------------------------ */

function ProjectTypes() {
  const { open } = useForm();
  const tiles = [
    { t: "Replaster & Resurface", r: "$9,800 – $22,000",   v: "deep",   key: "replaster" },
    { t: "New Pool Build",        r: "$55,000 – $120,000", v: "warm",   key: "new-build" },
    { t: "Equipment Repair",      r: "$280 – $4,200",      v: "sunset", key: "equipment" },
    { t: "Pool Heater Install",   r: "$3,600 – $8,400",    v: "dawn",   key: "heater" },
    { t: "Leak Detection",        r: "$450 – $1,900",      v: "deep",   key: "leak" },
    { t: "Remodel & Redesign",    r: "$18,000 – $65,000",  v: "warm",   key: "remodel" },
  ];
  return (
    <section id="contractors" className="py-32">
      <div className="max-w-[1360px] mx-auto px-10">
        <div className="flex items-end justify-between mb-16">
          <div>
            <div className="eyebrow text-[#131A24]/60 mb-5">Project types</div>
            <h2 className="font-display text-[56px] leading-[1.02] max-w-[780px]">
              Whatever your pool needs,<br />someone's already bid on it.
            </h2>
          </div>
          <div className="text-[14px] text-[#131A24]/70 max-w-[260px] text-right">
            Ranges reflect typical project pricing across our service areas. Hover for detail.
          </div>
        </div>

        <div className="grid grid-cols-3 gap-4">
          {tiles.map((t) => (
            <button
              key={t.t}
              onClick={() => open("intake", { projectType: t.key })}
              className="tile relative h-[340px] overflow-hidden cursor-pointer text-left"
            >
              <Photo variant={t.v} className="absolute inset-0">
                <div
                  className="absolute inset-x-0 bottom-0 h-[55%]"
                  style={{
                    background:
                      "linear-gradient(180deg, rgba(10,14,22,0) 0%, rgba(10,14,22,0.75) 100%)",
                  }}
                />
                <div className="absolute inset-x-0 bottom-0 p-6 text-white">
                  <div className="font-display text-[28px] leading-tight">{t.t}</div>
                  <div className="tile-reveal mt-3 flex items-center gap-3">
                    <span className="eyebrow text-white/70">Typical range</span>
                    <span className="tnum text-[14px]">{t.r}</span>
                  </div>
                </div>
              </Photo>
            </button>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ------------------------------ contractor quote -------------------------- */

function ContractorQuote() {
  return (
    <section className="py-32" style={{ background: "#131A24" }}>
      <div className="max-w-[1360px] mx-auto px-10 grid grid-cols-12 gap-10 items-center">
        <div className="col-span-4">
          <Photo variant="dawn" className="h-[480px]">
            <div
              className="absolute inset-0"
              style={{
                background: "linear-gradient(180deg, rgba(19,26,36,0) 40%, rgba(19,26,36,0.5) 100%)",
              }}
            />
          </Photo>
        </div>
        <div className="col-span-8 pl-6">
          <div className="eyebrow text-[#E8834B] mb-8">Why contractors compete for you</div>
          <blockquote className="font-display-italic text-[#F5F1EA] text-[52px] leading-[1.08] tracking-tight">
            "Poolbidder sends me homeowners who are ready to move. I put my best number forward because I know I'm up against two other pros. Everyone wins."
          </blockquote>
          <div className="mt-10 flex items-center gap-5">
            <div className="h-px w-12 bg-[#E1DAC9]/40" />
            <div className="text-[#F5F1EA]">
              <div className="text-[16px] font-medium">Mike H.</div>
              <div className="text-[13px] text-[#F5F1EA]/60">Licensed pool builder · 20+ years · Coastal US</div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ------------------------------ vetting process --------------------------- */

function Vetting() {
  const { open } = useForm();
  const items = [
    { h: "State license, verified", p: "We pull active license records from your state's contractor board regularly. Expired license, off the network." },
    { h: "General liability + workers' comp", p: "Minimum $1M general liability and current workers' compensation. Certificate on file before a contractor submits a first bid." },
    { h: "Ten reviews, minimum", p: "At least ten verified homeowner reviews across public platforms before joining. Average rating 4.6 or higher." },
    { h: "Background-checked ownership", p: "Owner-operators run a background and business-entity check. We look for lien history, bankruptcies, and unresolved complaints." },
    { h: "Written work guarantee", p: "Every bid is backed by a Poolbidder-mediated warranty. If a contractor walks, we find you a replacement at the bid price." },
  ];
  return (
    <section className="py-32">
      <div className="max-w-[1360px] mx-auto px-10 grid grid-cols-12 gap-16">
        <div className="col-span-4">
          <div className="eyebrow text-[#131A24]/60 mb-5">Vetting</div>
          <h2 className="font-display text-[52px] leading-[1.02]">
            Five gates.<br />No shortcuts.
          </h2>
          <p className="mt-8 text-[16px] leading-relaxed text-[#131A24]/70 max-w-[340px]">
            We turn down more contractor applications than we accept. Homeowners only see the ones who clear every gate.
          </p>
          <button onClick={() => open("contractor")} className="mt-8 inline-block text-[14px] underline underline-offset-4 decoration-[#131A24]/30">
            Apply to join the network →
          </button>
        </div>
        <div className="col-span-8">
          <ol className="divide-y hairline">
            {items.map((it, i) => (
              <li key={it.h} className="grid grid-cols-12 gap-6 py-8 first:pt-0">
                <div className="col-span-2 font-display text-[#1D6FA3] text-[44px] leading-none tnum">
                  {String(i + 1).padStart(2, "0")}
                </div>
                <div className="col-span-10">
                  <div className="font-display text-[26px] leading-tight">{it.h}</div>
                  <p className="mt-2 text-[16px] leading-relaxed text-[#131A24]/70 max-w-[640px]">
                    {it.p}
                  </p>
                </div>
              </li>
            ))}
          </ol>
        </div>
      </div>
    </section>
  );
}

/* ------------------------------------ faq --------------------------------- */

function FAQ() {
  const { open } = useForm();
  const qs = [
    { q: "What does Poolbidder cost the homeowner?", a: "Nothing. The service is free to homeowners. Contractors pay a flat listing fee only when a homeowner picks them — there's no markup on the bid itself." },
    { q: "Can I really pass on all three bids?", a: "Yes. You are under no obligation to accept any bid. Bids are honored for 14 days if you want to think it over. There are no re-listing fees or penalties." },
    { q: "How do you price a project I haven't measured yet?", a: "Rough numbers and photos are enough to start. For replaster, new build, or remodel jobs, the winning contractor does a free on-site measure before work begins. Final price can only go down from the bid, not up, unless you change the scope." },
    { q: "What if my pool is non-standard — raised spa, saltwater, vanishing edge?", a: "Every bid form has a detail section for equipment, finishes, and features. Contractors on Poolbidder specialize by category, so non-standard pools get matched accordingly." },
    { q: "What happens if the contractor flakes mid-project?", a: "Our warranty covers it. If a Poolbidder contractor walks off or misses agreed milestones, we find a replacement at the original bid price and mediate the handoff." },
    { q: "Are you available outside the listed service areas?", a: "Not yet. We're live in Florida, Texas, Arizona, California, and Nevada. Join the waitlist and we'll email when we open in your zip." },
  ];
  return (
    <section className="py-32" style={{ background: "#ECE4D3" }}>
      <div className="max-w-[1360px] mx-auto px-10 grid grid-cols-12 gap-16">
        <div className="col-span-4">
          <div className="eyebrow text-[#131A24]/60 mb-5">Questions</div>
          <h2 className="font-display text-[56px] leading-[1.02]">
            Fair questions,<br />straight answers.
          </h2>
          <p className="mt-8 text-[16px] leading-relaxed text-[#131A24]/70 max-w-[320px]">
            Can't find yours? Send us a note through the contact form — we answer every inquiry within one business day.
          </p>
          <button onClick={() => open("contact")} className="mt-6 text-[14px] underline underline-offset-4 decoration-[#131A24]/30">
            Ask us anything →
          </button>
        </div>
        <div className="col-span-8">
          <div className="divide-y hairline border-t border-b hairline">
            {qs.map((item, i) => (
              <details key={i} className="group py-6">
                <summary className="flex items-start justify-between gap-8">
                  <span className="font-display text-[24px] leading-tight max-w-[680px]">
                    {item.q}
                  </span>
                  <span className="faq-plus text-[#1D6FA3] text-[26px] leading-none shrink-0 mt-1">+</span>
                </summary>
                <p className="mt-4 text-[16px] leading-relaxed text-[#131A24]/75 max-w-[680px]">
                  {item.a}
                </p>
              </details>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}

/* ----------------------------- final cta band ----------------------------- */

function FinalCTA() {
  const { open } = useForm();
  return (
    <section id="cta" className="relative overflow-hidden" style={{ background: "#164F76" }}>
      <div
        className="absolute inset-0"
        style={{
          background:
            "radial-gradient(60% 120% at 85% 50%, rgba(232,131,75,0.35), transparent 60%), radial-gradient(80% 120% at 10% 80%, rgba(29,111,163,0.6), transparent 60%)",
        }}
      />
      <div className="relative max-w-[1360px] mx-auto px-10 py-40">
        <div className="grid grid-cols-12 gap-10 items-end">
          <div className="col-span-8">
            <div className="eyebrow text-[#E8834B] mb-8">Ready when you are</div>
            <h2 className="font-display text-white text-[88px] leading-[0.98] tracking-tight">
              Your pool deserves<br />real competition.
            </h2>
            <p className="mt-8 text-[18px] leading-relaxed text-white/80 max-w-[540px]">
              Three bids in 48 hours. No sales calls, no markups, no obligation. Describe your project and we'll take it from there.
            </p>
          </div>
          <div className="col-span-4 flex flex-col items-start gap-5">
            <button onClick={() => open("intake")} className="btn-orange px-8 py-5 text-[16px]">
              Describe my project →
            </button>
            <span className="text-[13px] text-white/60">Takes 3 minutes · $0 to homeowners</span>
          </div>
        </div>
      </div>
    </section>
  );
}

/* --------------------------------- footer --------------------------------- */

function Footer() {
  const { open } = useForm();
  return (
    <footer className="py-16" style={{ background: "#131A24", color: "#F5F1EA" }}>
      <div className="max-w-[1360px] mx-auto px-10">
        <div className="grid grid-cols-12 gap-10 items-start">
          <div className="col-span-5">
            <div className="font-display-italic text-[42px] leading-none">Poolbidder</div>
            <p className="mt-6 text-[14px] leading-relaxed text-[#F5F1EA]/60 max-w-[360px]">
              A marketplace for homeowner-driven pool work. Three bids, 48 hours, no obligation.
            </p>
            <button onClick={() => open("intake")} className="mt-6 btn-blue px-5 py-2.5 text-[13px]">
              Get my bids
            </button>
          </div>

          <div className="col-span-2">
            <div className="eyebrow text-[#F5F1EA]/50 mb-4">Product</div>
            <ul className="space-y-2 text-[14px] text-[#F5F1EA]/85">
              <li><a href="#how" className="hover:text-white">How it works</a></li>
              <li><a href="#contractors" className="hover:text-white">Project types</a></li>
              <li><a href="#reviews" className="hover:text-white">Sample bid sheet</a></li>
              <li><button onClick={() => open("contractor")} className="hover:text-white text-left">For contractors</button></li>
            </ul>
          </div>
          <div className="col-span-2">
            <div className="eyebrow text-[#F5F1EA]/50 mb-4">Company</div>
            <ul className="space-y-2 text-[14px] text-[#F5F1EA]/85">
              <li><button onClick={() => open("contact")} className="hover:text-white text-left">About</button></li>
              <li><button onClick={() => open("contact")} className="hover:text-white text-left">Press</button></li>
              <li><button onClick={() => open("contact")} className="hover:text-white text-left">Contact</button></li>
              <li><button onClick={() => open("contact")} className="hover:text-white text-left">Careers</button></li>
            </ul>
          </div>
          <div className="col-span-3">
            <div className="eyebrow text-[#F5F1EA]/50 mb-4">Trust</div>
            <ul className="space-y-2 text-[13px] text-[#F5F1EA]/70">
              <li>Every contractor is licensed &amp; insured in their state</li>
              <li>Every bid is warranty-backed</li>
              <li>Service: FL · TX · AZ · CA · NV</li>
            </ul>
          </div>
        </div>
        <div className="mt-16 pt-6 border-t border-[#F5F1EA]/15 flex items-center justify-between text-[12px] text-[#F5F1EA]/50">
          <span>© 2026 Poolbidder, Inc.</span>
          <span className="flex items-center gap-6">
            <button onClick={() => open("contact")} className="hover:text-white">Privacy</button>
            <button onClick={() => open("contact")} className="hover:text-white">Terms</button>
            <button onClick={() => open("contact")} className="hover:text-white">Do not sell my info</button>
          </span>
        </div>
      </div>
    </footer>
  );
}

/* ----------------------------- intake modal ------------------------------- */

const PROJECT_OPTIONS = [
  { key: "replaster",  label: "Replaster & resurface" },
  { key: "new-build",  label: "New pool build" },
  { key: "remodel",    label: "Remodel & redesign" },
  { key: "equipment",  label: "Equipment repair" },
  { key: "heater",     label: "Pool heater install" },
  { key: "leak",       label: "Leak detection" },
  { key: "other",      label: "Something else" },
];

function IntakeModal() {
  const { isOpen, mode, preset, close } = useForm();
  const [step, setStep] = useState(0);
  const [submitted, setSubmitted] = useState(false);
  const [data, setData] = useState({
    projectType: "",
    size: "",
    timing: "flexible",
    description: "",
    name: "",
    email: "",
    zip: "",
    // contractor fields
    company: "",
    license: "",
    years: "",
    // contact fields
    subject: "",
    message: "",
  });
  const [errors, setErrors] = useState({});

  // Reset on open / mode change
  useEffect(() => {
    if (isOpen) {
      setStep(0);
      setSubmitted(false);
      setErrors({});
      setData((d) => ({
        ...d,
        projectType: preset?.projectType || "",
      }));
      // lock body scroll
      document.body.style.overflow = "hidden";
    } else {
      document.body.style.overflow = "";
    }
    return () => { document.body.style.overflow = ""; };
  }, [isOpen, mode, preset]);

  // Close on esc
  useEffect(() => {
    if (!isOpen) return;
    const h = (e) => { if (e.key === "Escape") close(); };
    window.addEventListener("keydown", h);
    return () => window.removeEventListener("keydown", h);
  }, [isOpen, close]);

  if (!isOpen) return null;

  const setField = (k, v) => setData((d) => ({ ...d, [k]: v }));

  const modeConfig = {
    intake: {
      title: "Describe your project",
      subtitle: "Three vetted contractors will bid within 48 hours.",
      steps: 3,
    },
    contractor: {
      title: "Apply to the network",
      subtitle: "Licensed pool professionals only. We review each application by hand.",
      steps: 2,
    },
    contact: {
      title: "Send us a note",
      subtitle: "We answer every inquiry within one business day.",
      steps: 1,
    },
  };
  const cfg = modeConfig[mode];

  const validateStep = () => {
    const e = {};
    if (mode === "intake") {
      if (step === 0) {
        if (!data.projectType) e.projectType = "Pick a project type.";
      } else if (step === 1) {
        if (!data.description.trim() || data.description.trim().length < 15) {
          e.description = "Tell us a bit more (at least a sentence or two).";
        }
      } else if (step === 2) {
        if (!data.name.trim()) e.name = "Name is required.";
        if (!/^\S+@\S+\.\S+$/.test(data.email)) e.email = "Valid email, please.";
        if (!/^\d{5}$/.test(data.zip)) e.zip = "5-digit US zip.";
      }
    } else if (mode === "contractor") {
      if (step === 0) {
        if (!data.company.trim()) e.company = "Business name required.";
        if (!data.license.trim()) e.license = "State license # required.";
        if (!/^\d{1,2}$/.test(data.years)) e.years = "Years in business (number).";
      } else if (step === 1) {
        if (!data.name.trim()) e.name = "Name is required.";
        if (!/^\S+@\S+\.\S+$/.test(data.email)) e.email = "Valid email, please.";
        if (!/^\d{5}$/.test(data.zip)) e.zip = "5-digit US zip.";
      }
    } else if (mode === "contact") {
      if (!data.name.trim()) e.name = "Name is required.";
      if (!/^\S+@\S+\.\S+$/.test(data.email)) e.email = "Valid email, please.";
      if (!data.subject.trim()) e.subject = "Subject required.";
      if (!data.message.trim() || data.message.trim().length < 10) e.message = "A short note, please.";
    }
    setErrors(e);
    return Object.keys(e).length === 0;
  };

  const next = () => {
    if (!validateStep()) return;
    if (step + 1 < cfg.steps) setStep(step + 1);
    else setSubmitted(true);
  };
  const back = () => { if (step > 0) setStep(step - 1); };

  return (
    <div
      className="fixed inset-0 z-50 flex items-center justify-center p-6"
      style={{ background: "rgba(19,26,36,0.72)" }}
      onClick={close}
      role="dialog"
      aria-modal="true"
    >
      <div
        className="relative bg-[#F5F1EA] w-full max-w-[720px] max-h-[90vh] overflow-y-auto"
        onClick={(e) => e.stopPropagation()}
        style={{ boxShadow: "0 30px 80px rgba(10,14,22,0.35)" }}
      >
        {/* header */}
        <div className="sticky top-0 bg-[#F5F1EA] px-10 pt-8 pb-5 border-b hairline flex items-start justify-between gap-6">
          <div>
            <div className="eyebrow text-[#131A24]/60">{mode === "contact" ? "Contact" : mode === "contractor" ? "Contractors" : "Start a project"}</div>
            <h3 className="font-display text-[32px] leading-[1.05] mt-2">{submitted ? "Thank you." : cfg.title}</h3>
            {!submitted && <p className="mt-2 text-[14px] text-[#131A24]/70 max-w-[480px]">{cfg.subtitle}</p>}
          </div>
          <button onClick={close} className="shrink-0 w-9 h-9 flex items-center justify-center border hairline hover:bg-white" aria-label="Close">
            <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M1 1l12 12M13 1L1 13"/></svg>
          </button>
        </div>

        {/* body */}
        <div className="px-10 py-8">
          {submitted ? (
            <SuccessState mode={mode} data={data} onClose={close} />
          ) : (
            <>
              {cfg.steps > 1 && <StepIndicator total={cfg.steps} current={step} />}
              <div className="mt-2">
                {mode === "intake" && step === 0 && <IntakeStep0 data={data} setField={setField} errors={errors} />}
                {mode === "intake" && step === 1 && <IntakeStep1 data={data} setField={setField} errors={errors} />}
                {mode === "intake" && step === 2 && <IntakeStep2 data={data} setField={setField} errors={errors} />}
                {mode === "contractor" && step === 0 && <ContractorStep0 data={data} setField={setField} errors={errors} />}
                {mode === "contractor" && step === 1 && <ContractorStep1 data={data} setField={setField} errors={errors} />}
                {mode === "contact" && <ContactStep data={data} setField={setField} errors={errors} />}
              </div>

              <div className="mt-10 flex items-center justify-between">
                {step > 0 ? (
                  <button onClick={back} className="text-[14px] text-[#131A24]/70 hover:text-[#131A24]">
                    ← Back
                  </button>
                ) : <span />}
                <button onClick={next} className="btn-blue px-7 py-3.5 text-[14px]">
                  {step + 1 === cfg.steps ? (mode === "contact" ? "Send" : "Submit") : "Continue →"}
                </button>
              </div>
            </>
          )}
        </div>

        {!submitted && (
          <div className="px-10 py-4 border-t hairline text-[11px] text-[#131A24]/55 flex items-center gap-6">
            <span>Your info stays with Poolbidder. We never sell homeowner data.</span>
          </div>
        )}
      </div>
    </div>
  );
}

function StepIndicator({ total, current }) {
  return (
    <div className="flex items-center gap-2 mb-8">
      {Array.from({ length: total }).map((_, i) => (
        <div key={i} className="flex-1 h-[3px]" style={{ background: i <= current ? "#1D6FA3" : "#E1DAC9" }} />
      ))}
      <span className="ml-3 eyebrow text-[#131A24]/60">Step {current + 1} of {total}</span>
    </div>
  );
}

/* ------------------------------ form steps -------------------------------- */

const FieldLabel = ({ children, hint }) => (
  <div className="flex items-baseline justify-between mb-2">
    <span className="eyebrow text-[#131A24]/70">{children}</span>
    {hint && <span className="text-[11px] text-[#131A24]/50">{hint}</span>}
  </div>
);

const Input = ({ value, onChange, error, placeholder, type = "text" }) => (
  <div>
    <input
      type={type}
      value={value}
      onChange={(e) => onChange(e.target.value)}
      placeholder={placeholder}
      className="w-full bg-white border hairline px-4 py-3 text-[15px] focus:outline-none focus:border-[#1D6FA3]"
      style={{ borderColor: error ? "#E8834B" : undefined }}
    />
    {error && <div className="mt-1.5 text-[12px] text-[#B5532A]">{error}</div>}
  </div>
);

const Textarea = ({ value, onChange, error, placeholder, rows = 5 }) => (
  <div>
    <textarea
      value={value}
      onChange={(e) => onChange(e.target.value)}
      placeholder={placeholder}
      rows={rows}
      className="w-full bg-white border hairline px-4 py-3 text-[15px] focus:outline-none focus:border-[#1D6FA3] leading-relaxed"
      style={{ borderColor: error ? "#E8834B" : undefined }}
    />
    {error && <div className="mt-1.5 text-[12px] text-[#B5532A]">{error}</div>}
  </div>
);

function IntakeStep0({ data, setField, errors }) {
  return (
    <div>
      <FieldLabel>What kind of project?</FieldLabel>
      <div className="grid grid-cols-2 gap-2">
        {PROJECT_OPTIONS.map((o) => {
          const selected = data.projectType === o.key;
          return (
            <button
              key={o.key}
              onClick={() => setField("projectType", o.key)}
              className="px-4 py-4 text-left border hairline text-[14px] transition-colors"
              style={{
                background: selected ? "#131A24" : "#fff",
                color: selected ? "#F5F1EA" : "#131A24",
                borderColor: selected ? "#131A24" : undefined,
              }}
            >
              {o.label}
            </button>
          );
        })}
      </div>
      {errors.projectType && <div className="mt-2 text-[12px] text-[#B5532A]">{errors.projectType}</div>}

      <div className="mt-8">
        <FieldLabel>Pool size</FieldLabel>
        <div className="flex gap-2 flex-wrap">
          {["Under 15k gal", "15k – 25k gal", "25k – 40k gal", "Over 40k gal", "Not sure"].map((s) => {
            const selected = data.size === s;
            return (
              <button
                key={s}
                onClick={() => setField("size", s)}
                className="px-4 py-2.5 text-[13px] border hairline"
                style={{
                  background: selected ? "#1D6FA3" : "#fff",
                  color: selected ? "#fff" : "#131A24",
                  borderColor: selected ? "#1D6FA3" : undefined,
                }}
              >
                {s}
              </button>
            );
          })}
        </div>
      </div>

      <div className="mt-8">
        <FieldLabel>Timing</FieldLabel>
        <div className="flex gap-2 flex-wrap">
          {[
            { k: "asap", l: "As soon as possible" },
            { k: "month", l: "Within a month" },
            { k: "quarter", l: "Within 3 months" },
            { k: "flexible", l: "I'm flexible" },
          ].map((t) => {
            const selected = data.timing === t.k;
            return (
              <button
                key={t.k}
                onClick={() => setField("timing", t.k)}
                className="px-4 py-2.5 text-[13px] border hairline"
                style={{
                  background: selected ? "#1D6FA3" : "#fff",
                  color: selected ? "#fff" : "#131A24",
                  borderColor: selected ? "#1D6FA3" : undefined,
                }}
              >
                {t.l}
              </button>
            );
          })}
        </div>
      </div>
    </div>
  );
}

function IntakeStep1({ data, setField, errors }) {
  return (
    <div className="space-y-6">
      <div>
        <FieldLabel hint="The more detail, the tighter the bids">Describe your project</FieldLabel>
        <Textarea
          value={data.description}
          onChange={(v) => setField("description", v)}
          error={errors.description}
          placeholder="E.g. 30,000 gallon pool, plaster is stained and rough. Looking to replaster and re-grout the coping. Pool is 15 years old, equipment is working fine."
          rows={7}
        />
      </div>
      <div className="border hairline bg-white p-5">
        <div className="eyebrow text-[#131A24]/60 mb-2">Photos (optional)</div>
        <p className="text-[13px] text-[#131A24]/60">
          If you have photos, you can share them in a follow-up after we reply. They are not required — many bids start from a clear written description.
        </p>
      </div>
    </div>
  );
}

function IntakeStep2({ data, setField, errors }) {
  return (
    <div className="grid grid-cols-2 gap-5">
      <div className="col-span-2">
        <FieldLabel>Your name</FieldLabel>
        <Input value={data.name} onChange={(v) => setField("name", v)} error={errors.name} placeholder="First and last" />
      </div>
      <div>
        <FieldLabel>Email</FieldLabel>
        <Input value={data.email} onChange={(v) => setField("email", v)} error={errors.email} placeholder="Email for follow-up" type="email" />
      </div>
      <div>
        <FieldLabel>Project zip</FieldLabel>
        <Input value={data.zip} onChange={(v) => setField("zip", v.replace(/\D/g, "").slice(0,5))} error={errors.zip} placeholder="5-digit ZIP" />
      </div>
      <div className="col-span-2 text-[12px] text-[#131A24]/60 leading-relaxed">
        By continuing, you agree that up to three vetted contractors may reach out about bidding on your project. You can opt out of further messages at any time.
      </div>
    </div>
  );
}

function ContractorStep0({ data, setField, errors }) {
  return (
    <div className="grid grid-cols-2 gap-5">
      <div className="col-span-2">
        <FieldLabel>Business name</FieldLabel>
        <Input value={data.company} onChange={(v) => setField("company", v)} error={errors.company} placeholder="Your company name" />
      </div>
      <div>
        <FieldLabel>State license #</FieldLabel>
        <Input value={data.license} onChange={(v) => setField("license", v)} error={errors.license} placeholder="As issued by your state board" />
      </div>
      <div>
        <FieldLabel>Years in business</FieldLabel>
        <Input value={data.years} onChange={(v) => setField("years", v.replace(/\D/g, "").slice(0,2))} error={errors.years} placeholder="12" />
      </div>
      <div className="col-span-2">
        <FieldLabel>Which services? (optional)</FieldLabel>
        <Textarea
          value={data.description}
          onChange={(v) => setField("description", v)}
          error={null}
          placeholder="E.g. replaster, new build, equipment repair, heater install. Mention any specialties — vanishing edge, saltwater, natural pools, etc."
          rows={4}
        />
      </div>
    </div>
  );
}

function ContractorStep1({ data, setField, errors }) {
  return (
    <div className="grid grid-cols-2 gap-5">
      <div className="col-span-2">
        <FieldLabel>Contact name</FieldLabel>
        <Input value={data.name} onChange={(v) => setField("name", v)} error={errors.name} placeholder="Owner or primary contact" />
      </div>
      <div>
        <FieldLabel>Email</FieldLabel>
        <Input value={data.email} onChange={(v) => setField("email", v)} error={errors.email} placeholder="Company email" type="email" />
      </div>
      <div>
        <FieldLabel>Primary service zip</FieldLabel>
        <Input value={data.zip} onChange={(v) => setField("zip", v.replace(/\D/g, "").slice(0,5))} error={errors.zip} placeholder="5-digit ZIP" />
      </div>
      <div className="col-span-2 text-[12px] text-[#131A24]/60 leading-relaxed">
        We review applications in the order we receive them. Expect a response within 5 business days, including next steps for our vetting process.
      </div>
    </div>
  );
}

function ContactStep({ data, setField, errors }) {
  return (
    <div className="grid grid-cols-2 gap-5">
      <div>
        <FieldLabel>Your name</FieldLabel>
        <Input value={data.name} onChange={(v) => setField("name", v)} error={errors.name} placeholder="First and last" />
      </div>
      <div>
        <FieldLabel>Email</FieldLabel>
        <Input value={data.email} onChange={(v) => setField("email", v)} error={errors.email} placeholder="Email for follow-up" type="email" />
      </div>
      <div className="col-span-2">
        <FieldLabel>Subject</FieldLabel>
        <Input value={data.subject} onChange={(v) => setField("subject", v)} error={errors.subject} placeholder="What's this about?" />
      </div>
      <div className="col-span-2">
        <FieldLabel>Message</FieldLabel>
        <Textarea value={data.message} onChange={(v) => setField("message", v)} error={errors.message} placeholder="Tell us what's on your mind." rows={6} />
      </div>
    </div>
  );
}

/* ----------------------------- success state ------------------------------ */

function SuccessState({ mode, data, onClose }) {
  const copy = {
    intake: {
      heading: "Your project is in the queue.",
      body: "We're matching your description to vetted contractors in your coverage area. When bids are ready, you'll get a clean side-by-side summary to review — we only follow up when there is something actionable.",
      next: "What happens next",
      steps: [
        "We confirm project details on our side — typically same day on business days.",
        "Three contractors prepare itemized, warranty-backed bids.",
        "You review a single comparison at your own pace — no obligation to choose.",
      ],
    },
    contractor: {
      heading: "Application received.",
      body: "Thanks for applying to the Poolbidder network. A member of our vetting team will review your submission and respond within 5 business days.",
      next: "Our review covers",
      steps: [
        "State license verification and insurance certificates.",
        "A spot-check of recent homeowner reviews and public records.",
        "A short intro call to walk you through bid etiquette on the platform.",
      ],
    },
    contact: {
      heading: "Message received.",
      body: "We've captured your note. Our team replies to new inquiries within one business day during normal hours.",
      next: null,
      steps: [],
    },
  }[mode];

  return (
    <div>
      <div className="flex items-start gap-5">
        <div className="w-12 h-12 rounded-full flex items-center justify-center shrink-0" style={{ background: "#1D6FA3" }}>
          <svg width="22" height="22" viewBox="0 0 22 22" fill="none" stroke="#fff" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <path d="M4 11l5 5L18 6" />
          </svg>
        </div>
        <div className="flex-1">
          <h4 className="font-display text-[28px] leading-tight">{copy.heading}</h4>
          <p className="mt-3 text-[15px] leading-relaxed text-[#131A24]/75 max-w-[520px]">{copy.body}</p>
        </div>
      </div>

      {data.email && (
        <div className="mt-7 border hairline bg-white px-5 py-4 flex items-center justify-between">
          <div>
            <div className="eyebrow text-[#131A24]/60">Reply will use</div>
            <div className="mt-1 text-[15px]">{data.email}</div>
          </div>
          {data.zip && (
            <div className="text-right">
              <div className="eyebrow text-[#131A24]/60">ZIP on file</div>
              <div className="mt-1 text-[15px] tnum">{data.zip}</div>
            </div>
          )}
        </div>
      )}

      {copy.next && (
        <div className="mt-8">
          <div className="eyebrow text-[#131A24]/60 mb-4">{copy.next}</div>
          <ol className="space-y-3">
            {copy.steps.map((s, i) => (
              <li key={i} className="flex gap-4 text-[14px] leading-relaxed text-[#131A24]/80">
                <span className="font-display text-[#1D6FA3] text-[18px] leading-none mt-0.5 tnum">{String(i + 1).padStart(2, "0")}</span>
                <span>{s}</span>
              </li>
            ))}
          </ol>
        </div>
      )}

      <div className="mt-10 flex items-center justify-between">
        <button onClick={onClose} className="text-[14px] text-[#131A24]/70 hover:text-[#131A24]">
          Close
        </button>
        <button onClick={onClose} className="btn-blue px-6 py-3 text-[14px]">
          Back to the site
        </button>
      </div>
    </div>
  );
}

/* ---------------------------------- app ----------------------------------- */

function App() {
  return (
    <FormProvider>
      <Header />
      <Hero />
      <HowItWorks />
      <BidExample />
      <ProjectTypes />
      <ContractorQuote />
      <Vetting />
      <FAQ />
      <FinalCTA />
      <Footer />
      <IntakeModal />
    </FormProvider>
  );
}

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