/* Main App — Madhurendra & Diksha · 30-31 Jan 2027 */
const { useState: aUseState, useEffect: aUseEffect, useRef: aUseRef, useMemo: aUseMemo, useCallback: aUseCallback } = React;

/* ---------------- CONFIG ---------------- */
const CONFIG = /*EDITMODE-BEGIN*/{
  "groomName": "Madhurendra",
  "brideName": "Diksha",
  "familyName": "Sachan",
  "weddingDate": "2027-01-30",
  "dateDisplay": "30 \u2014 31 January 2027",
  "city": "Kanpur",
  "state": "Uttar Pradesh",
  "venueName": "The Wedding Venue",
  "venueAddress": "Kanpur, Uttar Pradesh",
  "venueMapUrl": "https://share.google/alv2JJvlTCLaoiApS",
  "friendsPasscode": "DOSTI2027"
}/*EDITMODE-END*/;

/* ---------------- DOORS / OPENER ---------------- */
function Opener({ onOpen }) {
  const [opened, setOpened] = aUseState(false);
  const handleOpen = () => {
    setOpened(true);
    setTimeout(() => onOpen && onOpen(), 1800);
  };
  return (
    <div className={`opener ${opened ? "opened" : ""}`}>
      <div className="stars" />
      <div className="toran"><Toran width={820} /></div>
      <div className="doors">
        <div className="door left">
          <div className="door-pattern"><DoorPattern side="left" /></div>
          <div className="door-knob" />
        </div>
        <div className="door right">
          <div className="door-pattern"><DoorPattern side="right" /></div>
          <div className="door-knob" />
        </div>
      </div>
      <div className="door-cta">
        <div style={{ fontFamily: "JetBrains Mono, monospace", fontSize: 11, letterSpacing: "0.35em", color: "#c9a961", textTransform: "uppercase" }}>
          ◆ Shubh Vivah · शुभ विवाह ◆
        </div>
        <div style={{ fontFamily: "Yatra One, serif", fontSize: "clamp(34px, 6vw, 56px)", color: "#fbf3e1", lineHeight: 1.1 }}>
          {CONFIG.groomName} <span style={{ color: "#ef8c1a", fontFamily: "Cormorant Garamond, serif", fontStyle: "italic" }}>&</span> {CONFIG.brideName}
        </div>
        <div style={{ fontFamily: "Cormorant Garamond, serif", fontStyle: "italic", color: "#c9a961", fontSize: 20 }}>
          request the pleasure of your company
        </div>
        <div style={{ fontFamily: "JetBrains Mono, monospace", fontSize: 12, letterSpacing: ".25em", color: "#fbf3e1" }}>
          30 — 31 · JANUARY · 2027
        </div>
        <button onClick={handleOpen}>Open the Invite ✦</button>
        <div style={{ fontFamily: "JetBrains Mono, monospace", fontSize: 10, letterSpacing: "0.3em", color: "rgba(251,243,225,.6)" }}>
          TAP TO ENTER
        </div>
      </div>
    </div>
  );
}

/* ---------------- NAV ---------------- */
const NAV = [
  { id: "hero", label: "Home" },
  { id: "celebration", label: "Celebration" },
  { id: "venue", label: "Where & When" },
  { id: "friends", label: "For Friends" },
];

function Nav({ activeId }) {
  return (
    <nav className="nav">
      {NAV.map((n) => (
        <a key={n.id} href={`#${n.id}`} className={activeId === n.id ? "active" : ""}>{n.label}</a>
      ))}
    </nav>
  );
}

/* ===================================================================
   HERO with INTERACTIVE BACKGROUND
=================================================================== */
function InteractiveBackground() {
  /* Mandala parallax + tappable ornaments + petal bursts on tap */
  const wrapRef = aUseRef(null);
  const [tilt, setTilt] = aUseState({ x: 0, y: 0 });
  const [bursts, setBursts] = aUseState([]);

  // mousemove parallax
  aUseEffect(() => {
    const el = wrapRef.current;
    if (!el) return;
    const onMove = (e) => {
      const r = el.getBoundingClientRect();
      const t = e.touches ? e.touches[0] : e;
      const dx = (t.clientX - r.left - r.width / 2) / r.width;
      const dy = (t.clientY - r.top  - r.height / 2) / r.height;
      setTilt({ x: dx, y: dy });
    };
    el.addEventListener("mousemove", onMove);
    el.addEventListener("touchmove", onMove, { passive: true });
    return () => {
      el.removeEventListener("mousemove", onMove);
      el.removeEventListener("touchmove", onMove);
    };
  }, []);

  // tap to burst petals
  const burstAt = aUseCallback((cx, cy) => {
    const r = wrapRef.current.getBoundingClientRect();
    const x = cx - r.left, y = cy - r.top;
    const id = Math.random();
    const count = 10;
    const petals = Array.from({ length: count }).map((_, i) => {
      const a = (i / count) * Math.PI * 2 + Math.random() * 0.6;
      const dist = 90 + Math.random() * 90;
      const hue = ["#ef8c1a", "#c2185b", "#d7263d", "#c9a961"][i % 4];
      return { id: id + i, x, y,
               dx: Math.cos(a) * dist, dy: Math.sin(a) * dist,
               rot: (Math.random() * 720 - 360),
               size: 10 + Math.random() * 12, hue };
    });
    setBursts((b) => [...b, ...petals]);
    // cleanup after animation
    setTimeout(() => {
      setBursts((b) => b.filter((p) => !petals.find((q) => q.id === p.id)));
    }, 1800);
  }, []);

  const onTap = (e) => {
    const t = e.changedTouches ? e.changedTouches[0] : e;
    burstAt(t.clientX, t.clientY);
  };

  // floating ornaments around the edges (interactive)
  const ornaments = aUseMemo(() => ([
    { x: "8%",  y: "18%", kind: "paisley", hue: "#c2185b", size: 70, rot: -20 },
    { x: "88%", y: "12%", kind: "marigold", hue: "#ef8c1a", size: 60, rot: 0 },
    { x: "92%", y: "62%", kind: "paisley", hue: "#06727d", size: 60, rot: 35 },
    { x: "6%",  y: "70%", kind: "marigold", hue: "#d7263d", size: 56, rot: 0 },
    { x: "78%", y: "82%", kind: "diya", hue: "#ef8c1a", size: 50, rot: 0 },
    { x: "16%", y: "88%", kind: "diya", hue: "#c9a961", size: 50, rot: 0 },
  ]), []);

  return (
    <div className="ibg" ref={wrapRef} onClick={onTap} onTouchEnd={onTap}>
      {/* Big background mandala — parallax */}
      <div className="ibg-mandala" style={{
        transform: `translate(-50%, 0) translate(${tilt.x * -30}px, ${tilt.y * -20}px) rotate(${tilt.x * 10}deg)`,
      }}>
        <Mandala size={900} color="#9d0d4a" accent="#ef8c1a" strokeW={1.2} rings={4} />
      </div>

      {/* Counter-spin smaller mandala */}
      <div className="ibg-mandala-2" style={{
        transform: `translate(-50%, 0) rotate(${tilt.x * -20}deg)`,
      }}>
        <Mandala size={400} color="#ef8c1a" accent="#c2185b" strokeW={1} rings={3} />
      </div>

      {/* Interactive ornaments */}
      {ornaments.map((o, i) => (
        <button
          key={i}
          className={`ibg-orn ibg-orn-${o.kind}`}
          style={{ left: o.x, top: o.y, "--rot": `${o.rot}deg` }}
          aria-label={o.kind}
          onClick={(e) => {
            e.stopPropagation();
            burstAt(e.clientX, e.clientY);
          }}
        >
          {o.kind === "paisley" && <Paisley size={o.size} color={o.hue} accent="#ef8c1a" />}
          {o.kind === "marigold" && <Marigold size={o.size} color={o.hue} center="#9d0d4a" />}
          {o.kind === "diya" && <Diya size={o.size} />}
        </button>
      ))}

      {/* Petal bursts */}
      {bursts.map((p) => (
        <span
          key={p.id}
          className="petal-burst"
          style={{
            left: p.x, top: p.y,
            "--dx": `${p.dx}px`, "--dy": `${p.dy}px`,
            "--rot": `${p.rot}deg`, "--size": `${p.size}px`,
            background: p.hue,
          }}
        />
      ))}
    </div>
  );
}

function Hero() {
  return (
    <ParallaxHero
      groomName={CONFIG.brideName}
      brideName={CONFIG.groomName}
      dateDisplay={CONFIG.dateDisplay}
      location={`${CONFIG.city}, ${CONFIG.state}`}
    />
  );
}

/* ===================================================================
   CELEBRATION with TAPPABLE ART → MODAL
=================================================================== */
const TIMELINE = [
  {
    day: "day1", date: "Saturday · 30 January 2027",
    items: [
      { key: "ganesh", art: "pattachitra", color: "#c2185b",
        time: "9:00 AM", name: "Ganesh Pujan", hindi: "गणेश पूजन",
        place: "Family home",
        desc: "Invocation of Lord Ganesha — sweets, incense, the first diya of the wedding.",
        dress: "Festive Indian",
        artState: "Odisha",
        artNote: "Pattachitra — cloth scrolls painted with the tree of life, Jagannath, and intricate borders. We chose it for Ganesh Pujan because Pattachitra always begins with an invocation panel." },
      { key: "haldi", art: "kalamkari", color: "#ef8c1a",
        time: "11:00 AM", name: "Haldi", hindi: "हल्दी",
        place: "Family courtyard",
        desc: "Turmeric, mustard oil and laughter — applied by family for the bride and groom’s glow.",
        dress: "Sunny yellows & whites",
        artState: "Andhra Pradesh",
        artNote: "Kalamkari — \"kalam\" (pen) art using natural dyes. Yellow-orange hues match haldi’s warmth, and the flowing flowers feel like the laughter of this rasm." },
      { key: "mehendi", art: "madhubani", color: "#4a7c3a",
        time: "1:30 PM", name: "Mehendi", hindi: "मेहंदी",
        place: "Garden lawn",
        desc: "Henna for the bride, palms-out joy for everyone. Dholki, masala chai and a long catch-up.",
        dress: "Greens, peach, soft pastels",
        artState: "Bihar",
        artNote: "Madhubani — painted on freshly-plastered walls by Mithila women for weddings. The fish-eye motif is said to bring fertility and prosperity to the marriage." },
      { key: "sangeet", art: "gond", color: "#9d0d4a",
        time: "7:30 PM", name: "Sangeet", hindi: "संगीत",
        place: "Banquet Hall · Stage",
        desc: "Choreographed numbers, family roasts, open dance floor, dinner under the lights.",
        dress: "Glam — sequins, lehengas, sherwanis",
        artState: "Madhya Pradesh",
        artNote: "Gond art — Pradhan Gond mythology told in dots and lines. The dancing peacock matches the rhythm and noise of Sangeet night perfectly." },
    ],
  },
  {
    day: "day2", date: "Sunday · 31 January 2027",
    items: [
      { key: "mayra", art: "phad", color: "#d7263d",
        time: "11:00 AM", name: "Mayra / Bhaat", hindi: "मायरा",
        place: "Family home",
        desc: "Maternal uncle’s blessings and gifts for the bride. Sweets, photographs, hugs.",
        dress: "Soft pastels",
        artState: "Rajasthan",
        artNote: "Phad — long red-and-orange scrolls of folk gods, traditionally unrolled and sung by Bhopas at night. A rasm of giving deserves an art of generosity." },
      { key: "baraat", art: "warli", color: "#6b3a0a",
        time: "4:00 PM", name: "Baraat", hindi: "बारात",
        place: "Procession to venue",
        desc: "The groom’s procession with band, baaja, and dancing all the way to the venue.",
        dress: "Festive Indian",
        artState: "Maharashtra",
        artNote: "Warli — tribal stick-figure dancers in a tarpa circle, painted on red-ochre walls with rice paste. There is no better metaphor for a wedding procession." },
      { key: "milni", art: "kerala", color: "#06727d",
        time: "5:00 PM", name: "Milni & Varmala", hindi: "मिलनी",
        place: "Venue entrance",
        desc: "Families greet, garlands are exchanged, the cameras start working overtime.",
        dress: "Traditional best",
        artState: "Kerala",
        artNote: "Kerala Murals — temple-wall art of caparisoned elephants in earthy mineral pigments. Like the Milni: ceremonial, abundant, full of ornament." },
      { key: "pheras", art: "pattachitra", color: "#9d0d4a",
        time: "6:30 PM", name: "Pheras", hindi: "विवाह",
        place: "Wedding mandap",
        desc: "Seven sacred vows around the holy fire — the moment we’ve all been waiting for.",
        dress: "Traditional best",
        artState: "Odisha",
        artNote: "Pattachitra’s tree of life — circling the mandap is itself like reading a Pattachitra: each turn another panel, another vow." },
      { key: "reception", art: "phad", color: "#ef8c1a",
        time: "9:00 PM", name: "Reception", hindi: "स्वागत समारोह",
        place: "Banquet Hall",
        desc: "Dinner, photos with the new couple, kulfi station, dessert that doesn’t believe in moderation.",
        dress: "Cocktail / Indo-western",
        artState: "Rajasthan",
        artNote: "Phad scrolls are festive and crowded — figures pressed together, colour everywhere. That is what a North Indian reception looks like." },
      { key: "vidaai", art: "madhubani", color: "#c2185b",
        time: "11:30 PM", name: "Vidaai", hindi: "विदाई",
        place: "Venue gate",
        desc: "Send-off for the bride. Tears optional, hugs mandatory.",
        dress: "—",
        artState: "Bihar",
        artNote: "Madhubani again — same art, different verse. The bride leaves her childhood walls and brings their motifs with her." },
    ],
  },
];

function ArtModal({ item, onClose }) {
  aUseEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => {
      window.removeEventListener("keydown", onKey);
      document.body.style.overflow = "";
    };
  }, [onClose]);

  return (
    <div className="art-modal" onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="art-modal-card" style={{ borderTop: `6px solid ${item.color}` }}>
        <button className="close" onClick={onClose} aria-label="close">✕</button>
        <div className="amc-left" style={{ background: `${item.color}11` }}>
          <StateArt kind={item.art} size={240} color={item.color} accent="#ef8c1a" />
        </div>
        <div className="amc-right">
          <div className="amc-eyebrow">
            <span className="dot" style={{ background: item.color }} />
            {item.time} · {item.place}
          </div>
          <h3>{item.name} <span className="amc-hindi">{item.hindi}</span></h3>
          <p className="amc-desc">{item.desc}</p>

          <div className="amc-divider"><span>The art</span></div>
          <div className="amc-art-meta">
            <span className="amc-state">{item.artState}</span>
            <span className="amc-art-name">{capitalize(item.art)}</span>
          </div>
          <p className="amc-art-note">{item.artNote}</p>

          <div className="amc-dress">
            <span>👗 Dress code</span>
            <strong>{item.dress}</strong>
          </div>
        </div>
      </div>
    </div>
  );
}
function capitalize(s) { return s.charAt(0).toUpperCase() + s.slice(1); }

function CelebrationSection() {
  const [day, setDay] = aUseState("day1");
  const [modal, setModal] = aUseState(null);
  const dayBlock = TIMELINE.find((d) => d.day === day);

  return (
    <section id="celebration" className="celebration" data-screen-label="02 Celebration">
      {/* Decorative state-art bg corners */}
      <div className="cel-bg-a"><GondPeacock size={200} color="#ef8c1a" accent="#c2185b" /></div>
      <div className="cel-bg-b"><PattachitraTree size={180} color="#c2185b" accent="#ef8c1a" leaf="#4a7c3a" /></div>

      <div className="container">
        <div className="center">
          <div className="eyebrow">The Celebration</div>
          <h2 className="section-title">All the functions, day by day</h2>
          <p className="section-sub">Come for all of them, come for one. Tap any picture to read more about it.</p>

          <div className="schedule-tabs" style={{ margin: "30px auto 10px" }}>
            <button className={day === "day1" ? "active" : ""} onClick={() => setDay("day1")}>
              Day 1 · 30 Jan
            </button>
            <button className={day === "day2" ? "active" : ""} onClick={() => setDay("day2")}>
              Day 2 · 31 Jan
            </button>
          </div>
          <div style={{ fontFamily: "Cormorant Garamond, serif", fontStyle: "italic", color: "var(--ink-soft)" }}>
            {dayBlock.date}
          </div>
        </div>

        <div className="ctimeline">
          {dayBlock.items.map((it) => (
            <div key={it.key} className="ct-row">
              <div className="ct-time">
                <span className="ct-time-icon" style={{ background: it.color }} />
                {it.time}
              </div>
              <div className="ct-card" style={{ borderLeft: `4px solid ${it.color}` }}>
                <button
                  className="ct-art-button"
                  onClick={() => setModal(it)}
                  aria-label={`Open ${it.name} details`}
                >
                  <StateArt kind={it.art} size={110} color={it.color} accent="#ef8c1a" />
                </button>
                <div className="ct-main">
                  <div className="ct-head">
                    <h3>{it.name}</h3>
                    <div className="ct-hindi">{it.hindi}</div>
                  </div>
                  <div className="ct-meta">
                    <span>📍 {it.place}</span>
                    <span>👗 {it.dress}</span>
                  </div>
                  <p className="ct-desc">{it.desc}</p>
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>

      {modal && <ArtModal item={modal} onClose={() => setModal(null)} />}
    </section>
  );
}

/* ===================================================================
   VENUE + SMART CARD (subtle tech accent)
=================================================================== */
function SmartCard() {
  const [tl, setTl] = aUseState({ d: 0, h: 0, m: 0, s: 0 });
  aUseEffect(() => {
    const target = new Date(CONFIG.weddingDate + "T18:00:00").getTime();
    const tick = () => {
      const now = Date.now();
      let diff = Math.max(0, target - now);
      const d = Math.floor(diff / 86400000); diff -= d * 86400000;
      const h = Math.floor(diff / 3600000);  diff -= h * 3600000;
      const m = Math.floor(diff / 60000);    diff -= m * 60000;
      const s = Math.floor(diff / 1000);
      setTl({ d, h, m, s });
    };
    tick();
    const t = setInterval(tick, 1000);
    return () => clearInterval(t);
  }, []);

  const downloadIcs = () => {
    const fmt = (d) => d.toISOString().replace(/[-:]/g, "").replace(/\.\d+/, "");
    const start1 = new Date("2027-01-30T09:00:00");
    const end1   = new Date("2027-01-30T23:30:00");
    const start2 = new Date("2027-01-31T11:00:00");
    const end2   = new Date("2027-01-31T23:59:00");
    const text = [
      "BEGIN:VCALENDAR", "VERSION:2.0", "PRODID:-//Sachan Wedding//EN",
      "BEGIN:VEVENT",
      `UID:day1-${Date.now()}@sachan.wedding`,
      `DTSTAMP:${fmt(new Date())}`,
      `DTSTART:${fmt(start1)}`, `DTEND:${fmt(end1)}`,
      `SUMMARY:${CONFIG.groomName} & ${CONFIG.brideName} — Day 1`,
      `DESCRIPTION:Haldi, Mehendi, Sangeet`,
      `LOCATION:${CONFIG.venueName}, ${CONFIG.city}`,
      "END:VEVENT",
      "BEGIN:VEVENT",
      `UID:day2-${Date.now()}@sachan.wedding`,
      `DTSTAMP:${fmt(new Date())}`,
      `DTSTART:${fmt(start2)}`, `DTEND:${fmt(end2)}`,
      `SUMMARY:${CONFIG.groomName} & ${CONFIG.brideName} — Day 2`,
      `DESCRIPTION:Baraat, Pheras, Reception`,
      `LOCATION:${CONFIG.venueName}, ${CONFIG.city}`,
      "END:VEVENT",
      "END:VCALENDAR"
    ].join("\r\n");
    const blob = new Blob([text], { type: "text/calendar;charset=utf-8" });
    const link = document.createElement("a");
    link.download = "madhurendra-diksha-wedding.ics";
    link.href = URL.createObjectURL(blob);
    link.click();
  };

  // ASCII binary love-easter-egg = "LOVE"
  // L=01001100 O=01001111 V=01010110 E=01000101

  return (
    <div className="smart-card">
      <div className="circuit-border" aria-hidden="true">
        <CircuitRangoli />
      </div>
      <div className="sc-head">
        <span className="sc-tag">◉ LIVE · 24·7</span>
        <span className="sc-title">Time Until Pheras</span>
      </div>
      <div className="sc-led">
        {[["d", "DAYS"], ["h", "HRS"], ["m", "MIN"], ["s", "SEC"]].map(([k, l]) => (
          <div className="sc-led-cell" key={k}>
            <div className="sc-led-num">{String(tl[k]).padStart(2, "0")}</div>
            <div className="sc-led-lbl">{l}</div>
          </div>
        ))}
      </div>
      <div className="sc-actions">
        <button className="btn-primary" onClick={downloadIcs}>
          📅 Add to Calendar (.ics)
        </button>
        <a href={CONFIG.venueMapUrl} target="_blank" rel="noreferrer" style={{ textDecoration: "none" }}>
          <button className="btn-ghost" style={{ color: "var(--marigold)", borderColor: "var(--marigold)" }}>
            📍 Open Location
          </button>
        </a>
      </div>
      <div className="sc-binary" title="LOVE in binary">
        01001100 · 01001111 · 01010110 · 01000101
      </div>
    </div>
  );
}

/* Circuit-rangoli border — a stylized rangoli where the "lines" look like circuit traces */
function CircuitRangoli() {
  return (
    <svg viewBox="0 0 400 240" preserveAspectRatio="none" width="100%" height="100%">
      {/* corner motifs */}
      {[[20, 20], [380, 20], [20, 220], [380, 220]].map(([x, y], i) => (
        <g key={i} transform={`translate(${x},${y})`}>
          <circle r="6" fill="none" stroke="#ef8c1a" strokeWidth="1.4" />
          <circle r="2" fill="#ef8c1a" />
          {[0, 90, 180, 270].map((a) => (
            <line key={a} x1="0" y1="0"
                  x2={Math.cos(a * Math.PI / 180) * 12}
                  y2={Math.sin(a * Math.PI / 180) * 12}
                  stroke="#ef8c1a" strokeWidth="1" />
          ))}
        </g>
      ))}
      {/* trace top */}
      <path d="M 30,20 L 90,20 L 90,28 L 150,28 L 150,20 L 250,20 L 250,28 L 310,28 L 310,20 L 370,20"
            fill="none" stroke="#ef8c1a" strokeWidth="1.2" opacity=".75" />
      {/* trace bottom */}
      <path d="M 30,220 L 80,220 L 80,212 L 140,212 L 140,220 L 260,220 L 260,212 L 320,212 L 320,220 L 370,220"
            fill="none" stroke="#ef8c1a" strokeWidth="1.2" opacity=".75" />
      {/* via dots */}
      {[90, 150, 250, 310, 80, 140, 260, 320].map((x, i) => (
        <circle key={i} cx={x} cy={i < 4 ? 28 : 212} r="2" fill="#ef8c1a" />
      ))}
      {/* side traces */}
      <path d="M 20,40 L 28,40 L 28,90 L 20,90 M 20,150 L 28,150 L 28,200 L 20,200" fill="none" stroke="#ef8c1a" strokeWidth="1.2" opacity=".75" />
      <path d="M 380,40 L 372,40 L 372,90 L 380,90 M 380,150 L 372,150 L 372,200 L 380,200" fill="none" stroke="#ef8c1a" strokeWidth="1.2" opacity=".75" />
    </svg>
  );
}

function Venue() {
  return (
    <section id="venue" className="venue" data-screen-label="03 Where & When">
      <div className="venue-bg">
        <KalamkariVine size={260} color="#06727d" accent="#9d0d4a" />
      </div>
      <div className="container">
        <div className="center scroll-in">
          <div className="eyebrow">Where & When</div>
          <h2 className="section-title">How to reach us</h2>
          <p className="section-sub">{CONFIG.venueName} · {CONFIG.city}, {CONFIG.state}</p>
        </div>

        <div className="venue-grid scroll-in">
          <div className="map-card">
            <MapArt />
            <div className="map-pin active" style={{ left: "50%", top: "55%" }}>
              <svg viewBox="0 0 36 48" width="44" height="58">
                <path d="M 18,2 C 9,2 3,9 3,18 C 3,30 18,46 18,46 C 18,46 33,30 33,18 C 33,9 27,2 18,2 Z" fill="#9d0d4a" stroke="#1a0e2e" strokeWidth="1.5"/>
                <circle cx="18" cy="18" r="6" fill="#fbf3e1"/>
              </svg>
            </div>
          </div>

          <div className="venue-info">
            <div className="travel-options">
              <div className="opt">
                <div className="ico"><TravelIcon kind="plane" /></div>
                <div>
                  <strong>By Air — Kanpur Airport (KNU)</strong>
                  <small>Daily flights from DEL · BOM · BLR</small>
                </div>
                <div className="km">14 km</div>
              </div>
              <div className="opt">
                <div className="ico"><TravelIcon kind="train" /></div>
                <div>
                  <strong>By Train — Kanpur Central (CNB)</strong>
                  <small>Major junction · auto/taxi at exit</small>
                </div>
                <div className="km">6 km</div>
              </div>
              <div className="opt">
                <div className="ico"><TravelIcon kind="car" /></div>
                <div>
                  <strong>By Road — Lucknow Highway</strong>
                  <small>~1.5 hrs from Lucknow on NH 27</small>
                </div>
                <div className="km">90 km</div>
              </div>
              <div className="opt">
                <div className="ico"><TravelIcon kind="hotel" /></div>
                <div>
                  <strong>Where to stay</strong>
                  <small>Block held — code SACHAN27</small>
                </div>
                <div className="km">5 min</div>
              </div>
            </div>

            <SmartCard />
          </div>
        </div>
      </div>
    </section>
  );
}

/* ===================================================================
   FRIENDS SECTION (passcode-gated game + memories + generator)
=================================================================== */
function FriendsSection() {
  const params = aUseMemo(() => {
    try {
      const u = new URL(window.location.href);
      const q = u.searchParams.get("key") || u.searchParams.get("passcode");
      const h = (u.hash || "").match(/key=([^&]+)/);
      return (q || (h && h[1]) || "").toUpperCase();
    } catch { return ""; }
  }, []);

  const stored = (() => {
    try { return (localStorage.getItem("friendsUnlocked") === "1"); } catch { return false; }
  })();

  const [unlocked, setUnlocked] = aUseState(stored || params === CONFIG.friendsPasscode.toUpperCase());
  const [inputCode, setInputCode] = aUseState("");
  const [shake, setShake] = aUseState(false);
  const [tab, setTab] = aUseState("game");

  aUseEffect(() => {
    if (unlocked) {
      try { localStorage.setItem("friendsUnlocked", "1"); } catch (e) {}
    }
  }, [unlocked]);

  const tryUnlock = (e) => {
    e.preventDefault();
    if (inputCode.trim().toUpperCase() === CONFIG.friendsPasscode.toUpperCase()) {
      setUnlocked(true);
    } else {
      setShake(true);
      setTimeout(() => setShake(false), 600);
    }
  };

  return (
    <section id="friends" className="friends" data-screen-label="05 Friends">
      <div className="friends-bg-a"><WarliDance size={220} color="#ef8c1a" /></div>
      <div className="friends-bg-b"><PhadLotus size={240} color="#ef8c1a" accent="#fbf3e1" /></div>

      <div className="container center scroll-in" style={{ position: "relative", zIndex: 2 }}>
        <div className="eyebrow">For our friends</div>
        <h2 className="section-title">A little something extra</h2>
        <p className="section-sub">Play a quick game, drop a memory, make your own save-the-date card.</p>

        {!unlocked ? (
          <div className={`gate ${shake ? "shake" : ""}`}>
            <div className="gate-lock">🔒</div>
            <div className="gate-title">Friends only — enter the passcode</div>
            <div className="gate-sub">
              We sent it to you on WhatsApp. Or just add <code>?key=YOURCODE</code> to the link.
            </div>
            <form onSubmit={tryUnlock} className="gate-form">
              <input
                type="text"
                value={inputCode}
                onChange={(e) => setInputCode(e.target.value)}
                placeholder="e.g. DOSTI2027"
                autoCapitalize="characters"
                spellCheck="false"
              />
              <button type="submit" className="btn-primary">Unlock</button>
            </form>
            <div className="gate-hint">
              Hint: the Hindi word for friendship, followed by the year.
            </div>
          </div>
        ) : (
          <div className="friends-unlocked">
            <div className="schedule-tabs" style={{ margin: "30px auto 10px" }}>
              <button className={tab === "game" ? "active" : ""} onClick={() => setTab("game")}>Maze Game</button>
              <button className={tab === "memories" ? "active" : ""} onClick={() => setTab("memories")}>Memories</button>
              <button className={tab === "card" ? "active" : ""} onClick={() => setTab("card")}>Save-the-Date</button>
            </div>
            {tab === "game" && <GamePanel />}
            {tab === "memories" && <MemoriesPanel />}
            {tab === "card" && (
              <div style={{ marginTop: 30 }}>
                <ImageGenerator dateLine={CONFIG.dateDisplay} names={[CONFIG.groomName, CONFIG.brideName]} />
              </div>
            )}
          </div>
        )}
      </div>
    </section>
  );
}

/* ---- Game panel + notes (unchanged content) ---- */
function GamePanel() {
  const [unlockedNotes, setUnlockedNotes] = aUseState(false);
  const [tab, setTab] = aUseState("from-him");
  const notes = {
    "from-him": { title: "From Madhurendra",
      body: `Diksha,\n\nThe first time I saw you, you were arguing with the chai-wala over change. You won, of course. I think that's when I decided I never wanted to argue with you about anything.\n\nYou make even Mondays feel like a festival. You let me be quieter than I am, and louder than I should be. You laugh at my jokes a beat too late, like you're double-checking they're worth it — and then you laugh harder than anyone in the room.\n\nThese two days are the easy part. The lifetime after is the part I'm really showing up for.\n\nForever your fan,`,
      sign: "— Madhurendra" },
    "from-her": { title: "From Diksha",
      body: `Madhu,\n\nI used to imagine the kind of person I'd marry, and I used to be wrong about most of it. You showed up with terrible playlists, a strange love for pickle in everything, and the calmest pair of eyes I've ever met.\n\nI am marrying my best friend, my Saturday plan, my emergency contact, and the person who will eat the last gulab jamun so I can pretend I am being good. There is no version of this life I want without you in it.\n\nThank you for being patient when I was loud, and loud when I was patient.\n\nYours, completely,`,
      sign: "— Diksha" },
    "to-you": { title: "To everyone reading this",
      body: `Thank you — really. You found the door, you typed the password, you made it through the maze.\n\nThese two days only happen because of the people who keep showing up for us. Our parents. Our friends. The aunties who fed us. The cousins who choreographed Sangeet. The strangers who became family.\n\nCome early. Eat too much. Dance badly. Take terrible selfies. Cry a little at the vidaai.\n\nWith all our love,`,
      sign: "— Madhurendra & Diksha" }
  };
  return (
    <div style={{ marginTop: 30, position: "relative" }}>
      <MazeGame onWin={() => setUnlockedNotes(true)} />
      {unlockedNotes && unlockedNotes !== "show" && (
        <div style={{ marginTop: 28, textAlign: "center" }}>
          <button className="btn-primary" onClick={() => setUnlockedNotes("show")}>Read the personal notes ♥</button>
        </div>
      )}
      {unlockedNotes === "show" && (
        <div className="notes-overlay" onClick={(e) => { if (e.target === e.currentTarget) setUnlockedNotes(true); }}>
          <div className="notes-card">
            <button className="close" onClick={() => setUnlockedNotes(true)} aria-label="close">✕</button>
            <div className="from">A letter, just for you</div>
            <h2>{notes[tab].title}</h2>
            <div className="tabs">
              <button className={tab === "from-him" ? "active" : ""} onClick={() => setTab("from-him")}>From Him</button>
              <button className={tab === "from-her" ? "active" : ""} onClick={() => setTab("from-her")}>From Her</button>
              <button className={tab === "to-you" ? "active" : ""} onClick={() => setTab("to-you")}>To You</button>
            </div>
            <div className="letter">
              {notes[tab].body.split("\n").map((p, i) => <p key={i} style={{ margin: "0 0 12px" }}>{p}</p>)}
              <div className="sign">{notes[tab].sign}</div>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

function MemoriesPanel() {
  const [memForm, setMemForm] = aUseState({ name: "", relation: "", message: "" });
  const [files, setFiles] = aUseState([]);
  const [wishes, setWishes] = aUseState([]);
  const [dragOver, setDragOver] = aUseState(false);

  aUseEffect(() => { setWishes(JSON.parse(localStorage.getItem("wishes") || "[]")); }, []);

  const addFiles = (fl) => {
    const arr = Array.from(fl).slice(0, 6 - files.length);
    Promise.all(arr.map((f) => new Promise((res) => {
      const r = new FileReader(); r.onload = () => res(r.result); r.readAsDataURL(f);
    }))).then((dataUrls) => setFiles((p) => [...p, ...dataUrls]));
  };

  const submit = (e) => {
    e.preventDefault();
    if (!memForm.message.trim()) return;
    const all = [{ ...memForm, files, ts: Date.now() }, ...wishes].slice(0, 20);
    localStorage.setItem("wishes", JSON.stringify(all));
    setWishes(all);
    setMemForm({ name: "", relation: "", message: "" });
    setFiles([]);
  };

  return (
    <div className="mem-grid" style={{ marginTop: 30 }}>
      <form className="mem-card" onSubmit={submit} style={{ textAlign: "left" }}>
        <div className="field">
          <label>Your name</label>
          <input type="text" value={memForm.name} onChange={(e) => setMemForm({ ...memForm, name: e.target.value })} placeholder="e.g. Riya Aunty" required />
        </div>
        <div className="field">
          <label>How do you know us?</label>
          <input type="text" value={memForm.relation} onChange={(e) => setMemForm({ ...memForm, relation: e.target.value })} placeholder="College friend / Cousin / Neighbour…" />
        </div>
        <div className="field">
          <label>Your message / memory</label>
          <textarea value={memForm.message} onChange={(e) => setMemForm({ ...memForm, message: e.target.value })} placeholder="Write about a moment, a wish, a bit of advice…" required />
        </div>
        <div className="field">
          <label>Upload photos (up to 6)</label>
          <div className={`upload-zone ${dragOver ? "dragging" : ""}`}
            onDragOver={(e) => { e.preventDefault(); setDragOver(true); }}
            onDragLeave={() => setDragOver(false)}
            onDrop={(e) => { e.preventDefault(); setDragOver(false); addFiles(e.dataTransfer.files); }}>
            <input type="file" accept="image/*" multiple onChange={(e) => addFiles(e.target.files)} />
            <div className="ico">
              <svg viewBox="0 0 48 48" width="48" height="48">
                <rect x="6" y="10" width="36" height="28" rx="4" fill="none" stroke="#ef8c1a" strokeWidth="2"/>
                <circle cx="16" cy="22" r="3" fill="#ef8c1a"/>
                <path d="M 8,36 L 20,24 L 28,30 L 36,22 L 42,28" fill="none" stroke="#ef8c1a" strokeWidth="2"/>
              </svg>
            </div>
            <p>Drop images here or tap to choose</p>
            <p className="hint">JPG · PNG · up to 6 files</p>
          </div>
          {files.length > 0 && <div className="thumbs">{files.map((u, i) => <img key={i} src={u} alt="" />)}</div>}
        </div>
        <button type="submit" className="btn-primary" style={{ marginTop: 8 }}>Send Memory →</button>
      </form>
      <div className="wishboard">
        <h3>✦ The Wish Wall</h3>
        {wishes.length === 0 && (
          <div style={{ fontFamily: "Cormorant Garamond, serif", fontStyle: "italic", color: "rgba(251,243,225,.6)", padding: "20px 0" }}>
            Be the first to leave a note. Your message will appear here.
          </div>
        )}
        {wishes.map((w, i) => (
          <div key={i} className="wish">
            “{w.message}”
            <span className="by">— {w.name || "Anonymous"}{w.relation ? ` · ${w.relation}` : ""}</span>
            {w.files && w.files.length > 0 && (
              <div className="thumbs" style={{ marginTop: 8 }}>
                {w.files.map((u, j) => <img key={j} src={u} alt="" style={{ width: 48, height: 48 }} />)}
              </div>
            )}
          </div>
        ))}
      </div>
    </div>
  );
}

/* ---------------- FOOTER ---------------- */
function Footer() {
  return (
    <footer className="footer">
      <div style={{ marginBottom: 16, display: "grid", placeItems: "center" }}>
        <Mandala size={80} color="#fbf3e1" accent="#ef8c1a" strokeW={1} rings={3} />
      </div>
      <div className="names">{CONFIG.groomName} & {CONFIG.brideName}</div>
      <div className="sub">30 — 31 · January · 2027 · {CONFIG.city}</div>
      <div className="mark">◆ MADE WITH LOVE FOR FAMILY & FRIENDS ◆</div>
    </footer>
  );
}

/* ---------------- APP ---------------- */
function App() {
  const [doorOpen, setDoorOpen] = aUseState(false);
  const [activeId, setActiveId] = aUseState("hero");
  const [fabricModal, setFabricModal] = aUseState(null);

  aUseEffect(() => {
    // Three.js cinema layer — init once
    if (!window.Cinema) return;
    const canvas = document.getElementById("cinema-canvas");
    if (!canvas) return;
    try { window.Cinema.init(canvas); } catch (e) { console.warn("Cinema init failed", e); }

    // scroll → camera waypoint progress (0..1 across whole document)
    const onScroll = () => {
      const max = Math.max(1, document.documentElement.scrollHeight - window.innerHeight);
      window.Cinema.setScroll(window.scrollY / max);
    };
    // mouse → particle / camera parallax
    const onMove = (e) => {
      const t = e.touches ? e.touches[0] : e;
      const nx = (t.clientX / window.innerWidth) * 2 - 1;
      const ny = (t.clientY / window.innerHeight) * 2 - 1;
      window.Cinema.setMouse(nx, ny);
    };
    const onOrient = (ev) => {
      if (ev.gamma == null) return;
      window.Cinema.setMouse(
        Math.max(-1, Math.min(1, ev.gamma / 45)),
        Math.max(-1, Math.min(1, (ev.beta - 30) / 60)),
      );
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("mousemove", onMove, { passive: true });
    window.addEventListener("touchmove", onMove, { passive: true });
    window.addEventListener("deviceorientation", onOrient);
    onScroll();
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("touchmove", onMove);
      window.removeEventListener("deviceorientation", onOrient);
    };
  }, []);

  aUseEffect(() => {
    // site-wide scroll-reveal
    const els = document.querySelectorAll(".scroll-in");
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => { if (e.isIntersecting) e.target.classList.add("is-visible"); });
    }, { threshold: 0.15 });
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, [doorOpen]);

  aUseEffect(() => {
    if (!doorOpen) return;
    const ids = NAV.map((n) => n.id);
    const onScroll = () => {
      let best = "hero", bestT = -Infinity;
      ids.forEach((id) => {
        const el = document.getElementById(id);
        if (!el) return;
        const top = el.getBoundingClientRect().top;
        if (top < window.innerHeight / 3 && top > bestT) {
          bestT = top; best = id;
        }
      });
      setActiveId(best);
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, [doorOpen]);

  return (
    <div className="app">
      <Opener onOpen={() => setDoorOpen(true)} />
      {doorOpen && <Nav activeId={activeId} />}
      <Hero />
      <ScrollStory />
      <EventsTabs />
      <FabricDivider kind="bandhani" onOpen={setFabricModal} />
      <Venue />
      <FabricDivider kind="phulkari" onOpen={setFabricModal} />
      <FriendsSection />
      <FabricDivider kind="patola" onOpen={setFabricModal} />
      <Footer />
      {fabricModal && <FabricModal kind={fabricModal} onClose={() => setFabricModal(null)} />}
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
