// Shared, page-agnostic section components for The Vivaan Hotel & Resorts.
// Built on top of window.VivaanDesignSystem_b1c8ba (Hero, Button, NavigationBar,
// BookingPanel, FormField). These are page-specific compositions, not formal
// DS components — same pattern as DiscoverSection/Footer in the DS's own
// ui_kit reference.

const { Button } = window.VivaanDesignSystem_b1c8ba;

/* ---------------------------------------------------------------------- */
/* Primitives                                                              */
/* ---------------------------------------------------------------------- */

// Tasteful abstract placeholder standing in for estate photography — the DS
// itself falls back to flat tone fields rather than fabricated photos, so we
// follow that convention throughout instead of pulling in stock imagery.
function PhotoBlock({ tone = "taupe", caption, ratio, style }) {
  // Flat single-token fields only — matches Hero's own no-photo fallback
  // (var(--vivaan-taupe), no gradient) and the DS's "no decorative
  // gradients" rule. A photo would replace this entirely; this is a stand-in.
  const tones = {
    taupe: "var(--vivaan-taupe)",
    cream: "var(--vivaan-cream)",
    ink: "var(--vivaan-black)",
    gold: "var(--vivaan-gold)",
  };
  const { backgroundImage, ...restStyle } = style || {};
  const wrap = {
    position: "relative",
    aspectRatio: ratio || "4 / 5",
    backgroundColor: tones[tone],
    overflow: "hidden",
    ...restStyle,
  };
  const cap = {
    position: "absolute",
    left: 20,
    bottom: 18,
    right: 20,
    color: tone === "cream" ? "var(--color-text-primary)" : "var(--color-text-on-dark)",
    fontFamily: "var(--font-serif)",
    fontSize: 11,
    letterSpacing: "0.18em",
    textTransform: "uppercase",
    opacity: 0.9,
  };
  return (
    <div style={wrap}>
      {caption ? <div style={cap}>{caption}</div> : null}
    </div>
  );
}

// Hover-swap: shows images[0] by default, crossfades to images[1] on
// hover/focus (and back on leave). Used for room cards with a "before/after"
// or two-angle photo pair. Falls back to a flat PhotoBlock if no images.
function HoverImageSwap({ images, tone, ratio, caption, style, fadeMs = 500 }) {
  const [hovered, setHovered] = React.useState(false);

  if (!images || images.length < 2) {
    return <PhotoBlock tone={tone} ratio={ratio} caption={caption} style={style} />;
  }

  const wrap2 = {
    position: "relative",
    aspectRatio: ratio || "4 / 5",
    overflow: "hidden",
    backgroundColor: "var(--vivaan-taupe)",
    ...style,
  };

  return (
    <div
      style={wrap2}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
      onFocus={() => setHovered(true)}
      onBlur={() => setHovered(false)}
      tabIndex={0}
    >
      {images.map((src, i) => (
        <div
          key={src}
          style={{
            position: "absolute",
            inset: 0,
            backgroundImage: `url(${src})`,
            backgroundSize: "cover",
            backgroundPosition: "center",
            opacity: (i === 1) === hovered ? 1 : 0,
            transition: `opacity ${fadeMs}ms ease`,
          }}
        />
      ))}
      {caption ? (
        <div style={{ position: "absolute", left: 20, bottom: 18, right: 20, color: "var(--color-text-on-dark)", fontFamily: "var(--font-serif)", fontSize: 11, letterSpacing: "0.18em", textTransform: "uppercase", opacity: 0.9 }}>
          {caption}
        </div>
      ) : null}
    </div>
  );
}

// Slow, editorial crossfade between a set of photographs — reusable anywhere
// a single PhotoBlock previously stood in for real imagery. Matches the
// brand's "luxury pace": long hold, slow fade, no motion on the images.
function PhotoSlideshow({ images, ratio, caption, style, holdMs = 4500, fadeMs = 1500 }) {
  const [active, setActive] = React.useState(0);

  React.useEffect(() => {
    if (!images || images.length < 2) return;
    const id = setInterval(() => {
      setActive((v) => (v + 1) % images.length);
    }, holdMs);
    return () => clearInterval(id);
  }, [images, holdMs]);

  const wrap = {
    position: "relative",
    aspectRatio: ratio || "4 / 5",
    overflow: "hidden",
    backgroundColor: "var(--vivaan-taupe)",
    ...style,
  };
  const cap = {
    position: "absolute",
    left: 20,
    bottom: 18,
    right: 20,
    zIndex: 2,
    color: "var(--color-text-on-dark)",
    fontFamily: "var(--font-serif)",
    fontSize: 11,
    letterSpacing: "0.18em",
    textTransform: "uppercase",
    opacity: 0.9,
  };

  return (
    <div style={wrap}>
      {(images || []).map((src, i) => (
        <div
          key={src}
          style={{
            position: "absolute",
            inset: 0,
            backgroundImage: `url(${src})`,
            backgroundSize: "cover",
            backgroundPosition: "center",
            opacity: i === active ? 1 : 0,
            transition: `opacity ${fadeMs}ms ease-in-out`,
          }}
        />
      ))}
      {caption ? <div style={cap}>{caption}</div> : null}
    </div>
  );
}

function SectionLabel({ children, dark, style }) {
  return (
    <span
      style={{
        fontFamily: "var(--font-serif)",
        fontSize: "var(--text-section-label-size)",
        letterSpacing: "var(--text-section-label-letter-spacing)",
        textTransform: "uppercase",
        color: dark ? "rgba(255,255,255,0.7)" : "var(--color-text-secondary)",
        ...style,
      }}
    >
      {children}
    </span>
  );
}

// parts: [{ text, italic }]
function EditorialHeading({ parts, size = 48, dark, style }) {
  // Fluid type: scales between ~58% and 100% of the given size across the
  // viewport, so every headline built on this component (home + inner pages)
  // is responsive without per-callsite breakpoint work.
  const fluidSize = typeof size === "number" ? `clamp(${Math.round(size * 0.58)}px, 6vw, ${size}px)` : size;
  return (
    <h2
      style={{
        fontFamily: "var(--font-serif)",
        fontWeight: 400,
        fontSize: fluidSize,
        lineHeight: 1.12,
        letterSpacing: "-0.01em",
        margin: 0,
        color: dark ? "var(--color-text-on-dark)" : "var(--color-text-primary)",
        ...style,
      }}
    >
      {parts.map((p, i) => (
        <span key={i} style={{ fontStyle: p.italic ? "italic" : "normal" }}>
          {p.text}
        </span>
      ))}
    </h2>
  );
}

function BodyCopy({ children, dark, style }) {
  return (
    <p
      style={{
        fontFamily: "var(--font-serif)",
        fontSize: "var(--text-body-size)",
        lineHeight: "var(--text-body-line-height)",
        color: dark ? "rgba(255,255,255,0.82)" : "var(--color-text-primary)",
        margin: 0,
        ...style,
      }}
    >
      {children}
    </p>
  );
}

/* ---------------------------------------------------------------------- */
/* Navigation + Footer                                                    */
/* ---------------------------------------------------------------------- */

const NAV_LINKS = [
  { label: "Stay", href: "rooms.html" },
  { label: "Dining", href: "dining.html" },
  { label: "Wedding & Events", href: "wedding.html" },
  { label: "Meetings & Conferences", href: "corporate.html" },
];

const VIVAAN_LOGO_SRC = (typeof window !== "undefined" && window.__resources && window.__resources.logoImg) ? window.__resources.logoImg : "assets/vivaan-logo-white.png";

function SiteNav() {
  const { NavigationBar } = window.VivaanDesignSystem_b1c8ba;
  const [scrolled, setScrolled] = React.useState(false);
  const [menuOpen, setMenuOpen] = React.useState(false);

  React.useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 60);
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  const navBg = scrolled ? "var(--vivaan-overlay-dark)" : "var(--color-surface-overlay-nav)";
  const logo = (
    <a href="index.html" style={{ display: "flex", alignItems: "center" }}>
      <img src={VIVAAN_LOGO_SRC} alt="The Vivaan Hotel & Resort, Karnal" style={{ height: 48, width: "auto" }} />
    </a>
  );

  return (
    <div style={{ position: "fixed", top: 0, left: 0, right: 0, zIndex: 30 }}>
      {/* Desktop / laptop / landscape-tablet nav (>=900px) — the DS NavigationBar as-is */}
      <div className="nav-desktop">
        <NavigationBar
          wordmark={<a href="index.html" style={{ display: "flex", alignItems: "center" }}><img src={VIVAAN_LOGO_SRC} alt="The Vivaan Hotel & Resort, Karnal" style={{ height: 58, width: "auto" }} /></a>}
          links={NAV_LINKS}
          cta={<Button variant="filled-gold" as="a" href="#book">Book Now</Button>}
          style={{
            backgroundColor: navBg,
            padding: "12px 40px",
            gap: "24px",
            transition: "background-color 0.3s ease",
          }}
        />
      </div>

      {/* Mobile / portrait-tablet nav (<900px) — compact bar + slide-down menu */}
      <div className="nav-mobile" style={{ backgroundColor: navBg, transition: "background-color 0.3s ease" }}>
        <div className="nav-mobile-bar">
          {logo}
          <button
            aria-label={menuOpen ? "Close menu" : "Open menu"}
            onClick={() => setMenuOpen((v) => !v)}
            className="nav-mobile-toggle"
          >
            {menuOpen ? (
              <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" strokeWidth="1.6">
                <line x1="4" y1="4" x2="20" y2="20" /><line x1="20" y1="4" x2="4" y2="20" />
              </svg>
            ) : (
              <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" strokeWidth="1.6">
                <line x1="3" y1="6" x2="21" y2="6" /><line x1="3" y1="12" x2="21" y2="12" /><line x1="3" y1="18" x2="21" y2="18" />
              </svg>
            )}
          </button>
        </div>
        {menuOpen ? (
          <div className="nav-mobile-menu">
            {NAV_LINKS.map((l) => (
              <a key={l.label} href={l.href} className="nav-mobile-link" onClick={() => setMenuOpen(false)}>{l.label}</a>
            ))}
            <Button variant="filled-gold" as="a" href="#book" onClick={() => setMenuOpen(false)} style={{ marginTop: 16, textAlign: "center", justifyContent: "center" }}>
              Book Now
            </Button>
          </div>
        ) : null}
      </div>
    </div>
  );
}

function SocialGlyph({ label, href, background, children }) {
  return (
    <a
      href={href}
      target="_blank"
      rel="noopener noreferrer"
      aria-label={label}
      style={{
        width: 36,
        height: 36,
        borderRadius: 8,
        background,
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        color: "#ffffff",
        textDecoration: "none",
        flexShrink: 0,
      }}
    >
      {children}
    </a>
  );
}

function InstagramGlyph() {
  return (
    <SocialGlyph
      label="Instagram"
      href="https://www.instagram.com/thevivaankarnal/"
      background="radial-gradient(circle at 30% 110%, #fdf497 0%, #fdf497 5%, #fd5949 45%, #d6249f 60%, #285AEB 90%)"
    >
      <svg width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="#ffffff" strokeWidth="1.8">
        <rect x="3" y="3" width="18" height="18" rx="5" />
        <circle cx="12" cy="12" r="4" />
        <circle cx="17.2" cy="6.8" r="1.1" fill="#ffffff" stroke="none" />
      </svg>
    </SocialGlyph>
  );
}

function FacebookGlyph() {
  return (
    <SocialGlyph label="Facebook" href="https://www.facebook.com/thevivaanresort/" background="#1877F2">
      <svg width="10" height="19" viewBox="0 0 10 19" fill="#ffffff">
        <path d="M6.5 19v-8.4H9l0.4-3H6.5V5.6c0-.87.24-1.46 1.5-1.46H9.5V1.44C9.2 1.4 8.2 1.3 7 1.3 4.6 1.3 3 2.77 3 5.3v2.3H0.4v3H3V19h3.5z" />
      </svg>
    </SocialGlyph>
  );
}

function YouTubeGlyph() {
  return (
    <SocialGlyph label="YouTube" href="https://www.youtube.com/@TheVivaanHotelResorts" background="#FF0000">
      <svg width="19" height="19" viewBox="0 0 24 24" fill="#ffffff">
        <path d="M21.6 7.2s-.21-1.49-.87-2.15c-.83-.87-1.76-.87-2.19-.92C15.44 4 12 4 12 4h-.01s-3.44 0-6.53.13c-.43.05-1.36.05-2.19.92C2.6 5.71 2.4 7.2 2.4 7.2S2.18 8.94 2.18 10.68v1.62c0 1.74.22 3.48.22 3.48s.21 1.49.87 2.15c.83.87 1.92.84 2.4.93 1.74.17 7.33.22 7.33.22s3.44-.01 6.53-.14c.43-.05 1.36-.05 2.19-.92.66-.66.87-2.15.87-2.15s.22-1.74.22-3.48v-1.62c0-1.74-.22-3.48-.22-3.48z" />
        <path d="M9.98 14.5V8.5l5.4 3-5.4 3z" fill="#FF0000" />
      </svg>
    </SocialGlyph>
  );
}

function LinkedInGlyph() {
  return (
    <SocialGlyph label="LinkedIn" href="https://www.linkedin.com/company/the-vivaan/?viewAsMember=true" background="#0A66C2">
      <svg width="17" height="17" viewBox="0 0 24 24" fill="#ffffff">
        <path d="M4.98 3.5C4.98 4.88 3.87 6 2.5 6S0 4.88 0 3.5 1.12 1 2.5 1 4.98 2.12 4.98 3.5zM.24 8.25h4.5V23h-4.5V8.25zM8.5 8.25h4.31v2.01h.06c.6-1.14 2.07-2.34 4.26-2.34 4.56 0 5.4 3 5.4 6.9V23h-4.5v-6.98c0-1.67-.03-3.81-2.32-3.81-2.33 0-2.69 1.82-2.69 3.7V23H8.5V8.25z" />
      </svg>
    </SocialGlyph>
  );
}

function SiteFooter() {
  const wrap = {
    position: "relative",
    backgroundColor: "var(--vivaan-black)",
    color: "var(--color-text-on-dark)",
    overflow: "hidden",
    fontFamily: "var(--font-serif)",
  };
  const inner = {
    position: "relative",
    zIndex: 1,
    padding: "var(--space-2xl) var(--space-xl) var(--space-lg)",
    display: "flex",
    flexDirection: "column",
    gap: "var(--space-xl)",
  };
  const watermark = {
    position: "absolute",
    right: "-40px",
    bottom: "-120px",
    fontSize: "560px",
    lineHeight: 1,
    fontWeight: 400,
    color: "rgba(255,255,255,0.04)",
    userSelect: "none",
    pointerEvents: "none",
  };
  const top = { display: "flex", justifyContent: "space-between", gap: "var(--space-xl)", flexWrap: "wrap" };
  const colTitle = { fontSize: 11, letterSpacing: "0.18em", textTransform: "uppercase", color: "rgba(255,255,255,0.5)", marginBottom: 16 };
  const linkStyle = {
    display: "block",
    fontSize: 14,
    color: "var(--color-text-on-dark)",
    textDecoration: "none",
    opacity: 0.85,
    marginBottom: 10,
  };
  const rule = {
    borderTop: "1px solid rgba(255,255,255,0.15)",
    paddingTop: "var(--space-sm)",
    display: "flex",
    justifyContent: "space-between",
    fontSize: 11,
    opacity: 0.55,
    letterSpacing: "0.05em",
    flexWrap: "wrap",
    gap: 12,
  };

  return (
    <footer style={wrap}>
      <div style={watermark}>V</div>
      <div style={inner}>
        <div style={top}>
          <div style={{ maxWidth: 320, display: "flex", flexDirection: "column", gap: 20 }}>
            <img src={VIVAAN_LOGO_SRC} alt="The Vivaan Hotel & Resort, Karnal" style={{ height: 96, width: "auto", alignSelf: "flex-start" }} />
            <BodyCopy dark style={{ fontSize: 14 }}>
              The Vivaan Hotel &amp; Resorts, NH-1, Karnal, Haryana, India.
            </BodyCopy>
            <div style={{ display: "flex", gap: 10 }}>
              <InstagramGlyph />
              <FacebookGlyph />
              <YouTubeGlyph />
              <LinkedInGlyph />
            </div>
          </div>

          <div>
            <div style={colTitle}>Explore</div>
            <a href="rooms.html" style={linkStyle}>Stay</a>
            <a href="dining.html" style={linkStyle}>Dining</a>
            <a href="wedding.html" style={linkStyle}>Wedding &amp; Events</a>
            <a href="corporate.html" style={linkStyle}>Meetings &amp; Conferences</a>
          </div>

          <div>
            <div style={colTitle}>Hotel</div>
            <a href="promotions.html" style={linkStyle}>Promotions</a>
            <a href="about.html" style={linkStyle}>About</a>
            <a href="#" style={linkStyle}>Blog</a>
            <a href="careers.html" style={linkStyle}>Careers</a>
          </div>

          <div>
            <div style={colTitle}>Contact</div>
            <a href="https://maps.app.goo.gl/aUTYwQJ4TrHUwURn8" target="_blank" rel="noopener noreferrer" style={linkStyle}>Get Directions</a>
            <a href="tel:+919896010000" style={linkStyle}>+91 98960 10000</a>
            <a href="tel:+917027710000" style={linkStyle}>+91 70277 10000</a>
            <a href="mailto:reservation@thevivaan.com" style={linkStyle}>reservation@thevivaan.com</a>
            <a href="mailto:info@thevivaan.com" style={linkStyle}>info@thevivaan.com</a>
          </div>
        </div>

        <div style={rule}>
          <span>&copy; {new Date().getFullYear()} The Vivaan Hotel &amp; Resorts. All rights reserved.</span>
          <span style={{ display: "flex", gap: 20 }}>
            <a href="#" style={{ color: "inherit", textDecoration: "none" }}>Privacy Policy</a>
            <a href="#" style={{ color: "inherit", textDecoration: "none" }}>Terms</a>
          </span>
        </div>
      </div>
    </footer>
  );
}

/* ---------------------------------------------------------------------- */
/* Page-header (for inner pages — a shorter hero band, not the full 100vh) */
/* ---------------------------------------------------------------------- */

function PageHeader({ eyebrow, parts, body, tone = "ink", images, video, vimeoId }) {
  return (
    <section style={{ position: "relative" }}>
      <SiteNav />
      {vimeoId ? (
        <div style={{ position: "relative", width: "100%", aspectRatio: "21 / 10", minHeight: 420, overflow: "hidden", background: "var(--vivaan-black)" }}>
          <iframe
            src={`https://player.vimeo.com/video/${vimeoId}?background=1&autoplay=1&loop=1&muted=1`}
            allow="autoplay; fullscreen"
            title="Hero video"
            style={{
              position: "absolute",
              top: "50%",
              left: "50%",
              width: "177.77vh",
              height: "100%",
              minWidth: "100%",
              minHeight: "56.25vw",
              transform: "translate(-50%, -50%)",
              border: "none",
              pointerEvents: "none",
            }}
          />
        </div>
      ) : video ? (
        <div style={{ position: "relative", width: "100%", aspectRatio: "21 / 10", minHeight: 420, overflow: "hidden", background: "var(--vivaan-black)" }}>
          <video
            src={video}
            autoPlay
            loop
            muted
            playsInline
            style={{ width: "100%", height: "100%", objectFit: "cover", display: "block" }}
          />
        </div>
      ) : images && images.length > 1 ? (
        <PhotoSlideshow images={images} ratio="21 / 10" style={{ minHeight: 420 }} holdMs={5000} fadeMs={1500} />
      ) : (
        <PhotoBlock tone={tone} ratio="21 / 10" style={{ minHeight: 420 }} />
      )}
      <div
        style={{
          position: "absolute",
          inset: 0,
          background: "linear-gradient(180deg, rgba(0,0,0,0.35) 0%, rgba(26,26,26,0.55) 100%)",
          display: "flex",
          alignItems: "flex-end",
        }}
      >
        <div style={{ padding: "var(--space-2xl) var(--space-xl)", maxWidth: 720, display: "flex", flexDirection: "column", gap: 20 }}>
          <EditorialHeading parts={parts} size={56} dark />
          {body ? <BodyCopy dark style={{ maxWidth: 480 }}>{body}</BodyCopy> : null}
        </div>
      </div>
      <style>{`
        @keyframes vivaan-scroll-cue {
          0%, 100% { transform: translateY(0); opacity: 0.55; }
          50% { transform: translateY(10px); opacity: 1; }
        }
        .vivaan-scroll-cue { animation: vivaan-scroll-cue 2.2s ease-in-out infinite; }
        @media (prefers-reduced-motion: reduce) {
          .vivaan-scroll-cue { animation: none; opacity: 0.8; }
        }
      `}</style>
      <div
        className="vivaan-scroll-cue"
        style={{
          position: "absolute",
          left: "50%",
          bottom: 28,
          transform: "translateX(-50%)",
          color: "var(--color-text-on-dark)",
          pointerEvents: "none",
        }}
        aria-hidden="true"
      >
        <svg width="22" height="34" viewBox="0 0 22 34" fill="none">
          <path d="M11 1v27" stroke="currentColor" strokeWidth="1.4" opacity="0.7" />
          <path d="M3 22l8 8 8-8" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
        </svg>
      </div>
    </section>
  );
}

/* ---------------------------------------------------------------------- */
/* Floating booking widget (persistent across pages)                      */
/* ---------------------------------------------------------------------- */

function FloatingBookButton() {
  const [visible, setVisible] = React.useState(false);

  React.useEffect(() => {
    const onScroll = () => setVisible(window.scrollY > window.innerHeight * 0.9);
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  if (!visible) return null;

  return (
    <a
      href="https://wa.me/919896010000"
      target="_blank"
      rel="noopener noreferrer"
      aria-label="Chat on WhatsApp"
      className="floating-book-btn"
      style={{
        position: "fixed",
        zIndex: 100,
        width: 64,
        height: 64,
        borderRadius: "50%",
        background: "#25D366",
        border: "3px solid #ffffff",
        boxShadow: "0 0 0 1px rgba(0,0,0,0.06), 0 8px 20px rgba(0,0,0,0.25), 0 0 24px rgba(255,255,255,0.55)",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        textDecoration: "none",
      }}
    >
      <svg width="32" height="32" viewBox="0 0 24 24" fill="#ffffff">
        <path d="M12.04 2C6.58 2 2.13 6.45 2.13 11.91c0 1.79.47 3.47 1.29 4.93L2 22l5.31-1.39a9.87 9.87 0 0 0 4.73 1.2h.01c5.46 0 9.9-4.45 9.9-9.91C21.96 6.45 17.5 2 12.04 2zm0 18.06h-.01a8.2 8.2 0 0 1-4.19-1.15l-.3-.18-3.15.82.84-3.07-.2-.32a8.14 8.14 0 0 1-1.26-4.35c0-4.5 3.66-8.17 8.17-8.17 2.18 0 4.23.85 5.78 2.4a8.13 8.13 0 0 1 2.39 5.78c0 4.5-3.67 8.17-8.17 8.17zm4.48-6.12c-.25-.12-1.45-.72-1.67-.8-.22-.08-.39-.12-.55.12-.16.25-.63.8-.78.96-.14.16-.29.18-.53.06-.25-.12-1.05-.39-2-1.23-.74-.66-1.24-1.48-1.39-1.72-.14-.25-.02-.38.11-.51.11-.11.25-.29.37-.43.12-.15.16-.25.25-.41.08-.16.04-.31-.02-.43-.06-.12-.55-1.33-.76-1.82-.2-.48-.4-.41-.55-.42-.14-.01-.31-.01-.47-.01a.9.9 0 0 0-.66.31c-.22.25-.86.85-.86 2.07 0 1.22.89 2.4 1.01 2.57.12.16 1.75 2.67 4.24 3.74.59.26 1.05.41 1.41.52.59.19 1.13.16 1.56.1.48-.07 1.45-.59 1.65-1.17.21-.57.21-1.06.14-1.17-.06-.11-.23-.17-.48-.29z" />
      </svg>
    </a>
  );
}

// Minimal line glyphs standing in for the brand's bespoke icon set (none
// supplied) — thin-stroke, single-color, matching the DS's icon convention.
function LayoutIcon({ name }) {
  const common = { width: 40, height: 40, viewBox: "0 0 40 40", fill: "none", stroke: "var(--vivaan-gold)", strokeWidth: 1.4 };
  switch (name) {
    case "Theatre":
      return (
        <svg {...common}>
          {[10, 16, 22, 28].map((y) => <line key={y} x1="4" y1={y} x2="36" y2={y} />)}
          <path d="M4 34 L20 4 L36 34" />
        </svg>
      );
    case "U Shape":
      return (
        <svg {...common}>
          <path d="M8 8 V28 H32 V8" />
        </svg>
      );
    case "Box Setup":
      return (
        <svg {...common}>
          <rect x="6" y="8" width="12" height="9" /><rect x="22" y="8" width="12" height="9" />
          <rect x="6" y="23" width="12" height="9" /><rect x="22" y="23" width="12" height="9" />
        </svg>
      );
    case "Cluster":
      return (
        <svg {...common}>
          <circle cx="13" cy="14" r="6" /><circle cx="27" cy="14" r="6" /><circle cx="20" cy="28" r="6" />
        </svg>
      );
    case "Round Table":
    default:
      return (
        <svg {...common}>
          <circle cx="20" cy="20" r="14" /><circle cx="20" cy="20" r="4" />
        </svg>
      );
  }
}

// Auto-scrolling "coverflow" filmstrip: images drift past continuously,
// the one nearest center scales up, and the whole thing can be grabbed
// and dragged to scrub back and forth (pauses auto-scroll while dragging).
// Positions are computed cumulatively each frame (not fixed flex gaps) so
// the visual gap between card edges stays constant even as cards scale.
function EstateFilmstrip({ tones }) {
  const containerRef = React.useRef(null);
  const itemRefs = React.useRef([]);
  const stateRef = React.useRef({ scrollX: 0, dragging: false, startX: 0, startScrollX: 0, lastTime: null, resumeAt: 0 });

  const ITEM_WIDTH = 220;
  const GAP = 20;
  const STEP = ITEM_WIDTH + GAP;
  const SPEED = 36; // px per second
  const RANGE = 3; // falloff range, in card-widths

  const items = React.useMemo(() => [...tones, ...tones, ...tones], [tones]);
  const singleSetWidth = tones.length * STEP;
  const n = items.length;

  React.useEffect(() => {
    stateRef.current.scrollX = singleSetWidth;
    let raf;
    function frame(time) {
      const st = stateRef.current;
      if (st.lastTime == null) st.lastTime = time;
      const dt = Math.min((time - st.lastTime) / 1000, 0.05);
      st.lastTime = time;
      if (!st.dragging && time > st.resumeAt) {
        st.scrollX += SPEED * dt;
      }
      if (st.scrollX >= singleSetWidth * 2) st.scrollX -= singleSetWidth;
      if (st.scrollX < 0) st.scrollX += singleSetWidth;

      const centerIndex = st.scrollX / STEP;

      // Pass 1: scale/ease for every card, from its index-distance to center.
      const scale = new Array(n);
      const eased = new Array(n);
      for (let i = 0; i < n; i++) {
        const norm = Math.min(Math.abs(i - centerIndex) / RANGE, 1);
        const e = 0.5 - 0.5 * Math.cos(norm * Math.PI);
        eased[i] = e;
        scale[i] = 1 - e * 0.5;
      }

      // Pass 2: cumulative centers, keeping a constant GAP between edges
      // regardless of each neighbour's scale.
      const centers = new Array(n);
      centers[0] = 0;
      for (let i = 1; i < n; i++) {
        centers[i] = centers[i - 1] + (ITEM_WIDTH * scale[i - 1]) / 2 + GAP + (ITEM_WIDTH * scale[i]) / 2;
      }

      const lo = Math.max(0, Math.min(n - 2, Math.floor(centerIndex)));
      const frac = centerIndex - lo;
      const virtualCenter = centers[lo] + (centers[lo + 1] - centers[lo]) * frac;
      const containerWidth = containerRef.current ? containerRef.current.offsetWidth : 0;
      const shift = containerWidth / 2 - virtualCenter;

      itemRefs.current.forEach((el, i) => {
        if (!el) return;
        const finalX = centers[i] + shift - ITEM_WIDTH / 2;
        const lift = -(1 - eased[i]) * 16;
        el.style.transform = `translate(${finalX}px, -50%) translateY(${lift}px) scale(${scale[i]})`;
        el.style.zIndex = String(1000 - Math.round(Math.abs(i - centerIndex) * 10));
        el.style.opacity = String(1 - eased[i] * 0.25);
      });
      raf = requestAnimationFrame(frame);
    }
    raf = requestAnimationFrame(frame);
    return () => cancelAnimationFrame(raf);
  }, [singleSetWidth, n]);

  function handlePointerDown(e) {
    const st = stateRef.current;
    st.dragging = true;
    st.startX = e.clientX;
    st.startScrollX = st.scrollX;
    if (containerRef.current) containerRef.current.style.cursor = "grabbing";
    e.currentTarget.setPointerCapture(e.pointerId);
  }
  function handlePointerMove(e) {
    const st = stateRef.current;
    if (!st.dragging) return;
    const dx = e.clientX - st.startX;
    st.scrollX = st.startScrollX - dx;
  }
  function handlePointerUp() {
    const st = stateRef.current;
    st.dragging = false;
    st.lastTime = null;
    st.resumeAt = performance.now() + 900;
    if (containerRef.current) containerRef.current.style.cursor = "grab";
  }

  return (
    <div
      ref={containerRef}
      onPointerDown={handlePointerDown}
      onPointerMove={handlePointerMove}
      onPointerUp={handlePointerUp}
      onPointerCancel={handlePointerUp}
      style={{
        position: "relative",
        height: 470,
        overflow: "hidden",
        cursor: "grab",
        touchAction: "pan-y",
        userSelect: "none",
        background: "var(--vivaan-black)",
        maskImage: "linear-gradient(90deg, transparent 0%, black 8%, black 92%, transparent 100%)",
        WebkitMaskImage: "linear-gradient(90deg, transparent 0%, black 8%, black 92%, transparent 100%)",
      }}
    >
      {items.map((tone, i) => (
        <div
          key={i}
          ref={(el) => (itemRefs.current[i] = el)}
          style={{
            position: "absolute",
            left: 0,
            top: "50%",
            width: ITEM_WIDTH,
            pointerEvents: "none",
            willChange: "transform",
          }}
        >
          <PhotoBlock tone={tone} ratio="4 / 5" style={{ borderRadius: 16 }} />
          <div
            style={{
              marginTop: 6,
              height: 56,
              borderRadius: 16,
              background:
                tone === "gold" ? "var(--vivaan-gold)" :
                tone === "taupe" ? "var(--vivaan-taupe)" :
                tone === "ink" ? "var(--vivaan-black)" : "var(--vivaan-cream)",
              opacity: 0.28,
              maskImage: "linear-gradient(to bottom, black, transparent)",
              WebkitMaskImage: "linear-gradient(to bottom, black, transparent)",
            }}
          />
        </div>
      ))}
    </div>
  );
}



function EnquiryForm({ title = "Send an Enquiry", showScheduleOptions = false }) {
  const { FormField } = window.VivaanDesignSystem_b1c8ba;
  const [sent, setSent] = React.useState(false);
  const [schedule, setSchedule] = React.useState(null);
  const [name, setName] = React.useState("");
  const [phone, setPhone] = React.useState("");
  const [email, setEmail] = React.useState("");
  const [guestCount, setGuestCount] = React.useState(100);
  const [errors, setErrors] = React.useState({});
  const wrap = { backgroundColor: "var(--vivaan-cream)", padding: "var(--space-xl)", display: "flex", flexDirection: "column", gap: "var(--space-md)", width: "100%", maxWidth: 480, boxSizing: "border-box" };
  const scheduleRow = { display: "flex", gap: 12, flexWrap: "wrap" };
  const scheduleBtn = (name) => ({
    flex: 1,
    padding: "12px 16px",
    fontFamily: "var(--font-serif)",
    fontSize: 12,
    letterSpacing: "0.1em",
    textTransform: "uppercase",
    textAlign: "center",
    border: schedule === name ? "1px solid var(--vivaan-gold)" : "1px solid var(--color-border-hairline)",
    color: schedule === name ? "var(--vivaan-gold)" : "var(--color-text-primary)",
    background: "transparent",
    cursor: "pointer",
  });
  const errorNote = { fontFamily: "var(--font-serif)", fontSize: 11, letterSpacing: "0.06em", color: "var(--vivaan-gold)", marginTop: -4 };

  const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.(com|in|co)$/i;

  function handleNameChange(v) {
    setName(v.replace(/[^A-Za-z\s]/g, ""));
  }
  function handlePhoneChange(v) {
    setPhone(v.replace(/[^0-9+\-]/g, ""));
  }

  function handleSubmit() {
    const nextErrors = {};
    if (!name.trim()) nextErrors.name = "Required";
    if (!phone.trim()) nextErrors.phone = "Required";
    else if (!/^[0-9+\-]+$/.test(phone)) nextErrors.phone = "Numbers, + and - only";
    if (email.trim() && !EMAIL_PATTERN.test(email.trim())) nextErrors.email = "Enter a valid email (.com, .in or .co)";
    if (!guestCount || guestCount < 1) nextErrors.guestCount = "Required";
    setErrors(nextErrors);
    if (Object.keys(nextErrors).length === 0) setSent(true);
  }

  if (sent) {
    return (
      <div style={wrap}>
        <SectionLabel>Thank You</SectionLabel>
        <BodyCopy>Your enquiry has been received. Our events team will be in touch within 24 hours.</BodyCopy>
      </div>
    );
  }

  return (
    <div style={wrap}>
      <SectionLabel>{title}</SectionLabel>
      <div className="form-row">
        <div>
          <FormField
            label="Full Name *"
            type="text"
            placeholder="Your name"
            value={name}
            onChange={handleNameChange}
          />
          {errors.name ? <div style={errorNote}>{errors.name}</div> : null}
        </div>
        <div>
          <FormField
            label="Phone *"
            type="text"
            placeholder="+91"
            value={phone}
            onChange={handlePhoneChange}
          />
          {errors.phone ? <div style={errorNote}>{errors.phone}</div> : null}
        </div>
      </div>
      <div>
        <FormField label="Email" type="email" placeholder="you@email.com" value={email} onChange={setEmail} />
        {errors.email ? <div style={errorNote}>{errors.email}</div> : null}
      </div>
      <div className="form-row">
        <FormField label="Preferred Date" type="date" />
        <div>
          <FormField label="Guest Count *" type="counter" value={guestCount} onChange={setGuestCount} min={0} max={2000} />
          {errors.guestCount ? <div style={errorNote}>{errors.guestCount}</div> : null}
        </div>
      </div>
      <FormField label="Tell us about your event" type="text" placeholder="A few details..." />
      {showScheduleOptions ? (
        <div>
          <div style={{ fontFamily: "var(--font-serif)", fontSize: "var(--text-form-label-size)", letterSpacing: "var(--text-form-label-letter-spacing)", textTransform: "uppercase", color: "var(--color-text-secondary)", marginBottom: 8 }}>
            Prefer to connect first?
          </div>
          <div style={scheduleRow}>
            <button style={scheduleBtn("visit")} onClick={() => setSchedule("visit")}>Site Visit</button>
            <button style={scheduleBtn("meet")} onClick={() => setSchedule("meet")}>Google Meet</button>
          </div>
        </div>
      ) : null}
      <Button variant="filled-gold" onClick={handleSubmit} style={{ marginTop: 8 }}>Submit Enquiry</Button>
    </div>
  );
}

Object.assign(window, {
  PhotoBlock,
  PhotoSlideshow,
  HoverImageSwap,
  LayoutIcon,
  EnquiryForm,
  EstateFilmstrip,
  SectionLabel,
  EditorialHeading,
  BodyCopy,
  SiteNav,
  SiteFooter,
  PageHeader,
  FloatingBookButton,
  NAV_LINKS,
});
