/* shared.jsx — Nav, Footer, palettes, ornaments, CTA, hooks
 * William R. Sherry · River Song Heart and Spirit
 * Loaded BEFORE each page's own .jsx file.
 */

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

/* External booking widget — William's live booking URL */
const BOOKING_URL = "https://api.leadconnectorhq.com/widget/booking/2mMvEkivWTnblNaByTxv";

/* Contact */
const EMAIL = "riversongheartandspirit@gmail.com";

/* Thematic imagery (Unsplash, people-free) chosen for William's story, in
 * place of portraits: his intake upload was a family photo of a child, which
 * should not go on a public site. Swap in real photos of him if he sends them. */
const HERO_IMAGE_URL = "https://images.unsplash.com/photo-1528184039930-bd03972bd974?q=80&w=1400&auto=format&fit=crop";          /* River Song: creek at golden hour */
const CHAIRS_IMAGE_URL = "https://images.unsplash.com/photo-1746537717492-5a8fffc0c43c?q=80&w=1200&auto=format&fit=crop";        /* nearly 50 years, still talking: two chairs by the fire at the water */
const MORNING_RIVER_IMAGE_URL = "https://images.unsplash.com/photo-1759434192768-fe3facebd5f6?q=80&w=1200&auto=format&fit=crop"; /* slow down and listen: still river, misty morning */
const BRIDGE_IMAGE_URL = "https://images.unsplash.com/photo-1625863057797-015fef6be7ea?q=80&w=1200&auto=format&fit=crop";        /* Mike & Kim: a bridge over troubled water */
const SUNRISE_IMAGE_URL = "https://images.unsplash.com/photo-1760019185488-907418046670?q=80&w=1000&auto=format&fit=crop";       /* Monday morning: mist lifting off the river at sunrise */

/* ============================================================
 * PALETTES — Sage Studio is default (per intake template preference "Sage")
 * ============================================================ */
const PALETTES = {
  sageStudio: {
    name: "Sage Studio",
    swatches: ["#EFF1E8", "#2E3A29", "#6B8E5A", "#8FA67D"],
    vars: {
      "--cream": "#EFF1E8", "--cream-2": "#E2E7D6", "--cream-3": "#D2DAC0",
      "--walnut": "#2E3A29", "--walnut-soft": "#46554A",
      "--terracotta": "#6B8E5A", "--terracotta-deep": "#547047",
      "--sage": "#8FA67D", "--sage-soft": "#B0C09D",
      "--ink": "#1F2818",
      "--rule": "rgba(46, 58, 41, 0.18)",
      "--rule-strong": "rgba(46, 58, 41, 0.32)",
    },
  },
  slate: {
    name: "Slate",
    swatches: ["#EEF1F5", "#1F2937", "#5B7A95", "#6B7F94"],
    vars: {
      "--cream": "#EEF1F5", "--cream-2": "#E2E7ED", "--cream-3": "#D2DAE3",
      "--walnut": "#1F2937", "--walnut-soft": "#475569",
      "--terracotta": "#5B7A95", "--terracotta-deep": "#46637D",
      "--sage": "#6B7F94", "--sage-soft": "#94A4B7",
      "--ink": "#0F172A",
      "--rule": "rgba(31, 41, 55, 0.18)",
      "--rule-strong": "rgba(31, 41, 55, 0.32)",
    },
  },
  slateMidnight: {
    name: "Slate Midnight",
    swatches: ["#E8ECF1", "#0F172A", "#475A75", "#5C6F87"],
    vars: {
      "--cream": "#E8ECF1", "--cream-2": "#DCE2EA", "--cream-3": "#C8D1DD",
      "--walnut": "#0F172A", "--walnut-soft": "#334155",
      "--terracotta": "#475A75", "--terracotta-deep": "#34465E",
      "--sage": "#5C6F87", "--sage-soft": "#8694A7",
      "--ink": "#070C16",
      "--rule": "rgba(15, 23, 42, 0.18)",
      "--rule-strong": "rgba(15, 23, 42, 0.32)",
    },
  },
  warmDevotional: {
    name: "Warm Devotional",
    swatches: ["#F5EFE6", "#3D2E1F", "#A66B3F", "#7A8B6F"],
    vars: {
      "--cream": "#F5EFE6", "--cream-2": "#EFE7D8", "--cream-3": "#E8DDC8",
      "--walnut": "#3D2E1F", "--walnut-soft": "#5A4838",
      "--terracotta": "#A66B3F", "--terracotta-deep": "#8C552F",
      "--sage": "#7A8B6F", "--sage-soft": "#9DA992",
      "--ink": "#2A1F14",
      "--rule": "rgba(61, 46, 31, 0.18)",
      "--rule-strong": "rgba(61, 46, 31, 0.32)",
    },
  },
  desertBloom: {
    name: "Desert Bloom",
    swatches: ["#F8F4ED", "#2C2825", "#B85C3D", "#D4A574"],
    vars: {
      "--cream": "#F8F4ED", "--cream-2": "#F0E8D8", "--cream-3": "#E5D6BE",
      "--walnut": "#2C2825", "--walnut-soft": "#4A4239",
      "--terracotta": "#B85C3D", "--terracotta-deep": "#9B4A2E",
      "--sage": "#7E8B6E", "--sage-soft": "#A0AB91",
      "--ink": "#1F1B17",
      "--rule": "rgba(44, 40, 37, 0.18)",
      "--rule-strong": "rgba(44, 40, 37, 0.32)",
    },
  },
  oliveAndIvory: {
    name: "Olive & Ivory",
    swatches: ["#EFE8DC", "#3A2E26", "#9B5D3F", "#7B7A4F"],
    vars: {
      "--cream": "#EFE8DC", "--cream-2": "#E5DCC8", "--cream-3": "#D8CCB2",
      "--walnut": "#3A2E26", "--walnut-soft": "#564539",
      "--terracotta": "#9B5D3F", "--terracotta-deep": "#80482D",
      "--sage": "#7B7A4F", "--sage-soft": "#9C9B72",
      "--ink": "#221B14",
      "--rule": "rgba(58, 46, 38, 0.20)",
      "--rule-strong": "rgba(58, 46, 38, 0.34)",
    },
  },
  morningChapel: {
    name: "Morning Chapel",
    swatches: ["#FAF6F0", "#1F1A14", "#C19A6B", "#6B5B47"],
    vars: {
      "--cream": "#FAF6F0", "--cream-2": "#F2EBDD", "--cream-3": "#E8DDC4",
      "--walnut": "#1F1A14", "--walnut-soft": "#3A322A",
      "--terracotta": "#C19A6B", "--terracotta-deep": "#A37E51",
      "--sage": "#6B5B47", "--sage-soft": "#8C7A66",
      "--ink": "#1A1510",
      "--rule": "rgba(31, 26, 20, 0.16)",
      "--rule-strong": "rgba(31, 26, 20, 0.30)",
    },
  },
};

function applyPalette(key) {
  const pal = PALETTES[key] || PALETTES.sageStudio;
  const root = document.documentElement;
  Object.entries(pal.vars).forEach(([k, v]) => root.style.setProperty(k, v));
}

/* ============================================================
 * Ornaments
 * ============================================================ */
function CrossMark({ size = 14, color = "currentColor" }) {
  return (
    <svg width={size} height={size} viewBox="0 0 14 14" aria-hidden="true">
      <rect x="6.2" y="0" width="1.6" height="14" fill={color} />
      <rect x="0" y="4.4" width="14" height="1.6" fill={color} />
    </svg>
  );
}
function DiamondMark({ size = 10, color = "currentColor" }) {
  return (
    <svg width={size} height={size} viewBox="0 0 10 10" aria-hidden="true">
      <rect x="2" y="2" width="6" height="6" transform="rotate(45 5 5)" fill={color} />
    </svg>
  );
}
function CircleMark({ size = 10, color = "currentColor", filled = true }) {
  return (
    <svg width={size} height={size} viewBox="0 0 10 10" aria-hidden="true">
      <circle cx="5" cy="5" r="4" fill={filled ? color : "none"} stroke={color} strokeWidth="1" />
    </svg>
  );
}

/* RiverMark — placeholder logo until William sends one. Three river currents
 * that double as a musical staff ("River Song"); the middle current carries
 * the accent color. Pure currentColor strokes, so it works on light and dark. */
function RiverMark({ size = 44, color = "currentColor", accent }) {
  const a = accent || color;
  return (
    <svg className="rivermark" width={size} height={size} viewBox="0 0 48 48" aria-hidden="true" style={{ display: "block", flexShrink: 0 }}>
      <circle cx="24" cy="24" r="22.5" fill="none" stroke={color} strokeWidth="1.4" />
      <path d="M11 16.5 C14.5 13, 18 20, 24 16.5 S33.5 20, 37 16.5" fill="none" stroke={color} strokeWidth="1.6" strokeLinecap="round" />
      <path d="M8 24 C12.5 20, 17.5 28, 24 24 S35.5 28, 40 24" fill="none" stroke={a} strokeWidth="2.4" strokeLinecap="round" />
      <path d="M11 31.5 C14.5 28, 18 35, 24 31.5 S33.5 35, 37 31.5" fill="none" stroke={color} strokeWidth="1.6" strokeLinecap="round" />
    </svg>
  );
}

/* ============================================================
 * Nav
 * ============================================================ */
function Nav({ current = "" }) {
  const [scrolled, setScrolled] = useState(false);
  const [mobileOpen, setMobileOpen] = useState(false);

  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 24);
    window.addEventListener("scroll", onScroll);
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  useEffect(() => {
    const prev = document.body.style.overflow;
    document.body.style.overflow = mobileOpen ? "hidden" : prev || "";
    return () => { document.body.style.overflow = prev || ""; };
  }, [mobileOpen]);

  const links = [
    { label: "About", href: "about.html", key: "about" },
    { label: "Work With Me", href: "work-with-me.html", key: "work" },
    { label: "Stories", href: "testimonials.html", key: "stories" },
    { label: "FAQ", href: "faq.html", key: "faq" },
    { label: "Contact", href: "contact.html", key: "contact" },
  ];

  const Logo = () => (
    <a href="index.html" style={{ display: "flex", alignItems: "center", gap: 12 }} aria-label="River Song Heart and Spirit, home">
      <RiverMark size={44} color="var(--walnut)" accent="var(--terracotta)" />
      <span style={{ display: "flex", flexDirection: "column", lineHeight: 1.1 }}>
        <span className="display" style={{ fontSize: 19, fontWeight: 600, color: "var(--walnut)" }}>
          William Sherry
        </span>
        <span className="smallcaps" style={{ color: "var(--terracotta)", fontSize: 9 }}>
          river song · heart &amp; spirit
        </span>
      </span>
    </a>
  );

  return (
    <nav
      style={{
        position: "sticky",
        top: 0,
        zIndex: 50,
        background: scrolled ? "var(--cream)" : "transparent",
        borderBottom: scrolled ? "1px solid var(--rule)" : "1px solid transparent",
        transition: "background 0.3s, border-color 0.3s",
        backdropFilter: scrolled ? "blur(8px)" : "none",
      }}
    >
      <div
        style={{
          maxWidth: 1320,
          margin: "0 auto",
          padding: "20px clamp(28px, 6vw, 96px)",
          display: "flex",
          alignItems: "center",
          justifyContent: "space-between",
          gap: 32,
        }}
      >
        <Logo />

        <div className="nav-desktop-links grotesk" style={{ display: "flex", alignItems: "center", gap: 28 }}>
          {links.map((l) => {
            const active = l.key === current;
            return (
              <a
                key={l.label}
                href={l.href}
                style={{
                  fontSize: 14,
                  color: active ? "var(--terracotta)" : "var(--walnut-soft)",
                  fontWeight: active ? 500 : 400,
                  position: "relative",
                  paddingBottom: 2,
                  borderBottom: active ? "1px solid var(--terracotta)" : "1px solid transparent",
                }}
                onMouseEnter={(e) => (e.currentTarget.style.color = "var(--terracotta)")}
                onMouseLeave={(e) =>
                  (e.currentTarget.style.color = active ? "var(--terracotta)" : "var(--walnut-soft)")
                }
              >
                {l.label}
              </a>
            );
          })}
          <a href={BOOKING_URL} target="_blank" rel="noopener noreferrer" className="btn btn-primary" style={{ padding: "12px 20px", fontSize: 13 }}>
            Book a Call <span className="arrow">→</span>
          </a>
        </div>

        <button
          type="button"
          className="nav-hamburger"
          aria-label="Open menu"
          aria-expanded={mobileOpen}
          onClick={() => setMobileOpen(true)}
        >
          <svg width="20" height="14" viewBox="0 0 20 14" aria-hidden="true">
            <rect x="0" y="0"  width="20" height="1.6" fill="currentColor" />
            <rect x="0" y="6.2" width="20" height="1.6" fill="currentColor" />
            <rect x="0" y="12.4" width="20" height="1.6" fill="currentColor" />
          </svg>
        </button>
      </div>

      {mobileOpen && (
        <div className="nav-mobile-drawer" role="dialog" aria-modal="true">
          <div className="nav-mobile-head">
            <Logo />
            <button
              type="button"
              className="nav-hamburger"
              aria-label="Close menu"
              onClick={() => setMobileOpen(false)}
              style={{ display: "inline-flex" }}
            >
              <svg width="18" height="18" viewBox="0 0 18 18" aria-hidden="true">
                <rect x="-1" y="8.2" width="20" height="1.6" fill="currentColor" transform="rotate(45 9 9)" />
                <rect x="-1" y="8.2" width="20" height="1.6" fill="currentColor" transform="rotate(-45 9 9)" />
              </svg>
            </button>
          </div>

          <div className="nav-mobile-links">
            {links.map((l) => {
              const active = l.key === current;
              return (
                <a
                  key={l.label}
                  href={l.href}
                  className={active ? "active" : ""}
                  onClick={() => setMobileOpen(false)}
                >
                  {l.label}
                  <span style={{ color: "var(--terracotta)", fontSize: 14 }}>→</span>
                </a>
              );
            })}
          </div>

          <a
            href={BOOKING_URL}
            target="_blank"
            rel="noopener noreferrer"
            className="btn btn-primary nav-mobile-cta"
            onClick={() => setMobileOpen(false)}
          >
            Book a Call <span className="arrow">→</span>
          </a>
        </div>
      )}
    </nav>
  );
}

/* ============================================================
 * Universal CTA block (used at bottom of every page)
 * ============================================================ */
function CTA({
  headline = "Tired, and not sure why?",
  headlineItalic = "Let's talk about it.",
  eyebrow = "✦ Your next step · free 30-min Riverside Chat",
  checklist,
}) {
  const defaultList = [
    "Why you're so tired, even when you can't put your finger on the reason",
    "Which lies you've been believing about yourself, and whether Scripture backs up a single one",
    "What you want most for this season: your walk with God, your marriage, your purpose",
    "Whether the Wherever You Go 1:1 journey is the right fit, answered honestly",
  ];
  const list = checklist || defaultList;

  return (
    <section
      style={{
        padding: "clamp(80px, 10vw, 140px) clamp(28px, 6vw, 96px)",
        background: "var(--terracotta)",
        color: "var(--cream)",
      }}
    >
      <div style={{ maxWidth: 1320, margin: "0 auto" }}>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 80, alignItems: "start" }}>
          <div>
            <div className="smallcaps" style={{ color: "var(--cream)", opacity: 0.85, marginBottom: 20 }}>
              {eyebrow}
            </div>
            <h2
              className="display"
              style={{
                fontSize: "clamp(48px, 6.4vw, 96px)",
                lineHeight: 0.95,
                color: "var(--cream)",
                fontWeight: 500,
                marginBottom: 32,
              }}
            >
              {headline}{" "}
              <span style={{ fontStyle: "italic", fontFamily: "'Source Serif 4', serif", fontWeight: 300 }}>
                {headlineItalic}
              </span>
            </h2>

            <p style={{ fontSize: 19, lineHeight: 1.55, maxWidth: 460, marginBottom: 36, color: "rgba(239,241,232,0.9)" }}>
              Book a free 30-minute Riverside Chat. You talk, I listen, and together we see whether
              walking this stretch of the river side by side is the right next step. No script, no
              pressure, no judgment. The Lord is already with you wherever you go. This is just a
              conversation.
            </p>

            <div style={{ display: "flex", gap: 14, flexWrap: "wrap" }}>
              <a href={BOOKING_URL} target="_blank" rel="noopener noreferrer" className="btn" style={{ background: "var(--cream)", color: "var(--walnut)" }}>
                Book a Free Call <span className="arrow">→</span>
              </a>
              <a
                href="contact.html"
                className="btn"
                style={{ background: "transparent", color: "var(--cream)", border: "1px solid rgba(239,241,232,0.5)" }}
              >
                Send a Message
              </a>
            </div>
          </div>

          <div>
            <div style={{ background: "var(--cream)", color: "var(--walnut)", padding: "36px 36px 32px" }}>
              <div className="smallcaps" style={{ color: "var(--terracotta)", marginBottom: 18 }}>
                On the call we'll explore
              </div>
              <ul style={{ listStyle: "none", display: "flex", flexDirection: "column", gap: 18 }}>
                {list.map((c, i) => (
                  <li key={i} style={{ display: "flex", gap: 14, alignItems: "flex-start" }}>
                    <span className="mono" style={{ fontSize: 11, color: "var(--terracotta)", marginTop: 6, minWidth: 22 }}>
                      0{i + 1}
                    </span>
                    <span style={{ fontSize: 16, lineHeight: 1.45, color: "var(--walnut)" }}>{c}</span>
                  </li>
                ))}
              </ul>
              <div
                style={{
                  marginTop: 28,
                  paddingTop: 22,
                  borderTop: "1px solid var(--rule)",
                  fontStyle: "italic",
                  fontFamily: "'Source Serif 4', serif",
                  fontSize: 15,
                  color: "var(--walnut-soft)",
                  lineHeight: 1.5,
                }}
              >
                "You'll get a listening ear that won't run. No judgment, full confidentiality, and
                you set the direction. If I'm not the right coach for you, I'll tell you so."
              </div>
            </div>

            <div style={{ marginTop: 18, display: "flex", alignItems: "center", gap: 14, color: "rgba(239,241,232,0.85)" }}>
              <CrossMark size={11} color="var(--cream)" />
              <span className="serif-italic" style={{ fontSize: 16 }}>
                Romans 5:20 · "Where sin increased, grace abounded all the more."
              </span>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ============================================================
 * Footer
 * ============================================================ */
function Footer() {
  return (
    <footer
      style={{
        background: "var(--walnut)",
        color: "var(--cream)",
        padding: "clamp(60px, 7vw, 96px) clamp(28px, 6vw, 96px) 36px",
      }}
    >
      <div style={{ maxWidth: 1320, margin: "0 auto" }}>
        <div
          style={{
            display: "grid",
            gridTemplateColumns: "1.6fr 1fr 1fr 1fr",
            gap: 48,
            paddingBottom: 56,
            borderBottom: "1px solid rgba(239,241,232,0.15)",
          }}
        >
          <div>
            <div style={{ display: "flex", alignItems: "center", gap: 14, marginBottom: 18 }}>
              <RiverMark size={48} color="var(--cream)" accent="var(--sage-soft)" />
              <div className="display" style={{ fontSize: 24, fontWeight: 600 }}>
                William Sherry
              </div>
            </div>
            <div className="smallcaps" style={{ color: "var(--sage-soft)", marginBottom: 22 }}>
              River Song Heart and Spirit · Christian life coaching
            </div>
            <p className="serif-italic" style={{ fontSize: 18, lineHeight: 1.45, color: "rgba(239,241,232,0.75)", maxWidth: 380 }}>
              For tired believers who need to know God loves them for who they are, not what they do.
              A listening ear, a lot of grace, and every lie held up to Scripture.
            </p>
          </div>

          {[
            { title: "Navigate", links: [["Home", "index.html"], ["About", "about.html"], ["Work With Me", "work-with-me.html"], ["Stories", "testimonials.html"], ["FAQ", "faq.html"], ["Contact", "contact.html"], ["Book a Call", BOOKING_URL]] },
            { title: "River Song", links: [["1:1 Coaching · Wherever You Go", "work-with-me.html"], ["Couples Group · Learning to Talk Again", "work-with-me.html"], ["Self-Paced · Monday Morning", "work-with-me.html"], ["Email William", `mailto:${EMAIL}`]] },
            { title: "Legal", links: [["Privacy Policy", "legal.html"], ["Terms of Service", "legal.html"], ["Coaching Disclaimer", "legal.html"], ["Refund Policy", "legal.html"]] },
          ].map((col) => (
            <div key={col.title}>
              <div className="smallcaps" style={{ color: "var(--sage-soft)", marginBottom: 20 }}>
                {col.title}
              </div>
              <ul style={{ listStyle: "none", display: "flex", flexDirection: "column", gap: 10 }}>
                {col.links.map(([label, href]) => {
                  const external = /^https?:\/\//.test(href);
                  return (
                    <li key={label}>
                      <a
                        href={href}
                        {...(external ? { target: "_blank", rel: "noopener noreferrer" } : {})}
                        style={{ fontSize: 15, color: "rgba(239,241,232,0.85)" }}
                      >
                        {label}
                      </a>
                    </li>
                  );
                })}
              </ul>
            </div>
          ))}
        </div>

        <div
          style={{
            display: "flex",
            justifyContent: "space-between",
            alignItems: "center",
            paddingTop: 30,
            color: "rgba(239,241,232,0.55)",
            fontSize: 13,
            flexWrap: "wrap",
            gap: 16,
          }}
        >
          <div>© 2026 William R. Sherry · River Song Heart and Spirit. All rights reserved.</div>
          <div className="serif-italic" style={{ fontSize: 14 }}>
            Psalm 46:4 · "There is a river whose streams make glad the city of God."
          </div>
          <div style={{ display: "flex", gap: 18 }}>
            <a href="legal.html" style={{ color: "rgba(239,241,232,0.55)" }}>Privacy</a>
            <a href="legal.html" style={{ color: "rgba(239,241,232,0.55)" }}>Terms</a>
          </div>
        </div>
      </div>
    </footer>
  );
}

/* ============================================================
 * Page-level palette tweaks panel
 * ============================================================ */
const SHARED_TWEAK_DEFAULTS = { palette: "sageStudio" };

function PaletteTweaksPanel() {
  const [tweaks, setTweak] = useTweaks(SHARED_TWEAK_DEFAULTS);
  useEffect(() => { applyPalette(tweaks.palette); }, [tweaks.palette]);

  return (
    <TweaksPanel title="Tweaks">
      <TweakSection title="Palette">
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          {Object.entries(PALETTES).map(([key, p]) => (
            <button
              key={key}
              onClick={() => setTweak("palette", key)}
              style={{
                display: "flex", alignItems: "center", gap: 12, padding: "10px 12px",
                background: tweaks.palette === key ? "rgba(0,0,0,0.05)" : "transparent",
                border: tweaks.palette === key ? "1px solid rgba(0,0,0,0.25)" : "1px solid rgba(0,0,0,0.1)",
                borderRadius: 6, cursor: "pointer", textAlign: "left",
                fontFamily: "inherit", color: "inherit",
              }}
            >
              <div style={{ display: "flex", borderRadius: 4, overflow: "hidden", flexShrink: 0 }}>
                {p.swatches.map((c, i) => (
                  <div key={i} style={{ width: 16, height: 24, background: c }} />
                ))}
              </div>
              <div style={{ fontSize: 13, fontWeight: 500 }}>{p.name}</div>
              {tweaks.palette === key && (
                <div style={{ marginLeft: "auto", fontSize: 11, opacity: 0.6 }}>active</div>
              )}
            </button>
          ))}
        </div>
      </TweakSection>
    </TweaksPanel>
  );
}

/* ============================================================
 * Stripe placeholder (used when photos aren't provided)
 * ============================================================ */
function Placeholder({ label = "image", style = {}, src, alt, objectPosition, ...rest }) {
  if (src) {
    const { aspectRatio, width, height, borderRadius, position, inset, top, left, right, bottom, marginTop, ...frameRest } = style || {};
    const frameStyle = {
      position: position || (inset !== undefined || top !== undefined ? "absolute" : "relative"),
      inset, top, left, right, bottom,
      width: width ?? (inset !== undefined ? undefined : "100%"),
      height,
      aspectRatio,
      borderRadius,
      marginTop,
      overflow: "hidden",
      background: "var(--cream-2)",
      ...frameRest,
    };
    return (
      <div style={frameStyle} {...rest}>
        <img
          src={src}
          alt={alt || label}
          style={{
            width: "100%",
            height: "100%",
            objectFit: "cover",
            objectPosition: objectPosition || "center",
            display: "block",
          }}
        />
      </div>
    );
  }
  return (
    <div
      className="stripe-placeholder"
      data-label={label}
      style={style}
      {...rest}
    />
  );
}

/* ============================================================
 * Inner page hero — reusable
 * ============================================================ */
function PageHero({ eyebrow, title, italic, subtitle, verse, verseRef }) {
  return (
    <section
      style={{
        padding: "clamp(60px, 7vw, 110px) clamp(28px, 6vw, 96px) clamp(60px, 7vw, 100px)",
        position: "relative",
      }}
    >
      <div style={{ maxWidth: 1320, margin: "0 auto" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 14, marginBottom: 48, color: "var(--walnut-soft)" }}>
          <CircleMark size={6} color="var(--terracotta)" />
          <span className="smallcaps">{eyebrow}</span>
          <span style={{ flex: 1, height: 1, background: "var(--rule)" }} />
        </div>

        <div style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr", gap: 80, alignItems: "end" }}>
          <h1
            className="display"
            style={{
              fontSize: "clamp(54px, 7.6vw, 116px)",
              color: "var(--walnut)",
              lineHeight: 0.96,
              fontWeight: 500,
              margin: 0,
            }}
          >
            {title}{" "}
            {italic && (
              <span style={{ fontStyle: "italic", fontFamily: "'Source Serif 4', serif", fontWeight: 300, color: "var(--terracotta)" }}>
                {italic}
              </span>
            )}
          </h1>

          <div>
            {subtitle && (
              <p style={{ fontSize: 19, lineHeight: 1.55, color: "var(--walnut-soft)", marginBottom: 24, maxWidth: 420 }}>
                {subtitle}
              </p>
            )}
            {verse && (
              <div style={{ borderLeft: "1px solid var(--terracotta)", paddingLeft: 18, maxWidth: 420 }}>
                <div className="smallcaps" style={{ color: "var(--terracotta)", marginBottom: 8 }}>
                  {verseRef}
                </div>
                <p className="serif-italic" style={{ fontSize: 17, color: "var(--walnut)", lineHeight: 1.45 }}>
                  "{verse}"
                </p>
              </div>
            )}
          </div>
        </div>
      </div>
    </section>
  );
}

// Export to window so per-page Babel scripts can use these.
Object.assign(window, {
  PALETTES, applyPalette,
  CrossMark, DiamondMark, CircleMark, RiverMark,
  Nav, Footer, CTA, PaletteTweaksPanel, Placeholder, PageHero,
  SHARED_TWEAK_DEFAULTS, BOOKING_URL, EMAIL,
  HERO_IMAGE_URL, CHAIRS_IMAGE_URL, MORNING_RIVER_IMAGE_URL, BRIDGE_IMAGE_URL, SUNRISE_IMAGE_URL,
});
