// boda.jsx — Estadía · Guía de Boda (demo "Ana & Carlos")
// Misma arquitectura interactiva que la guía de Airbnb, con tema de boda.
const { useState, useEffect, useRef, createContext, useContext } = React;

// ===================== Paleta (suave y clara) =====================
const C = {
  ivory: "#FBF8F2", cream: "#F4EEE3", paper: "#FFFFFF",
  ink: "#3A3631", soft: "#6B655C", faint: "#A89F90",
  line: "#E6DFD2",
  sage: "#8A9A7B", sageDeep: "#5E6E50", sageSoft: "#EaEee3",
  gold: "#C2A468", goldDeep: "#A8884A"
};
const SERIF = "'Cormorant Garamond', Georgia, serif";
const SANS = "'Jost', system-ui, sans-serif";

// ===================== Imágenes (stock suave de boda) =====================
const IMG = typeof window !== "undefined" && window.__BODA_IMG || {
  cover: "https://images.unsplash.com/photo-1519741497674-611481863552?auto=format&fit=crop&w=1400&q=75",
  story1: "https://images.unsplash.com/photo-1606800052052-a08af7148866?auto=format&fit=crop&w=1000&q=75",
  story2: "https://images.unsplash.com/photo-1583939003579-730e3918a45a?auto=format&fit=crop&w=1000&q=75",
  venue: "https://images.unsplash.com/photo-1464366400600-7168b8af9bc3?auto=format&fit=crop&w=1200&q=75",
  dress1: "https://images.unsplash.com/photo-1594552072238-b8a33785b261?auto=format&fit=crop&w=800&q=75",
  dress2: "https://images.unsplash.com/photo-1566174053879-31528523f8ae?auto=format&fit=crop&w=800&q=75"
};

// ===================== Invitado (nombre dinámico desde la URL) =====================
// Soporta:  /boda/ana-carlos/maria-rivera   ·   ?g=maria-rivera   ·   ?invitado=...
function parseGuest() {
  let slug = "";
  try {
    const q = new URLSearchParams(location.search);
    slug = q.get("g") || q.get("invitado") || q.get("guest") || "";
    if (!slug) {
      const parts = location.pathname.split("/").filter(Boolean);
      const i = parts.indexOf("boda");
      if (i >= 0 && parts[i + 2]) slug = decodeURIComponent(parts[i + 2]);
    }
  } catch (e) {}
  const isDemo = !slug; // sin invitado en la URL = modo demo (marketing)
  if (!slug) slug = "maria-rivera"; // demo por defecto
  const name = slug.split(/[-_]/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
  const first = name.split(" ")[0];
  return { slug, name, first, isDemo };
}
const GUEST = parseGuest();
// Saludo con género aproximado (es). En inglés es neutro.
function greet(lang) {
  if (lang === "en") return "Welcome, " + GUEST.name;
  const f = GUEST.first.toLowerCase();
  const fem = f === "familia" || /a$/.test(f);
  return (fem ? "Bienvenida" : "Bienvenido") + " " + GUEST.name;
}

// ===================== Audio (loop suave) =====================
class AudioPlayer {
  constructor(src) {this.src = src;this.audio = null;this.target = 0.5;this.fadeTimer = null;this.playing = false;}
  _init() {this.audio = new Audio(this.src);this.audio.loop = true;this.audio.preload = "auto";this.audio.volume = 0;try {this.audio.load();} catch (e) {}}
  _fadeTo(target, ms) {if (!this.audio) return;if (this.fadeTimer) clearInterval(this.fadeTimer);const start = this.audio.volume;const steps = Math.max(1, Math.round(ms / 60));let i = 0;
    this.fadeTimer = setInterval(() => {i++;const v = start + (target - start) * (i / steps);try {this.audio.volume = Math.max(0, Math.min(1, v));} catch (e) {}if (i >= steps) {clearInterval(this.fadeTimer);this.fadeTimer = null;if (target === 0) {try {this.audio.pause();} catch (e) {}}}}, 60);}
  play() {if (!this.audio) this._init();this.playing = true;const p = this.audio.play();if (p && p.catch) p.catch(() => {});this._fadeTo(this.target, 2500);}
  stop() {this.playing = false;if (!this.audio) return;this._fadeTo(0, 1200);}
}
let _player = null;
const getPlayer = () => _player || (_player = new AudioPlayer("audio/piano.mp3"));
const _audioSubs = new Set();
const audioState = { isOn: (() => {try {return sessionStorage.getItem("boda_audio") !== "0";} catch (e) {return true;}})() };
const setAudioOn = (on) => {if (audioState.isOn === on) return;audioState.isOn = on;_audioSubs.forEach((fn) => fn(on));};
const startAudio = () => {getPlayer().play();setAudioOn(true);try {sessionStorage.setItem("boda_audio", "1");} catch (e) {}};
const stopAudio = () => {getPlayer().stop();setAudioOn(false);try {sessionStorage.setItem("boda_audio", "0");} catch (e) {}};

function SoundToggle({ tone = "light" }) {
  const [on, setOn] = useState(audioState.isOn);
  useEffect(() => {_audioSubs.add(setOn);return () => {_audioSubs.delete(setOn);};}, []);
  const toggle = () => {audioState.isOn ? stopAudio() : startAudio();};
  const fg = on ? C.gold : tone === "dark" ? C.ivory : C.soft;
  const bg = on ? "rgba(194,164,104,0.18)" : tone === "dark" ? "rgba(251,248,242,0.20)" : "rgba(58,54,49,0.07)";
  return (
    <button onClick={toggle} aria-label="música" title="música"
    style={{ width: 34, height: 34, border: "none", borderRadius: 100, background: bg, color: fg, cursor: "pointer",
      display: "inline-flex", alignItems: "center", justifyContent: "center", flexShrink: 0, transition: "all .25s" }}>
      <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
        <path d="M8 17 V 6 L 19 4 V 15"><animateTransform attributeName="transform" type="translate" dur="2.4s" repeatCount="indefinite" values="0 0; 0 -0.6; 0 0" /></path>
        <circle cx="6" cy="17" r="2.2" fill="currentColor" stroke="none" />
        <circle cx="17" cy="15" r="2.2" fill="currentColor" stroke="none" />
        {!on && <line x1="3" y1="3" x2="21" y2="21" stroke="currentColor" strokeWidth="1.7" opacity="0.55" />}
      </svg>
    </button>);

}

// ===================== i18n =====================
const LangCtx = createContext({ lang: "es", setLang: () => {} });
const useLang = () => useContext(LangCtx);
const tr = (v, lang) => typeof v === "string" ? v : v?.[lang] ?? "";

// ===================== DATOS (demo Ana & Carlos) =====================
const WEDDING_DATE = "2027-03-13T17:00:00"; // fecha de la boda (demo)
const DATA = {
  couple: { a: "Ana", b: "Carlos", hashtag: "#AnaYCarlos2027" },
  dateLabel: { es: "Sábado, 13 de marzo de 2027", en: "Saturday, March 13, 2027" },
  city: { es: "Hacienda Siesta Alegre · Río Grande, PR", en: "Hacienda Siesta Alegre · Río Grande, PR" },
  welcome: {
    es: "Con muchísima alegría queremos compartir contigo el día más importante de nuestras vidas. Aquí encontrarás todos los detalles para acompañarnos. ¡No podemos esperar a celebrar contigo!",
    en: "With so much joy, we want to share the most important day of our lives with you. Here you'll find every detail to join us. We can't wait to celebrate with you!"
  },
  story: {
    es: "Nos conocimos una tarde de verano en el Viejo San Juan, entre café y conversación que no terminaba. Siete años, dos mudanzas y un perrito después, Carlos se arrodilló frente al mar en Cabo Rojo. Dijimos que sí — y ahora queremos celebrarlo rodeados de la gente que amamos.",
    en: "We met one summer afternoon in Old San Juan, over coffee and a conversation that never ended. Seven years, two moves and one puppy later, Carlos got down on one knee by the sea in Cabo Rojo. We said yes — and now we want to celebrate surrounded by the people we love."
  },
  itinerary: [
  { icon: "⛪", time: "4:30 PM", title: { es: "Ceremonia", en: "Ceremony" }, note: { es: "Jardín principal. Llega 20 minutos antes, por favor.", en: "Main garden. Please arrive 20 minutes early." } },
  { icon: "🥂", time: "5:30 PM", title: { es: "Cóctel", en: "Cocktail hour" }, note: { es: "Terraza con vista. Música en vivo y pasapalos.", en: "Terrace with a view. Live music and hors d'oeuvres." } },
  { icon: "🍽️", time: "7:00 PM", title: { es: "Recepción", en: "Reception" }, note: { es: "Cena, brindis y nuestro primer baile.", en: "Dinner, toasts and our first dance." } },
  { icon: "💃", time: "10:00 PM", title: { es: "After Party", en: "After Party" }, note: { es: "¡A bailar hasta tarde! Zapatos cómodos recomendados.", en: "Dancing into the night! Comfy shoes recommended." } },
  { icon: "☕", time: "11:00 AM", title: { es: "Brunch (domingo)", en: "Brunch (Sunday)" }, note: { es: "Despedida relajada para quienes se queden.", en: "A relaxed farewell for those who stay over." } }],

  locations: [
  { name: { es: "Hacienda Siesta Alegre", en: "Hacienda Siesta Alegre" }, role: { es: "Ceremonia y recepción", en: "Ceremony & reception" }, mapq: "Hacienda Siesta Alegre, Rio Grande, Puerto Rico" },
  { name: { es: "Estacionamiento", en: "Parking" }, role: { es: "Gratis en el lugar · valet disponible", en: "Free on-site · valet available" }, mapq: "Hacienda Siesta Alegre, Rio Grande, Puerto Rico" }],

  dress: {
    code: { es: "Formal de jardín", en: "Garden formal" },
    note: {
      es: "Tonos tierra, verde salvia y pasteles suaves. Ellas: vestido largo o midi. Ellos: traje claro o guayabera elegante. Evita el blanco, por favor 😊. Tacones de aguja no recomendados (césped).",
      en: "Earth tones, sage green and soft pastels. Her: long or midi dress. Him: light suit or elegant guayabera. Please avoid white 😊. Stilettos not recommended (grass)."
    }
  },
  hotels: [
  { name: "Wyndham Grand Rio Mar", type: { es: "Hotel · 10 min", en: "Hotel · 10 min" }, note: { es: "Bloque de habitaciones con tarifa especial — menciona 'Boda Ana & Carlos'.", en: "Room block with special rate — mention 'Ana & Carlos Wedding'." }, mapq: "Wyndham Grand Rio Mar Puerto Rico" },
  { name: "Hyatt Regency Grand Reserve", type: { es: "Resort · 12 min", en: "Resort · 12 min" }, note: { es: "Ideal para familias. Piscinas y playa.", en: "Great for families. Pools and beach." }, mapq: "Hyatt Regency Grand Reserve Puerto Rico" },
  { name: { es: "Airbnbs en Río Grande", en: "Airbnbs in Río Grande" }, type: { es: "Casas · 5-15 min", en: "Homes · 5-15 min" }, note: { es: "Perfectos para grupos. Reserva temprano.", en: "Perfect for groups. Book early." }, mapq: "Rio Grande Puerto Rico" }],

  registry: [
  { name: "Amazon", note: { es: "Lista de regalos", en: "Gift list" }, url: "https://www.amazon.com" },
  { name: "Crate & Barrel", note: { es: "Para el hogar", en: "For the home" }, url: "https://www.crateandbarrel.com" },
  { name: { es: "Luna de miel", en: "Honeymoon fund" }, note: { es: "Ayúdanos a soñar", en: "Help us dream" }, url: "https://www.paypal.com" }]

};

// ===================== Labels =====================
const L = {
  kicker: { es: "NOS CASAMOS", en: "WE'RE GETTING MARRIED" },
  welcomeSub: { es: "Ana & Carlos desean compartir este momento contigo", en: "Ana & Carlos would love to share this moment with you" },
  slideToOpen: { es: "Desliza para abrir", en: "Slide to open" },
  dragRibbon: { es: "Arrastra el listón con los anillos →", en: "Drag the ribbon with the rings →" },
  gladToShare: { es: "Nos alegra compartir este día contigo", en: "We're so glad to share this day with you" },
  coverLead: { es: "Acompáñanos a celebrar nuestro amor", en: "Join us to celebrate our love" },
  openGuide: { es: "Abrir invitación", en: "Open invitation" },
  countdown: { es: "FALTAN", en: "COUNTDOWN" },
  days: { es: "días", en: "days" }, hours: { es: "horas", en: "hrs" }, mins: { es: "min", en: "min" }, secs: { es: "seg", en: "sec" },

  sec_inicio: { es: "Inicio", en: "Welcome" }, sec_historia: { es: "Historia", en: "Our Story" },
  sec_itinerario: { es: "Itinerario", en: "Itinerary" }, sec_lugar: { es: "Lugar", en: "Location" },
  sec_dress: { es: "Dress Code", en: "Dress Code" }, sec_hospedaje: { es: "Hospedaje", en: "Stay" },
  sec_regalos: { es: "Regalos", en: "Registry" }, sec_rsvp: { es: "RSVP", en: "RSVP" },

  h_inicio: { es: "¡Bienvenidos!", en: "Welcome!" },
  h_historia: { es: "Nuestra historia", en: "Our story" },
  h_itinerario: { es: "El gran día", en: "The big day" },
  h_lugar: { es: "Dónde será", en: "Where" },
  h_dress: { es: "¿Qué me pongo?", en: "What to wear" },
  h_hospedaje: { es: "Dónde quedarse", en: "Where to stay" },
  h_regalos: { es: "Mesa de regalos", en: "Gift registry" },
  h_rsvp: { es: "Confirma tu asistencia", en: "Confirm your attendance" },

  k_bienvenida: { es: "Con cariño", en: "With love" },
  k_nosotros: { es: "Ana & Carlos", en: "Ana & Carlos" },
  k_agenda: { es: "Agenda del día", en: "The day" },
  k_comollegar: { es: "Cómo llegar", en: "Getting there" },
  k_estilo: { es: "Código de vestimenta", en: "Dress code" },
  k_dormir: { es: "Hoteles y casas", en: "Hotels & homes" },
  k_detalle: { es: "Un detalle", en: "A gift" },
  k_confirma: { es: "Te esperamos", en: "We're saving you a seat" },

  regalosLead: { es: "Tu presencia es nuestro mejor regalo. Si deseas obsequiarnos algo, aquí tienes algunas ideas.", en: "Your presence is the greatest gift. If you'd like to give us something, here are a few ideas." },
  hospLead: { es: "Reserva con tiempo — la zona se llena en temporada de bodas.", en: "Book early — the area fills up during wedding season." },
  rsvpLead: { es: "Por favor confírmanos antes del 1 de febrero de 2027.", en: "Please let us know before February 1, 2027." },
  yes: { es: "Sí, ahí estaré", en: "Yes, I'll be there" },
  no: { es: "No podré asistir", en: "I can't make it" },
  rsvpThanksYes: { es: "¡Qué alegría! Nos vemos pronto 💛", en: "So happy! See you soon 💛" },
  rsvpThanksNo: { es: "Te vamos a extrañar. Gracias por avisar 🤍", en: "We'll miss you. Thanks for letting us know 🤍" },
  parking: { es: "Estacionamiento", en: "Parking" },
  openMap: { es: "Abrir en el mapa", en: "Open in maps" },
  dressCodeLabel: { es: "Código", en: "Code" },
  withLove: { es: "Con amor,", en: "With love," }
};
const t = (k, lang) => tr(L[k], lang) || k;

const SECTIONS = [
{ id: "inicio", labelKey: "sec_inicio" },
{ id: "historia", labelKey: "sec_historia" },
{ id: "itinerario", labelKey: "sec_itinerario" },
{ id: "lugar", labelKey: "sec_lugar" },
{ id: "dress", labelKey: "sec_dress" },
{ id: "hospedaje", labelKey: "sec_hospedaje" },
{ id: "regalos", labelKey: "sec_regalos" },
{ id: "rsvp", labelKey: "sec_rsvp" }];


// ===================== UI compartida =====================
function mapsUrl(q) {return "https://www.google.com/maps/search/?api=1&query=" + encodeURIComponent(q);}

function Photo({ src, alt, h = 220 }) {
  return <div style={{ height: h, overflow: "hidden", borderRadius: 6, background: C.sageSoft }}>
    <img src={src} alt={alt} style={{ width: "100%", height: "100%", objectFit: "cover", display: "block" }} />
  </div>;
}

function MapPin({ query, label }) {
  const { lang } = useLang();
  return <a href={mapsUrl(query)} target="_blank" rel="noopener noreferrer" onClick={(e) => e.stopPropagation()}
  style={{ display: "inline-flex", alignItems: "center", gap: 5, fontFamily: SANS, fontSize: 11, letterSpacing: "0.12em",
    textTransform: "uppercase", color: C.sageDeep, textDecoration: "none", whiteSpace: "nowrap", fontWeight: 500 }}>
    <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M21 10c0 7-9 12-9 12s-9-5-9-12a9 9 0 0 1 18 0Z" /><circle cx="12" cy="10" r="3" />
    </svg>{label || (lang === "es" ? "Mapa" : "Map")}
  </a>;
}

function Monogram({ size = 58, color = C.gold }) {
  return <svg width={size} height={size} viewBox="0 0 100 100" fill="none">
    <circle cx="50" cy="50" r="47" stroke={color} strokeWidth="1.3" />
    <text x="34" y="60" textAnchor="middle" fontFamily={SERIF} fontStyle="italic" fontSize="34" fill={color}>A</text>
    <text x="51" y="62" textAnchor="middle" fontFamily={SERIF} fontSize="20" fill={color} opacity="0.8">&amp;</text>
    <text x="68" y="60" textAnchor="middle" fontFamily={SERIF} fontStyle="italic" fontSize="34" fill={color}>C</text>
  </svg>;
}

function SectionHeader({ num, kicker, title }) {
  return <div style={{ marginBottom: 26 }}>
    <div style={{ display: "flex", alignItems: "center", gap: 10, fontFamily: SANS, fontSize: 11, letterSpacing: "0.22em",
      textTransform: "uppercase", color: C.faint, marginBottom: 14, fontWeight: 500 }}>
      <span>{num}</span><span style={{ flex: 1, height: 1, background: C.line }}></span><span>{kicker}</span>
    </div>
    <h2 style={{ fontFamily: SERIF, fontSize: 44, lineHeight: 1.0, color: C.ink, margin: 0, fontWeight: 500, letterSpacing: "-0.01em" }}>{title}</h2>
  </div>;
}

function Divider() {
  return <div style={{ display: "flex", alignItems: "center", gap: 14, margin: "44px 0", color: C.gold }}>
    <span style={{ flex: 1, height: 1, background: C.line }}></span>
    <span style={{ fontFamily: SERIF, fontSize: 20 }}>❦</span>
    <span style={{ flex: 1, height: 1, background: C.line }}></span>
  </div>;
}

function LangPill() {
  const { lang, setLang } = useLang();
  return <div style={{ display: "inline-flex", background: "rgba(58,54,49,0.08)", borderRadius: 100, padding: 3 }}>
    {["es", "en"].map((l) =>
    <button key={l} onClick={() => setLang(l)} style={{ border: "none",
      background: lang === l ? C.ink : "transparent", color: lang === l ? C.ivory : C.soft, fontFamily: SANS, fontSize: 10,
      letterSpacing: "0.15em", padding: "6px 11px", borderRadius: 100, cursor: "pointer", fontWeight: 600 }}>{l.toUpperCase()}</button>
    )}
  </div>;
}

// ===================== Countdown =====================
function useCountdown(target) {
  const [now, setNow] = useState(Date.now());
  useEffect(() => {const id = setInterval(() => setNow(Date.now()), 1000);return () => clearInterval(id);}, []);
  const diff = Math.max(0, new Date(target).getTime() - now);
  const d = Math.floor(diff / 86400000);
  const h = Math.floor(diff / 3600000) % 24;
  const m = Math.floor(diff / 60000) % 60;
  const s = Math.floor(diff / 1000) % 60;
  return { d, h, m, s };
}

function Countdown({ tone = "light" }) {
  const { lang } = useLang();
  const { d, h, m, s } = useCountdown(WEDDING_DATE);
  const col = tone === "dark" ? C.ivory : C.ink;
  const sub = tone === "dark" ? "rgba(251,248,242,0.65)" : C.faint;
  const items = [[d, t("days", lang)], [h, t("hours", lang)], [m, t("mins", lang)], [s, t("secs", lang)]];
  return <div style={{ display: "flex", gap: 0, justifyContent: "center" }}>
    {items.map(([val, lbl], i) =>
    <div key={i} style={{ flex: 1, textAlign: "center", borderLeft: i ? `1px solid ${tone === "dark" ? "rgba(251,248,242,0.25)" : C.line}` : "none" }}>
        <div style={{ fontFamily: SERIF, fontSize: 38, lineHeight: 1, color: col, fontWeight: 500 }}>{String(val).padStart(2, "0")}</div>
        <div style={{ fontFamily: SANS, fontSize: 9, letterSpacing: "0.18em", textTransform: "uppercase", color: sub, marginTop: 6 }}>{lbl}</div>
      </div>
    )}
  </div>;
}

// ===================== Botánica vectorial (baby's breath, rosas, bokeh) =====================
function _rng(seed) {let s = seed;return () => (s = (s * 9301 + 49297) % 233280) / 233280;}

// Baby's breath — ramillete de florecitas blancas desde una esquina
function Puff({ x, y, r }) {
  const pet = [];
  for (let i = 0; i < 6; i++) {const a = i / 6 * Math.PI * 2;pet.push(<circle key={i} cx={x + Math.cos(a) * r} cy={y + Math.sin(a) * r} r={r * 0.6} fill="#FFFFFF" />);}
  return <g>{pet}<circle cx={x} cy={y} r={r * 0.68} fill="#FBF1D6" /></g>;
}
function BabysBreath({ size = 240, seed = 3, opacity = 1 }) {
  const rand = _rng(seed);const stems = [],blooms = [];
  const N = 10;
  for (let i = 0; i < N; i++) {
    const a = i / N * (Math.PI * 0.52) + 0.06;
    const len = size * (0.42 + rand() * 0.5);
    const ex = Math.cos(a) * len,ey = Math.sin(a) * len;
    const cx = Math.cos(a - 0.35) * len * 0.6,cy = Math.sin(a - 0.35) * len * 0.6;
    stems.push(<path key={"s" + i} d={`M0 0 Q ${cx} ${cy} ${ex} ${ey}`} stroke="#AEC29C" strokeWidth="0.9" fill="none" opacity="0.55" />);
    const nb = 3 + Math.floor(rand() * 3);
    for (let j = 0; j < nb; j++) {
      const tt = 0.45 + j / nb * 0.55;
      const bx = 2 * (1 - tt) * tt * cx + tt * tt * ex;
      const by = 2 * (1 - tt) * tt * cy + tt * tt * ey;
      blooms.push(<Puff key={"b" + i + "_" + j} x={bx} y={by} r={2.4 + rand() * 1.7} />);
    }
  }
  return <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} style={{ display: "block", opacity }}>{stems}{blooms}</svg>;
}

// Rosa de jardín (capas de pétalos)
function Rose({ cx, cy, R, rot = 0, light = "#FCF7EE", mid = "#F1E6CF", deep = "#E4D4AF" }) {
  const g = [];const layers = [{ r: R, pr: R * 0.5, n: 8, col: light }, { r: R * 0.64, pr: R * 0.4, n: 7, col: mid }, { r: R * 0.36, pr: R * 0.3, n: 6, col: deep }];
  layers.forEach((Lr, li) => {for (let i = 0; i < Lr.n; i++) {
      const a = rot + i / Lr.n * Math.PI * 2 + li * 0.4;const px = cx + Math.cos(a) * Lr.r * 0.5,py = cy + Math.sin(a) * Lr.r * 0.5;
      g.push(<ellipse key={li + "_" + i} cx={px} cy={py} rx={Lr.pr} ry={Lr.pr * 0.68} fill={Lr.col} stroke="#DAC9A2" strokeWidth="0.5" transform={`rotate(${a * 180 / Math.PI + 90} ${px} ${py})`} />);
    }});
  g.push(<circle key="c" cx={cx} cy={cy} r={R * 0.2} fill={deep} />);
  return <g>{g}</g>;
}
function Leaf({ cx, cy, len, rot, col = "#9DB389" }) {
  return <g transform={`rotate(${rot} ${cx} ${cy})`}>
    <path d={`M${cx} ${cy} q ${len * 0.3} ${-len * 0.42} ${len} 0 q ${-len * 0.7} ${len * 0.42} ${-len} 0 z`} fill={col} />
    <line x1={cx} y1={cy} x2={cx + len} y2={cy} stroke="#86A073" strokeWidth="0.7" />
  </g>;
}
// Ramo de esquina: rosas + hojas + baby's breath
function RoseCorner({ size = 230, seed = 5, flip = false }) {
  return (
    <svg width={size} height={size} viewBox="0 0 230 230" style={{ display: "block", transform: flip ? "scaleX(-1)" : "none" }}>
      <Leaf cx={70} cy={70} len={58} rot={20} col="#A6BA92" />
      <Leaf cx={60} cy={95} len={50} rot={70} col="#92A87E" />
      <Leaf cx={110} cy={55} len={52} rot={-25} col="#A6BA92" />
      <g transform="translate(8,8)"><BabysBreath size={150} seed={seed + 2} /></g>
      <Rose cx={62} cy={66} R={40} rot={0.3} />
      <Rose cx={108} cy={92} R={34} rot={1.1} light="#FBF4E6" mid="#EFE2C8" />
      <Rose cx={92} cy={44} R={28} rot={2.0} />
      <Leaf cx={120} cy={110} len={44} rot={120} col="#8FA67B" />
    </svg>);

}

// Bokeh dorado (luces suaves)
function Bokeh({ seed = 9, count = 16 }) {
  const rand = _rng(seed);const dots = [];
  for (let i = 0; i < count; i++) {
    const sz = 6 + rand() * 26;
    dots.push(<span key={i} style={{ position: "absolute", left: (rand() * 100).toFixed(1) + "%", top: (rand() * 100).toFixed(1) + "%",
      width: sz, height: sz, borderRadius: "50%", background: "radial-gradient(circle, rgba(244,228,176,0.9) 0%, rgba(226,196,120,0.25) 55%, transparent 75%)",
      filter: "blur(1px)", opacity: (0.3 + rand() * 0.5).toFixed(2), pointerEvents: "none" }} />);
  }
  return <div style={{ position: "absolute", inset: 0, overflow: "hidden", pointerEvents: "none" }}>{dots}</div>;
}
// Pétalos dispersos
function Petals({ seed = 11, count = 10 }) {
  const rand = _rng(seed);const ps = [];
  for (let i = 0; i < count; i++) {
    const w = 8 + rand() * 10;
    ps.push(<div key={i} style={{ position: "absolute", left: (rand() * 100).toFixed(1) + "%", top: (rand() * 100).toFixed(1) + "%",
      width: w, height: w * 0.7, borderRadius: "60% 60% 62% 62% / 80% 80% 50% 50%", background: "linear-gradient(180deg,#FFFFFF,#F1E7D4)",
      boxShadow: "0 2px 5px rgba(168,136,74,0.18)", transform: `rotate(${(rand() * 360).toFixed(0)}deg)`, opacity: (0.55 + rand() * 0.4).toFixed(2), pointerEvents: "none" }} />);
  }
  return <div style={{ position: "absolute", inset: 0, overflow: "hidden", pointerEvents: "none" }}>{ps}</div>;
}

// ===================== Portada =====================
function Cover({ onEnter }) {
  const { lang } = useLang();
  return (
    <section style={{ padding: 0, position: "relative", height: "100%", overflow: "hidden",
      background: "radial-gradient(circle at 50% 18%, #F3ECDC 0%, #E9DFC9 55%, #DACDB0 100%)" }}>
      {/* atmósfera */}
      <Bokeh seed={4} count={20} />
      <Petals seed={8} count={12} />
      {/* sobre detrás (esquinas) */}
      <div style={{ position: "absolute", inset: 0, pointerEvents: "none",
        background: "linear-gradient(135deg, rgba(233,220,193,0.0) 60%, rgba(214,197,163,0.55) 100%), linear-gradient(-135deg, rgba(233,220,193,0.0) 60%, rgba(214,197,163,0.45) 100%)" }} />

      {/* barra superior */}
      <div style={{ position: "absolute", top: 16, right: 16, display: "flex", alignItems: "center", gap: 8, zIndex: 5 }}>
        <SoundToggle /><LangPill />
      </div>

      {/* Tarjeta enmarcada */}
      <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", padding: "30px 22px" }}>
        <div style={{ position: "relative", width: "100%", maxWidth: 360, background: "linear-gradient(180deg,#FFFDF8,#FBF6EC)",
          boxShadow: "0 40px 80px -34px rgba(120,98,60,0.55)", padding: 8 }}>
          {/* doble marco dorado */}
          <div style={{ border: "1px solid rgba(194,164,104,0.9)", padding: 3 }}>
            <div style={{ border: "1px solid rgba(194,164,104,0.45)", padding: "44px 20px 30px", position: "relative", overflow: "hidden" }}>
              {/* flores esquina */}
              <div style={{ position: "absolute", top: -26, left: -30, pointerEvents: "none" }}><RoseCorner size={200} seed={5} /></div>
              <div style={{ position: "absolute", bottom: -34, right: -34, pointerEvents: "none" }}><RoseCorner size={190} seed={9} flip /></div>

              <div style={{ position: "relative", textAlign: "center" }}>
                <div style={{ fontFamily: SANS, fontSize: 11, letterSpacing: "0.2em", textTransform: "uppercase", color: C.sageDeep, lineHeight: 1.7 }}>
                  {lang === "es" ? "Con mucha alegría" : "With great joy"}<br />{lang === "es" ? "te invitamos a nuestra boda" : "we invite you to our wedding"}
                </div>
                <div style={{ color: C.gold, fontSize: 15, margin: "10px 0 4px" }}>♥</div>
                <h1 style={{ fontFamily: SERIF, fontSize: 50, lineHeight: 1.04, color: C.sageDeep, margin: "4px 0 8px", fontWeight: 500, whiteSpace: "nowrap" }}>
                  Ana <span style={{ fontStyle: "italic", color: C.gold }}>&amp;</span> Carlos
                </h1>
                <div style={{ color: C.gold, fontSize: 15, marginBottom: 18 }}>❦</div>

                <div style={{ fontFamily: SANS, fontSize: 14, letterSpacing: "0.12em", textTransform: "uppercase", color: C.ink, fontWeight: 500 }}>{tr(DATA.dateLabel, lang)}</div>
                <div style={{ fontFamily: SERIF, fontSize: 18, fontStyle: "italic", color: C.goldDeep, marginTop: 6, marginBottom: 22 }}>{tr(DATA.city, lang)}</div>

                {/* countdown */}
                <div style={{ background: "rgba(255,255,255,0.7)", border: `1px solid ${C.line}`, borderRadius: 6, padding: "16px 14px", marginBottom: 22 }}>
                  <div style={{ fontFamily: SANS, fontSize: 9, letterSpacing: "0.22em", textTransform: "uppercase", color: C.faint, marginBottom: 12 }}>{t("countdown", lang)}</div>
                  <Countdown />
                </div>

                <button onClick={onEnter} style={{ width: "100%", padding: "16px", background: C.sageDeep, color: C.ivory, border: "none",
                  borderRadius: 3, fontFamily: SANS, fontWeight: 600, fontSize: 12, letterSpacing: "0.18em", textTransform: "uppercase", cursor: "pointer",
                  display: "flex", alignItems: "center", justifyContent: "center", gap: 10, boxShadow: "0 12px 24px -12px rgba(94,110,80,0.7)" }}>
                  {lang === "es" ? "Comenzar a explorar" : "Start exploring"} <span style={{ fontSize: 16 }}>→</span>
                </button>
                <div style={{ marginTop: 16, fontFamily: SANS, fontSize: 11, letterSpacing: "0.18em", color: C.gold }}>{DATA.couple.hashtag}</div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>);

}

// ===================== Secciones =====================
function Inicio() {
  const { lang } = useLang();
  return <section>
    <SectionHeader num="01" kicker={t("k_bienvenida", lang)} title={t("h_inicio", lang)} />
    <div style={{ textAlign: "center", marginBottom: 24 }}><Monogram size={64} /></div>
    <p style={{ fontFamily: SERIF, fontSize: 21, fontStyle: "italic", color: C.sageDeep, textAlign: "center", margin: "0 0 18px" }}>{t("gladToShare", lang)}, {GUEST.first}.</p>
    <p style={{ fontSize: 17, lineHeight: 1.7, color: C.ink, marginBottom: 28, fontFamily: SERIF, textAlign: "center" }}>{tr(DATA.welcome, lang)}</p>
    <div style={{ background: C.sageSoft, borderRadius: 8, padding: "22px 20px", textAlign: "center" }}>
      <div style={{ fontFamily: SANS, fontSize: 10, letterSpacing: "0.2em", textTransform: "uppercase", color: C.sageDeep, marginBottom: 14 }}>{t("countdown", lang)}</div>
      <Countdown />
    </div>
  </section>;
}

function Historia() {
  const { lang } = useLang();
  return <section>
    <SectionHeader num="02" kicker={t("k_nosotros", lang)} title={t("h_historia", lang)} />
    <Photo src={IMG.story1} alt="" h={230} />
    <p style={{ fontSize: 16, lineHeight: 1.75, color: C.ink, margin: "24px 0", fontFamily: SERIF }}>{tr(DATA.story, lang)}</p>
    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
      <Photo src={IMG.story2} alt="" h={150} />
      <Photo src={IMG.venue} alt="" h={150} />
    </div>
  </section>;
}

function Itinerario() {
  const { lang } = useLang();
  return <section>
    <SectionHeader num="03" kicker={t("k_agenda", lang)} title={t("h_itinerario", lang)} />
    <div style={{ position: "relative" }}>
      {DATA.itinerary.map((it, i) =>
      <div key={i} style={{ display: "flex", gap: 16, padding: "4px 0 26px", position: "relative" }}>
          <div style={{ display: "flex", flexDirection: "column", alignItems: "center", flexShrink: 0 }}>
            <div style={{ width: 46, height: 46, borderRadius: "50%", background: C.sageSoft, border: `1px solid ${C.line}`,
            display: "flex", alignItems: "center", justifyContent: "center", fontSize: 20 }}>{it.icon}</div>
            {i < DATA.itinerary.length - 1 && <div style={{ flex: 1, width: 1, background: C.line, marginTop: 6, minHeight: 30 }}></div>}
          </div>
          <div style={{ flex: 1, paddingTop: 2 }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 10, marginBottom: 4, background: "rgba(234, 238, 227, 0)" }}>
              <h3 style={{ fontFamily: SERIF, fontSize: 25, color: C.ink, margin: 0, fontWeight: 500 }}>{tr(it.title, lang)}</h3>
              <span style={{ fontFamily: SANS, fontSize: 12, letterSpacing: "0.1em", color: C.gold, fontWeight: 600, whiteSpace: "nowrap" }}>{it.time}</span>
            </div>
            <p style={{ fontSize: 14, color: C.soft, lineHeight: 1.55, margin: 0 }}>{tr(it.note, lang)}</p>
          </div>
        </div>
      )}
    </div>
  </section>;
}

function Lugar() {
  const { lang } = useLang();
  return <section>
    <SectionHeader num="04" kicker={t("k_comollegar", lang)} title={t("h_lugar", lang)} />
    <Photo src={IMG.venue} alt="" h={210} />
    <div style={{ height: 22 }} />
    {DATA.locations.map((lo, i) =>
    <div key={i} style={{ padding: "16px 0", borderBottom: i === DATA.locations.length - 1 ? "none" : `1px solid ${C.line}` }}>
        <div style={{ fontFamily: SERIF, fontSize: 24, color: C.ink, fontWeight: 500, marginBottom: 2 }}>{tr(lo.name, lang)}</div>
        <div style={{ fontSize: 13, color: C.soft, marginBottom: 10 }}>{tr(lo.role, lang)}</div>
        <MapPin query={lo.mapq} label={t("openMap", lang)} />
      </div>
    )}
  </section>;
}

function Dress() {
  const { lang } = useLang();
  return <section>
    <SectionHeader num="05" kicker={t("k_estilo", lang)} title={t("h_dress", lang)} />
    <div style={{ textAlign: "center", borderRadius: 8, padding: "22px 18px", marginBottom: 22, background: "rgb(234, 238, 227)" }}>
      <div style={{ fontFamily: SANS, fontSize: 10, letterSpacing: "0.2em", textTransform: "uppercase", color: C.sageDeep, marginBottom: 8 }}>{t("dressCodeLabel", lang)}</div>
      <div style={{ fontFamily: SERIF, fontSize: 32, color: C.ink, fontWeight: 500 }}>{tr(DATA.dress.code, lang)}</div>
    </div>
    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 20 }}>
      <Photo src={IMG.dress1} alt="" h={200} />
      <Photo src={IMG.dress2} alt="" h={200} />
    </div>
    <p style={{ fontSize: 15, lineHeight: 1.7, color: C.ink, fontFamily: SERIF }}>{tr(DATA.dress.note, lang)}</p>
    {/* paleta de colores sugerida */}
    <div style={{ display: "flex", gap: 10, justifyContent: "center", marginTop: 22 }}>
      {["#D8C7A8", "#8A9A7B", "#C2A468", "#E3D7C3", "#A88C6A"].map((c, i) =>
      <div key={i} style={{ width: 38, height: 38, borderRadius: "50%", background: c, border: `1px solid ${C.line}` }}></div>
      )}
    </div>
  </section>;
}

function Hospedaje() {
  const { lang } = useLang();
  return <section>
    <SectionHeader num="06" kicker={t("k_dormir", lang)} title={t("h_hospedaje", lang)} />
    <p style={{ fontSize: 15, lineHeight: 1.65, color: C.soft, marginBottom: 22, fontStyle: "italic", fontFamily: SERIF }}>{t("hospLead", lang)}</p>
    {DATA.hotels.map((ho, i) =>
    <div key={i} style={{ padding: "16px 0", borderBottom: i === DATA.hotels.length - 1 ? "none" : `1px solid ${C.line}` }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 10, marginBottom: 4 }}>
          <div style={{ fontFamily: SERIF, fontSize: 23, color: C.ink, fontWeight: 500 }}>{tr(ho.name, lang)}</div>
          <span style={{ fontFamily: SANS, fontSize: 11, letterSpacing: "0.08em", color: C.gold, fontWeight: 600, whiteSpace: "nowrap" }}>{tr(ho.type, lang)}</span>
        </div>
        <p style={{ fontSize: 14, color: C.soft, lineHeight: 1.55, margin: "0 0 8px" }}>{tr(ho.note, lang)}</p>
        <MapPin query={ho.mapq} label={t("openMap", lang)} />
      </div>
    )}
  </section>;
}

function Regalos() {
  const { lang } = useLang();
  return <section>
    <SectionHeader num="07" kicker={t("k_detalle", lang)} title={t("h_regalos", lang)} />
    <p style={{ fontSize: 16, lineHeight: 1.7, color: C.ink, marginBottom: 26, fontFamily: SERIF, textAlign: "center" }}>{t("regalosLead", lang)}</p>
    <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
      {DATA.registry.map((r, i) =>
      <a key={i} href={r.url} target="_blank" rel="noopener noreferrer"
      style={{ display: "flex", justifyContent: "space-between", alignItems: "center", background: C.paper,
        border: `1px solid ${C.line}`, borderRadius: 8, padding: "18px 20px", textDecoration: "none" }}>
          <div>
            <div style={{ fontFamily: SERIF, fontSize: 22, color: C.ink, fontWeight: 500 }}>{tr(r.name, lang)}</div>
            <div style={{ fontSize: 13, color: C.soft }}>{tr(r.note, lang)}</div>
          </div>
          <span style={{ color: C.gold, fontSize: 22 }}>→</span>
        </a>
      )}
    </div>
  </section>;
}

function RSVP() {
  const { lang } = useLang();
  const [resp, setResp] = useState(null);
  return <section>
    <SectionHeader num="08" kicker={t("k_confirma", lang)} title={t("h_rsvp", lang)} />
    <p style={{ fontSize: 15, lineHeight: 1.65, color: C.soft, marginBottom: 26, fontStyle: "italic", fontFamily: SERIF, textAlign: "center" }}>{t("rsvpLead", lang)}</p>
    {!resp ?
    <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
        <button onClick={() => setResp("yes")} style={{ padding: "18px", background: C.sageDeep, color: C.ivory, border: "none", borderRadius: 4,
        fontFamily: SANS, fontWeight: 600, fontSize: 13, letterSpacing: "0.12em", textTransform: "uppercase", cursor: "pointer" }}>{t("yes", lang)}</button>
        <button onClick={() => setResp("no")} style={{ padding: "18px", background: "transparent", color: C.ink, border: `1px solid ${C.ink}`, borderRadius: 4,
        fontFamily: SANS, fontWeight: 600, fontSize: 13, letterSpacing: "0.12em", textTransform: "uppercase", cursor: "pointer" }}>{t("no", lang)}</button>
      </div> :

    <div style={{ textAlign: "center", background: C.sageSoft, borderRadius: 8, padding: "34px 24px" }}>
        <div style={{ fontFamily: SERIF, fontSize: 26, color: C.ink, lineHeight: 1.25 }}>{resp === "yes" ?
        lang === "es" ? `¡Gracias ${GUEST.name} por confirmar! Nos vemos pronto 💛` : `Thank you ${GUEST.name} for confirming! See you soon 💛` :
        lang === "es" ? `Te vamos a extrañar, ${GUEST.first}. Gracias por avisar 🤍` : `We'll miss you, ${GUEST.first}. Thanks for letting us know 🤍`}</div>
        <button onClick={() => setResp(null)} style={{ marginTop: 18, background: "none", border: "none", color: C.sageDeep,
        fontFamily: SANS, fontSize: 12, letterSpacing: "0.1em", textTransform: "uppercase", cursor: "pointer", textDecoration: "underline" }}>
          {lang === "es" ? "Cambiar respuesta" : "Change answer"}
        </button>
      </div>
    }
    <div style={{ marginTop: 44, textAlign: "center", paddingTop: 30, borderTop: `1px solid ${C.line}` }}>
      <Monogram size={52} />
      <div style={{ fontFamily: SERIF, fontSize: 17, fontStyle: "italic", color: C.soft, margin: "12px 0 4px" }}>{t("withLove", lang)}</div>
      <div style={{ fontFamily: SERIF, fontSize: 26, color: C.ink, fontWeight: 500 }}>Ana &amp; Carlos</div>
    </div>
  </section>;
}

const COMPONENTS = { inicio: Inicio, historia: Historia, itinerario: Itinerario, lugar: Lugar, dress: Dress, hospedaje: Hospedaje, regalos: Regalos, rsvp: RSVP };

// ===================== Anillos dorados entrelazados =====================
// ===================== Anillos dorados (se unen al tocar) =====================
function Rings({ joined }) {
  // separados: gap; unidos: se entrelazan (overlap)
  const dx = joined ? 16 : 40;
  return (
    <div style={{ position: "relative", width: 200, height: 120, filter: "drop-shadow(0 6px 10px rgba(168,136,74,0.4))" }}>
      <svg width="200" height="120" viewBox="0 0 200 120" fill="none" style={{ position: "absolute", inset: 0 }}>
        <defs>
          <linearGradient id="goldA" x1="0" y1="0" x2="1" y2="1">
            <stop offset="0" stopColor="#F0DCA8" /><stop offset="0.5" stopColor="#C2A468" /><stop offset="1" stopColor="#A8884A" />
          </linearGradient>
          <linearGradient id="goldB" x1="0" y1="0" x2="1" y2="1">
            <stop offset="0" stopColor="#F4E4B4" /><stop offset="0.5" stopColor="#CDAE70" /><stop offset="1" stopColor="#B0904E" />
          </linearGradient>
          <radialGradient id="joinGlow" cx="0.5" cy="0.5" r="0.5">
            <stop offset="0" stopColor="#FFF3D0" stopOpacity={joined ? 0.95 : 0} /><stop offset="1" stopColor="#FFF3D0" stopOpacity="0" />
          </radialGradient>
        </defs>
        {/* destello al unirse */}
        <circle cx="100" cy="60" r="46" fill="url(#joinGlow)" style={{ transition: "opacity .5s ease" }} />
        {/* anillo izquierdo */}
        <g style={{ transition: "transform .85s cubic-bezier(.34,1.4,.5,1)", transform: `translateX(${-dx}px) rotate(-9deg)`, transformOrigin: "100px 60px" }}>
          <circle cx="100" cy="60" r="34" stroke="url(#goldA)" strokeWidth="9" />
          <ellipse cx="86" cy="42" rx="4" ry="8" fill="#FFFFFF" opacity="0.5" transform="rotate(-30 86 42)" />
        </g>
        {/* anillo derecho */}
        <g style={{ transition: "transform .85s cubic-bezier(.34,1.4,.5,1)", transform: `translateX(${dx}px) rotate(9deg)`, transformOrigin: "100px 60px" }}>
          <circle cx="100" cy="60" r="34" stroke="url(#goldB)" strokeWidth="9" />
          <ellipse cx="114" cy="42" rx="4" ry="8" fill="#FFFFFF" opacity="0.5" transform="rotate(30 114 42)" />
        </g>
      </svg>
    </div>);

}

// ===================== Pantalla de bienvenida (un toque une los anillos) =====================
function Welcome({ onOpen }) {
  const { lang } = useLang();
  const [joined, setJoined] = useState(false);
  const [opening, setOpening] = useState(false);
  const sparks = useRef(Array.from({ length: 20 }, () => ({
    left: Math.random() * 100, top: Math.random() * 100, delay: (Math.random() * 5).toFixed(2), dur: (2.4 + Math.random() * 3.2).toFixed(2), size: (2 + Math.random() * 4).toFixed(1)
  }))).current;

  const join = () => {
    if (joined) return;
    setJoined(true);
    startAudio(); // la música comienza al unirse — símbolo de unión
    setTimeout(() => setOpening(true), 2800);
    setTimeout(() => onOpen(), 3700);
  };

  const hintText = lang === "es" ?
    <>Toca para unir los anillos</> :
    <>Tap to join the rings</>;
  const unionText = lang === "es" ?
    <>Dos historias, una sola vida</> :
    <>Two stories, one life</>;

  return (
    <div className="welcome" style={{
      position: "absolute", inset: 0, overflowY: "auto", overflowX: "hidden",
      background: "linear-gradient(118deg, #FBF4E6 0%, #F2E7D1 16%, #FDF8EE 30%, #ECDDC2 46%, #FCF7EA 60%, #EFE2C7 78%, #FAF3E3 100%)",
      opacity: opening ? 0 : 1, transform: opening ? "scale(1.06)" : "scale(1)", filter: opening ? "blur(3px)" : "none",
      transition: "opacity .9s ease, transform .9s ease, filter .9s ease"
    }}>
      {/* pliegues de seda */}
      <div style={{ position: "absolute", inset: 0, pointerEvents: "none",
        background: "radial-gradient(120% 60% at 80% 18%, rgba(255,255,255,0.55), transparent 55%), radial-gradient(120% 70% at 12% 92%, rgba(255,255,255,0.4), transparent 55%), radial-gradient(90% 50% at 50% 50%, rgba(214,190,128,0.10), transparent 70%)" }} />
      {/* baby's breath esquinas */}
      <div style={{ position: "absolute", top: -14, left: -10, pointerEvents: "none", opacity: 0.95 }}><BabysBreath size={210} seed={6} /></div>
      <div style={{ position: "absolute", bottom: -14, right: -10, pointerEvents: "none", opacity: 0.95, transform: "rotate(180deg)" }}><BabysBreath size={200} seed={14} /></div>

      {/* destellos */}
      {sparks.map((sp, i) =>
      <span key={i} className="spark" style={{ left: sp.left + "%", top: sp.top + "%", width: sp.size + "px", height: sp.size + "px", ["--d"]: sp.dur + "s", animationDelay: sp.delay + "s" }} />
      )}

      {/* contenido centrado */}
      <div style={{ position: "relative", zIndex: 2, minHeight: "100%", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", padding: "54px 28px", textAlign: "center", boxSizing: "border-box" }}>
        {/* texto */}
        <div style={{ marginBottom: 30 }}>
          <div style={{ fontFamily: SANS, fontSize: 12, letterSpacing: "0.32em", textTransform: "uppercase", color: C.gold, marginBottom: 12 }}>{t("kicker", lang)}</div>
          <div style={{ fontFamily: SERIF, fontSize: 30, color: C.gold, fontStyle: "italic", lineHeight: 1.1, marginBottom: 4 }}>{lang === "en" ? "Welcome" : /(a|familia)$/i.test(GUEST.first) ? "Bienvenida" : "Bienvenido"}</div>
          <h1 style={{ fontFamily: SERIF, fontSize: 44, lineHeight: 1.12, color: C.ink, margin: "0 0 22px", fontWeight: 600 }}>{GUEST.name}</h1>
          <p style={{ fontFamily: SERIF, fontSize: 20, fontStyle: "italic", lineHeight: 1.45, color: C.soft, margin: "0 auto", maxWidth: 300 }}>{t("welcomeSub", lang)}</p>
        </div>

        {/* anillos — un toque los une */}
        <button onClick={join} aria-label={lang === "es" ? "Unir los anillos" : "Join the rings"} style={{
          background: "none", border: "none", cursor: joined ? "default" : "pointer", padding: 10,
          borderRadius: "50%", outline: "none", WebkitTapHighlightColor: "transparent"
        }}>
          <div className={joined ? "" : "rings-breathe"}><Rings joined={joined} /></div>
        </button>

        {/* pista / mensaje de unión */}
        <div style={{ position: "relative", zIndex: 2, marginTop: 18, minHeight: 64 }}>
          {!joined ?
          <React.Fragment>
            <div style={{ display: "flex", justifyContent: "center", marginBottom: 8 }}>
              <svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke={C.gold} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" className="chev">
                <path d="M9 11V6.5a1.5 1.5 0 0 1 3 0V11" /><path d="M12 11V5a1.5 1.5 0 0 1 3 0v6" /><path d="M15 11V7.5a1.5 1.5 0 0 1 3 0V14a6 6 0 0 1-6 6h-2.2a5 5 0 0 1-3.5-1.5L4 15.5a1.6 1.6 0 0 1 2.3-2.2L8 15V9a1.5 1.5 0 0 1 3 0" />
              </svg>
            </div>
            <div style={{ fontFamily: SERIF, fontSize: 20, fontStyle: "italic", color: C.goldDeep, lineHeight: 1.35 }}>{hintText}</div>
          </React.Fragment> :

          <div className="union-msg" style={{ fontFamily: SERIF, fontSize: 23, fontStyle: "italic", color: C.sageDeep, lineHeight: 1.35 }}>
            ♥ {unionText}
          </div>
          }
        </div>
      </div>

      <div style={{ position: "absolute", top: 18, right: 18, zIndex: 4, display: "flex", alignItems: "center", gap: 8 }}><SoundToggle /><LangPill /></div>
    </div>);

}

// ===================== CTA demo (solo marketing, no en invitaciones reales) =====================
function DemoCTA({ lang }) {
  if (!GUEST.isDemo) return null;
  try { if (window.self !== window.top) return null; } catch (e) { return null; } // oculto si va embebido (iframe)
  return (
    <a href="bodas-formulario.html" style={{
      position: "absolute", left: "50%", bottom: 16, transform: "translateX(-50%)", zIndex: 60,
      display: "inline-flex", alignItems: "center", gap: 8, whiteSpace: "nowrap",
      background: "rgba(94,110,80,0.95)", color: "#FBF8F2", textDecoration: "none",
      fontFamily: "'Jost',sans-serif", fontSize: 13, fontWeight: 600, letterSpacing: "0.04em",
      padding: "12px 20px", borderRadius: 100, boxShadow: "0 14px 30px -12px rgba(58,54,49,0.6)",
      backdropFilter: "blur(6px)", WebkitBackdropFilter: "blur(6px)"
    }}>
      💍 {lang === "en" ? "Create your own invitation" : "Crea la invitación de tu boda"} →
    </a>
  );
}

// ===================== App =====================
function App() {
  const [lang, setLang] = useState("es");
  const [view, setView] = useState("welcome");
  const [active, setActive] = useState("inicio");
  const scrollRef = useRef(null);

  const scrollTo = (id) => {setActive(id);const el = document.getElementById(`section-${id}`);
    if (el && scrollRef.current) {scrollRef.current.scrollTo({ top: el.offsetTop - 70, behavior: "smooth" });}};

  useEffect(() => {
    if (view !== "guide") return;
    const onScroll = () => {if (!scrollRef.current) return;const top = scrollRef.current.scrollTop + 90;
      for (let i = SECTIONS.length - 1; i >= 0; i--) {const el = document.getElementById(`section-${SECTIONS[i].id}`);
        if (el && el.offsetTop <= top) {setActive(SECTIONS[i].id);break;}}};
    const sc = scrollRef.current;sc?.addEventListener("scroll", onScroll);return () => sc?.removeEventListener("scroll", onScroll);
  }, [view]);

  const ctx = { lang, setLang };

  if (view === "welcome") {
    return <LangCtx.Provider value={ctx}><div className="phone"><Welcome onOpen={() => setView("cover")} /><DemoCTA lang={lang} /></div></LangCtx.Provider>;
  }

  if (view === "cover") {
    return <LangCtx.Provider value={ctx}><div className="phone"><Cover onEnter={() => {if (audioState.isOn) getPlayer().play();setView("guide");}} /><DemoCTA lang={lang} /></div></LangCtx.Provider>;
  }

  return (
    <LangCtx.Provider value={ctx}>
      <div className="phone">
        {/* Top bar */}
        <div style={{ position: "absolute", top: 0, left: 0, right: 0, height: 58, background: "rgba(251,248,242,0.92)",
          backdropFilter: "blur(10px)", WebkitBackdropFilter: "blur(10px)", borderBottom: `1px solid ${C.line}`,
          display: "flex", alignItems: "center", justifyContent: "space-between", padding: "0 18px", zIndex: 20 }}>
          <button onClick={() => {setView("cover");setActive("inicio");}} style={{ background: "none", border: "none", cursor: "pointer",
            fontFamily: SERIF, fontSize: 22, color: C.ink, display: "flex", alignItems: "center", gap: 6, fontWeight: 500 }}>
            <span style={{ fontStyle: "italic" }}>A</span><span style={{ color: C.gold }}>&amp;</span><span style={{ fontStyle: "italic" }}>C</span>
          </button>
          <div style={{ display: "flex", alignItems: "center", gap: 8 }}><SoundToggle /><LangPill /></div>
        </div>

        {/* Nav tabs */}
        <div style={{ position: "absolute", top: 58, left: 0, right: 0, height: 44, background: C.ivory, borderBottom: `1px solid ${C.line}`,
          display: "flex", alignItems: "center", gap: 4, padding: "0 12px", overflowX: "auto", zIndex: 19, whiteSpace: "nowrap" }} className="navscroll">
          {SECTIONS.map((s) =>
          <button key={s.id} onClick={() => scrollTo(s.id)} style={{ flexShrink: 0, border: "none", background: active === s.id ? C.sageDeep : "transparent",
            color: active === s.id ? C.ivory : C.soft, fontFamily: SANS, fontSize: 12, fontWeight: active === s.id ? 600 : 500, letterSpacing: "0.04em",
            padding: "7px 13px", borderRadius: 100, cursor: "pointer", transition: "all .2s" }}>{t(s.labelKey, lang)}</button>
          )}
        </div>

        {/* Scroll body */}
        <div ref={scrollRef} style={{ position: "absolute", top: 102, left: 0, right: 0, bottom: 0, overflowY: "auto", background: C.ivory }}>
          <div style={{ padding: "34px 26px 60px" }}>
            {SECTIONS.map((s, i) => {const Comp = COMPONENTS[s.id];return (
                <div key={s.id} id={`section-${s.id}`}>
                <Comp />
                {i < SECTIONS.length - 1 && <Divider />}
              </div>);
            })}
          </div>
        </div>
      </div>
    </LangCtx.Provider>);

}

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