/* Sections: Hunting, Trophy Wall, Gallery, Contact, Footer */

/**
 * Past-deer archive.
 * Drop 500×500 photos in /assets/gallery/ named YYYY-SCORE.jpg
 * Example: 2022-235.jpg  →  2022 · 235" B&C
 * Just add filenames below — grouping + sorting is automatic.
 */
const PAST_DEER = [
  // 2022
  "2022-235.jpg",
  "2022-211.jpg",
  "2022-202.jpg",
  "2022-202-a.jpg",
  "2022-199.jpg",
  "2022-186.jpg",
  "2022-182.jpg",
  "2022-180.jpg",
  "2022-176.jpg",
  "2022-174.jpg",
  "2022-167.jpg",
  "2022-162.jpg",
  "2022-155.jpg",
  "2022-152.jpg",
  // 2021
  "2021-247.jpg",
  "2021-230.jpg",
  "2021-207.jpg",
  "2021-201.jpg",
  "2021-197.jpg",
  "2021-197-a.jpg",
  "2021-193.jpg",
  "2021-193-a.jpg",
  "2021-190.jpg",
  "2021-189.jpg",
  "2021-181.jpg",
  "2021-177.jpg",
  "2021-175.jpg",
  "2021-172.jpg",
  "2021-169.jpg",
  "2021-164.jpg",
  "2021-156.jpg",
  "2021-150.jpg",
  "2021-a.jpg",
  // 2019
  "2019-a.jpg",
  "2019-b.jpg",
  "2019-c.jpg",
  "2019-d.jpg",
  "2019-e.jpg",
  "2019-f.jpg",
  "2019-g.jpg",
  "2019-h.jpg",
  "2019-i.jpg",
  "2019-j.jpg",
  // 2017
  "2017-a.jpg",
  "2017-b.jpg",
  "2017-c.jpg",
  "2017-d.jpg",
  "2017-e.jpg",
  "2017-f.jpg",
];

const parseDeerFile = (f) => {
  const base = f.replace(/\.(jpg|jpeg|png|webp)$/i, "");
  const parts = base.split("-");
  const year = Number(parts[0]);
  const rawScore = parts[1];
  const scored = rawScore && /^\d/.test(rawScore);
  return { year, score: scored ? rawScore : null, file: f };
};

const groupDeerByYear = (files) => {
  const map = new Map();
  for (const d of files.map(parseDeerFile)) {
    if (!map.has(d.year)) map.set(d.year, []);
    map.get(d.year).push(d);
  }
  for (const arr of map.values()) {
    arr.sort((a, b) => {
      if (a.score === null && b.score === null) return 0;
      if (a.score === null) return 1;
      if (b.score === null) return -1;
      return Number(b.score) - Number(a.score);
    });
  }
  return [...map.entries()].sort((a, b) => b[0] - a[0]);
};

const PastDeerModal = ({ open, onClose }) => {
  React.useEffect(() => {
    if (!open) return;
    const onKey = (e) => e.key === "Escape" && onClose();
    document.addEventListener("keydown", onKey);
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return () => {
      document.removeEventListener("keydown", onKey);
      document.body.style.overflow = prev;
    };
  }, [open, onClose]);
  if (!open) return null;
  const years = groupDeerByYear(PAST_DEER);
  return (
    <div className="archive-backdrop" onClick={onClose} role="dialog" aria-modal="true" aria-label="Past deer archive">
      <div className="archive-modal" onClick={(e) => e.stopPropagation()}>
        <div className="archive-head">
          <div>
            <div className="eyebrow" style={{ color: "rgba(255,255,255,0.55)", marginBottom: 12 }}>
              <Star size={10} style={{marginRight:8, opacity:0.8}} />The Archive · All Bucks of Record
            </div>
            <h3 className="archive-title">
              Past <em>seasons.</em>
            </h3>
          </div>
          <button className="archive-close" onClick={onClose} aria-label="Close archive">×</button>
        </div>
        <div className="archive-body">
          {years.length === 0 ? (
            <div className="archive-empty">Photographs arriving soon.</div>
          ) : (
            years.map(([year, deer]) => (
              <div key={year} className="archive-year">
                <div className="archive-year-head">
                  <div className="year-label">— {year} —</div>
                  <div className="year-count">
                    {deer.length} {deer.length === 1 ? "buck" : "bucks"}
                  </div>
                </div>
                <div className="archive-grid">
                  {deer.map((d) => (
                    <div key={d.file} className="archive-item">
                      <img
                        src={`assets/gallery/${d.file}`}
                        alt={d.score ? `${d.year} · ${d.score}" B&C` : `${d.year} · unscored buck`}
                        loading="lazy"
                      />
                      <div className="archive-caption">
                        {d.score ? (
                          <>
                            <span className="score">{d.score}"</span>
                            <span className="unit">Gross B&amp;C</span>
                          </>
                        ) : (
                          <>
                            <span className="score unscored">—</span>
                            <span className="unit">Unscored</span>
                          </>
                        )}
                      </div>
                    </div>
                  ))}
                </div>
              </div>
            ))
          )}
        </div>
      </div>
    </div>
  );
};

const HUNT_CARDS = [
  {
    tag: "Signature",
    title: "Trophy Whitetail",
    desc: "Our flagship pursuit — mature, free‑ranging South Texas bucks managed for age and genetics over decades. Mid‑140s to 200+ B&C class, taken with the rifle of your choice.",
    season: "Oct - Jan",
    feat: true,
    img: "trophy-whitetail.jpg",            // ← 16:9 crop recommended
    label: "img / trophy buck in sendero",
    size: "1600×900 · 16:9",
  },
  {
    tag: "Program",
    title: "Management Whitetail",
    desc: "A deliberate part of our herd program — mature cull bucks that help keep our genetics strong. A more affordable way to hunt a real South Texas whitetail.",
    season: "Oct - Jan",
    img: "management-whitetail.jpg",   // ← 3:2 crop recommended
    label: "img / management buck",
    size: "1200×800 · 3:2",
  },
];

// 14 trophy bucks — optional 5th element: image filename in /assets
const TROPHIES = [
  ["The Patriarch",      "247", 2021, "", "chula-vista-buck-1.jpg"],
  ["Brushline King",     "223 4/8", 2025, "", "rob-deer.jpg"],
  ["Old Crooked Horn",   "235 6/8", 2023, "", "gallery/2022-235.jpg"],
  ["Sendero Six",        "202 0/8", 2022, "", "gallery/2022-202.jpg"],
  ["The Mayor",          "202 3/8", 2022, "", "gallery/2022-202-a.jpg"],
  ["Widowmaker",         "211 1/8", 2021, "", "gallery/2022-211.jpg"],
  ["Triple Beam",        "230 5/8", 2021, "", "gallery/2021-230.jpg"],
  ["Mesquite",           "207 2/8", 2020, "", "gallery/2021-207.jpg"],
  ["Duval",              "197 4/8", 2020, "", "gallery/2021-197.jpg"],
  ["Golden Hour",        "197 7/8", 2019, "", "gallery/2021-197-a.jpg"],
  ["The Ghost",          "193 0/8", 2019, "", "gallery/2021-193.jpg"],
  ["Freer 12",           "193 3/8", 2021, "", "gallery/2021-193-a.jpg"],
  ["Mid‑Day",            "199 6/8", 2022, "", "gallery/2022-199.jpg"],
  ["First Light",        "186 2/8", 2022, "", "gallery/2022-186.jpg"],
];

const Hunting = () => {
  const [showArchive, setShowArchive] = React.useState(false);
  return (
  <section className="section dark" id="hunting">
    <div className="container">
      <div className="section-head">
        <div className="head-left">
          <div className="section-num" style={{ color: "rgba(255,255,255,0.55)" }}>
            <Star size={12} style={{marginRight:8, opacity:0.8}} /> § 03 · Hunting Program
          </div>
          <h2 className="display-xl">
            The Pursuit,
            <br />
            <em>at the Heart of It.</em>
          </h2>
        </div>
        <div className="head-right">
          <p style={{ color: "rgba(255,255,255,0.75)" }}>
            A limited program centered on trophy whitetail. Tags are few,
            guides are dedicated, and every hunt runs one‑on‑one.
          </p>
        </div>
      </div>

      <div className="hunt-grid">
        {HUNT_CARDS.map((c, i) => (
          <article key={i} className={`hunt-card ${c.feat ? "feat" : ""}`}>
            {c.img ? (
              <img src={`assets/${c.img}`} alt={`${c.title} — guided hunt at O.D.'s Chula Vista Ranch in South Texas`} className="hunt-img" />
            ) : (
              <Placeholder label={c.label} size={c.size} tone="dark" />
            )}
            <div className="body">
              <div className="tag">
                <span
                  style={{
                    width: 6,
                    height: 6,
                    background: "currentColor",
                    display: "inline-block",
                  }}
                />
                {c.tag}
              </div>
              <h3>{c.title}</h3>
              <p>{c.desc}</p>
              <div className="meta">
                <span>Season · {c.season}</span>
                <span>1:1 Guide</span>
              </div>
            </div>
          </article>
        ))}
      </div>

      {/* Pricing — gross B&C tiers */}
      <div className="pricing-tiers">
        <div className="pricing-head">
          <div>
            <div className="eyebrow" style={{ color: "rgba(255,255,255,0.55)", marginBottom: 14 }}>
              By the Score · Trophy Whitetail
            </div>
            <h3 className="pricing-title">
              Pricing, <em>gross B&amp;C.</em>
            </h3>
          </div>
          <div className="meta">
            Measured at harvest<br />
            Gross Boone &amp; Crockett
          </div>
        </div>

        <div className="pricing-list">
          {[
            ["01", "150 – 165\"", "$6,500"],
            ["02", "166 – 175\"", "$7,500"],
            ["03", "176 – 185\"", "$8,500"],
            ["04", "186 – 195\"", "$10,000"],
            ["05", "196 – 205\"", "$12,500"],
            ["06", "206\" and up", "$13,000"],
          ].map(([i, r, f]) => (
            <div className="pricing-row" key={i}>
              <div className="idx">{i}</div>
              <div className="range">{r}</div>
              <div className="fee">{f}</div>
            </div>
          ))}
        </div>
        <div className="pricing-foot">+ $150 per inch above 206"</div>
      </div>

      {/* Trophy wall */}
      <div className="trophy-section">
        <div className="trophy-head">
          <div>
            <div
              className="eyebrow"
              style={{ color: "rgba(255,255,255,0.55)", marginBottom: 14 }}
            >
              The Trophy Wall · A Selection
            </div>
            <h2 className="display-xl">
              Bucks of <em>record.</em>
            </h2>
          </div>
          <div className="meta">
            Scores per Boone &amp; Crockett · Gross
            <br />
            {TROPHIES.length} of many · 2017 - 2026
          </div>
        </div>

        <div className="trophy-grid">
          {TROPHIES.map((t, i) => (
            <div className="trophy" key={i}>
              {t[4] ? (
                <img src={`assets/${t[4]}`} alt={`${t[0]} — ${t[1]}" B&C trophy whitetail buck harvested ${t[2]} at O.D.'s Chula Vista Ranch`} className="trophy-img" />
              ) : (
                <div className="ph">
                  <div className="ph-ticks" />
                  <div className="ph-label">
                    Trophy · {String(i + 1).padStart(2, "0")}
                    <span className="ph-size">1000×1000 · 1:1</span>
                  </div>
                </div>
              )}
              <div className="info">
                <div className="name">{t[0]}</div>
                <div className="score">{t[1]}"</div>
                <div className="year">Harvested · {t[2]}</div>
                <div className="unit">{t[3]}</div>
              </div>
            </div>
          ))}

          {/* CTA tile — opens the archive modal */}
          <button
            type="button"
            className="trophy trophy-cta"
            onClick={() => setShowArchive(true)}
            aria-label="Open past deer archive"
          >
            <div className="trophy-cta-face">
              <div className="trophy-cta-star"><Star size={48} /></div>
              <div className="trophy-cta-eyebrow">The Archive</div>
            </div>
            <div className="info">
              <div className="name">Past Seasons</div>
              <div className="score">→</div>
              <div className="year">All bucks · all years</div>
              <div className="unit">Gross B&amp;C</div>
            </div>
          </button>
        </div>
      </div>

      {/* House Notes — wounded animal + alcohol */}
      <div className="house-notes">
        <div className="label"><Star size={10} style={{marginRight:8, opacity:0.8}} />§ House Notes</div>
        <div className="notes">
          <div className="note">
            <strong>On the hit.</strong>
            If the shot draws blood, the buck is counted — recovered or not. In the rare case an animal cannot be found, his score is estimated from the evidence and the tier is honored.
          </div>
          <div className="note">
            <strong>On the bar.</strong>
            We don't stock liquor, though setups and ice are always on hand — bring what you like. We ask only that drinks wait until the rifles are cased for the night.
          </div>
        </div>
      </div>
    </div>

    <PastDeerModal open={showArchive} onClose={() => setShowArchive(false)} />
  </section>
  );
};

const Gallery = () => {
  // optional 4th element: image filename in /assets
  const items = [
    // [cls, placeholderLabel, size, file?, alt?]
    ["g-1",  "img / hero · buck at dawn",   "1600×1050", "hero-buck.jpg",                "Trophy whitetail buck on the ranch at dawn"],
    ["g-2",  "img / deer in the brush",     "800×700",   "deer-in-the-brush.jpg",        "Whitetail deer in the South Texas brush country"],
    ["g-3",  "img / deer blind",            "800×700",   "chula-vista-deer-blind.jpg",   "Hunting blind overlooking a sendero at O.D.'s Chula Vista Ranch"],
    ["g-4",  "img / trophy close‑up",       "800×700",   "trophy-buck.jpg",              "Close-up of a trophy whitetail buck"],
    ["g-5",  "img / back porch fire pit",   "800×700",   "sunset.jpg",                   "Fire pit on the back porch at dusk, looking out over the ranch"],
    ["g-6",  "img / house from above",      "1000×700",  "house-from-above.jpg",         "Aerial view of the main lodge at O.D.'s Chula Vista Ranch"],
    ["g-7",  "img / sunset pano",           "1000×700",  "sunset-at-chula-vista.jpg",    "Sunset over the ranch in South Texas"],
    ["g-8",  "img / inside the blind",      "1000×700",  "deer-blind.jpg",               "Hunters glassing from inside an enclosed deer blind"],
    ["g-9",  "img / ranch roads",           "800×700",   "ranch-roads.jpg",              "Ranch road through the South Texas brush country"],
    ["g-10", "img / dining hall",           "1600×700", "rainbow.jpg",                    "Rainbow over the dining hall at O.D.'s Chula Vista Ranch"],
    ["g-11", "img / ranch sign",            "800×700",   "od-chula-vista-sign.jpg",      "O.D.'s Chula Vista Ranch entrance sign"],
    ["g-12", "img / cactus",                "1000×700",  "cactus.jpg",                   "Prickly pear cactus on the ranch"],
    ["g-13", "img / front of house",        "1000×700",  "chula-vista-front.jpg",        "Front of the main lodge at O.D.'s Chula Vista Ranch"],
    ["g-14", "img / poker night",           "1000×700",  "poker-night.jpg",              "Guests at the lodge after a day in the field"],
  ];
  return (
    <section className="section" id="gallery">
      <div className="container">
        <div className="section-head">
          <div className="head-left">
            <div className="section-num"><Star size={12} style={{marginRight:8, opacity:0.8}} /> § 04 · Gallery</div>
            <h2 className="display-xl">
              A season
              <br />
              <em>in pictures.</em>
            </h2>
          </div>
          <div className="head-right">
            <p>
              First light on a sendero. The back porch. The hunt. What the
              drive back feels like.
            </p>
          </div>
        </div>

        <div className="gallery-grid">
          {items.map(([cls, label, size, file, alt], i) => (
            <div key={cls} className={`g-item ${cls}`}>
              {file ? (
                <img src={`assets/${file}`} alt={alt || label.replace(/^img \/ /, "")} className="g-img" />
              ) : (
                <Placeholder
                  label={label}
                  size={size}
                  tone={i % 3 === 0 ? "warm" : i % 3 === 1 ? "" : "dark"}
                />
              )}
            </div>
          ))}
        </div>
      </div>
    </section>
  );
};

const ContactMap = () => (
  <div className="contact-map">
    <svg viewBox="0 0 400 300" preserveAspectRatio="xMidYMid slice">
      <defs>
        <pattern id="mapgrid" width="24" height="24" patternUnits="userSpaceOnUse">
          <path d="M24 0 L0 0 0 24" fill="none" stroke="currentColor" strokeWidth="0.4" opacity="0.12" />
        </pattern>
      </defs>

      {/* pale olive-green map ground */}
      <rect width="400" height="300" fill="color-mix(in srgb, var(--olive-light) 28%, var(--bg))" />
      {/* subtle sandy "cleared" shapes — abstract parcels */}
      <g fill="color-mix(in srgb, var(--khaki) 60%, var(--bg))" opacity="0.85">
        <ellipse cx="80" cy="70" rx="34" ry="18" />
        <ellipse cx="330" cy="50" rx="26" ry="14" />
        <ellipse cx="60" cy="210" rx="28" ry="16" />
        <ellipse cx="340" cy="230" rx="30" ry="14" />
        <ellipse cx="200" cy="70" rx="22" ry="12" />
        <ellipse cx="270" cy="200" rx="26" ry="13" />
        <ellipse cx="130" cy="250" rx="22" ry="12" />
      </g>
      {/* grid overlay */}
      <rect width="400" height="300" fill="url(#mapgrid)" color="var(--ink)" />

      {/* ROADS — radiating out of Freer at center (200, 150) */}
      <g stroke="color-mix(in srgb, var(--walnut) 55%, var(--bg))" fill="none" strokeLinecap="round">
        {/* US 59 — SW to NE diagonal through center */}
        <path d="M 20 250 L 200 150 L 380 70" strokeWidth="3.4" />
        {/* TX 16 — straight N/S through center */}
        <path d="M 200 10 L 200 150 L 200 290" strokeWidth="3.4" />
        {/* TX 44 — W to E through center, with a NW branch */}
        <path d="M 10 150 L 200 150 L 390 180" strokeWidth="3.4" />
        {/* TX 44 northwest branch (secondary) */}
        <path d="M 200 150 Q 140 115 80 130 Q 40 138 15 120" strokeWidth="2.6" opacity="0.85" />
        {/* Minor road to the SE */}
        <path d="M 200 150 Q 260 200 340 260" strokeWidth="1.4" opacity="0.55" strokeDasharray="0" />
      </g>

      {/* HIGHWAY SHIELDS */}
      {/* US 59 SW */}
      <g transform="translate(70 215)">
        <circle r="11" fill="var(--bg)" stroke="color-mix(in srgb, var(--walnut) 60%, var(--bg))" strokeWidth="1.2" />
        <text textAnchor="middle" y="3.5" fontFamily="var(--font-mono)" fontSize="9" fill="var(--ink)" fontWeight="600">59</text>
      </g>
      {/* US 59 NE */}
      <g transform="translate(340 92)">
        <circle r="11" fill="var(--bg)" stroke="color-mix(in srgb, var(--walnut) 60%, var(--bg))" strokeWidth="1.2" />
        <text textAnchor="middle" y="3.5" fontFamily="var(--font-mono)" fontSize="9" fill="var(--ink)" fontWeight="600">59</text>
      </g>
      {/* TX 16 N */}
      <g transform="translate(200 40)">
        <rect x="-11" y="-10" width="22" height="20" fill="var(--bg)" stroke="color-mix(in srgb, var(--walnut) 60%, var(--bg))" strokeWidth="1.2" rx="2" />
        <text textAnchor="middle" y="3.5" fontFamily="var(--font-mono)" fontSize="9" fill="var(--ink)" fontWeight="600">16</text>
      </g>
      {/* TX 16 S */}
      <g transform="translate(200 260)">
        <rect x="-11" y="-10" width="22" height="20" fill="var(--bg)" stroke="color-mix(in srgb, var(--walnut) 60%, var(--bg))" strokeWidth="1.2" rx="2" />
        <text textAnchor="middle" y="3.5" fontFamily="var(--font-mono)" fontSize="9" fill="var(--ink)" fontWeight="600">16</text>
      </g>
      {/* TX 44 E */}
      <g transform="translate(340 175)">
        <rect x="-11" y="-10" width="22" height="20" fill="var(--bg)" stroke="color-mix(in srgb, var(--walnut) 60%, var(--bg))" strokeWidth="1.2" rx="2" />
        <text textAnchor="middle" y="3.5" fontFamily="var(--font-mono)" fontSize="9" fill="var(--ink)" fontWeight="600">44</text>
      </g>
      {/* TX 44 W */}
      <g transform="translate(55 145)">
        <rect x="-11" y="-10" width="22" height="20" fill="var(--bg)" stroke="color-mix(in srgb, var(--walnut) 60%, var(--bg))" strokeWidth="1.2" rx="2" />
        <text textAnchor="middle" y="3.5" fontFamily="var(--font-mono)" fontSize="9" fill="var(--ink)" fontWeight="600">44</text>
      </g>

      {/* FREER marker at center */}
      <g transform="translate(200 150)">
        <circle r="22" fill="var(--olive-deep)" fillOpacity="0.12" />
        <circle r="11" fill="var(--olive-deep)" fillOpacity="0.25" />
        <circle r="4.5" fill="var(--olive-deep)" />
      </g>
      <g transform="translate(213 148)">
        <rect x="-2" y="-9" width="50" height="14" fill="var(--bg)" opacity="0.92" />
        <text x="0" y="1" fontFamily="var(--font-ui)" fontSize="11" fontWeight="600" fill="var(--ink)">Freer</text>
      </g>

      {/* nearby small-town labels */}
      <text x="275" y="215" fontFamily="var(--font-ui)" fontSize="8" fill="var(--ink-mute)">Pila Blanca</text>
      <text x="305" y="245" fontFamily="var(--font-ui)" fontSize="8" fill="var(--ink-mute)">Rosita</text>
      <text x="85" y="185" fontFamily="var(--font-ui)" fontSize="8" fill="var(--ink-mute)">Magnolia Rd</text>

      {/* corner legend */}
      <text x="12" y="22" fontFamily="var(--font-mono)" fontSize="7" fill="var(--ink-mute)" letterSpacing="2" opacity="0.7">
        DUVAL COUNTY · TEXAS
      </text>
      <text x="388" y="292" textAnchor="end" fontFamily="var(--font-mono)" fontSize="7" fill="var(--ink-mute)" letterSpacing="2" opacity="0.7">
        N ↑  ·  EXACT LOCATION ON REQUEST
      </text>
    </svg>
  </div>
);

const CONTACT_EMAIL = "kenny_h@beaed.com";

/**
 * Cloudflare Turnstile. The site key is public — paste it here. It must pair
 * with TURNSTILE_SECRET in Vercel; api/inquiry.js refuses every submission
 * without a valid token, so set both together.
 *
 * Same pattern as Premium Precision's TurnstileWidget:
 * - execution "execute": nothing runs on page load; getToken() runs the
 *   challenge at submit. Rendering on load mints tokens nobody redeems, and
 *   Cloudflare then warns "siteverify isn't being called".
 * - Tokens are single-use, so getToken() resets the widget before every run.
 * - appearance "interaction-only": invisible unless a visitor is challenged,
 *   so no space is reserved for it.
 */
const TURNSTILE_SITE_KEY = "0x4AAAAAAFreduGFV8j77ODi"; // public; secret lives in Vercel
const TURNSTILE_SRC = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
let turnstileScript = null;
const loadTurnstile = () => {
  if (window.turnstile) return Promise.resolve();
  if (!turnstileScript) {
    turnstileScript = new Promise((resolve, reject) => {
      const s = document.createElement("script");
      s.src = TURNSTILE_SRC;
      s.async = true;
      s.onload = resolve;
      s.onerror = () => { turnstileScript = null; reject(); };
      document.head.appendChild(s);
    });
  }
  return turnstileScript;
};

// Resolves "" on every failure (blocked script, error, expiry, 30s timeout) —
// the server then rejects, so a dead widget never counts as a pass.
const Turnstile = React.forwardRef((props, ref) => {
  const holder = React.useRef(null);
  const id = React.useRef(null);
  const pending = React.useRef(null);
  const settle = (token) => {
    const p = pending.current;
    if (!p) return;
    pending.current = null;
    clearTimeout(p.timer);
    p.resolve(token);
  };

  React.useImperativeHandle(ref, () => ({
    getToken: () => new Promise((resolve) => {
      if (!window.turnstile || id.current === null) return resolve("");
      settle("");
      window.turnstile.reset(id.current);
      const p = { resolve, timer: setTimeout(() => { if (pending.current === p) { pending.current = null; resolve(""); } }, 30000) };
      pending.current = p;
      window.turnstile.execute(id.current);
    }),
  }));

  React.useEffect(() => {
    if (!TURNSTILE_SITE_KEY) return;
    let cancelled = false;
    loadTurnstile()
      .then(() => {
        if (cancelled || !holder.current) return;
        id.current = window.turnstile.render(holder.current, {
          sitekey: TURNSTILE_SITE_KEY,
          action: "inquiry",
          theme: "light",
          execution: "execute",
          appearance: "interaction-only",
          callback: (token) => settle(token),
          "expired-callback": () => settle(""),
          "timeout-callback": () => settle(""),
          "error-callback": () => { settle(""); return true; },
        });
      })
      .catch(() => settle(""));
    return () => {
      cancelled = true;
      settle("");
      if (id.current !== null && window.turnstile) window.turnstile.remove(id.current);
      id.current = null;
    };
  }, []);

  return TURNSTILE_SITE_KEY ? <div ref={holder} className="form-turnstile" /> : null;
});
const EMPTY_FORM = {
  name: "", email: "", phone: "", dates: "", group: "2", species: "Trophy Whitetail", message: "", company: "",
};

const ContactForm = () => {
  const [f, setF] = React.useState(EMPTY_FORM);
  const [sent, setSent] = React.useState(false);
  const [sending, setSending] = React.useState(false);
  const [error, setError] = React.useState("");
  const errRef = React.useRef(null);
  const tsRef = React.useRef(null);
  const on = (k) => (e) => setF({ ...f, [k]: e.target.value });

  React.useEffect(() => {
    if (error && errRef.current) errRef.current.scrollIntoView({ block: "nearest", behavior: "smooth" });
  }, [error]);

  // noValidate + our own checks: iOS Safari can drop a submit on native
  // validation without showing anything.
  const submit = async (e) => {
    e.preventDefault();
    if (sending) return;
    if (!f.name.trim()) return setError("Please add your name.");
    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(f.email.trim())) return setError("Please add a valid email address.");
    setError("");
    setSending(true);
    try {
      const token = (await tsRef.current?.getToken()) || "";
      const r = await fetch("/api/inquiry", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ ...f, "cf-turnstile-response": token }),
      });
      const data = await r.json().catch(() => ({}));
      if (!r.ok || !data.ok) throw new Error(data.error || String(r.status));
      setSent(true);
    } catch (err) {
      setError(err.message === "verify" ? "verify" : "send");
    } finally {
      setSending(false);
    }
  };
  if (sent) {
    return (
      <div className="form-success">
        <div className="eyebrow" style={{ color: "rgba(255,255,255,0.7)" }}>Inquiry received</div>
        <h4>Thank you, {f.name || "friend"}.</h4>
        <p>
          We'll be in touch within 24 hours to discuss dates, species, and
          availability for your party of {f.group}.
        </p>
        <button className="btn btn-ghost" style={{ marginTop: 20, alignSelf: "flex-start" }} onClick={() => { setSent(false); setF(EMPTY_FORM); }}>
          Send Another
        </button>
      </div>
    );
  }
  return (
    <form className="form" onSubmit={submit} noValidate>
      <div className="row">
        <div className="field">
          <label htmlFor="cf-name">Name *</label>
          <input id="cf-name" autoComplete="name" value={f.name} onChange={on("name")} placeholder="Your full name" />
        </div>
        <div className="field">
          <label htmlFor="cf-email">Email *</label>
          <input id="cf-email" type="email" autoComplete="email" value={f.email} onChange={on("email")} placeholder="you@domain.com" />
        </div>
      </div>
      <div className="row">
        <div className="field">
          <label htmlFor="cf-phone">Phone</label>
          <input id="cf-phone" type="tel" autoComplete="tel" value={f.phone} onChange={on("phone")} placeholder="(000) 000‑0000" />
        </div>
        <div className="field">
          <label htmlFor="cf-dates">Preferred Dates</label>
          <input id="cf-dates" value={f.dates} onChange={on("dates")} placeholder="e.g. mid‑November" />
        </div>
      </div>
      <div className="row">
        <div className="field">
          <label htmlFor="cf-group">Group Size</label>
          <select id="cf-group" value={f.group} onChange={on("group")}>
            {["1","2","3","4","5","6","7","8+"].map(n => <option key={n}>{n}</option>)}
          </select>
        </div>
        <div className="field">
          <label htmlFor="cf-species">Species</label>
          <select id="cf-species" value={f.species} onChange={on("species")}>
            {["Trophy Whitetail","Management Whitetail"].map(s => <option key={s}>{s}</option>)}
          </select>
        </div>
      </div>
      <div className="field">
        <label htmlFor="cf-message">Message</label>
        <textarea id="cf-message" value={f.message} onChange={on("message")} placeholder="Tell us about your group and any special requests." />
      </div>
      {/* Honeypot — hidden from people, filled by bots */}
      <div className="form-hp" aria-hidden="true">
        <label htmlFor="cf-company">Company</label>
        <input id="cf-company" tabIndex={-1} autoComplete="off" value={f.company} onChange={on("company")} />
      </div>
      <Turnstile ref={tsRef} />
      {error && (
        <div className="form-error" role="alert" ref={errRef}>
          {error === "send" || error === "verify" ? (
            <>
              {error === "verify"
                ? "We couldn't complete the spam check. Please try again, "
                : "Your inquiry didn't go through. Please try again, "}
              or email us directly at <a href={`mailto:${CONTACT_EMAIL}`}>{CONTACT_EMAIL}</a>.
            </>
          ) : error}
        </div>
      )}
      <div className="form-foot">
        <div className="note">* Required fields. Your information stays with the ranch.</div>
        <button type="submit" className="btn btn-dark" disabled={sending}>
          {sending ? "Sending…" : <>Send Inquiry <span className="arrow">→</span></>}
        </button>
      </div>
    </form>
  );
};

const Contact = () => (
  <section className="section alt" id="contact">
    <div className="container">
      <div className="section-head">
        <div className="head-left">
          <div className="section-num"><Star size={12} style={{marginRight:8, opacity:0.8}} /> § 05 · Get in Touch</div>
          <h2 className="display-xl">
            Plan your
            <br />
            <em>visit.</em>
          </h2>
        </div>
        <div className="head-right">
          <p>
            Dates are limited and book early. Send us a note below or reach out
            directly — we'll respond personally within 24 hours.
          </p>
        </div>
      </div>

      <div className="contact-grid">
        <div className="contact-info">
          <div className="line big">
            <div className="lbl">Email</div>
            <div className="val"><a href={`mailto:${CONTACT_EMAIL}`}>{CONTACT_EMAIL}</a></div>
          </div>
          <div className="line">
            <div className="lbl">Ranch Address</div>
            <div className="val">
              O.D.'s Chula Vista Ranch<br />
              Freer, Texas · Duval County
            </div>
          </div>
          <div className="line">
            <div className="lbl">Office Hours</div>
            <div className="val" style={{ fontSize: 18 }}>
              Mon - Fri · 8am - 6pm CT
            </div>
          </div>
          <ContactMap />
        </div>

        <ContactForm />
      </div>
    </div>
  </section>
);

const Footer = () => (
  <footer className="foot">
    <div className="container">
      <div className="foot-top">
        <div className="foot-brand">
          <img src="assets/texas-outline.png" alt="Texas" className="foot-texas" />
          <div>
            <h5>O.D.'s Chula Vista Ranch</h5>
            <div style={{ fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: "0.22em", textTransform: "uppercase", opacity: 0.55, display: "inline-flex", alignItems: "center", gap: 8 }}>
              <span>Freer</span>
              <Star size={10} style={{opacity: 0.8}} />
              <span>Duval County</span>
              <Star size={10} style={{opacity: 0.8}} />
              <span>Texas</span>
            </div>
          </div>
        </div>
        <div style={{ display: "flex", gap: 40, flexWrap: "wrap" }}>
          {NAV_ITEMS.map(i => (
            <a key={i.id} href={`#${i.id}`} style={{ color: "inherit", textDecoration: "none", fontSize: 13 }}>
              {i.label}
            </a>
          ))}
        </div>
      </div>
      <div className="foot-bot">
        <div>© {new Date().getFullYear()} O.D.'s Chula Vista Ranch. All rights reserved.</div>
        <div style={{ display: "inline-flex", alignItems: "center", gap: 6, flexWrap: "wrap" }}>
          <span>Designed for hunters by <a href="https://www.brassandboneco.com" target="_blank" rel="noopener noreferrer">Brass &amp; Bone Co.</a></span>
          <Star size={10} style={{opacity: 0.8}} />
          <span>Freer, TX</span>
        </div>
      </div>
    </div>
  </footer>
);

Object.assign(window, { Hunting, Gallery, Contact, Footer });
