// pages.jsx — Home, Services, Portfolio, About, Contact, Blog

const { useState: useStateP, useEffect: useEffectP, useRef: useRefP } = React;

// ─── Hero (Home) ───────────────────────────────────────────────────────────
function Hero({ setRoute }) {
  const heroRef = useRefP(null);

  return (
    <section className="sem-hero" ref={heroRef} data-screen-label="Home / Hero" aria-label="Hero">
      <div className="sem-hero-media">
        <video
          className="sem-hero-video sem-hero-video-desktop"
          autoPlay
          muted
          loop
          playsInline
          preload="metadata"
        >
          <source src="assets/hero-desktop.mp4" type="video/mp4" />
        </video>
        <video className="sem-hero-video sem-hero-video-mobile" autoPlay muted loop playsInline preload="metadata">
          <source src="assets/hero-mobile.mp4" type="video/mp4" />
        </video>
        <div className="sem-hero-overlay" />
      </div>

      <div className="sem-hero-content">
        <h1 className="sem-hero-title">
          London property media.
          <br />
          <span className="sem-hero-title-em">No shortcuts.</span>
        </h1>
        <p className="sem-hero-sub">
          Photography, video, drone, floorplans and EPC — from one trusted source.
        </p>
        <div className="sem-hero-cta">
          <CTA
            tone="dark"
            onClick={() => {
              if (window.semTrack) window.semTrack("cta_click", { location: "hero", label: "Get in touch" });
              setRoute("contact");
            }}
          >
            Get in touch
          </CTA>
        </div>
      </div>

      <div className="sem-hero-scroll" aria-hidden="true">
        <span>Scroll</span>
        <span className="sem-hero-scroll-line" />
      </div>
    </section>
  );
}

// ─── EPC rating chart (inline SVG — avoids broken <img> src on static hosts) ─
function EpcRatingChart({ style = {} }) {
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 400 500"
      role="img"
      aria-label="UK energy performance certificate rating scale from A to G"
      preserveAspectRatio="xMidYMid slice"
      style={{ display: "block", width: "100%", height: "100%", ...style }}
    >
      <rect width="400" height="500" fill="#FAFAF8" />
      <text x="200" y="52" textAnchor="middle" fill="#111111" fontFamily="DM Sans, system-ui, sans-serif" fontSize="11" fontWeight="500" letterSpacing="0.22em">ENERGY RATING</text>
      <line x1="120" y1="66" x2="280" y2="66" stroke="rgba(17,17,17,0.12)" strokeWidth="1" />
      <g transform="translate(48, 88)">
        <path d="M52 0 H198 L248 22 L198 44 H52 Z" fill="#008054" />
        <text x="18" y="30" fill="#111111" fontFamily="DM Sans, system-ui, sans-serif" fontSize="22" fontWeight="600">A</text>
        <path d="M52 52 H216 L276 74 L216 96 H52 Z" fill="#19B459" />
        <text x="18" y="82" fill="#111111" fontFamily="DM Sans, system-ui, sans-serif" fontSize="22" fontWeight="600">B</text>
        <path d="M52 104 H234 L294 126 L234 148 H52 Z" fill="#8DCE46" />
        <text x="18" y="134" fill="#111111" fontFamily="DM Sans, system-ui, sans-serif" fontSize="22" fontWeight="600">C</text>
        <path d="M52 156 H252 L312 178 L252 200 H52 Z" fill="#FFD500" />
        <text x="18" y="186" fill="#111111" fontFamily="DM Sans, system-ui, sans-serif" fontSize="22" fontWeight="600">D</text>
        <path d="M52 208 H270 L330 230 L270 252 H52 Z" fill="#FCAA65" />
        <text x="18" y="238" fill="#111111" fontFamily="DM Sans, system-ui, sans-serif" fontSize="22" fontWeight="600">E</text>
        <path d="M52 260 H288 L348 282 L288 304 H52 Z" fill="#EF8023" />
        <text x="18" y="290" fill="#111111" fontFamily="DM Sans, system-ui, sans-serif" fontSize="22" fontWeight="600">F</text>
        <path d="M52 312 H304 L364 334 L304 356 H52 Z" fill="#E9153B" />
        <text x="18" y="342" fill="#111111" fontFamily="DM Sans, system-ui, sans-serif" fontSize="22" fontWeight="600">G</text>
      </g>
      <text x="200" y="468" textAnchor="middle" fill="rgba(17,17,17,0.45)" fontFamily="Inter, system-ui, sans-serif" fontSize="10" letterSpacing="0.14em">A — MOST EFFICIENT · G — LEAST EFFICIENT</text>
    </svg>
  );
}

// ─── Home: services overview (five blocks with imagery) ────────────────────
const HOME_SERVICE_BLOCKS = [
  {
    id: "photography",
    title: "Photography",
    copy: "Natural light property photography with clean composition, accurate colour and a magazine-led finish.",
    image: "assets/living_room_over_sofa-0c4abcfa-ff9f-476f-97cf-59ce32528e21.png",
    imageAlt: "Interior living space photographed in natural light",
  },
  {
    id: "video",
    title: "Video",
    copy: "Calm, considered property films designed to show flow, proportion and atmosphere.",
    image: "assets/fnt_of_prop-2-d70caff4-98e0-4a7b-a118-e311e93cb22c.png",
    imageAlt: "Property exterior showing context and setting",
  },
  {
    id: "drone",
    title: "Drone",
    copy: "CAA-compliant aerial footage for homes, developments and location-led listings.",
    image: "assets/drone-london-c3bb899d-b428-4da6-88f2-be977e798d92.png",
    imageAlt: "Aerial view of a London residential street and gardens",
  },
  {
    id: "floorplans",
    title: "Floorplans",
    copy: "Clear, accurate floorplans that support buyers, agents and online listing platforms.",
    image:
      "assets/planning-of-construction-of-the-house-repair-work-2026-03-26-02-06-01-utc-fade21e1-d329-4612-8193-e746d1bec8af.png",
    imageAlt: "Technical floor plan drawing with tools on a desk",
  },
  {
    id: "epc",
    title: "EPC",
    copy: "DEA-accredited EPC certificates, billed directly to the vendor or landlord as a separate invoice.",
    imageAlt: "UK energy performance certificate rating scale from A to G",
  },
];

function HomeServicesOverview({ setRoute }) {
  return (
    <section className="sem-section sem-home-service-blocks" data-screen-label="Home / Services overview">
      <div className="sem-container">
        <SectionHead eyebrow="Services" title="Five disciplines. One standard." intro={null} tone="dark" />
        <div className="sem-service-blocks">
          {HOME_SERVICE_BLOCKS.map((s) => (
            <article key={s.id} className="sem-service-block">
              <div className="sem-service-block-media">
                {s.id === "epc" ? (
                  <EpcRatingChart style={{ position: "absolute", inset: 0 }} />
                ) : (
                  <img src={s.image} alt={s.imageAlt} loading="lazy" decoding="async" />
                )}
              </div>
              <h3 className="sem-service-block-title">{s.title}</h3>
              <p className="sem-service-block-copy">{s.copy}</p>
            </article>
          ))}
        </div>
      </div>
    </section>
  );
}

// ─── Home: portfolio teaser with category filters ──────────────────────────
const PORTFOLIO_FILTERS = ["All", "Interiors", "Exteriors", "Drone", "Video"];

/** Order matters: home “Selected work” (All) uses the first six as the editorial highlight row. */
const PORTFOLIO_ITEMS = [
  {
    title: "Living space, water view",
    meta: "Interiors",
    ratio: "4 / 5",
    image: "assets/living_room_over_sofa-0c4abcfa-ff9f-476f-97cf-59ce32528e21.png",
    categories: ["Interiors"],
  },
  {
    title: "Kitchen, daylight",
    meta: "Interiors",
    ratio: "3 / 4",
    image: "assets/kitchen-9acf5093-3ebd-440f-bda1-3bbd10520815.png",
    categories: ["Interiors"],
  },
  {
    title: "Bedroom, calm palette",
    meta: "Interiors",
    ratio: "4 / 5",
    image: "assets/bedroom_1-12070465-6a4e-4cdc-9a04-72f912cdf296.png",
    categories: ["Interiors"],
  },
  {
    title: "Property context, exterior",
    meta: "Exteriors",
    ratio: "4 / 5",
    image: "assets/fnt_of_prop-2-d70caff4-98e0-4a7b-a118-e311e93cb22c.png",
    categories: ["Exteriors"],
  },
  {
    title: "Interior, hearth and seating",
    meta: "Interiors",
    ratio: "4 / 5",
    image: "assets/firehut-0ee04d79-2f41-4c68-b386-6693513db825.png",
    categories: ["Interiors"],
  },
  {
    title: "Drone, wide establishing",
    meta: "Drone",
    ratio: "16 / 10",
    image: "assets/drone_footage_open_secne-e9a84652-3ec7-4539-bc95-7740d35da321.png",
    categories: ["Exteriors", "Drone"],
  },
  {
    title: "Evening interior, film still",
    meta: "Interiors",
    ratio: "4 / 5",
    image: "assets/living_room_night-65192f35-cec5-422d-9da0-b8af4ed1cb4a.png",
    categories: ["Interiors"],
  },
  {
    title: "Deck, exterior context",
    meta: "Exteriors",
    ratio: "3 / 4",
    image: "assets/decking-aaf4c7b8-4e1e-4034-bb68-dda39a601bb4.png",
    categories: ["Exteriors"],
  },
  {
    title: "Bedroom detail",
    meta: "Interiors",
    ratio: "4 / 5",
    image: "assets/bedroom_3-5676e9d2-6564-41f5-b982-c0ef115afda2.png",
    categories: ["Interiors"],
  },
  {
    title: "Drone footage reel",
    meta: "Video",
    ratio: "16 / 10",
    image: "assets/drone_footage_open_secne-e9a84652-3ec7-4539-bc95-7740d35da321.png",
    videoSrc: "assets/drone-movie.mp4",
    categories: ["Exteriors", "Drone", "Video"],
  },
  {
    title: "House walkthrough",
    meta: "Video",
    ratio: "16 / 10",
    image: "assets/living_room_over_sofa-0c4abcfa-ff9f-476f-97cf-59ce32528e21.png",
    videoSrc: "assets/house-walkthrough.mp4",
    categories: ["Interiors", "Video"],
  },
  {
    title: "Landscape, night exposure",
    meta: "Exteriors",
    ratio: "3 / 4",
    image: "assets/northan_lights_fjord-1e4abbc0-a12f-4242-bf00-546404e263bf.png",
    categories: ["Exteriors"],
  },
];

function filterPortfolioItems(active) {
  if (active === "All") return PORTFOLIO_ITEMS;
  return PORTFOLIO_ITEMS.filter((it) => it.categories && it.categories.includes(active));
}

function HomePortfolioTeaser({ setRoute }) {
  const [active, setActive] = useStateP("All");
  const items = filterPortfolioItems(active).slice(0, 6);
  const ratios = ["3 / 4", "1 / 1", "4 / 5", "3 / 4", "4 / 3", "1 / 1"];
  const visibleImageGallery = items
    .filter((x) => !x.videoSrc)
    .map((x) => ({ src: x.image, alt: x.title }));

  if (!items.length) {
    return (
      <section className="sem-section sem-portfolio-teaser" data-screen-label="Home / Portfolio teaser">
        <div className="sem-container">
          <SectionHead eyebrow="Portfolio" title="Selected work" intro="" tone="dark" />
          <p className="sem-portfolio-empty">No frames in this category yet.</p>
        </div>
      </section>
    );
  }

  return (
    <section className="sem-section sem-portfolio-teaser" data-screen-label="Home / Portfolio teaser">
      <div className="sem-container">
        <SectionHead
          eyebrow="Portfolio"
          title="Selected work"
          intro="Photography-led frames and walkthrough clips — filter by interiors, exteriors, drone or video."
          tone="dark"
        />
        <div className="sem-portfolio-filters sem-portfolio-filters--home" role="tablist" aria-label="Portfolio categories">
          {PORTFOLIO_FILTERS.map((f) => (
            <button
              key={f}
              type="button"
              role="tab"
              aria-selected={active === f}
              className={`sem-portfolio-filter ${active === f ? "is-active" : ""}`}
              onClick={() => setActive(f)}
            >
              {f}
            </button>
          ))}
        </div>
        <div className="sem-portfolio sem-portfolio-masonry">
          {items.map((it, i) => (
            <article
              key={`${it.title}-${i}`}
              className="sem-portfolio-item sem-portfolio-item--clickable"
              data-cursor="hover"
            >
              <button
                type="button"
                className="sem-portfolio-hit"
                aria-label={`View full screen — ${it.title}`}
                onClick={() => {
                  if (window.semTrack) window.semTrack("portfolio_teaser_click", { title: it.title });
                  if (it.videoSrc && window.semOpenMedia) {
                    window.semOpenMedia({ mediaType: "video", src: it.videoSrc, poster: it.image, alt: it.title });
                  } else if (window.semOpenLightbox) {
                    window.semOpenLightbox(it.image, it.title, { gallery: visibleImageGallery });
                  }
                }}
              >
                <Plate label={it.title} caption={it.meta} ratio={ratios[i % ratios.length]} src={it.image} alt={it.title} />
              </button>
              <div className="sem-portfolio-meta">
                <div className="sem-portfolio-title">{it.title}</div>
                <div className="sem-portfolio-tags">{it.meta}</div>
              </div>
            </article>
          ))}
        </div>
        <div className="sem-section-end">
          <button type="button" className="sem-link-quiet" onClick={() => setRoute("portfolio")}>
            View portfolio
          </button>
        </div>
      </div>
    </section>
  );
}

// ─── Home page ─────────────────────────────────────────────────────────────
function HomePage({ setRoute }) {
  return (
    <main className="sem-home" data-screen-label="Home">
      <Hero setRoute={setRoute} />

      <section className="sem-section sem-intro" data-screen-label="Home / Intro">
        <div className="sem-container sem-intro-grid">
          <div>
            <Eyebrow tone="dark">Editorial</Eyebrow>
            <h2 className="sem-intro-headline">Built for agents who care how their listings are seen.</h2>
          </div>
          <div className="sem-intro-body">
            <p>
              Signature Estate Media supplies clean, natural, professional property media for London agents who need
              reliable, consistent, listing-ready assets — photography, video, drone, floorplans and EPC from one
              accountable operator.
            </p>
          </div>
        </div>
      </section>

      <HomeServicesOverview setRoute={setRoute} />

      <section className="sem-section sem-quality" data-screen-label="Home / Quality">
        <div className="sem-container sem-quality-inner">
          <div className="sem-quality-grid">
            <div className="sem-quality-copy">
              <Eyebrow tone="dark">Discipline</Eyebrow>
              <h2 className="sem-section-title">Quiet quality. Clear process. No shortcuts.</h2>
              <p className="sem-quality-body">
                Every property is approached with the same discipline: considered angles, clean light, careful editing and
                assets prepared for professional listing use. Natural light where it serves the architecture — never a
                substitute for judgement.
              </p>
            </div>
            <div className="sem-quality-media">
              <img
                src="assets/drone-london-2-ac6a55f6-c2c2-47e3-aec3-e8f77728cf05.png"
                alt="Top-down aerial view of London residential rooftops, gardens and street"
                loading="lazy"
                decoding="async"
              />
            </div>
          </div>
        </div>
      </section>

      <HomePortfolioTeaser setRoute={setRoute} />

      <section className="sem-section sem-about-teaser" data-screen-label="Home / About teaser">
        <div className="sem-container sem-about-teaser-grid">
          <div>
            <Eyebrow tone="dark">Operator</Eyebrow>
            <h2 className="sem-section-title">Handled by one accountable operator.</h2>
          </div>
          <div className="sem-about-teaser-body">
            <p>
              One professional, end-to-end: DEA-accredited EPCs, CAA-compliant drone work, and photography led with an
              editorial eye. Built around consistency, accountability and quality — not volume.
            </p>
            <button type="button" className="sem-text-link" onClick={() => setRoute("about")}>
              About the studio
            </button>
          </div>
        </div>
      </section>

      <FinalCTA setRoute={setRoute} />
    </main>
  );
}

const SERVICES_DETAIL = [
  {
    id: "photography",
    title: "Photography",
    headline: "Property photography",
    description:
      "Natural light property photography with clean composition, accurate colour and a magazine-led finish.",
    bestFor: "Prime London listings where stills need to read as credible, not overcooked.",
    outputs: "High-resolution stills, web-optimised exports, print-ready files on request.",
    image: "assets/living_room_sofas-ea7a5a98-3ea9-40fb-bdd5-97b0c7fe349f.png",
  },
  {
    id: "video",
    title: "Video",
    headline: "Property film",
    description: "Calm, considered property films designed to show flow, proportion and atmosphere.",
    bestFor: "Homes where sequence, light and proportion matter more than gimmicks.",
    outputs: "4K master, HD delivery, platform-specific aspect ratios on request.",
    image: "assets/drone-london-2-ac6a55f6-c2c2-47e3-aec3-e8f77728cf05.png",
    imageAlt: "Top-down aerial view of London residential rooftops, gardens and street",
  },
  {
    id: "drone",
    title: "Drone",
    headline: "Aerial footage",
    description: "CAA-compliant aerial footage for homes, developments and location-led listings.",
    bestFor: "Garden plots, rooflines, context shots and developments needing a clear sense of place.",
    outputs: "Aerial stills and short aerial sequences, supplied colour-corrected and stabilised.",
    image: "assets/ariel_overhead-a957d430-6877-477f-8713-e8d9346b2c6c.png",
  },
  {
    id: "floorplans",
    title: "Floorplans",
    headline: "Measured floorplans",
    description: "Clear, accurate floorplans that support buyers, agents and online listing platforms.",
    bestFor: "Listings where buyers expect clarity on flow, room labels and total area.",
    outputs: "2D plans, branded to agency template where required; turnaround agreed at booking.",
    image:
      "assets/planning-of-construction-of-the-house-repair-work-2026-03-26-02-06-01-utc-fade21e1-d329-4612-8193-e746d1bec8af.png",
    imageAlt: "2D residential floorplan showing room layout",
  },
  {
    id: "epc",
    title: "EPC certificates",
    headline: "Domestic EPC",
    description: "DEA-accredited EPC certificates, lodged on the national register.",
    bestFor: "Sales and lettings where an up-to-date certificate is required before marketing or tenancy.",
    outputs: "Registered EPC document and recommendation report.",
    epcNote:
      "EPC certificates are billed directly to the vendor or landlord — never to the estate agent — on a separate invoice, as required for this service line.",
  },
];

function ServicesPage({ setRoute }) {
  const servicesGallery = SERVICES_DETAIL.filter((s) => s.image).map((s) => ({
    src: s.image,
    alt: `${s.title} sample frame`,
  }));
  return (
    <main className="sem-page" data-screen-label="Services">
      <PageHeader
        eyebrow="Services"
        title="Five services. One operator."
        intro="Photography, video, drone, floorplans and EPC — briefed, produced and delivered with one accountable standard."
      />

      <section className="sem-section sem-services-detail-page">
        <div className="sem-container">
          {SERVICES_DETAIL.map((s) => {
            const sampleAlt = s.imageAlt || `${s.title} sample frame`;
            return (
            <article key={s.id} className="sem-service-page-block">
              <div className="sem-service-page-media">
                {s.id === "epc" ? (
                  <div style={{ aspectRatio: "4 / 5", width: "100%" }}>
                    <EpcRatingChart />
                  </div>
                ) : (
                  <button
                    type="button"
                    className="sem-portfolio-hit"
                    aria-label={`View full screen — ${s.title}`}
                    onClick={() => {
                      if (window.semOpenLightbox) {
                        window.semOpenLightbox(s.image, sampleAlt, { gallery: servicesGallery });
                      }
                    }}
                  >
                    <Plate src={s.image} alt={sampleAlt} ratio="4 / 5" label={s.title} caption="" />
                  </button>
                )}
              </div>
              <div className="sem-service-page-copy">
                <h2 className="sem-service-page-headline">{s.headline}</h2>
                <p className="sem-service-page-lead">{s.description}</p>
                <div className="sem-service-page-meta">
                  <p>
                    <strong>Best for:</strong> {s.bestFor}
                  </p>
                  <p>
                    <strong>Deliverables:</strong> {s.outputs}
                  </p>
                  {s.epcNote && (
                    <p className="sem-service-page-epc">
                      <strong>EPC billing:</strong> {s.epcNote}
                    </p>
                  )}
                </div>
              </div>
            </article>
            );
          })}
        </div>
      </section>

      <FinalCTA setRoute={setRoute} />
    </main>
  );
}

// ─── Portfolio grid ─────────────────────────────────────────────────────────
function PortfolioGrid({ layout = "uniform", count = 9, filterCategory = "All" }) {
  let items = filterPortfolioItems(filterCategory);
  items = items.slice(0, count);
  const activeLayout = "uniform";
  const visibleImageGallery = items
    .filter((x) => !x.videoSrc)
    .map((x) => ({ src: x.image, alt: x.title }));

  const mediaRatio = (it, ratio) => (it.videoSrc ? "16 / 9" : ratio);

  const renderPortfolioMedia = (it, ratio) => {
    const effectiveRatio = mediaRatio(it, ratio);
    if (it.videoSrc) {
      return (
        <div className="sem-portfolio-video-preview">
          <Plate label={it.title} caption={it.meta} ratio={effectiveRatio} src={it.image} alt={it.title} />
          <span className="sem-portfolio-video-pill">Play video</span>
        </div>
      );
    }
    return <Plate label={it.title} caption={it.meta} ratio={effectiveRatio} src={it.image} alt={it.title} />;
  };

  /** Image + caption row share one control so the whole card opens the fullscreen viewer. */
  const portfolioCardHit = (it, mediaChild) => {
    if (it.videoSrc) {
      return (
        <button
          type="button"
          className="sem-portfolio-hit sem-portfolio-card-hit sem-portfolio-card-hit-video"
          aria-label={`Play video — ${it.title}`}
          onClick={() => {
            if (window.semOpenMedia) {
              window.semOpenMedia({
                mediaType: "video",
                src: it.videoSrc,
                poster: it.image,
                alt: it.title,
              });
            }
          }}
        >
          {mediaChild}
          <div className="sem-portfolio-meta">
            <div className="sem-portfolio-title">{it.title}</div>
            <div className="sem-portfolio-tags">{it.meta}</div>
          </div>
        </button>
      );
    }
    return (
      <button
        type="button"
        className="sem-portfolio-hit sem-portfolio-card-hit"
        aria-label={`View full screen — ${it.title}`}
        onClick={() => {
          if (window.semOpenLightbox) window.semOpenLightbox(it.image, it.title, { gallery: visibleImageGallery });
        }}
      >
        {mediaChild}
        <div className="sem-portfolio-meta">
          <div className="sem-portfolio-title">{it.title}</div>
          <div className="sem-portfolio-tags">{it.meta}</div>
        </div>
      </button>
    );
  };

  if (activeLayout === "masonry") {
    const ratios = ["3 / 4", "1 / 1", "4 / 5", "3 / 4", "4 / 3", "1 / 1", "3 / 4", "4 / 5", "1 / 1"];
    if (!items.length) {
      return <p className="sem-portfolio-empty">No frames in this category yet.</p>;
    }
    return (
      <div className="sem-portfolio sem-portfolio-masonry">
        {items.map((it, i) => (
          <article key={`${it.title}-${i}`} className="sem-portfolio-item" data-cursor="hover">
            {portfolioCardHit(it, renderPortfolioMedia(it, ratios[i % ratios.length]))}
          </article>
        ))}
      </div>
    );
  }

  if (activeLayout === "editorial") {
    if (!items.length) {
      return <p className="sem-portfolio-empty">No frames in this category yet.</p>;
    }
    return (
      <div className="sem-portfolio sem-portfolio-editorial">
        {items.map((it, i) => {
          const big = i % 3 === 0;
          return (
            <article key={`${it.title}-${i}`} className={`sem-portfolio-item ${big ? "is-big" : ""}`} data-cursor="hover">
              {portfolioCardHit(it, renderPortfolioMedia(it, big ? "16 / 10" : "4 / 5"))}
            </article>
          );
        })}
      </div>
    );
  }

  if (!items.length) {
    return <p className="sem-portfolio-empty">No frames in this category yet.</p>;
  }
  return (
    <div className="sem-portfolio sem-portfolio-uniform">
      {items.map((it, i) => (
        <article key={`${it.title}-${i}`} className="sem-portfolio-item" data-cursor="hover">
          {portfolioCardHit(it, renderPortfolioMedia(it, "16 / 10"))}
        </article>
      ))}
    </div>
  );
}

function PortfolioPage({ setRoute }) {
  const [active, setActive] = useStateP("All");
  return (
    <main className="sem-page" data-screen-label="Portfolio">
      <PageHeader
        eyebrow="Portfolio"
        title="Selected work"
        intro="Inline grid with consistent sizing — filter by interiors, exteriors, drone or video."
      />
      <section className="sem-section sem-portfolio-section">
        <div className="sem-container">
          <div className="sem-portfolio-toolbar">
            <div className="sem-portfolio-filters" role="tablist" aria-label="Portfolio filters">
              {PORTFOLIO_FILTERS.map((f) => (
                <button
                  key={f}
                  type="button"
                  className={`sem-portfolio-filter ${active === f ? "is-active" : ""}`}
                  onClick={() => setActive(f)}
                >
                  {f}
                </button>
              ))}
            </div>
          </div>
          <PortfolioGrid layout="uniform" count={12} filterCategory={active} />
        </div>
      </section>
      <FinalCTA setRoute={setRoute} />
    </main>
  );
}

// ─── About page ────────────────────────────────────────────────────────────
function AboutPage({ setRoute }) {
  return (
    <main className="sem-page" data-screen-label="About">
      <PageHeader
        eyebrow="About"
        title="One operator. One standard."
        intro="London property media for agents who understand that how a home is presented directly affects how quickly it sells."
      />

      <section className="sem-section sem-about-portrait">
        <div className="sem-about-portrait-grid">
          <div className="sem-about-portrait-img">
            <button
              type="button"
              className="sem-portfolio-hit"
              aria-label="View full screen — aerial view of London"
              onClick={() => {
                if (window.semOpenLightbox) {
                  window.semOpenLightbox(
                    "assets/drone-london-c3bb899d-b428-4da6-88f2-be977e798d92.png",
                    "Aerial view of a London residential street and gardens"
                  );
                }
              }}
            >
              <Plate
                label="Studio"
                caption="Natural light"
                ratio="3 / 4"
                src="assets/drone-london-c3bb899d-b428-4da6-88f2-be977e798d92.png"
                alt="Aerial view of a London residential street and gardens"
                fit="cover"
              />
            </button>
          </div>
          <div className="sem-about-portrait-copy">
            <Eyebrow tone="dark">Practice</Eyebrow>
            <h2 className="sem-about-name">London-first. Editorial discipline.</h2>
            <div className="sem-about-body">
              <p>
                I came to property media through selling my own home — and being genuinely frustrated by the standard
                of photography on the market. Most of what I saw was rushed, over-processed, and doing the properties no
                favours.
              </p>
              <p>
                I&apos;ve been working with cameras professionally for over two decades — portrait, events, weddings — so
                I knew what good looked like. Property felt like a market that needed it badly.
              </p>
              <p>
                Signature Estate Media is built around one principle: every property deserves to be shown at its best,
                accurately and without shortcuts. Natural light where it serves the space. Considered composition. No HDR
                processing. No rushing through a job to get to the next one.
              </p>
            </div>
            <div className="sem-about-credentials">
              {[
                ["DEA", "Accredited Domestic Energy Assessor"],
                ["CAA", "Compliant aerial work · relevant permissions"],
                ["Public liability", "£2m public liability"],
                ["Professional indemnity", "£250,000 — covers EPC assessments and floorplan production"],
                ["Commercial drone insurance", "£1m"],
                ["Data", "Handled on UK-appropriate infrastructure"],
              ].map(([k, v]) => (
                <div key={k} className="sem-about-cred">
                  <div className="sem-about-cred-k">{k}</div>
                  <div className="sem-about-cred-v">{v}</div>
                </div>
              ))}
            </div>
          </div>
        </div>
      </section>

      <section className="sem-section sem-about-philosophy">
        <div className="sem-container">
          <div className="sem-about-philosophy-grid">
            <Eyebrow tone="dark">Approach</Eyebrow>
            <div>
              <p className="sem-about-quote">Photography leads. Copy supports.</p>
              <p className="sem-about-quote-meta">
                Every shoot starts with understanding the property — its light, its proportions, its best angles. The
                goal is always images that are true to life and compelling enough to stop a buyer mid-scroll. If it
                doesn&apos;t look right, we don&apos;t move on.
              </p>
            </div>
          </div>
        </div>
      </section>

      <FinalCTA setRoute={setRoute} />
    </main>
  );
}

// ─── Contact page ──────────────────────────────────────────────────────────
function metaGet(name) {
  if (typeof document === "undefined") return "";
  const el = document.querySelector(`meta[name="${name}"]`);
  return el && el.getAttribute("content") ? el.getAttribute("content").trim() : "";
}

function formatContactBody(f) {
  const lines = [
    `Name: ${f.name}`,
    `Agency: ${f.agency || "—"}`,
    `Email: ${f.email || "—"}`,
    `Services: ${f.services.length ? f.services.join(", ") : "—"}`,
    `Best time to call: ${f.time}`,
    `Property postcode: ${f.postcode || "—"}`,
    `Preferred shoot date: ${f.shootDate || "—"}`,
    "",
    f.message || "",
  ];
  return lines.join("\n");
}

function ContactPage() {
  const [form, setForm] = useStateP({
    name: "",
    agency: "",
    email: "",
    services: [],
    time: "Morning",
    message: "",
    postcode: "",
    shootDate: "",
  });
  const [successMessage, setSuccessMessage] = useStateP("");
  const [submitError, setSubmitError] = useStateP("");
  const services = ["Photography", "Video", "Drone", "Floorplans", "EPC"];
  const times = ["Morning", "Afternoon", "Evening", "Any time"];

  const emptyForm = {
    name: "",
    agency: "",
    email: "",
    services: [],
    time: "Morning",
    message: "",
    postcode: "",
    shootDate: "",
  };

  const toggle = (svc) => {
    setForm((f) => ({
      ...f,
      services: f.services.includes(svc) ? f.services.filter((s) => s !== svc) : [...f.services, svc],
    }));
  };

  const submit = async (e) => {
    e.preventDefault();
    setSubmitError("");
    setSuccessMessage("");

    const endpoint = metaGet("sem:contact-endpoint");
    if (!endpoint) {
      setSubmitError("Something went wrong. Please email us directly at hello@signatureestatemedia.co.uk");
      return;
    }

    if (window.semTrack) window.semTrack("contact_submit", { services: form.services });

    const payload = {
      name: form.name,
      agency: form.agency,
      email: form.email,
      services: form.services,
      time: form.time,
      message: form.message,
      postcode: form.postcode,
      shootDate: form.shootDate,
      _subject: `Website enquiry — ${form.name || "Signature Estate Media"}`,
    };
    if ((form.email || "").trim()) payload._replyto = form.email.trim();

    try {
      const res = await fetch(endpoint, {
        method: "POST",
        headers: { "Content-Type": "application/json", Accept: "application/json" },
        body: JSON.stringify(payload),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok || data.ok === false) throw new Error("Form submission failed");

      setForm(emptyForm);
      setSuccessMessage("Message sent. We'll be in touch shortly.");
    } catch (err) {
      setSubmitError("Something went wrong. Please email us directly at hello@signatureestatemedia.co.uk");
      if (window.semTrack) window.semTrack("contact_submit_error", { message: String(err) });
    }
  };

  return (
    <main className="sem-page" data-screen-label="Contact">
      <PageHeader
        eyebrow="Contact"
        title="Book a call."
        intro="Send a listing address, scope or timing preference. Replies same working day where possible."
      />
      <section className="sem-section sem-contact-section">
        <div className="sem-contact-grid">
          <aside className="sem-contact-aside">
            <div className="sem-contact-block">
              <div className="sem-contact-h">Direct</div>
              <a href="mailto:hello@signatureestatemedia.co.uk" className="sem-contact-email">
                hello@signatureestatemedia.co.uk
              </a>
            </div>
            <div className="sem-contact-block">
              <div className="sem-contact-h">Hours</div>
              <div>Monday – Saturday</div>
              <div>By appointment</div>
            </div>
            <div className="sem-contact-block">
              <div className="sem-contact-h">Coverage</div>
              <div>Greater London</div>
              <div>Home Counties on request</div>
            </div>
            <div className="sem-contact-block">
              <div className="sem-contact-h">Lead time</div>
              <div>Typically one to two weeks</div>
              <div>Urgent slots when diary allows</div>
            </div>
          </aside>

          <div className="sem-contact-form-wrap">
            <form className="sem-contact-form" onSubmit={submit} noValidate>
                <div className="sem-field">
                  <label htmlFor="sem-name">Name</label>
                  <input
                    id="sem-name"
                    required
                    value={form.name}
                    onChange={(e) => setForm({ ...form, name: e.target.value })}
                    autoComplete="name"
                  />
                </div>
                <div className="sem-field">
                  <label htmlFor="sem-agency">Agency</label>
                  <input
                    id="sem-agency"
                    value={form.agency}
                    onChange={(e) => setForm({ ...form, agency: e.target.value })}
                    autoComplete="organization"
                  />
                </div>
                <div className="sem-field">
                  <label htmlFor="sem-email">Email (optional)</label>
                  <input
                    id="sem-email"
                    type="email"
                    value={form.email}
                    onChange={(e) => setForm({ ...form, email: e.target.value })}
                    autoComplete="email"
                    placeholder="For a direct reply"
                  />
                </div>
                <div className="sem-field">
                  <span id="sem-svc-label" className="sem-field-label-span">
                    Services needed
                  </span>
                  <div className="sem-field-chips" role="group" aria-labelledby="sem-svc-label">
                    {services.map((s) => (
                      <button
                        key={s}
                        type="button"
                        className={`sem-chip ${form.services.includes(s) ? "is-on" : ""}`}
                        onClick={() => toggle(s)}
                      >
                        {s}
                      </button>
                    ))}
                  </div>
                </div>
                <div className="sem-field">
                  <span id="sem-time-label" className="sem-field-label-span">
                    Best time to call
                  </span>
                  <div className="sem-field-chips" role="group" aria-labelledby="sem-time-label">
                    {times.map((t) => (
                      <button
                        key={t}
                        type="button"
                        className={`sem-chip ${form.time === t ? "is-on" : ""}`}
                        onClick={() => setForm({ ...form, time: t })}
                      >
                        {t}
                      </button>
                    ))}
                  </div>
                </div>
                <div className="sem-field-row">
                  <div className="sem-field">
                    <label htmlFor="sem-postcode">Property postcode (optional)</label>
                    <input
                      id="sem-postcode"
                      value={form.postcode}
                      onChange={(e) => setForm({ ...form, postcode: e.target.value })}
                      autoComplete="postal-code"
                    />
                  </div>
                  <div className="sem-field">
                    <label htmlFor="sem-date">Preferred shoot date (optional)</label>
                    <input
                      id="sem-date"
                      type="date"
                      value={form.shootDate}
                      onChange={(e) => setForm({ ...form, shootDate: e.target.value })}
                    />
                  </div>
                </div>
                <div className="sem-field">
                  <label htmlFor="sem-msg">Message</label>
                  <textarea
                    id="sem-msg"
                    rows="5"
                    value={form.message}
                    onChange={(e) => setForm({ ...form, message: e.target.value })}
                    placeholder="Listing address, access notes, scope, deadlines."
                  />
                </div>
                {successMessage && <p className="sem-form-success">{successMessage}</p>}
                {submitError && <p className="sem-form-error">{submitError}</p>}
                <div className="sem-form-submit">
                  <button type="submit" className="sem-cta sem-cta-light sem-cta-md">
                    <span>Get in touch</span>
                    <svg width="18" height="10" viewBox="0 0 18 10" fill="none" aria-hidden="true">
                      <path d="M1 5H17M17 5L13 1M17 5L13 9" stroke="currentColor" strokeWidth="1.25" strokeLinecap="square" />
                    </svg>
                  </button>
                  <p className="sem-form-disclaimer">
                    No fees quoted here — scope agreed in writing after brief.
                  </p>
                </div>
              </form>
          </div>
        </div>
      </section>
    </main>
  );
}

// ─── Journal / Blog ───────────────────────────────────────────────────────────

function inlineFormat(text) {
  return text
    .replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>")
    .replace(/\*(.+?)\*/g, "<em>$1</em>")
    .replace(/\[(.+?)\]\((.+?)\)/g, '<a href="$2" rel="noopener noreferrer" style="color:#D4A830">$1</a>');
}

function parseMarkdown(md) {
  if (!md) return "";
  return md.split(/\n\n+/).map((block) => {
    const t = block.trim();
    if (!t) return "";
    if (t.startsWith("### ")) return `<h3>${inlineFormat(t.slice(4))}</h3>`;
    if (t.startsWith("## "))  return `<h2>${inlineFormat(t.slice(3))}</h2>`;
    if (t.startsWith("# "))   return `<h2>${inlineFormat(t.slice(2))}</h2>`;
    if (t.startsWith("- ")) {
      const items = t.split("\n").filter(l=>l.startsWith("- ")).map(l=>`<li>${inlineFormat(l.slice(2))}</li>`).join("");
      return `<ul>${items}</ul>`;
    }
    return `<p>${t.split("\n").map(inlineFormat).join(" ")}</p>`;
  }).join("\n");
}

function InstagramSection() {
  useEffectP(() => {
    const scriptId = "EmbedSocialHashtagScript";
    if (document.getElementById(scriptId)) return;
    const js = document.createElement("script");
    js.id = scriptId;
    js.src = "https://embedsocial.com/cdn/ht.js";
    document.head.appendChild(js);
  }, []);

  return (
    <section className="sem-section" style={{ background: "#111", borderTop: "1px solid rgba(212,168,48,0.15)" }}>
      <div className="sem-container">
        <div style={{ display:"flex", alignItems:"flex-end", justifyContent:"space-between", flexWrap:"wrap", gap:"1rem", marginBottom:"2.5rem" }}>
          <div>
            <Eyebrow tone="light">Instagram</Eyebrow>
            <h2 className="sem-section-title" style={{ color:"#fff", marginTop:"0.5rem" }}>Behind the shoot.</h2>
            <p style={{ color:"rgba(255,255,255,0.55)", fontSize:"0.95rem", marginTop:"0.5rem", maxWidth:"36ch" }}>Process, property detail and field notes — follow the work in real time.</p>
          </div>
          <a href="https://www.instagram.com/signature_estate_media" target="_blank" rel="noopener noreferrer"
            style={{ display:"inline-flex", alignItems:"center", gap:"0.5rem", color:"#D4A830", fontSize:"0.85rem", letterSpacing:"0.1em", textTransform:"uppercase", textDecoration:"none", fontWeight:500, border:"1px solid rgba(212,168,48,0.4)", padding:"0.6rem 1.2rem" }}>
            @signature_estate_media
            <svg width="14" height="8" viewBox="0 0 18 10" fill="none" aria-hidden="true"><path d="M1 5H17M17 5L13 1M17 5L13 9" stroke="currentColor" strokeWidth="1.25" strokeLinecap="square"/></svg>
          </a>
        </div>
        <div className="embedsocial-hashtag" data-ref="c06b75e672b15bf0d3fcd35f99b6f49249f1e51e" style={{ minHeight:"200px" }}>
          <a
            className="feed-powered-by-es feed-powered-by-es-feed-img es-widget-branding"
            href="https://embedsocial.com/instagram-widget/"
            target="_blank"
            rel="noopener noreferrer"
            title="Instagram widget"
          >
            <img src="https://embedsocial.com/cdn/icon/embedsocial-logo.webp" alt="EmbedSocial" />
            <div className="es-widget-branding-text">Instagram widget</div>
          </a>
        </div>
      </div>
    </section>
  );
}

function ArticleCard({ post, onClick }) {
  return (
    <article
      onClick={onClick}
      style={{
        background: "#fff", border: "1px solid rgba(0,0,0,0.1)",
        cursor: "pointer", transition: "border-color 0.2s, box-shadow 0.2s",
        display: "flex", flexDirection: "column", overflow: "hidden",
      }}
    >
      {post.image && (
        <div style={{ width: "100%", height: "200px", overflow: "hidden", flexShrink: 0 }}>
          <img
            src={post.image}
            alt={post.title}
            loading="lazy"
            decoding="async"
            style={{ width: "100%", height: "100%", objectFit: "cover", display: "block", transition: "transform 0.3s ease" }}
          />
        </div>
      )}
      <div style={{ padding: "1.5rem", display: "flex", flexDirection: "column", gap: "0.75rem", flex: 1 }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: "1rem" }}>
          <span style={{ fontSize: "0.75rem", color: "rgba(0,0,0,0.35)", letterSpacing: "0.08em" }}>{post.date}</span>
          {post.tags && post.tags.length > 0 && (
            <div style={{ display: "flex", gap: "0.5rem" }}>
              {post.tags.slice(0, 2).map((t) => (
                <span key={t} style={{ fontSize: "0.65rem", letterSpacing: "0.15em", textTransform: "uppercase", color: "#D4A830", fontWeight: 500 }}>{t}</span>
              ))}
            </div>
          )}
        </div>
        <h3 style={{ color: "#111", fontSize: "1.1rem", fontWeight: 500, lineHeight: 1.4, margin: 0 }}>{post.title}</h3>
        {post.excerpt && (
          <p style={{ color: "rgba(0,0,0,0.5)", fontSize: "0.875rem", lineHeight: 1.65, margin: 0 }}>{post.excerpt}</p>
        )}
        <span style={{ fontSize: "0.75rem", color: "#D4A830", letterSpacing: "0.1em", textTransform: "uppercase", fontWeight: 500, marginTop: "0.25rem" }}>
          Read article →
        </span>
      </div>
    </article>
  );
}

function BlogPage({ setRoute }) {
  const [posts, setPosts]               = useStateP([]);
  const [page, setPage]                 = useStateP(1);
  const [winWidth, setWinWidth]         = useStateP(typeof window !== "undefined" ? window.innerWidth : 768);
  const [activeSlug, setActiveSlug]     = useStateP(null);
  const [articleHtml, setArticleHtml]   = useStateP("");
  const [articleState, setArticleState] = useStateP("idle");
  const pageScrollReady                 = useRefP(false);

  useEffectP(() => {
    fetch("content/blog/manifest.json", { cache:"no-cache" })
      .then(r => r.ok ? r.json() : [])
      .then(data => setPosts(Array.isArray(data) ? data : []))
      .catch(() => setPosts([]));
  }, []);

  useEffectP(() => {
    if (!activeSlug) { setArticleHtml(""); setArticleState("idle"); return; }
    setArticleState("loading");
    fetch(`content/blog/${activeSlug}.md`, { cache:"no-cache" })
      .then(r => { if (!r.ok) throw new Error("not found"); return r.text(); })
      .then(md => { setArticleHtml(parseMarkdown(md)); setArticleState("ready"); })
      .catch(() => { setArticleHtml(""); setArticleState("error"); });
  }, [activeSlug]);

  useEffectP(() => {
    if (!activeSlug) return;
    const url = new URL(window.location.href);
    url.searchParams.set("post", activeSlug);
    window.history.replaceState({}, "", url.pathname + "?" + url.searchParams.toString());
  }, [activeSlug]);

  useEffectP(() => {
    const q = new URLSearchParams(window.location.search).get("post");
    if (q) setActiveSlug(q);
  }, []);

  useEffectP(() => {
    const onResize = () => setWinWidth(window.innerWidth);
    window.addEventListener("resize", onResize);
    return () => window.removeEventListener("resize", onResize);
  }, []);

  useEffectP(() => {
    if (!pageScrollReady.current) {
      pageScrollReady.current = true;
      return;
    }
    window.scrollTo({ top: 0, behavior: "instant" });
  }, [page]);

  const activePost = activeSlug ? posts.find(p => p.slug === activeSlug) : null;
  const postsPerPage = winWidth < 768 ? 4 : 6;
  const totalPages = Math.ceil(posts.length / postsPerPage);
  const currentPage = totalPages > 0 ? Math.min(page, totalPages) : 1;
  const paginatedPosts = posts.slice((currentPage - 1) * postsPerPage, currentPage * postsPerPage);

  if (activeSlug) {
    return (
      <main className="sem-page" data-screen-label="Journal article">
        <section className="sem-section">
          <div className="sem-container" style={{ maxWidth:"720px" }}>
            <button type="button" onClick={() => { setActiveSlug(null); window.history.replaceState({}, "", "/journal"); }}
              style={{ background:"none", border:"none", color:"rgba(0,0,0,0.45)", fontSize:"0.8rem", letterSpacing:"0.1em", textTransform:"uppercase", cursor:"pointer", padding:"0", marginBottom:"2.5rem", display:"inline-flex", alignItems:"center", gap:"0.4rem" }}>
              ← Back to journal
            </button>
            {activePost && (
              <React.Fragment>
                <p style={{ color:"rgba(0,0,0,0.45)", fontSize:"0.8rem", letterSpacing:"0.08em", marginBottom:"1rem" }}>{activePost.date}</p>
                <h1 style={{ color:"#111", fontSize:"clamp(1.6rem, 4vw, 2.4rem)", fontWeight:500, lineHeight:1.25, marginBottom:"1.25rem" }}>{activePost.title}</h1>
                {activePost.excerpt && <p style={{ color:"rgba(0,0,0,0.6)", fontSize:"1.1rem", lineHeight:1.65, borderLeft:"2px solid #D4A830", paddingLeft:"1.25rem", marginBottom:"2.5rem" }}>{activePost.excerpt}</p>}
              </React.Fragment>
            )}
            {articleState === "loading" && <p style={{ color:"rgba(0,0,0,0.45)", fontSize:"0.875rem" }}>Loading…</p>}
            {articleState === "error"   && <p style={{ color:"rgba(0,0,0,0.45)", fontSize:"0.875rem" }}>Article could not be loaded.</p>}
            {articleState === "ready"   && <div style={{ color:"rgba(0,0,0,0.75)", fontSize:"1rem", lineHeight:1.8 }} dangerouslySetInnerHTML={{ __html: articleHtml }} />}
          </div>
        </section>
      </main>
    );
  }

  return (
    <main className="sem-page" data-screen-label="Journal">
      <PageHeader eyebrow="Journal" title="Guidance and field notes."
        intro="Short articles for estate agents, vendors and property professionals — on photography, presentation and the London market." />
      <div style={{ borderBottom:"1px solid rgba(0,0,0,0.06)" }}>
        <div className="sem-container" style={{ padding:"0.85rem 0", display:"flex", alignItems:"center", justifyContent:"flex-end" }}>
          <a href="/api/rss" title="Subscribe via RSS"
            style={{ display:"inline-flex", alignItems:"center", gap:"0.4rem", color:"rgba(0,0,0,0.45)", fontSize:"0.72rem", letterSpacing:"0.12em", textTransform:"uppercase", textDecoration:"none" }}>
            <svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="6" cy="19" r="2"/><path d="M2 13.5c4.142 0 7.5 3.358 7.5 7.5H12c0-5.523-4.477-10-10-10v2.5z"/><path d="M2 6c8.837 0 16 7.163 16 16h2.5C20.5 11.82 12.18 4 2 4V6z"/></svg>
            Subscribe via RSS
          </a>
        </div>
      </div>
      <section className="sem-section">
        <div className="sem-container">
          {posts.length === 0 ? (
            <div style={{ padding:"3rem 0" }}>
              <p style={{ color:"rgba(0,0,0,0.45)", fontSize:"0.95rem", lineHeight:1.7, maxWidth:"42ch" }}>Articles will appear here as they are published. Check back soon.</p>
              <button type="button" onClick={() => setRoute("contact")}
                style={{ marginTop:"1.5rem", background:"none", border:"none", color:"#D4A830", fontSize:"0.85rem", letterSpacing:"0.1em", textTransform:"uppercase", cursor:"pointer", padding:0, fontWeight:500 }}>
                Get in touch instead →
              </button>
            </div>
          ) : (
            <React.Fragment>
              <div style={{ display:"grid", gridTemplateColumns:"repeat(auto-fill, minmax(min(100%, 340px), 1fr))", gap:"1.5rem" }}>
                {paginatedPosts.map(p => <ArticleCard key={p.slug} post={p} onClick={() => setActiveSlug(p.slug)} />)}
              </div>
              {totalPages > 1 && (
                <div style={{ display:"flex", alignItems:"center", justifyContent:"center", gap:"1.5rem", marginTop:"2.5rem" }}>
                  <button
                    type="button"
                    onClick={() => setPage(p => Math.max(1, p - 1))}
                    disabled={currentPage === 1}
                    style={{
                      background:"none", border:"1px solid rgba(0,0,0,0.15)", color: currentPage === 1 ? "rgba(0,0,0,0.25)" : "#111",
                      fontSize:"0.75rem", letterSpacing:"0.1em", textTransform:"uppercase", cursor: currentPage === 1 ? "default" : "pointer",
                      padding:"0.65rem 1.2rem", fontWeight:500,
                    }}
                  >
                    Prev
                  </button>
                  <span style={{ fontSize:"0.75rem", color:"rgba(0,0,0,0.45)", letterSpacing:"0.08em" }}>
                    Page {currentPage} of {totalPages}
                  </span>
                  <button
                    type="button"
                    onClick={() => setPage(p => Math.min(totalPages, p + 1))}
                    disabled={currentPage === totalPages}
                    style={{
                      background:"none", border:"1px solid rgba(0,0,0,0.15)", color: currentPage === totalPages ? "rgba(0,0,0,0.25)" : "#111",
                      fontSize:"0.75rem", letterSpacing:"0.1em", textTransform:"uppercase", cursor: currentPage === totalPages ? "default" : "pointer",
                      padding:"0.65rem 1.2rem", fontWeight:500,
                    }}
                  >
                    Next
                  </button>
                </div>
              )}
            </React.Fragment>
          )}
        </div>
      </section>
      <InstagramSection />
      <FinalCTA setRoute={setRoute} />
    </main>
  );
}

// ─── Page header ─────────────────────────────────────────────────────────────
function PageHeader({ eyebrow, title, intro }) {
  return (
    <section className="sem-page-header" aria-labelledby="sem-page-h1">
      <div className="sem-container">
        <Eyebrow tone="dark">{eyebrow}</Eyebrow>
        <h1 id="sem-page-h1" className="sem-page-title">
          {title}
        </h1>
        {intro && <p className="sem-page-intro">{intro}</p>}
      </div>
    </section>
  );
}

// ─── Final CTA ─────────────────────────────────────────────────────────────
function FinalCTA({ setRoute }) {
  return (
    <section className="sem-final-cta" data-screen-label="Final CTA">
      <div className="sem-container">
        <Eyebrow tone="light" align="center">
          Contact
        </Eyebrow>
        <h2 className="sem-final-cta-title">Property media for agents who do not cut corners.</h2>
        <p className="sem-final-cta-sub">
          Send a brief, a listing address or a service request and we will respond with the next step.
        </p>
        <CTA
          tone="dark"
          onClick={() => {
            if (window.semTrack) window.semTrack("cta_click", { location: "final_band", label: "Get in touch" });
            setRoute("contact");
          }}
          size="lg"
        >
          Get in touch
        </CTA>
      </div>
    </section>
  );
}

Object.assign(window, {
  HomePage,
  ServicesPage,
  PortfolioPage,
  AboutPage,
  ContactPage,
  BlogPage,
  Hero,
  PortfolioGrid,
  FinalCTA,
  PageHeader,
  PORTFOLIO_ITEMS,
});
