// Convite — Chá de Bebê Emanuela
// Componente principal do convite, com RSVP e tweaks.

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

// Paletas de tema (sálvia, rosa antigo, lavanda, mel)
const PALETTES = {
  salvia: {
    name: "Sálvia",
    bg: "#f3efe6",
    paper: "#fbf8f1",
    ink: "#33372a",
    inkSoft: "#5a5e4e",
    accent: "#8a9a7b",
    accentDeep: "#5b6b51",
    blush: "#c9a99a",
    line: "#d8d1be",
  },
  rosa: {
    name: "Rosa antigo",
    bg: "#f6ece6",
    paper: "#fcf5f0",
    ink: "#3c2e2a",
    inkSoft: "#6b5750",
    accent: "#c08a82",
    accentDeep: "#9a6058",
    blush: "#d9b1a8",
    line: "#e6cfc4",
  },
  lavanda: {
    name: "Lavanda",
    bg: "#efeaf2",
    paper: "#f9f5fb",
    ink: "#352e3d",
    inkSoft: "#605668",
    accent: "#9b8aaf",
    accentDeep: "#6e5d83",
    blush: "#c5b1d1",
    line: "#dfd3e3",
  },
  mel: {
    name: "Mel",
    bg: "#f5ecd9",
    paper: "#fcf6e6",
    ink: "#3d3320",
    inkSoft: "#6a5b3e",
    accent: "#c4a25b",
    accentDeep: "#937535",
    blush: "#d8be84",
    line: "#e6d4a8",
  },
};

// ─────────────────────────────────────────────────────────────────────────────
// Pontos flutuantes — animação ambiente suave
function FloatingDots({ color }) {
  const dots = useMemo(() => {
    return Array.from({ length: 22 }).map((_, i) => ({
      left: Math.random() * 100,
      top: Math.random() * 100,
      size: 2 + Math.random() * 4,
      delay: Math.random() * 8,
      duration: 9 + Math.random() * 8,
      opacity: 0.25 + Math.random() * 0.45,
    }));
  }, []);
  return (
    <div style={{ position: "absolute", inset: 0, overflow: "hidden", pointerEvents: "none" }}>
      {dots.map((d, i) => (
        <span
          key={i}
          style={{
            position: "absolute",
            left: `${d.left}%`,
            top: `${d.top}%`,
            width: d.size,
            height: d.size,
            borderRadius: "50%",
            background: color,
            opacity: d.opacity,
            animation: `dotFloat ${d.duration}s ease-in-out ${d.delay}s infinite`,
          }}
        />
      ))}
    </div>
  );
}

// Nome revelado letra-por-letra
function RevealedName({ name, color }) {
  const letters = useMemo(() => name.split(""), [name]);
  return (
    <h1
      style={{
        fontFamily: '"Cormorant Garamond", serif',
        fontWeight: 300,
        fontStyle: "italic",
        fontSize: "clamp(64px, 13vw, 168px)",
        lineHeight: 0.95,
        color,
        margin: 0,
        letterSpacing: "-0.02em",
        textAlign: "center",
      }}
    >
      {letters.map((ch, i) => (
        <span
          key={i}
          style={{
            display: "inline-block",
            opacity: 0,
            animation: `letterIn 1.1s cubic-bezier(.2,.7,.2,1) ${0.4 + i * 0.09}s forwards`,
            transform: "translateY(18px)",
          }}
        >
          {ch === " " ? "\u00A0" : ch}
        </span>
      ))}
    </h1>
  );
}

// Pequeno ornamento de regra com ponto
function Rule({ color, label }) {
  return (
    <div style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 14, color }}>
      <span style={{ flex: 1, height: 1, background: "currentColor", opacity: 0.35, maxWidth: 80 }} />
      <span style={{ fontFamily: '"Cormorant Garamond", serif', fontStyle: "italic", fontSize: 16, opacity: 0.7, letterSpacing: "0.04em" }}>
        {label}
      </span>
      <span style={{ flex: 1, height: 1, background: "currentColor", opacity: 0.35, maxWidth: 80 }} />
    </div>
  );
}

// Card com bloco de informação
function InfoBlock({ kicker, title, body, color, soft }) {
  return (
    <div style={{ textAlign: "center", color: color }}>
      <div style={{ fontFamily: "Inter, sans-serif", fontSize: 10.5, fontWeight: 500, letterSpacing: "0.28em", textTransform: "uppercase", color: soft, marginBottom: 14 }}>
        {kicker}
      </div>
      <div style={{ fontFamily: '"Cormorant Garamond", serif', fontSize: 36, fontWeight: 400, lineHeight: 1.1, marginBottom: 8 }}>
        {title}
      </div>
      {body && (
        <div style={{ fontFamily: "Inter, sans-serif", fontSize: 14, color: soft, lineHeight: 1.6 }}>
          {body}
        </div>
      )}
    </div>
  );
}

// Contador regressivo
function Countdown({ targetIso, color, soft }) {
  const [now, setNow] = useState(Date.now());
  useEffect(() => {
    const t = setInterval(() => setNow(Date.now()), 1000 * 30);
    return () => clearInterval(t);
  }, []);
  const target = new Date(targetIso).getTime();
  const diff = Math.max(0, target - now);
  const days = Math.floor(diff / 86400000);
  const hours = Math.floor((diff % 86400000) / 3600000);
  const mins = Math.floor((diff % 3600000) / 60000);
  const cells = [
    { v: days, l: "dias" },
    { v: hours, l: "horas" },
    { v: mins, l: "min" },
  ];
  return (
    <div style={{ display: "flex", justifyContent: "center", gap: 28 }}>
      {cells.map((c, i) => (
        <div key={i} style={{ textAlign: "center", minWidth: 64 }}>
          <div style={{ fontFamily: '"Cormorant Garamond", serif', fontSize: 48, fontWeight: 300, color, lineHeight: 1, fontVariantNumeric: "tabular-nums" }}>
            {String(c.v).padStart(2, "0")}
          </div>
          <div style={{ fontFamily: "Inter, sans-serif", fontSize: 10, letterSpacing: "0.24em", textTransform: "uppercase", color: soft, marginTop: 6 }}>
            {c.l}
          </div>
        </div>
      ))}
    </div>
  );
}

// Formulário de RSVP
function RSVP({ palette }) {
  const [name, setName] = useState("");
  const [going, setGoing] = useState(null); // 'sim' | 'nao'
  const [count, setCount] = useState(1);
  const [msg, setMsg] = useState("");
  const [sent, setSent] = useState(false);
  const [sending, setSending] = useState(false);
  const [serverError, setServerError] = useState(null);
  const [errors, setErrors] = useState({});

  const submit = async () => {
    const e = {};
    if (!name.trim()) e.name = true;
    if (going === null) e.going = true;
    setErrors(e);
    if (Object.keys(e).length > 0) return;

    setSending(true);
    setServerError(null);
    try {
      const res = await fetch("/api/rsvp", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name: name.trim(),
          going,
          count: going === "sim" ? count : 0,
          msg,
        }),
      });
      if (!res.ok) throw new Error("falha");
      setSent(true);
    } catch (err) {
      setServerError("Não foi possível enviar. Tente novamente em instantes.");
    } finally {
      setSending(false);
    }
  };

  const reset = () => {
    setSent(false);
    setName("");
    setGoing(null);
    setCount(1);
    setMsg("");
    setErrors({});
    setServerError(null);
  };

  if (sent) {
    return (
      <div style={{ textAlign: "center", padding: "20px 0" }}>
        <div
          style={{
            width: 64,
            height: 64,
            borderRadius: "50%",
            background: palette.accent,
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            margin: "0 auto 24px",
            animation: "popIn 0.6s cubic-bezier(.2,.9,.3,1.4)",
          }}
        >
          <svg width="26" height="26" viewBox="0 0 26 26" fill="none">
            <path d="M5 13 L11 19 L21 7" stroke={palette.paper} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />
          </svg>
        </div>
        <div style={{ fontFamily: '"Cormorant Garamond", serif', fontSize: 32, color: palette.ink, marginBottom: 8 }}>
          {going === "sim" ? "Que alegria!" : "Vamos sentir sua falta!"}
        </div>
        <div style={{ fontFamily: "Inter, sans-serif", fontSize: 14, color: palette.inkSoft, lineHeight: 1.7, maxWidth: 360, margin: "0 auto" }}>
          {going === "sim"
            ? `Obrigada por confirmar, ${name.split(" ")[0]}. Já estamos contando os dias para te receber e celebrar a chegada da Manuela.`
            : `Obrigada por avisar, ${name.split(" ")[0]}. Você fará falta — mande um abraço para a Manuela!`}
        </div>
        <button
          onClick={reset}
          style={{
            marginTop: 28,
            background: "transparent",
            border: "none",
            color: palette.accentDeep,
            fontFamily: "Inter, sans-serif",
            fontSize: 12,
            letterSpacing: "0.2em",
            textTransform: "uppercase",
            cursor: "pointer",
            textDecoration: "underline",
            textUnderlineOffset: 6,
          }}
        >
          Enviar outra resposta
        </button>
      </div>
    );
  }

  const fieldStyle = (hasErr) => ({
    width: "100%",
    background: "transparent",
    border: "none",
    borderBottom: `1px solid ${hasErr ? palette.accentDeep : palette.line}`,
    padding: "10px 0",
    fontFamily: "Inter, sans-serif",
    fontSize: 15,
    color: palette.ink,
    outline: "none",
    transition: "border-color 0.2s",
  });

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 22 }}>
      <div>
        <label style={{ fontFamily: "Inter, sans-serif", fontSize: 10.5, letterSpacing: "0.24em", textTransform: "uppercase", color: palette.inkSoft }}>
          Seu nome
        </label>
        <input
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="Como vamos te chamar"
          style={fieldStyle(errors.name)}
        />
      </div>

      <div>
        <label style={{ fontFamily: "Inter, sans-serif", fontSize: 10.5, letterSpacing: "0.24em", textTransform: "uppercase", color: palette.inkSoft, display: "block", marginBottom: 12 }}>
          Você virá?
        </label>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
          {[
            { v: "sim", l: "Sim, com alegria" },
            { v: "nao", l: "Não poderei ir" },
          ].map((opt) => {
            const active = going === opt.v;
            return (
              <button
                key={opt.v}
                onClick={() => setGoing(opt.v)}
                style={{
                  padding: "14px 12px",
                  background: active ? palette.accent : "transparent",
                  border: `1px solid ${active ? palette.accent : errors.going ? palette.accentDeep : palette.line}`,
                  borderRadius: 2,
                  color: active ? palette.paper : palette.ink,
                  fontFamily: '"Cormorant Garamond", serif',
                  fontSize: 18,
                  fontStyle: "italic",
                  cursor: "pointer",
                  transition: "all 0.2s",
                }}
              >
                {opt.l}
              </button>
            );
          })}
        </div>
      </div>

      {going === "sim" && (
        <div style={{ animation: "fadeIn 0.4s ease" }}>
          <label style={{ fontFamily: "Inter, sans-serif", fontSize: 10.5, letterSpacing: "0.24em", textTransform: "uppercase", color: palette.inkSoft, display: "block", marginBottom: 12 }}>
            Quantos virão com você
          </label>
          <div style={{ display: "flex", alignItems: "center", gap: 16 }}>
            <button
              onClick={() => setCount(Math.max(1, count - 1))}
              style={{
                width: 36, height: 36, borderRadius: "50%",
                border: `1px solid ${palette.line}`, background: "transparent",
                color: palette.ink, fontSize: 18, cursor: "pointer",
              }}
            >−</button>
            <div style={{ fontFamily: '"Cormorant Garamond", serif', fontSize: 32, color: palette.ink, minWidth: 40, textAlign: "center" }}>
              {count}
            </div>
            <button
              onClick={() => setCount(Math.min(8, count + 1))}
              style={{
                width: 36, height: 36, borderRadius: "50%",
                border: `1px solid ${palette.line}`, background: "transparent",
                color: palette.ink, fontSize: 18, cursor: "pointer",
              }}
            >+</button>
            <div style={{ fontFamily: "Inter, sans-serif", fontSize: 12, color: palette.inkSoft, marginLeft: 8 }}>
              {count === 1 ? "pessoa" : "pessoas"}
            </div>
          </div>
        </div>
      )}

      <div>
        <label style={{ fontFamily: "Inter, sans-serif", fontSize: 10.5, letterSpacing: "0.24em", textTransform: "uppercase", color: palette.inkSoft }}>
          Mensagem para a Manuela (opcional)
        </label>
        <textarea
          value={msg}
          onChange={(e) => setMsg(e.target.value)}
          placeholder="Um carinho, um conselho, uma promessa…"
          rows={3}
          style={{ ...fieldStyle(false), resize: "vertical", fontFamily: '"Cormorant Garamond", serif', fontSize: 17, fontStyle: "italic", paddingTop: 12 }}
        />
      </div>

      <button
        onClick={submit}
        disabled={sending}
        style={{
          marginTop: 8,
          padding: "18px 24px",
          background: palette.ink,
          color: palette.paper,
          border: "none",
          borderRadius: 2,
          fontFamily: "Inter, sans-serif",
          fontSize: 12,
          fontWeight: 500,
          letterSpacing: "0.28em",
          textTransform: "uppercase",
          cursor: sending ? "wait" : "pointer",
          opacity: sending ? 0.6 : 1,
          transition: "transform 0.15s",
        }}
        onMouseDown={(e) => (e.currentTarget.style.transform = "scale(0.98)")}
        onMouseUp={(e) => (e.currentTarget.style.transform = "scale(1)")}
      >
        {sending ? "Enviando…" : "Confirmar Presença"}
      </button>

      {serverError && (
        <div style={{ textAlign: "center", fontFamily: "Inter, sans-serif", fontSize: 12, color: palette.accentDeep }}>
          {serverError}
        </div>
      )}
    </div>
  );
}

// Bloco de endereço com copiar
function LocationCard({ palette, address, addressLine2, coords }) {
  const [copied, setCopied] = useState(false);
  const copy = () => {
    const full = `${address} — ${addressLine2}`;
    navigator.clipboard?.writeText(full).then(() => {
      setCopied(true);
      setTimeout(() => setCopied(false), 1800);
    });
  };
  const mapsUrl = coords
    ? `https://www.google.com/maps/search/?api=1&query=${coords}`
    : `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(`${address}, ${addressLine2}`)}`;

  return (
    <div
      style={{
        border: `1px solid ${palette.line}`,
        background: palette.paper,
        padding: "36px 28px",
        textAlign: "center",
      }}
    >
      <div style={{ fontFamily: "Inter, sans-serif", fontSize: 10.5, letterSpacing: "0.28em", textTransform: "uppercase", color: palette.inkSoft, marginBottom: 16 }}>
        Onde · Nossa Casa
      </div>
      <div style={{ fontFamily: '"Cormorant Garamond", serif', fontSize: 26, color: palette.ink, lineHeight: 1.3, marginBottom: 6 }}>
        {address}
      </div>
      <div style={{ fontFamily: "Inter, sans-serif", fontSize: 14, color: palette.inkSoft, marginBottom: 24 }}>
        {addressLine2}
      </div>
      <div style={{ display: "flex", justifyContent: "center", gap: 10, flexWrap: "wrap" }}>
        <button
          onClick={copy}
          style={{
            padding: "11px 20px",
            background: "transparent",
            color: palette.ink,
            border: `1px solid ${palette.ink}`,
            borderRadius: 2,
            fontFamily: "Inter, sans-serif",
            fontSize: 11,
            letterSpacing: "0.24em",
            textTransform: "uppercase",
            cursor: "pointer",
            minWidth: 160,
          }}
        >
          {copied ? "Copiado ✓" : "Copiar endereço"}
        </button>
        <a
          href={mapsUrl}
          target="_blank"
          rel="noreferrer"
          style={{
            padding: "11px 20px",
            background: palette.ink,
            color: palette.paper,
            border: `1px solid ${palette.ink}`,
            borderRadius: 2,
            fontFamily: "Inter, sans-serif",
            fontSize: 11,
            letterSpacing: "0.24em",
            textTransform: "uppercase",
            textDecoration: "none",
            minWidth: 160,
            textAlign: "center",
          }}
        >
          Abrir no Maps
        </a>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Lightbox para navegar mídia em tela cheia
function Lightbox({ items, index, onClose, onIndex, palette }) {
  const item = items[index];
  useEffect(() => {
    const onKey = (e) => {
      if (e.key === "Escape") onClose();
      else if (e.key === "ArrowRight") onIndex(Math.min(items.length - 1, index + 1));
      else if (e.key === "ArrowLeft") onIndex(Math.max(0, index - 1));
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [index, items.length, onClose, onIndex]);

  if (!item) return null;
  return (
    <div
      onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}
      style={{
        position: "fixed", inset: 0, zIndex: 9999,
        background: "rgba(20,20,18,0.92)",
        display: "flex", alignItems: "center", justifyContent: "center",
        padding: 24,
        animation: "fadeIn 0.25s ease",
      }}
    >
      <button
        onClick={onClose}
        aria-label="Fechar"
        style={{
          position: "absolute", top: 18, right: 22,
          background: "transparent", border: 0, color: "#fff",
          fontSize: 28, cursor: "pointer", lineHeight: 1,
        }}
      >×</button>
      <button
        onClick={() => onIndex(Math.max(0, index - 1))}
        disabled={index === 0}
        style={{
          position: "absolute", left: 16, top: "50%", transform: "translateY(-50%)",
          width: 44, height: 44, borderRadius: "50%",
          background: "rgba(255,255,255,0.1)", border: 0, color: "#fff",
          fontSize: 22, cursor: index === 0 ? "default" : "pointer",
          opacity: index === 0 ? 0.3 : 1,
        }}
      >‹</button>
      <button
        onClick={() => onIndex(Math.min(items.length - 1, index + 1))}
        disabled={index === items.length - 1}
        style={{
          position: "absolute", right: 16, top: "50%", transform: "translateY(-50%)",
          width: 44, height: 44, borderRadius: "50%",
          background: "rgba(255,255,255,0.1)", border: 0, color: "#fff",
          fontSize: 22, cursor: index === items.length - 1 ? "default" : "pointer",
          opacity: index === items.length - 1 ? 0.3 : 1,
        }}
      >›</button>
      <div style={{ maxWidth: "92vw", maxHeight: "86vh", display: "flex", flexDirection: "column", gap: 12, alignItems: "center" }}>
        {item.kind === "video" ? (
          <video src={item.url} controls autoPlay playsInline style={{ maxWidth: "92vw", maxHeight: "82vh", background: "#000" }} />
        ) : (
          <img src={item.url} alt={item.name} style={{ maxWidth: "92vw", maxHeight: "82vh", objectFit: "contain" }} />
        )}
        <div style={{ color: "rgba(255,255,255,0.7)", fontFamily: "Inter, sans-serif", fontSize: 12, letterSpacing: "0.16em" }}>
          {index + 1} / {items.length}{item.author ? ` · ${item.author}` : ""}
        </div>
      </div>
    </div>
  );
}

// Carrossel auto-rotativo (scroll-snap)
function MediaCarousel({ items, palette, onPick }) {
  const ref = useRef(null);
  const idxRef = useRef(0);
  useEffect(() => {
    if (!items.length) return;
    const el = ref.current;
    if (!el) return;
    let paused = false;
    const onEnter = () => (paused = true);
    const onLeave = () => (paused = false);
    el.addEventListener("mouseenter", onEnter);
    el.addEventListener("mouseleave", onLeave);
    const t = setInterval(() => {
      if (paused) return;
      idxRef.current = (idxRef.current + 1) % items.length;
      const card = el.children[idxRef.current];
      if (card) el.scrollTo({ left: card.offsetLeft - el.offsetLeft, behavior: "smooth" });
    }, 4500);
    return () => {
      clearInterval(t);
      el.removeEventListener("mouseenter", onEnter);
      el.removeEventListener("mouseleave", onLeave);
    };
  }, [items.length]);

  if (!items.length) return null;
  return (
    <div
      ref={ref}
      style={{
        display: "flex", gap: 14, overflowX: "auto",
        scrollSnapType: "x mandatory",
        scrollbarWidth: "none", paddingBottom: 4,
        WebkitOverflowScrolling: "touch",
      }}
    >
      {items.map((it, i) => (
        <button
          key={`${it.source}-${it.name}-${i}`}
          onClick={() => onPick(i)}
          style={{
            flex: "0 0 78%",
            scrollSnapAlign: "center",
            border: `1px solid ${palette.line}`,
            background: palette.paper,
            padding: 0,
            cursor: "pointer",
            aspectRatio: "4 / 3",
            position: "relative",
            overflow: "hidden",
          }}
        >
          {it.kind === "video" ? (
            <video src={it.url} muted playsInline preload="metadata" style={{ width: "100%", height: "100%", objectFit: "cover" }} />
          ) : (
            <img src={it.url} alt="" loading="lazy" style={{ width: "100%", height: "100%", objectFit: "cover" }} />
          )}
          {it.kind === "video" && (
            <div style={{
              position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center",
              background: "rgba(0,0,0,0.18)", color: "#fff", fontSize: 36, pointerEvents: "none",
            }}>▶</div>
          )}
        </button>
      ))}
    </div>
  );
}

// Seção principal de mídia (gallery + carrossel + upload + lightbox)
function Memorias({ palette, dateIso }) {
  const [media, setMedia] = useState({ curated: [], uploads: [], uploads_open: true, opens_at: null });
  const [loading, setLoading] = useState(true);
  const [uploading, setUploading] = useState(false);
  const [progress, setProgress] = useState(0); // 0..1
  const [uploadMsg, setUploadMsg] = useState(null);
  const [lightboxIdx, setLightboxIdx] = useState(-1);
  const [showAll, setShowAll] = useState(false);
  const [now, setNow] = useState(Date.now());
  const inputRef = useRef(null);

  const load = () => {
    fetch("/api/media")
      .then((r) => r.json())
      .then((d) => { setMedia(d); setLoading(false); })
      .catch(() => setLoading(false));
  };
  useEffect(() => { load(); }, []);
  useEffect(() => {
    const t = setInterval(() => setNow(Date.now()), 30000);
    return () => clearInterval(t);
  }, []);

  const all = useMemo(() => [...media.uploads, ...media.curated], [media]);
  const preview = all.slice(0, 9);
  const carouselItems = all.slice(0, 8);

  const opensAtMs = media.opens_at ? Date.parse(media.opens_at) : 0;
  const isOpen = media.uploads_open;
  const timeUntil = opensAtMs ? Math.max(0, opensAtMs - now) : 0;

  const openPicker = () => {
    if (!isOpen) return;
    inputRef.current?.click();
  };

  const onFiles = (e) => {
    const files = Array.from(e.target.files || []);
    if (!files.length) return;
    setUploading(true);
    setUploadMsg(null);
    setProgress(0);
    const fd = new FormData();
    files.forEach((f) => fd.append("files", f));

    const xhr = new XMLHttpRequest();
    xhr.open("POST", "/api/uploads");
    xhr.upload.onprogress = (ev) => {
      if (ev.lengthComputable) setProgress(ev.loaded / ev.total);
    };
    xhr.onload = () => {
      let data = {};
      try { data = JSON.parse(xhr.responseText || "{}"); } catch {}
      if (xhr.status >= 200 && xhr.status < 300) {
        setUploadMsg({ ok: true, text: `${data.files?.length || files.length} ${files.length === 1 ? "arquivo enviado" : "arquivos enviados"}!` });
        load();
      } else {
        const err = data?.error === "closed"
          ? "Os envios ainda não estão liberados."
          : data?.error?.includes("não suportado")
            ? "Tipo de arquivo não suportado."
            : "Não foi possível enviar. Verifique tamanho e conexão.";
        setUploadMsg({ ok: false, text: err });
      }
      setUploading(false);
      setProgress(0);
      if (inputRef.current) inputRef.current.value = "";
      setTimeout(() => setUploadMsg(null), 5000);
    };
    xhr.onerror = () => {
      setUploadMsg({ ok: false, text: "Falha de rede no envio." });
      setUploading(false);
      setProgress(0);
      if (inputRef.current) inputRef.current.value = "";
    };
    xhr.send(fd);
  };

  const fmtCountdown = (ms) => {
    const d = Math.floor(ms / 86400000);
    const h = Math.floor((ms % 86400000) / 3600000);
    const m = Math.floor((ms % 3600000) / 60000);
    if (d > 0) return `${d}d ${h}h`;
    if (h > 0) return `${h}h ${m}min`;
    return `${m}min`;
  };

  return (
    <section style={{ padding: "20px 24px 80px", maxWidth: 980, margin: "0 auto" }}>
      <div style={{ textAlign: "center", marginBottom: 32 }}>
        <Rule color={palette.accentDeep} label="memórias" />
        <h2 style={{ fontFamily: '"Cormorant Garamond", serif', fontSize: 52, fontWeight: 300, color: palette.ink, margin: "16px 0 8px", lineHeight: 1 }}>
          guarde com a gente
        </h2>
        <p style={{ fontFamily: "Inter, sans-serif", fontSize: 13, color: palette.inkSoft, lineHeight: 1.7, maxWidth: 420, margin: "0 auto" }}>
          {isOpen
            ? "Compartilhe suas fotos e vídeos do nosso encontro. Tudo o que enviar vai virar lembrança da chegada da Manuela."
            : "No dia do chá esta seção abre e você poderá enviar suas fotos e vídeos para guardarmos com carinho."}
        </p>
      </div>

      {/* Botão upload */}
      <div style={{ display: "flex", justifyContent: "center", marginBottom: 24 }}>
        <input
          ref={inputRef}
          type="file"
          accept="image/*,video/*"
          multiple
          onChange={onFiles}
          style={{ display: "none" }}
        />
        <button
          onClick={openPicker}
          disabled={!isOpen || uploading}
          style={{
            display: "inline-flex", alignItems: "center", gap: 12,
            padding: "16px 28px",
            background: isOpen ? palette.ink : "transparent",
            color: isOpen ? palette.paper : palette.inkSoft,
            border: `1px solid ${isOpen ? palette.ink : palette.line}`,
            borderRadius: 2,
            fontFamily: "Inter, sans-serif",
            fontSize: 12,
            fontWeight: 500,
            letterSpacing: "0.24em",
            textTransform: "uppercase",
            cursor: isOpen ? (uploading ? "wait" : "pointer") : "not-allowed",
            opacity: uploading ? 0.6 : 1,
            transition: "transform 0.15s",
          }}
        >
          <span style={{ fontSize: 18, lineHeight: 1 }}>{isOpen ? "+" : "🔒"}</span>
          {uploading
            ? "Enviando…"
            : isOpen
              ? "Adicionar foto / vídeo"
              : opensAtMs && timeUntil > 0
                ? `Abre em ${fmtCountdown(timeUntil)}`
                : "Em breve"}
        </button>
      </div>

      {uploading && (
        <div style={{ maxWidth: 360, margin: "-10px auto 20px" }}>
          <div style={{ height: 4, background: palette.line, position: "relative", overflow: "hidden" }}>
            <div style={{
              position: "absolute", inset: 0,
              transform: `scaleX(${Math.max(0.02, progress)})`,
              transformOrigin: "left center",
              background: palette.accent,
              transition: "transform 0.2s",
            }} />
          </div>
          <div style={{ textAlign: "center", fontFamily: "Inter, sans-serif", fontSize: 11, letterSpacing: "0.16em", textTransform: "uppercase", color: palette.inkSoft, marginTop: 8 }}>
            enviando {Math.round(progress * 100)}%
          </div>
        </div>
      )}

      {uploadMsg && !uploading && (
        <div style={{
          textAlign: "center", fontFamily: "Inter, sans-serif", fontSize: 12,
          color: uploadMsg.ok ? palette.accentDeep : palette.accentDeep,
          marginTop: -10, marginBottom: 20,
        }}>
          {uploadMsg.text}
        </div>
      )}

      {/* Grid de thumbs */}
      {loading ? (
        <div style={{ textAlign: "center", fontFamily: '"Cormorant Garamond", serif', fontStyle: "italic", color: palette.inkSoft, padding: 40 }}>
          carregando…
        </div>
      ) : preview.length === 0 ? (
        <div style={{
          textAlign: "center",
          fontFamily: '"Cormorant Garamond", serif', fontStyle: "italic",
          color: palette.inkSoft, padding: "40px 20px",
          border: `1px dashed ${palette.line}`, background: palette.paper,
        }}>
          ainda sem fotos por aqui…
        </div>
      ) : (
        <>
          <div style={{
            display: "grid",
            gridTemplateColumns: "repeat(3, 1fr)",
            gap: 10,
            marginBottom: 40,
          }}>
            {preview.map((it, i) => (
              <button
                key={`${it.source}-${it.name}-${i}`}
                onClick={() => setLightboxIdx(i)}
                style={{
                  border: `1px solid ${palette.line}`,
                  background: palette.paper,
                  padding: 0,
                  cursor: "pointer",
                  aspectRatio: "1 / 1",
                  position: "relative",
                  overflow: "hidden",
                }}
              >
                {it.kind === "video" ? (
                  <video src={it.url} muted playsInline preload="metadata" style={{ width: "100%", height: "100%", objectFit: "cover" }} />
                ) : (
                  <img src={it.url} alt="" loading="lazy" style={{ width: "100%", height: "100%", objectFit: "cover" }} />
                )}
                {it.kind === "video" && (
                  <div style={{
                    position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center",
                    background: "rgba(0,0,0,0.18)", color: "#fff", fontSize: 24, pointerEvents: "none",
                  }}>▶</div>
                )}
              </button>
            ))}
          </div>

          {/* Carrossel */}
          {carouselItems.length > 1 && (
            <div style={{ marginBottom: 28 }}>
              <div style={{ fontFamily: "Inter, sans-serif", fontSize: 10, letterSpacing: "0.3em", textTransform: "uppercase", color: palette.inkSoft, textAlign: "center", marginBottom: 14 }}>
                em destaque
              </div>
              <MediaCarousel items={carouselItems} palette={palette} onPick={(i) => setLightboxIdx(i)} />
            </div>
          )}

          {/* Ver tudo */}
          {all.length > preview.length && (
            <div style={{ textAlign: "center", marginTop: 16 }}>
              <button
                onClick={() => setShowAll(true)}
                style={{
                  background: "transparent",
                  border: `1px solid ${palette.ink}`,
                  color: palette.ink,
                  padding: "12px 24px",
                  fontFamily: "Inter, sans-serif",
                  fontSize: 11,
                  letterSpacing: "0.24em",
                  textTransform: "uppercase",
                  cursor: "pointer",
                }}
              >
                Ver tudo ({all.length}) →
              </button>
            </div>
          )}
        </>
      )}

      {/* Lightbox single item */}
      {lightboxIdx >= 0 && (
        <Lightbox
          items={all}
          index={lightboxIdx}
          onClose={() => setLightboxIdx(-1)}
          onIndex={setLightboxIdx}
          palette={palette}
        />
      )}

      {/* Modal Ver tudo */}
      {showAll && (
        <div
          onClick={(e) => { if (e.target === e.currentTarget) setShowAll(false); }}
          style={{
            position: "fixed", inset: 0, zIndex: 9998,
            background: "rgba(20,20,18,0.92)",
            display: "flex", flexDirection: "column",
            padding: "60px 16px 24px",
            animation: "fadeIn 0.25s ease",
            overflow: "auto",
          }}
        >
          <button
            onClick={() => setShowAll(false)}
            style={{
              position: "fixed", top: 18, right: 22,
              background: "transparent", border: 0, color: "#fff",
              fontSize: 28, cursor: "pointer", zIndex: 1,
            }}
          >×</button>
          <div style={{ color: "rgba(255,255,255,0.85)", fontFamily: '"Cormorant Garamond", serif', fontStyle: "italic", fontSize: 28, textAlign: "center", marginBottom: 24 }}>
            todas as memórias · {all.length}
          </div>
          <div style={{
            display: "grid",
            gridTemplateColumns: "repeat(auto-fill, minmax(160px, 1fr))",
            gap: 8,
            maxWidth: 1100,
            width: "100%",
            margin: "0 auto",
          }}>
            {all.map((it, i) => (
              <button
                key={`${it.source}-${it.name}-${i}`}
                onClick={() => { setShowAll(false); setLightboxIdx(i); }}
                style={{
                  border: 0, padding: 0, cursor: "pointer",
                  aspectRatio: "1 / 1",
                  background: "#000",
                  position: "relative",
                  overflow: "hidden",
                }}
              >
                {it.kind === "video" ? (
                  <video src={it.url} muted playsInline preload="metadata" style={{ width: "100%", height: "100%", objectFit: "cover" }} />
                ) : (
                  <img src={it.url} alt="" loading="lazy" style={{ width: "100%", height: "100%", objectFit: "cover" }} />
                )}
                {it.kind === "video" && (
                  <div style={{
                    position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center",
                    background: "rgba(0,0,0,0.25)", color: "#fff", fontSize: 20, pointerEvents: "none",
                  }}>▶</div>
                )}
              </button>
            ))}
          </div>
        </div>
      )}
    </section>
  );
}

// Ursinho rosa decorativo (SVG inline, sem dependências)
function PinkBear() {
  return (
    <div style={{ display: "flex", justifyContent: "center", marginBottom: 18 }}>
      <svg width="96" height="96" viewBox="0 0 120 120" aria-hidden="true">
        {/* orelhas externas */}
        <circle cx="32" cy="34" r="14" fill="#e8a5b8" />
        <circle cx="88" cy="34" r="14" fill="#e8a5b8" />
        {/* orelhas internas */}
        <circle cx="32" cy="34" r="7" fill="#f6cdd5" />
        <circle cx="88" cy="34" r="7" fill="#f6cdd5" />
        {/* cabeça */}
        <circle cx="60" cy="64" r="32" fill="#f1b7c6" />
        {/* focinho */}
        <ellipse cx="60" cy="76" rx="16" ry="13" fill="#fde6ec" />
        {/* olhos */}
        <circle cx="49" cy="62" r="3" fill="#3b2a2f" />
        <circle cx="71" cy="62" r="3" fill="#3b2a2f" />
        {/* brilho dos olhos */}
        <circle cx="50" cy="61" r="0.9" fill="#fff" />
        <circle cx="72" cy="61" r="0.9" fill="#fff" />
        {/* nariz */}
        <ellipse cx="60" cy="72" rx="3.2" ry="2.4" fill="#3b2a2f" />
        {/* boquinha */}
        <path d="M56 78 Q60 82 64 78" stroke="#3b2a2f" strokeWidth="1.6" fill="none" strokeLinecap="round" />
        {/* bochechas */}
        <circle cx="42" cy="72" r="3.5" fill="#f59cae" opacity="0.55" />
        <circle cx="78" cy="72" r="3.5" fill="#f59cae" opacity="0.55" />
      </svg>
    </div>
  );
}

// Bloco de presente com tamanho de fralda atribuído ao visitante
function DiaperGift({ palette, fallback }) {
  const [state, setState] = useState({ loading: true, size: null });
  useEffect(() => {
    let alive = true;
    fetch("/api/diaper", { credentials: "same-origin" })
      .then((r) => (r.ok ? r.json() : Promise.reject(r.status)))
      .then((j) => { if (alive) setState({ loading: false, size: j.size || null }); })
      .catch(() => { if (alive) setState({ loading: false, size: null }); });
    return () => { alive = false; };
  }, []);

  if (state.loading) {
    return (
      <div style={{ textAlign: "center", color: palette.ink, minHeight: 140 }}>
        <div style={{ fontFamily: "Inter, sans-serif", fontSize: 10.5, fontWeight: 500, letterSpacing: "0.28em", textTransform: "uppercase", color: palette.inkSoft, marginBottom: 14 }}>
          Ideia de presente
        </div>
        <div style={{ fontFamily: '"Cormorant Garamond", serif', fontSize: 22, fontStyle: "italic", color: palette.inkSoft }}>
          escolhendo um tamanho pra você…
        </div>
      </div>
    );
  }

  if (!state.size) {
    return (
      <InfoBlock
        kicker="Ideia de presente"
        title={fallback}
        body="Mas o mais importante é a sua presença."
        color={palette.ink}
        soft={palette.inkSoft}
      />
    );
  }

  return (
    <div style={{ textAlign: "center", color: palette.ink }}>
      <div style={{ fontFamily: "Inter, sans-serif", fontSize: 10.5, fontWeight: 500, letterSpacing: "0.28em", textTransform: "uppercase", color: palette.inkSoft, marginBottom: 14 }}>
        Ideia de presente · só pra você
      </div>
      <PinkBear />
      <div style={{ fontFamily: '"Cormorant Garamond", serif', fontSize: 36, fontWeight: 400, lineHeight: 1.1, marginBottom: 18 }}>
        Fralda Pampers
      </div>
      <div style={{ display: "inline-flex", alignItems: "baseline", gap: 14, padding: "18px 32px", border: `1px solid ${palette.line}`, background: palette.paper }}>
        <span style={{ fontFamily: "Inter, sans-serif", fontSize: 10.5, letterSpacing: "0.28em", textTransform: "uppercase", color: palette.inkSoft }}>
          tamanho
        </span>
        <span style={{ fontFamily: '"Cormorant Garamond", serif', fontSize: 56, fontWeight: 300, color: palette.accentDeep, lineHeight: 1 }}>
          {state.size}
        </span>
      </div>
      <div style={{ fontFamily: "Inter, sans-serif", fontSize: 13, color: palette.inkSoft, lineHeight: 1.6, marginTop: 20, maxWidth: 380, margin: "20px auto 0" }}>
        Combinamos os tamanhos pra não sobrar nem faltar — esse é o seu.
        Mas o mais importante é a sua presença.
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
function App() {
  const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
    "theme": "salvia",
    "babyName": "Manuela",
    "momName": "Mamãe",
    "dadName": "Papai",
    "dateIso": "2026-06-20T17:00",
    "giftHint": "Fraldas tamanho P ou RN",
    "showCountdown": true
  }/*EDITMODE-END*/;

  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const palette = PALETTES[t.theme] || PALETTES.salvia;

  const date = new Date(t.dateIso);
  const dateStr = date.toLocaleDateString("pt-BR", { weekday: "long", day: "2-digit", month: "long" });
  const timeStr = date.toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" });
  const yearStr = date.getFullYear();
  const dayNum = String(date.getDate()).padStart(2, "0");
  const monthName = date.toLocaleDateString("pt-BR", { month: "long" });
  const weekdayName = date.toLocaleDateString("pt-BR", { weekday: "long" });

  return (
    <div
      style={{
        minHeight: "100vh",
        background: palette.bg,
        color: palette.ink,
        fontFamily: "Inter, sans-serif",
        position: "relative",
        overflow: "hidden",
      }}
    >
      <FloatingDots color={palette.accent} />

      {/* HERO */}
      <section style={{ position: "relative", padding: "80px 24px 100px", maxWidth: 980, margin: "0 auto" }}>
        <div style={{ textAlign: "center", animation: "fadeIn 1s ease 0.1s both" }}>
          <div style={{ fontFamily: "Inter, sans-serif", fontSize: 11, letterSpacing: "0.5em", textTransform: "uppercase", color: palette.inkSoft, marginBottom: 28 }}>
            {t.momName} & {t.dadName} convidam
          </div>
          <div style={{ fontFamily: '"Cormorant Garamond", serif', fontSize: 18, fontStyle: "italic", color: palette.accentDeep, marginBottom: 8, letterSpacing: "0.04em" }}>
            para o chá de bebê da nossa
          </div>
        </div>

        <RevealedName name={t.babyName} color={palette.ink} />

        <div style={{ textAlign: "center", marginTop: 28, animation: "fadeIn 1s ease 1.8s both" }}>
          <div style={{ display: "inline-flex", alignItems: "center", gap: 16, color: palette.inkSoft }}>
            <span style={{ width: 36, height: 1, background: palette.accent }} />
            <span style={{ fontFamily: '"Cormorant Garamond", serif', fontStyle: "italic", fontSize: 18 }}>
              um pequeno milagre a caminho
            </span>
            <span style={{ width: 36, height: 1, background: palette.accent }} />
          </div>
        </div>

        {/* Data em destaque */}
        <div style={{ marginTop: 80, display: "grid", gridTemplateColumns: "1fr auto 1fr", gap: 32, alignItems: "center", animation: "fadeIn 1s ease 2.2s both" }}>
          <div style={{ textAlign: "right" }}>
            <div style={{ fontFamily: "Inter, sans-serif", fontSize: 10.5, letterSpacing: "0.28em", textTransform: "uppercase", color: palette.inkSoft, marginBottom: 6 }}>
              {weekdayName}
            </div>
            <div style={{ fontFamily: '"Cormorant Garamond", serif', fontSize: 22, fontStyle: "italic", color: palette.ink }}>
              {monthName}
            </div>
          </div>
          <div style={{ fontFamily: '"Cormorant Garamond", serif', fontSize: 132, fontWeight: 300, color: palette.accentDeep, lineHeight: 1, fontVariantNumeric: "tabular-nums" }}>
            {dayNum}
          </div>
          <div>
            <div style={{ fontFamily: "Inter, sans-serif", fontSize: 10.5, letterSpacing: "0.28em", textTransform: "uppercase", color: palette.inkSoft, marginBottom: 6 }}>
              às {timeStr}h
            </div>
            <div style={{ fontFamily: '"Cormorant Garamond", serif', fontSize: 22, fontStyle: "italic", color: palette.ink }}>
              {yearStr}
            </div>
          </div>
        </div>

        {t.showCountdown && (
          <div style={{ marginTop: 56, animation: "fadeIn 1s ease 2.6s both" }}>
            <Rule color={palette.accentDeep} label="faltam" />
            <div style={{ marginTop: 22 }}>
              <Countdown targetIso={t.dateIso} color={palette.ink} soft={palette.inkSoft} />
            </div>
          </div>
        )}
      </section>

      {/* CARTA MANUSCRITA */}
      <section style={{ padding: "20px 24px 80px", maxWidth: 620, margin: "0 auto" }}>
        <div
          style={{
            background: palette.paper,
            padding: "56px 44px",
            borderTop: `1px solid ${palette.line}`,
            borderBottom: `1px solid ${palette.line}`,
            position: "relative",
            textAlign: "center",
          }}
        >
          <div
            style={{
              position: "absolute",
              top: -10, left: "50%", transform: "translateX(-50%)",
              background: palette.bg,
              padding: "0 16px",
              fontFamily: "Inter, sans-serif", fontSize: 10, letterSpacing: "0.3em", textTransform: "uppercase",
              color: palette.inkSoft,
            }}
          >
            uma palavrinha
          </div>
          <p style={{ fontFamily: '"Cormorant Garamond", serif', fontSize: 22, fontStyle: "italic", lineHeight: 1.6, color: palette.ink, margin: 0 }}>
            Esperamos a {t.babyName} com o coração transbordando.
            Queremos celebrar essa chegada com quem amamos —
            com afeto, comida boa e muitas memórias para guardar.
          </p>
          <p style={{ fontFamily: "Inter, sans-serif", fontSize: 13, color: palette.inkSoft, marginTop: 32, letterSpacing: "0.04em" }}>
            com amor,<br />
            <span style={{ fontFamily: '"Cormorant Garamond", serif', fontSize: 22, fontStyle: "italic", color: palette.accentDeep }}>
              {t.momName} &amp; {t.dadName}
            </span>
          </p>
        </div>
      </section>

      {/* LOCAL */}
      <section style={{ padding: "0 24px 80px", maxWidth: 620, margin: "0 auto" }}>
        <LocationCard
          palette={palette}
          address="Rua Maria Célia Rigotti, 205"
          addressLine2="Santa Rita 2 · Pouso Alegre, MG · 37559-527"
          coords="-22.268714,-45.933682"
        />
      </section>

      {/* DETALHES */}
      <section style={{ padding: "0 24px 80px", maxWidth: 540, margin: "0 auto" }}>
        <DiaperGift palette={palette} fallback={t.giftHint} />
      </section>

      {/* MEMÓRIAS */}
      <Memorias palette={palette} dateIso={t.dateIso} />

      {/* RSVP */}
      <section style={{ padding: "40px 24px 80px", maxWidth: 540, margin: "0 auto" }}>
        <div style={{ textAlign: "center", marginBottom: 40 }}>
          <Rule color={palette.accentDeep} label="confirmação" />
          <h2 style={{ fontFamily: '"Cormorant Garamond", serif', fontSize: 56, fontWeight: 300, color: palette.ink, margin: "20px 0 10px", lineHeight: 1 }}>
            Você vem?
          </h2>
          <p style={{ fontFamily: "Inter, sans-serif", fontSize: 13, color: palette.inkSoft, lineHeight: 1.7, maxWidth: 380, margin: "0 auto" }}>
            Por favor, confirme sua presença até uma semana antes para
            organizarmos tudo com carinho.
          </p>
        </div>
        <RSVP palette={palette} />
      </section>

      {/* RODAPÉ */}
      <footer style={{ padding: "40px 24px 80px", textAlign: "center" }}>
        <div style={{ display: "inline-flex", flexDirection: "column", gap: 4, alignItems: "center" }}>
          <span style={{ width: 4, height: 4, borderRadius: "50%", background: palette.accent }} />
          <span style={{ fontFamily: '"Cormorant Garamond", serif', fontStyle: "italic", fontSize: 18, color: palette.accentDeep, marginTop: 8 }}>
            esperamos por você
          </span>
          <span style={{ fontFamily: "Inter, sans-serif", fontSize: 10, letterSpacing: "0.32em", textTransform: "uppercase", color: palette.inkSoft, marginTop: 4 }}>
            {t.babyName} · {yearStr}
          </span>
        </div>
      </footer>

      {/* TWEAKS */}
      <TweaksPanel>
        <TweakSection label="Bebê & família" />
        <TweakText label="Nome do bebê" value={t.babyName} onChange={(v) => setTweak("babyName", v)} />
        <TweakText label="Mamãe" value={t.momName} onChange={(v) => setTweak("momName", v)} />
        <TweakText label="Papai" value={t.dadName} onChange={(v) => setTweak("dadName", v)} />

        <TweakSection label="Data e horário" />
        <TweakText label="Data (ISO)" value={t.dateIso} onChange={(v) => setTweak("dateIso", v)} />
        <TweakToggle label="Mostrar contador" value={t.showCountdown} onChange={(v) => setTweak("showCountdown", v)} />

        <TweakSection label="Tema" />
        <TweakRadio
          label="Paleta"
          value={t.theme}
          options={["salvia", "rosa", "lavanda", "mel"]}
          onChange={(v) => setTweak("theme", v)}
        />

        <TweakSection label="Detalhes" />
        <TweakText label="Ideia de presente" value={t.giftHint} onChange={(v) => setTweak("giftHint", v)} />
      </TweaksPanel>
    </div>
  );
}

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