/* global React, GS_SERVICES, GS_REVIEWS, GS_ZIPS, GS_FAQ,
   Icon, Button, Eyebrow, Chip, TierPill, Price, SteelPhoto, Logo, Stars, Section, ServiceCard */
const { useState, useEffect, useMemo } = React;

// ================= HOME =================

function HomePage({ nav }) {
  return (
    <>
      {/* HERO */}
      <Section pad="120px 0 96px" style={{ background: "var(--bg-page)" }}>
        <div style={{ display: "grid", gridTemplateColumns: "1.15fr 0.85fr", gap: 64, alignItems: "center" }}>
          <div>
            <Eyebrow style={{ marginBottom: 24 }}>{window.HP_REGION || window.HP_CITY || "Metro Area"}</Eyebrow>
            <h1 className="hero-display" style={{
              fontFamily: "var(--font-display)", fontSize: "clamp(3rem, 5.6vw, 5.25rem)",
              lineHeight: 1.05, letterSpacing: "-0.03em", color: "var(--fg-1)",
              margin: "0 0 32px", fontWeight: 400, paddingBottom: 6,
            }}>
              Insured handyman.<br/>
              <em style={{ fontStyle: "italic", color: "var(--fg-2)" }}>Same&#8209;day.</em>
            </h1>
            <p className="lead" style={{ fontSize: 19, lineHeight: 1.55, color: "var(--fg-2)", maxWidth: 520, margin: "0 0 36px" }}>
              {window.HP_ABOUT_BIO || `Professional handyman serving ${window.HP_REGION || window.HP_CITY}. Book a 90-minute visit. We arrive with the tools and a plan.`}
            </p>
            <div style={{ display: "flex", gap: 14, alignItems: "center", flexWrap: "wrap" }}>
              <Button icon="calendar" onClick={() => nav("contact")}>Book a visit</Button>
              <Button variant="secondary" icon="phone">{window.HP_PHONE || 'Call Us'}</Button>
            </div>
            <div style={{ display: "flex", gap: 28, marginTop: 48, alignItems: "center", flexWrap: "wrap" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                <Stars/>
                <span style={{ fontFamily: "var(--font-mono)", fontSize: 13, color: "var(--fg-2)" }}>4.97 · 284 jobs</span>
              </div>
              <Chip tone="success" dot>Open · 2:30 PM today</Chip>
            </div>
          </div>
          <div style={{ position: "relative" }}>
            <div style={{
              aspectRatio: "4/5", borderRadius: 18, overflow: "hidden",
              border: "1px solid var(--border-subtle)", boxShadow: "var(--shadow-lg)",
            }}>
              <SteelPhoto height="100%" seed={1} label="" />
            </div>
            <div style={{
              position: "absolute", right: -24, bottom: 40, background: "#fff",
              border: "1px solid var(--border-subtle)", borderRadius: 12,
              padding: "16px 20px", boxShadow: "var(--shadow-md)", maxWidth: 220,
            }}>
              <Eyebrow style={{ marginBottom: 8 }}>Today</Eyebrow>
              <div style={{ fontFamily: "var(--font-mono)", fontSize: 13, color: "var(--fg-1)", lineHeight: 1.7 }}>
                10:00 · 94301 · TV<br/>
                12:30 · 94025 · Drywall<br/>
                <span style={{ color: "var(--accent)" }}>14:30 · open slot</span>
              </div>
            </div>
          </div>
        </div>
      </Section>

      {/* TRUST STRIP */}
      <div style={{ borderTop: "1px solid var(--border-subtle)", borderBottom: "1px solid var(--border-subtle)", background: "#fff" }}>
        <div style={{ maxWidth: "var(--container)", margin: "0 auto", padding: "22px var(--gutter)", display: "flex", gap: 40, flexWrap: "wrap", justifyContent: "space-between", alignItems: "center" }}>
          {[
            ["shield-check", window.HP_LICENSE_LINE || "Fully Insured & Bonded"],
            ["clock", "Same-day response"],
            ["badge-check", window.HP_EXEMPTION_LINE ? window.HP_EXEMPTION_LINE.split("(")[0].trim() : "AB 2622 exempt"],
            ["languages", window.HP_LANGUAGES || "EN"],
            ["map-pin", `${(window.GS_ZIPS||[]).length} ZIP codes`],
          ].map(([ic, t]) => (
            <div key={t} style={{ display: "flex", alignItems: "center", gap: 10, color: "var(--fg-2)" }}>
              <Icon name={ic} size={18} style={{ color: "var(--fg-accent)" }} />
              <span style={{ fontSize: 13, fontWeight: 500 }}>{t}</span>
            </div>
          ))}
        </div>
      </div>

      {/* SERVICES PREVIEW */}
      <Section pad="96px 0">
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", marginBottom: 48 }}>
          <div>
            <Eyebrow style={{ marginBottom: 14 }}>What I do</Eyebrow>
            <h2 style={{ fontFamily: "var(--font-display)", fontSize: 44, margin: 0, letterSpacing: "-0.02em", color: "var(--fg-1)", fontWeight: 400, lineHeight: 1.05 }}>
              Eighteen services. One standard of finish.
            </h2>
          </div>
          <Button variant="tertiary" iconRight="arrow-right" onClick={() => nav("services")}>See all services</Button>
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 24 }}>
          {GS_SERVICES.slice(0, 6).map(s => <ServiceCard key={s.id} s={s} onOpen={() => nav("services")} />)}
        </div>
      </Section>

      {/* PROMISE */}
      <Section pad="96px 0" style={{ background: "var(--bg-sunken)" }}>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1.2fr", gap: 80, alignItems: "center" }}>
          <div>
            <Eyebrow style={{ marginBottom: 14 }}>The promise</Eyebrow>
            <h2 style={{ fontFamily: "var(--font-display)", fontSize: 40, margin: "0 0 20px", letterSpacing: "-0.02em", color: "var(--fg-1)", fontWeight: 400, lineHeight: 1.08 }}>
              <em>White glove</em> is a posture, not a slogan.
            </h2>
            <p style={{ fontSize: 17, lineHeight: 1.65, color: "var(--fg-2)", maxWidth: 460 }}>
              I arrive on time. I wear covers over my shoes. I clean up after the work. I quote the price before I start. If something is outside my scope, I tell you — and I refer you to someone I would hire for my own family.
            </p>
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 20 }}>
            {[
              ["watch", "On-time window", "20-minute heads-up by text."],
              ["sparkles", "Cleanup included", "No dust, no debris, nothing left behind."],
              ["receipt", "Priced up front", "Quote confirmed before work begins."],
              ["phone-call", "Real phone, real human", "No call trees, no bots."],
            ].map(([ic, t, d]) => (
              <div key={t} style={{ background: "#fff", border: "1px solid var(--border-subtle)", borderRadius: 12, padding: 20 }}>
                <Icon name={ic} size={22} style={{ color: "var(--fg-accent)", marginBottom: 12 }} />
                <div style={{ fontSize: 15, fontWeight: 600, color: "var(--fg-1)", marginBottom: 4 }}>{t}</div>
                <div style={{ fontSize: 13.5, color: "var(--fg-3)", lineHeight: 1.55 }}>{d}</div>
              </div>
            ))}
          </div>
        </div>
      </Section>

      {/* AREAS TEASER */}
      <Section pad="96px 0">
        <div style={{ textAlign: "center", marginBottom: 48 }}>
          <Eyebrow style={{ marginBottom: 14 }}>Coverage</Eyebrow>
          <h2 style={{ fontFamily: "var(--font-display)", fontSize: 40, margin: 0, letterSpacing: "-0.02em", color: "var(--fg-1)", fontWeight: 400 }}>
            {(window.GS_ZIPS||[]).length} ZIP codes across {window.HP_REGION || window.HP_CITY || "the metro area"}.
          </h2>
        </div>
        <div style={{ display: "flex", flexWrap: "wrap", gap: 8, justifyContent: "center", maxWidth: 900, margin: "0 auto" }}>
          {GS_ZIPS.map(z => (
            <span key={z.zip} style={{
              fontFamily: "var(--font-mono)", fontSize: 13, padding: "6px 12px",
              background: z.same ? "#E8F5EF" : "#fff",
              color: z.same ? "#1F6D4B" : "var(--fg-3)",
              border: `1px solid ${z.same ? "transparent" : "var(--border-subtle)"}`,
              borderRadius: 999,
            }}>
              {z.zip}
            </span>
          ))}
        </div>
        <div style={{ textAlign: "center", marginTop: 32, fontSize: 13, color: "var(--fg-3)" }}>
          <span style={{ display: "inline-flex", alignItems: "center", gap: 8 }}>
            <span style={{ width: 8, height: 8, borderRadius: "50%", background: "#2D9A6A" }}/>Same-day available
          </span>
          <span style={{ margin: "0 18px", color: "var(--fg-4)" }}>·</span>
          <span style={{ display: "inline-flex", alignItems: "center", gap: 8 }}>
            <span style={{ width: 8, height: 8, borderRadius: "50%", background: "var(--border-default)" }}/>Scheduled visits only
          </span>
        </div>
      </Section>

      {/* REVIEWS TEASER */}
      <Section pad="96px 0" style={{ background: "#fff", borderTop: "1px solid var(--border-subtle)" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", marginBottom: 48 }}>
          <div>
            <Eyebrow style={{ marginBottom: 14 }}>Verified reviews</Eyebrow>
            <h2 style={{ fontFamily: "var(--font-display)", fontSize: 40, margin: 0, letterSpacing: "-0.02em", color: "var(--fg-1)", fontWeight: 400 }}>
              From your neighbors.
            </h2>
          </div>
          <Button variant="tertiary" iconRight="arrow-right" onClick={() => nav("reviews")} aria-label="Read more reviews">Read more</Button>
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 24 }}>
          {GS_REVIEWS.slice(0, 3).map((r, i) => (
            <div key={i} style={{ padding: 28, border: "1px solid var(--border-subtle)", borderRadius: 14, background: "var(--bg-page)" }}>
              <Stars/>
              <p style={{ fontSize: 15, lineHeight: 1.65, color: "var(--fg-2)", margin: "16px 0 20px" }}>&ldquo;{r.text}&rdquo;</p>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", paddingTop: 14, borderTop: "1px solid var(--border-subtle)" }}>
                <div style={{ fontSize: 13.5, fontWeight: 500, color: "var(--fg-1)" }}>{r.name}</div>
                <div style={{ fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--fg-3)" }}>{r.zip} · {r.city}</div>
              </div>
            </div>
          ))}
        </div>
      </Section>
    </>
  );
}

// ================= SERVICES =================
function ServicesPage() {
  const [tier, setTier] = useState("All");
  const tiers = ["All", "Essential", "Standard", "Premium"];
  const list = useMemo(() => tier === "All" ? GS_SERVICES : GS_SERVICES.filter(s => s.tier === tier), [tier]);
  return (
    <>
      <Section pad="88px 0 40px">
        <Eyebrow style={{ marginBottom: 20 }}>Services</Eyebrow>
        <h1 style={{ fontFamily: "var(--font-display)", fontSize: 64, margin: 0, letterSpacing: "-0.03em", color: "var(--fg-1)", fontWeight: 400, lineHeight: 0.98, maxWidth: 900 }}>
          Eighteen services. One standard of finish.
        </h1>
        <p className="lead" style={{ fontSize: 19, lineHeight: 1.55, color: "var(--fg-2)", maxWidth: 600, marginTop: 24 }}>
          Every job capped at $1,000 so I can serve you under CA AB 2622. Anything larger, I refer out to someone I would hire for my own family.
        </p>
      </Section>
      <Section pad="0 0 24px">
        <div style={{ display: "flex", gap: 8, borderBottom: "1px solid var(--border-subtle)", paddingBottom: 18 }}>
          {tiers.map(t => (
            <button key={t} onClick={() => setTier(t)} aria-pressed={tier === t} style={{
              background: tier === t ? "var(--bg-inverse)" : "transparent",
              color: tier === t ? "#fff" : "var(--fg-2)",
              border: tier === t ? "0" : "1px solid var(--border-subtle)",
              borderRadius: 999, padding: "8px 16px", fontSize: 13, fontWeight: 500,
              fontFamily: "var(--font-sans)", cursor: "pointer",
            }}>{t}</button>
          ))}
        </div>
      </Section>
      <Section pad="32px 0 120px">
        <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 24 }}>
          {list.map(s => <ServiceCard key={s.id} s={s} />)}
        </div>
      </Section>
    </>
  );
}

// ================= ABOUT =================
function AboutPage() {
  return (
    <>
      <Section pad="88px 0 40px" style={{ background: "var(--bg-sunken)" }}>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 80, alignItems: "end" }}>
          <div>
            <Eyebrow style={{ marginBottom: 20 }}>About</Eyebrow>
            <h1 style={{ fontFamily: "var(--font-display)", fontSize: 64, margin: 0, letterSpacing: "-0.03em", color: "var(--fg-1)", fontWeight: 400, lineHeight: 0.98 }}>
              One van.<br/><em>One standard.</em>
            </h1>
          </div>
          <div>
            <p style={{ fontSize: 17, lineHeight: 1.65, color: "var(--fg-2)", margin: 0 }}>
              {window.HP_ABOUT_BIO || "Professional handyman service. Quality work, on time, every time."}
            </p>
          </div>
        </div>
      </Section>
      <Section pad="80px 0">
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1.4fr", gap: 80 }}>
          <div style={{ aspectRatio: "4/5", borderRadius: 14, overflow: "hidden", border: "1px solid var(--border-subtle)" }}>
            <SteelPhoto height="100%" seed={2} label="— Founder · Grace" />
          </div>
          <div style={{ maxWidth: 560 }}>
            <h2 style={{ fontFamily: "var(--font-display)", fontSize: 36, letterSpacing: "-0.02em", fontWeight: 400, color: "var(--fg-1)", margin: "0 0 20px" }}>
              {window.HP_BUSINESS_NAME || "Grace Services"} — trusted by homeowners.
            </h2>
            <p style={{ fontSize: 16, lineHeight: 1.7, color: "var(--fg-2)" }}>
              Fifteen years in residential finish work, from Burlingame to Cupertino. Licensed in California. Insured to $1M. I speak English, Russian, and Spanish — useful when a job has three generations of family on the scene.
            </p>
            <p style={{ fontSize: 16, lineHeight: 1.7, color: "var(--fg-2)" }}>
              I cap every project at $1,000 so I can legally operate as an AB 2622-exempt handyman. It keeps the work small, specific, and finished the same day. That&rsquo;s a feature, not a constraint.
            </p>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 20, marginTop: 40, padding: "24px 0", borderTop: "1px solid var(--border-subtle)", borderBottom: "1px solid var(--border-subtle)" }}>
              {[
                ["2019", "Founded"],
                ["284", "Verified jobs"],
                ["36", "ZIP codes served"],
                ["EN · RU · ES", "Languages"],
              ].map(([k, v]) => (
                <div key={v}>
                  <div style={{ fontFamily: "var(--font-display)", fontSize: 30, color: "var(--fg-1)", letterSpacing: "-0.02em" }}>{k}</div>
                  <div style={{ fontSize: 12, textTransform: "uppercase", letterSpacing: "0.14em", color: "var(--fg-3)", marginTop: 4 }}>{v}</div>
                </div>
              ))}
            </div>
          </div>
        </div>
      </Section>
    </>
  );
}

// ================= GALLERY =================
function GalleryPage() {
  return (
    <>
      <Section pad="88px 0 48px">
        <Eyebrow style={{ marginBottom: 20 }}>Gallery</Eyebrow>
        <h1 style={{ fontFamily: "var(--font-display)", fontSize: 64, margin: 0, letterSpacing: "-0.03em", color: "var(--fg-1)", fontWeight: 400, lineHeight: 0.98 }}>
          Before. <em>After.</em>
        </h1>
        <p className="lead" style={{ fontSize: 19, color: "var(--fg-2)", maxWidth: 600, marginTop: 20 }}>
          Same framing, same light. The work speaks for itself.
        </p>
      </Section>
      <Section pad="0 0 120px">
        <div style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 28 }}>
          {GS_SERVICES.slice(0, 6).map((s, i) => (
            <figure key={s.id} style={{ margin: 0 }}>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 2, borderRadius: 14, overflow: "hidden", border: "1px solid var(--border-subtle)" }}>
                <SteelPhoto height={280} seed={i} label="Before" />
                <SteelPhoto height={280} seed={i + 5} label="After" />
              </div>
              <figcaption style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginTop: 14 }}>
                <div>
                  <Eyebrow>{s.cat}</Eyebrow>
                  <div style={{ fontFamily: "var(--font-display)", fontSize: 22, color: "var(--fg-1)", letterSpacing: "-0.01em", marginTop: 4 }}>{s.title}</div>
                </div>
                <div style={{ fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--fg-3)" }}>{(window.GS_ZIPS||[])[i]?.zip || ""} · {(window.GS_ZIPS||[])[i]?.city || ""}</div>
              </figcaption>
            </figure>
          ))}
        </div>
      </Section>
    </>
  );
}

// ================= REVIEWS =================
function ReviewsPage() {
  return (
    <>
      <Section pad="88px 0 48px">
        <div style={{ display: "grid", gridTemplateColumns: "1.3fr 1fr", gap: 60, alignItems: "end" }}>
          <div>
            <Eyebrow style={{ marginBottom: 20 }}>Reviews</Eyebrow>
            <h1 style={{ fontFamily: "var(--font-display)", fontSize: 64, margin: 0, letterSpacing: "-0.03em", color: "var(--fg-1)", fontWeight: 400, lineHeight: 0.98 }}>
              Word from the block.
            </h1>
          </div>
          <div style={{ background: "#fff", border: "1px solid var(--border-subtle)", borderRadius: 14, padding: 24 }}>
            <div style={{ display: "flex", alignItems: "baseline", gap: 14 }}>
              <span style={{ fontFamily: "var(--font-display)", fontSize: 54, color: "var(--fg-1)", lineHeight: 1, letterSpacing: "-0.02em" }}>4.97</span>
              <div>
                <Stars size={16} />
                <div style={{ fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--fg-3)", marginTop: 6 }}>284 verified jobs</div>
              </div>
            </div>
          </div>
        </div>
      </Section>
      <Section pad="0 0 120px">
        <div style={{ columnCount: 2, columnGap: 28 }}>
          {GS_REVIEWS.map((r, i) => (
            <div key={i} style={{ breakInside: "avoid", background: "#fff", border: "1px solid var(--border-subtle)", borderRadius: 14, padding: 28, marginBottom: 24 }}>
              <Stars/>
              <p style={{ fontSize: 16, lineHeight: 1.7, color: "var(--fg-2)", margin: "16px 0 22px" }}>&ldquo;{r.text}&rdquo;</p>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", paddingTop: 16, borderTop: "1px solid var(--border-subtle)" }}>
                <div>
                  <div style={{ fontSize: 14, fontWeight: 500, color: "var(--fg-1)" }}>{r.name}</div>
                  <div style={{ fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--fg-3)", marginTop: 3 }}>{r.zip} · {r.city}</div>
                </div>
                <div style={{ fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--fg-3)" }}>{r.date}</div>
              </div>
            </div>
          ))}
        </div>
      </Section>
    </>
  );
}


// ================= ZONE MAP =================
function ZoneMap() {
  useEffect(() => {
    if (!window.L) return;
    const container = document.getElementById("hp-zone-map");
    if (!container || container._leaflet_id) return;

    // COORDS for both SAC metro and SF Peninsula
    const COORDS = {
      // Sacramento metro
      "Sacramento":[38.5816,-121.4944],"Carmichael":[38.6279,-121.3293],
      "Citrus Heights":[38.7071,-121.2810],"Rancho Cordova":[38.5890,-121.3024],
      "Roseville":[38.7521,-121.2879],"Folsom":[38.6780,-121.1761],
      "Davis":[38.5449,-121.7405],"North Highlands":[38.6657,-121.3729],
      "Woodland":[38.6785,-121.7733],"Rocklin":[38.7907,-121.2357],
      "Fair Oaks":[38.6493,-121.2726],"Antelope":[38.7149,-121.3588],
      "Orangevale":[38.6832,-121.2260],"Granite Bay":[38.7671,-121.1786],
      "El Dorado Hills":[38.6768,-121.0633],"Loomis":[38.8196,-121.1933],
      "Elverta":[38.7282,-121.4697],
      // SF Peninsula + South Bay
      "Palo Alto":[37.441,-122.143],"Menlo Park":[37.454,-122.182],
      "Atherton":[37.462,-122.197],"Los Altos":[37.385,-122.114],
      "Mountain View":[37.386,-122.083],"Sunnyvale":[37.369,-122.038],
      "Cupertino":[37.323,-122.032],"San Mateo":[37.563,-122.323],
      "Foster City":[37.555,-122.268],"Burlingame":[37.584,-122.366],
      "Millbrae":[37.600,-122.387],"Redwood City":[37.485,-122.236],
      "San Carlos":[37.507,-122.261],"Belmont":[37.521,-122.276],
      "Portola Valley":[37.375,-122.218],"Saratoga":[37.264,-122.023],
      "Los Gatos":[37.226,-121.982],"Campbell":[37.287,-121.950],
      "San Jose SW":[37.234,-121.912]
    };

    // Auto-center: compute from known COORDS in GS_ZIPS
    const cities = [...new Set((window.GS_ZIPS || []).map(z => z.city))].filter(c => COORDS[c]);
    const defaultCenter = cities.length
      ? [cities.reduce((s,c)=>s+COORDS[c][0],0)/cities.length, cities.reduce((s,c)=>s+COORDS[c][1],0)/cities.length]
      : [37.43, -122.14];

    const map = L.map("hp-zone-map", { zoomControl: true, scrollWheelZoom: false })
      .setView(defaultCenter, 10);

    L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
      attribution: "\u00a9 OpenStreetMap contributors", maxZoom: 14
    }).addTo(map);

    const SAME_DAY = new Set((window.GS_ZIPS || []).filter(z => z.same).map(z => z.zip));

    function addLegend() {
      const leg = L.control({ position: "bottomright" });
      leg.onAdd = () => {
        const d = L.DomUtil.create("div");
        d.style.cssText = "background:#fff;padding:8px 12px;border-radius:8px;border:1px solid var(--border-subtle);font:13px/1.9 system-ui,sans-serif;box-shadow:0 2px 8px rgba(0,0,0,.08)";
        d.innerHTML = '<span style="color:#2D9A6A">&#9679;</span> Same-day &nbsp; <span style="color:#94A0AD">&#9679;</span> Scheduled';
        return d;
      };
      leg.addTo(map);
    }

    function addFallback() {
      const seen = new Set();
      (window.GS_ZIPS || []).forEach(z => {
        if (seen.has(z.city) || !COORDS[z.city]) return;
        seen.add(z.city);
        const col = z.same ? "#2D9A6A" : "#94A0AD";
        L.circleMarker(COORDS[z.city], { radius: 9, color: "#fff", weight: 2, fillColor: col, fillOpacity: 0.9 })
          .addTo(map)
          .bindPopup('<strong>' + z.city + '</strong><br><span style="color:' + col + '">&#9679; ' + (z.same ? 'Same-day' : 'Scheduled') + '</span>');
      });
    }

    const zips = (window.GS_ZIPS || []).map(z => z.zip);
    const where = "ZCTA5 IN (" + zips.map(z => "'" + z + "'").join(",") + ")";
    const url = "https://tigerweb.geo.census.gov/arcgis/rest/services/TIGERweb/PUMA_TAD_TAZ_UGA_ZCTA/MapServer/1/query?"
      + "where=" + encodeURIComponent(where)
      + "&outFields=ZCTA5&f=geojson&returnGeometry=true&maxAllowableOffset=0.0001";

    fetch(url)
      .then(r => { if (!r.ok) throw new Error("http " + r.status); return r.json(); })
      .then(data => {
        if (!data.features || !data.features.length) throw new Error("no features");
        const layer = L.geoJSON(data, {
          style: f => {
            const sd = SAME_DAY.has(f.properties.ZCTA5);
            return { color: sd ? "#1A7A52" : "#7A8A96", fillColor: sd ? "#2D9A6A" : "#94A0AD", fillOpacity: 0.4, weight: 1.5 };
          },
          onEachFeature: (f, lyr) => {
            const z = f.properties.ZCTA5;
            const sd = SAME_DAY.has(z);
            const entry = (window.GS_ZIPS || []).find(x => x.zip === z) || {};
            lyr.bindPopup('<strong>ZIP ' + z + '</strong>' + (entry.city ? '<br>' + entry.city : '') + '<br><span style="color:' + (sd ? '#2D9A6A' : '#94A0AD') + '">&#9679; ' + (sd ? 'Same-day available' : 'Scheduled visits') + '</span>');
          }
        }).addTo(map);
        map.fitBounds(layer.getBounds(), { padding: [20, 20] });
        addLegend();
      })
      .catch(() => { addFallback(); addLegend(); });
  }, []);

  return <div id="hp-zone-map" style={{ height: 460, borderRadius: 12, border: "1px solid var(--border-subtle)", marginBottom: 48 }} />;
}

      <Section id="zones" pad="80px 0 0">
        <div style={{ maxWidth: "var(--container)", margin: "0 auto", padding: "0 var(--gutter)" }}>
          <div style={{ textAlign: "center", marginBottom: 32 }}>
            <Eyebrow style={{ marginBottom: 10 }}>Coverage Map</Eyebrow>
            <h2 style={{ fontFamily: "var(--font-display)", fontSize: "clamp(24px,2.5vw,36px)", fontWeight: 400, color: "var(--fg-1)", letterSpacing: "-0.02em", margin: "0 0 10px" }}>
              {window.HP_REGION || "Metro Area"}
            </h2>
            <p style={{ fontSize: 14, color: "var(--fg-3)", margin: 0 }}>
              {(window.GS_ZIPS || []).length} ZIP codes &middot; <span style={{ color: "#2D9A6A" }}>&#9679;</span> Same-day available &middot; <span style={{ color: "#94A0AD" }}>&#9679;</span> Scheduled visits
            </p>
          </div>
          <ZoneMap />
        </div>
      </Section>

// ================= AREAS =================
function AreasPage() {
  const grouped = useMemo(() => {
    const m = {};
    GS_ZIPS.forEach(z => { (m[z.city] ||= []).push(z); });
    return m;
  }, []);
  return (
    <>
      <Section pad="88px 0 48px">
        <Eyebrow style={{ marginBottom: 20 }}>Coverage</Eyebrow>
        <h1 style={{ fontFamily: "var(--font-display)", fontSize: 64, margin: 0, letterSpacing: "-0.03em", color: "var(--fg-1)", fontWeight: 400, lineHeight: 0.98, maxWidth: 960 }}>
          {(window.GS_ZIPS||[]).length} ZIP codes. One van. Routed daily.
        </h1>
        <p className="lead" style={{ fontSize: 19, color: "var(--fg-2)", maxWidth: 600, marginTop: 22 }}>
          Green dots are reachable same-day when booked before noon. Grey dots are scheduled visits — usually within two business days.
        </p>
      </Section>
      <Section pad="24px 0 120px">
        <ZoneMap />
        <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 28 }}>
          {Object.entries(grouped).map(([city, zips]) => (
            <div key={city} style={{ background: "#fff", border: "1px solid var(--border-subtle)", borderRadius: 12, padding: 22 }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 12 }}>
                <div style={{ fontFamily: "var(--font-sans)", fontSize: 15, fontWeight: 600, color: "var(--fg-1)" }}>{city}</div>
                <div style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--fg-3)" }}>{zips.length} ZIP</div>
              </div>
              <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
                {zips.map(z => (
                  <div key={z.zip} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", fontFamily: "var(--font-mono)", fontSize: 13 }}>
                    <span style={{ color: "var(--fg-2)" }}>{z.zip}</span>
                    <span style={{ display: "inline-flex", alignItems: "center", gap: 6, color: z.same ? "#1F6D4B" : "var(--fg-3)" }}>
                      <span style={{ width: 6, height: 6, borderRadius: "50%", background: z.same ? "#2D9A6A" : "var(--border-default)" }} />
                      {z.same ? "Same-day" : "Scheduled"}
                    </span>
                  </div>
                ))}
              </div>
            </div>
          ))}
        </div>
      </Section>
    </>
  );
}

// ================= FAQ =================
function FAQPage() {
  const [open, setOpen] = useState(0);
  return (
    <>
      <Section pad="88px 0 56px">
        <Eyebrow style={{ marginBottom: 20 }}>Frequently asked</Eyebrow>
        <h1 style={{ fontFamily: "var(--font-display)", fontSize: 64, margin: 0, letterSpacing: "-0.03em", color: "var(--fg-1)", fontWeight: 400, lineHeight: 0.98, maxWidth: 800 }}>
          The short, honest answers.
        </h1>
      </Section>
      <Section pad="0 0 120px">
        <div style={{ maxWidth: 820, margin: "0 auto", borderTop: "1px solid var(--border-subtle)" }}>
          {GS_FAQ.map((f, i) => {
            const isOpen = open === i;
            return (
              <div key={i} style={{ borderBottom: "1px solid var(--border-subtle)" }}>
                <button id={"faq-btn-" + i} onClick={() => setOpen(isOpen ? -1 : i)} aria-expanded={isOpen} aria-controls={"faq-panel-" + i} style={{
                  width: "100%", textAlign: "left", background: "transparent", border: 0,
                  padding: "24px 0", display: "flex", justifyContent: "space-between", alignItems: "center",
                  cursor: "pointer", fontFamily: "var(--font-sans)",
                }}>
                  <span style={{ fontSize: 18, fontWeight: 500, color: "var(--fg-1)", letterSpacing: "-0.01em" }}>{f.q}</span>
                  <Icon name={isOpen ? "minus" : "plus"} size={20} style={{ color: "var(--fg-3)" }} />
                </button>
                <div id={"faq-panel-" + i} role="region" aria-labelledby={"faq-btn-" + i} hidden={!isOpen} style={{ paddingBottom: 24, fontSize: 16, lineHeight: 1.7, color: "var(--fg-2)", maxWidth: 680 }}>
                  {f.a}
                </div>
              </div>
            );
          })}
        </div>
      </Section>
    </>
  );
}

// ================= CONTACT =================
function ContactPage() {
  const [sent, setSent] = useState(false);
  return (
    <>
      <Section pad="88px 0 56px">
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 80, alignItems: "start" }}>
          <div>
            <Eyebrow style={{ marginBottom: 20 }}>Contact &amp; book</Eyebrow>
            <h1 style={{ fontFamily: "var(--font-display)", fontSize: 56, margin: 0, letterSpacing: "-0.03em", color: "var(--fg-1)", fontWeight: 400, lineHeight: 0.98 }}>
              Call, or tell me what you need.
            </h1>
            <p className="lead" style={{ fontSize: 18, color: "var(--fg-2)", marginTop: 22, maxWidth: 420 }}>
              Fastest route is the phone. Form works too — I reply within an hour during business hours.
            </p>
            <div style={{ marginTop: 40, display: "flex", flexDirection: "column", gap: 16 }}>
              <a href={"tel:" + (window.HP_PHONE_RAW || "")} aria-label={"Call " + (window.HP_PHONE || "")} style={{ display: "flex", alignItems: "center", gap: 16, padding: "20px 22px", background: "var(--bg-inverse)", color: "#fff", borderRadius: 12, textDecoration: "none", boxShadow: "var(--shadow-md)" }}>
                <Icon name="phone" size={22} />
                <div>
                  <div style={{ fontFamily: "var(--font-mono)", fontSize: 20, fontWeight: 500 }}>{window.HP_PHONE || ""}</div>
                  <div style={{ fontSize: 12.5, color: "rgba(255,255,255,0.7)", marginTop: 2 }}>Mon–Sat · 7am–7pm · EN · RU · ES</div>
                </div>
              </a>
              <div style={{ display: "flex", gap: 16, flexWrap: "wrap", color: "var(--fg-3)", fontFamily: "var(--font-mono)", fontSize: 12 }}>
                {window.HP_LICENSE_LINE && <><span>{window.HP_LICENSE_LINE}</span><span>·</span></>}{window.HP_INSURANCE_LINE && <><span>{window.HP_INSURANCE_LINE}</span></>}
              </div>
            </div>
          </div>
          <form onSubmit={e => { e.preventDefault(); setSent(true); }} style={{ background: "#fff", border: "1px solid var(--border-subtle)", borderRadius: 14, padding: 32, boxShadow: "var(--shadow-sm)" }}>
            {sent ? (
              <div style={{ textAlign: "center", padding: "30px 10px" }}>
                <Icon name="check-circle-2" size={40} style={{ color: "var(--fg-accent)" }} />
                <h2 style={{ fontFamily: "var(--font-display)", fontSize: 28, color: "var(--fg-1)", margin: "16px 0 8px", letterSpacing: "-0.02em", fontWeight: 400 }}>Got it.</h2>
                <p style={{ fontSize: 15, color: "var(--fg-2)" }}>I&rsquo;ll text you within an hour.</p>
              </div>
            ) : (
              <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
                <FieldRow>
                  <Field label="Your name" placeholder="Anna K." name="name" autoComplete="name" required aria-required="true" />
                  <Field label="Phone" placeholder="(650) 555-0199" mono type="tel" name="phone" autoComplete="tel" required aria-required="true" />
                </FieldRow>
                <FieldRow>
                  <Field label="ZIP" placeholder="94301" mono name="zip" autoComplete="postal-code" />
                  <Field label="Service" select name="service" options={["TV mounting", "Drywall", "Light fixture", "Other"]} />
                </FieldRow>
                <Field label="What needs doing?" textarea name="message" placeholder="65&quot; TV on drywall, soundbar, 2 cords concealed. Sunday morning if possible." />
                <Button type="submit" icon="send" style={{ marginTop: 8, justifyContent: "center" }}>Send request</Button>
                <p style={{ fontSize: 12, color: "var(--fg-3)", textAlign: "center", margin: 0 }}>No spam. No follow-ups after the job unless you want a receipt.</p>
              </div>
            )}
          </form>
        </div>
      </Section>
    </>
  );
}

const FieldRow = ({ children }) => <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>{children}</div>;

const Field = ({ label, placeholder, mono, textarea, select, options = [], name, autoComplete, required, type, ...rest }) => {
  const baseStyle = {
    width: "100%", boxSizing: "border-box",
    fontFamily: mono ? "var(--font-mono)" : "var(--font-sans)",
    fontSize: 15, padding: "11px 14px",
    border: "1px solid var(--border-default)", borderRadius: 8,
    background: "#fff", color: "var(--fg-1)", outline: "none",
  };
  const commonProps = { name, autoComplete, required, ...(rest["aria-required"] ? { "aria-required": rest["aria-required"] } : {}) };
  return (
    <label style={{ display: "flex", flexDirection: "column", gap: 6 }}>
      <span style={{ fontSize: 12, fontWeight: 500, color: "var(--fg-3)", textTransform: "uppercase", letterSpacing: "0.12em" }}>{label}</span>
      {textarea ? <textarea rows={4} placeholder={placeholder} name={name} aria-required={rest["aria-required"]} style={{ ...baseStyle, resize: "vertical", fontFamily: "var(--font-sans)" }} />
        : select ? <select name={name} aria-required={rest["aria-required"]} style={baseStyle}>{options.map(o => <option key={o}>{o}</option>)}</select>
        : <input type={type || "text"} placeholder={placeholder} {...commonProps} style={baseStyle} />}
    </label>
  );
};

Object.assign(window, { HomePage, ServicesPage, AboutPage, GalleryPage, ReviewsPage, AreasPage, FAQPage, ContactPage });
