/* eslint-disable */
// Lucía Di Stante — portfolio app

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": ["#F97316", "#EC4899", "#8B5CF6"],
  "accent": "solid",
  "displayFont": "Bricolage Grotesque",
  "density": "regular",
  "marquee": true,
  "stickers": true
}/*EDITMODE-END*/;

const PALETTES = [
  ["#F97316", "#EC4899", "#8B5CF6"], // original orange/pink/purple
  ["#FF3D7F", "#FFB400", "#7C3AED"], // hot pink + yellow + violet
  ["#06B6D4", "#FB7185", "#A3E635"], // cyan + coral + lime
  ["#FFD60A", "#FF006E", "#003566"], // yellow + magenta + navy
  ["#0F0F12", "#F97316", "#EC4899"], // black-led pop
];

const DISPLAY_FONTS = [
  { value: "Bricolage Grotesque", label: "Bricolage" },
  { value: "Familjen Grotesk", label: "Familjen" },
  { value: "Archivo", label: "Archivo" },
  { value: "DM Serif Display", label: "DM Serif" },
];

const NICHES = [
  { label: "Belleza & makeup", color: 1 },
  { label: "Lifestyle", color: 0 },
  { label: "Comida", color: 2 },
  { label: "Apps", color: 3 },
  { label: "Moda", color: 1 },
  { label: "Viajes", color: 0 },
];

const SERVICES = [
  { num: "01", title: "Contenido UGC para marcas", desc: "Videos auténticos que tu marca usa en sus redes y pauta. Me mandas el producto, yo creo el contenido listo para publicar.", featured: false },
  { num: "02", title: "Colaboraciones en mis redes", desc: "Reels y TikToks publicados en mis perfiles, con mi comunidad detrás. Ideal para dar a conocer tu marca a una audiencia real.", featured: false },
  { num: "03", title: "Reseñas y experiencias", desc: "Reseñas de productos, restaurantes, hoteles y lugares. Cuento la experiencia real para que tu audiencia confíe.", featured: false },
  { num: "04", title: "Demostraciones de producto", desc: "Muestro tu producto en uso: cómo funciona y por qué vale la pena. Perfecto para skincare, apps y gadgets.", featured: false },
  { num: "05", title: "Storytelling de marca", desc: "Convierto el mensaje de tu marca en una historia que engancha y se recuerda, no en un anuncio que se saltea.", featured: false },
  { num: "06", title: "Contenido para campañas", desc: "Packs de varios videos pensados para una campaña: lanzamientos, fechas especiales o sorteos.", featured: false },
];

// Cuando tengas los archivos reales, completá `video` con la ruta (ej. "videos/belleza-skincare.mp4")
// y `poster` con la portada. Para Creadora de contenido pegá la URL de TikTok en `tiktokUrl`,
// formato: "https://www.tiktok.com/@ludistante/video/1234567890123456789"
const WORKS = [
  // ── UGC (contenido para que la marca publique en sus redes) ──
  { type: "ugc", tag: "Finanzas", brand: "Mapfre · seguros", title: "UGC para Mapfre", duration: "0:51", color: 2, video: "videos/ugc-mapfre.mp4", poster: "imagenes/ugc-mapfre.webp" },
  { type: "ugc", tag: "Belleza", brand: "L'Oréal · máscara", title: "Máscara de pestañas L'Oréal", duration: "0:15", color: 1, video: "videos/ugc-loreal-mascara.mp4", poster: "imagenes/ugc-loreal-mascara.webp" },
  { type: "ugc", tag: "Belleza", brand: "Cacharel · perfume", title: "Perfume Cacharel", duration: "0:19", color: 1, video: "videos/ugc-cacharel.mp4", poster: "imagenes/ugc-cacharel.webp" },
  { type: "ugc", tag: "Belleza", brand: "L'Oréal · labial", title: "Labial L'Oréal", duration: "0:16", color: 1, video: "videos/ugc-loreal-labial.mp4", poster: "imagenes/ugc-loreal-labial.webp" },
  { type: "ugc", tag: "Belleza", brand: "La Provençale · aceite", title: "Aceite de belleza La Provençale", duration: "0:23", color: 0, video: "videos/ugc-laprovencale.mp4", poster: "imagenes/ugc-laprovencale.webp" },
  { type: "ugc", tag: "Belleza", brand: "Dove · desodorante", title: "Desodorante Dove", duration: "0:24", color: 0, video: "videos/ugc-dove.mp4", poster: "imagenes/ugc-dove.webp" },
  { type: "ugc", tag: "Belleza", brand: "CeraVe · skincare", title: "Crema CeraVe", duration: "0:25", color: 1, video: "videos/ugc-cerave.mp4", poster: "imagenes/ugc-cerave.webp" },
  { type: "ugc", tag: "Bienestar", brand: "Innova Naturals · vitaminas", title: "Vitaminas Innova Naturals", duration: "0:23", color: 2, video: "videos/ugc-innova.mp4", poster: "imagenes/ugc-innova.webp" },

  // ── Creadora de contenido (publicado en mis redes — TikTok embed) ──
  { type: "creator", tag: "Belleza", brand: "Dossier · perfumería", title: "Mi colab con Dossier", duration: "0:45", color: 1, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7643872431253294343" },
  { type: "creator", tag: "Comida", brand: "SAO Medialunas · Madrid", title: "Las mejores medialunas de Madrid", duration: "0:38", color: 0, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7638340014799097106" },
  { type: "creator", tag: "Apps", brand: "Brubank · banco digital", title: "Brubank, mi banco desde España", duration: "0:42", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7623095588191489300" },
  { type: "creator", tag: "Comida", brand: "La Birra Bar · Madrid", title: "Hamburguesas argentinas en Madrid", duration: "0:40", color: 0, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7612340254099442945" },
  { type: "creator", tag: "Moda", brand: "Billy's Tour · vintage", title: "Vintage shopping en Madrid", duration: "0:50", color: 1, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7610429717061045520" },
  { type: "creator", tag: "Educación", brand: "BIG School · cursos financieros", title: "Aprender de finanzas con BIG School", duration: "0:44", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7604977144409689352" },
  { type: "creator", tag: "Comida", brand: "Somos Re · cafetería", title: "Café de especialidad en Madrid", duration: "0:36", color: 0, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7607073632010915089" },
  { type: "creator", tag: "Apps", brand: "Brubank · banco digital", title: "Segunda colab con Brubank", duration: "0:48", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7636115303797247253" },
  { type: "creator", tag: "Apps", brand: "Monefy · app de gastos", title: "Así controlo mis gastos con Monefy", duration: "0:40", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7592719676577271047" },
  { type: "creator", tag: "Apps", brand: "DinnersMate · app social", title: "Cené con desconocidos en Madrid", duration: "0:42", color: 0, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7643880175758839048" },
  { type: "creator", tag: "Educación", brand: "Vive España · estudiar afuera", title: "Cómo vine a estudiar a España", duration: "0:55", color: 0, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7571949616946498823" },
  { type: "creator", tag: "Apps", brand: "The Fork · reservas", title: "Comer rico y barato con The Fork", duration: "0:38", color: 0, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7585940973566332167" },
  { type: "creator", tag: "Apps", brand: "The Fork · reservas", title: "Segunda colab con The Fork", duration: "0:42", color: 0, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7600155142675107079" },
  { type: "creator", tag: "Comida", brand: "YOPRO · yogures proteicos", title: "Mis snacks con YOPRO", duration: "0:35", color: 0, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7632670285870664981" },
  { type: "creator", tag: "Comida", brand: "The Vic Bros · burgers", title: "Las burgers de The Vic Bros", duration: "0:40", color: 0, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7571925686089239816" },
  { type: "creator", tag: "Comida", brand: "Pancakes House · Madrid", title: "Pancakes en Madrid · Pancakes House", duration: "0:38", color: 0, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7612356590045318417" },
  { type: "creator", tag: "Lifestyle", brand: "Amazon · accesorios", title: "Mi accesorio favorito para el móvil", duration: "0:35", color: 0, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7530353119939611910" },
  { type: "creator", tag: "Apps", brand: "EMT Madrid · transporte", title: "Moverse en Madrid con la app de EMT", duration: "0:42", color: 0, tiktokUrl: "https://vt.tiktok.com/ZSxV6R7FU/" },
  { type: "creator", tag: "Educación", brand: "Forward College · universidad", title: "Estudiar en Forward College", duration: "0:48", color: 2, tiktokUrl: "https://vt.tiktok.com/ZSxV6dG9C/" },
  { type: "creator", tag: "Lifestyle", brand: "Cupra · concesionario", title: "Cupra City Garage en Madrid", duration: "0:50", color: 0, tiktokUrl: "https://vt.tiktok.com/ZSxV62V8J/" },
  { type: "creator", tag: "Lifestyle", brand: "Shein · kit de viaje", title: "Mi kit de viaje con Shein", duration: "0:45", color: 1, tiktokUrl: "https://vt.tiktok.com/ZSxV63Brx/" },
  { type: "creator", tag: "Apps", brand: "Vinted · app de ropa", title: "Cómo vendo mi ropa en Vinted", duration: "0:46", color: 1, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7573041544672955666" },
  { type: "creator", tag: "Comida", brand: "Little Moons · mochi", title: "Campaña Little Moons Mochi", duration: "0:35", color: 0, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7646880910868073749" },
  { type: "creator", tag: "Apps", brand: "Santander · tarjeta Iberia", title: "Suma puntos con Santander x Iberia", duration: "0:42", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7580076225633209608" },
  { type: "creator", tag: "Comida", brand: "Cantina Mariachi · mexicano", title: "Comida mexicana en Cantina Mariachi", duration: "0:38", color: 0, instagramUrl: "https://www.instagram.com/p/DZGHTUmIz1X/", poster: "imagenes/ig-cantinamariachi.webp" },
  { type: "creator", tag: "Bienestar", brand: "Yun Bienestar · spa", title: "Día de spa en Yun Bienestar", duration: "0:40", color: 2, instagramUrl: "https://www.instagram.com/p/DYpgUs2IcLd/", poster: "imagenes/ig-yunbienestar.webp" },
  { type: "creator", tag: "Lifestyle", brand: "Mutears · earplugs", title: "Mis earplugs de Mutears", duration: "0:32", color: 1, instagramUrl: "https://www.instagram.com/p/DYNB7cZMI79/", poster: "imagenes/ig-mutears.webp" },

  // ── Vlogs & reseñas (contenido propio, sin brief comercial) ──
  { type: "vlog", tag: "Viajes", brand: "Vlog · Budapest día 1", title: "Mi primer día en Budapest", duration: "0:48", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7641999019429891346" },
  { type: "vlog", tag: "Viajes", brand: "Vlog · Budapest día 2", title: "Día 2 en Budapest", duration: "0:46", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7645379961062231314" },
  { type: "vlog", tag: "Viajes", brand: "Vlog · Norte de España día 1", title: "Norte de España · día 1", duration: "0:48", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7627190982244568327" },
  { type: "vlog", tag: "Viajes", brand: "Vlog · Norte de España día 2", title: "Norte de España · día 2", duration: "0:46", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7627599097335139592" },
  { type: "vlog", tag: "Viajes", brand: "Vlog · Norte de España día 3", title: "Norte de España · día 3", duration: "0:47", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7628715856519875847" },
  { type: "vlog", tag: "Viajes", brand: "Vlog · Norte de España día 4", title: "Norte de España · día 4", duration: "0:49", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7630853181668461842" },
  { type: "vlog", tag: "Viajes", brand: "Vlog · Norte de España día 5", title: "Norte de España · día 5", duration: "0:48", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7631636083402394888" },
  { type: "vlog", tag: "Viajes", brand: "Vlog · Buenos Aires → Madrid", title: "De Buenos Aires a Madrid", duration: "0:52", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7632327242621685013" },
  { type: "vlog", tag: "Viajes", brand: "Vlog · Madrid → Buenos Aires", title: "De Madrid a Buenos Aires", duration: "0:50", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7619470807864970517" },
  { type: "vlog", tag: "Creativo", brand: "Videoclip · edición propia", title: "Lipsync \"Tu Chat\" · Quevedo", duration: "0:30", color: 1, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7602983665861152008" },  { type: "vlog", tag: "Lifestyle", brand: "Vlog · un jueves en Madrid", title: "Un jueves conmigo en Madrid", duration: "0:50", color: 0, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7600533599867145479" },
  { type: "vlog", tag: "Hoteles", brand: "Reseña · Airbnb Budapest", title: "Mi Airbnb en Budapest", duration: "0:45", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7642006166687468808" },
  { type: "vlog", tag: "Hoteles", brand: "Reseña · Zarautz, País Vasco", title: "Alojamiento en Zarautz", duration: "0:42", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7617606803173510421" },
  { type: "vlog", tag: "Hoteles", brand: "Reseña · Ribadesella, Asturias", title: "Dónde dormir en Ribadesella", duration: "0:40", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7617228374913617160" },
  { type: "vlog", tag: "Hoteles", brand: "Reseña · Oviedo", title: "Mi alojamiento en Oviedo", duration: "0:38", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7617059863411117319" },
  { type: "vlog", tag: "Hoteles", brand: "Reseña · Bilbao", title: "Dónde dormir en Bilbao", duration: "0:41", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7617894022258052373" },
  { type: "vlog", tag: "Hoteles", brand: "Reseña · Hotel Meliá Castilla", title: "Reseña Hotel Meliá Castilla", duration: "0:44", color: 2, tiktokUrl: "https://www.tiktok.com/@ludistante/video/7618542773012073736" },
];

const TYPE_TABS = [
  { value: "ugc", label: "UGC para marcas", desc: "Contenido que entrego para que la marca publique en sus canales." },
  { value: "creator", label: "Colabs en mis redes", desc: "Contenido pagado, publicado en mis redes con mi audiencia detrás." },
  { value: "vlog", label: "Vlogs & reseñas", desc: "Formatos propios y experiencias reales que muestran mi estilo sin brief comercial." },
];

const FILTERS = ["Todos", "Apps", "Comida", "Educación", "Belleza", "Bienestar", "Moda", "Viajes", "Hoteles", "Lifestyle", "Finanzas", "Creativo", "Hogar"];

const WHY = [
  { n: "01", title: "Estética cuidada, propósito claro", desc: "Cada pieza tiene una intención. No subo por subir: cuido la dirección de arte, el ritmo y el final del video." },
  { n: "02", title: "Storytelling que retiene", desc: "Mi diferencial es la narrativa. Hooks afilados, desarrollo y cierre que invitan a quedarse y volver." },
  { n: "03", title: "Vínculo real con la comunidad", desc: "Respondo, escucho y conozco a mi audiencia. Cuando recomiendo algo, lo creen — porque es real." },
  { n: "04", title: "Trabajo con criterio editorial", desc: "Vengo de probar muchos formatos y nichos. Eso me da contexto para proponerte ideas, no solo ejecutarlas." },
];

// ─── Placeholder cover ────────────────────────────────────────────────
function Placeholder({ tone, label, accent, animated }) {
  const colors = {
    a: ["#241a14", "#3a2418"],
    b: ["#231625", "#3b1d3a"],
    c: ["#16202a", "#1c2f3f"],
    d: ["#1a2418", "#283b25"],
    e: ["#241a1a", "#3a1f1f"],
  };
  const [c1, c2] = colors[tone] || colors.a;
  return (
    <div
      className={`ph ${animated ? "ph-anim" : ""}`}
      data-ph={label}
      style={{
        "--bg-color": c1,
        "--accent": accent,
        backgroundImage: `radial-gradient(circle at 30% 25%, ${accent}33 0%, transparent 45%), linear-gradient(150deg, ${c1}, ${c2}), linear-gradient(135deg, rgba(255,255,255,0.05) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.05) 50%, rgba(255,255,255,0.05) 75%, transparent 75%, transparent)`,
        backgroundSize: "auto, auto, 18px 18px",
      }}
    >
      {animated && (
        <>
          <span className="ph-blob ph-blob-1" />
          <span className="ph-blob ph-blob-2" />
          <span className="ph-shimmer" />
          <span className="ph-tag">video preview</span>
        </>
      )}
    </div>
  );
}

// ─── Hero ─────────────────────────────────────────────────────────────
function Hero({ t, palette }) {
  return (
    <section className="hero" data-screen-label="01 Hero">
      <div className="wrap">
        <div className="hero-grid">
          <div>
            <div className="hero-eyebrow">Creadora de contenido · multinicho</div>
            <h1 data-comment-anchor="hero-name">
              Lucía<br />
              Agustina<br />
              <em>Di Stante</em>
            </h1>
            <p className="hero-tag" data-comment-anchor="hero-tag">
              Creo contenido para marcas que quieren contar historias reales:
              belleza, lifestyle, comida, apps, moda y viajes con dirección y storytelling.
            </p>
            <div className="hero-cta-row">
              <button className="btn-secondary" onClick={() => {
                document.getElementById("trabajos")?.scrollIntoView({ behavior: "smooth", block: "start" });
              }}>
                Ver mis trabajos
                <span className="btn-arrow">→</span>
              </button>
            </div>
            <div className="hero-meta">
              <span className="chip">📍 España</span>
              <span className="chip"><span className="live-dot" />Disponible para colaboraciones</span>
            </div>
          </div>
          <div className="hero-portrait" data-comment-anchor="hero-portrait">
            <img src="imagenes/lucia-hero.webp" alt="Lucía Agustina Di Stante" />
            <div className="hero-portrait-tag">España · 2026</div>
          </div>
        </div>
      </div>
      {t.stickers && (
        <div className="stickers">
          <div className="sticker s1">✦ storytelling first</div>
          <div className="sticker s2">multinicho · ar</div>
        </div>
      )}
    </section>
  );
}

// ─── Contact sheet (strip de retratos) ────────────────────────────────
function ContactSheet() {
  const imgs = [
    "imagenes/lucia-mini-1.webp",
    "imagenes/lucia-mini-2.webp",
    "imagenes/lucia-mini-3.webp",
    "imagenes/lucia-mini-4.webp",
  ];
  return (
    <div className="contact-sheet" aria-hidden="true">
      {imgs.map((src, i) => (
        <div key={src} className="cs-cell" style={{ "--i": i }}>
          <img src={src} alt="" loading="lazy" />
        </div>
      ))}
    </div>
  );
}

// ─── Marquee ──────────────────────────────────────────────────────────
function Marquee() {
  const items = (
    <span>
      Lifestyle <span className="dot" />
      Moda <em>&amp;</em> belleza <span className="dot p" />
      Comida <span className="dot v" />
      Finanzas <span className="dot" />
      Viajes <span className="dot p" />
      Storytelling <em>real</em> <span className="dot v" />
    </span>
  );
  return (
    <div className="marquee" data-screen-label="02 Marquee">
      <div className="marquee-track">
        {items}{items}{items}
      </div>
    </div>
  );
}

// ─── Sobre mí ─────────────────────────────────────────────────────────
function About({ palette }) {
  return (
    <section className="s s-about" id="sobre-mi" data-screen-label="03 Sobre mí">
      <div className="wrap">
        <div className="s-head">
          <div className="s-num">01 — Sobre mí</div>
          <h2 className="s-title">Detrás de cámara hay <em>una historia</em>.</h2>
        </div>
        <div className="about-grid">
          <div className="about-portrait" data-comment-anchor="about-portrait">
            <img src="imagenes/lucia-about.webp" alt="Lucía Agustina Di Stante" />
            <div className="badge">@ludienmadrid</div>
          </div>
          <div className="about-body">
            <p data-comment-anchor="about-bio-1">
              Soy <em>Lucía Agustina</em>, creadora de contenido en España. Convierto
              productos, lugares y marcas en contenido que la gente quiere{" "}
              <span className="hl">ver, guardar y compartir</span>.
            </p>
            <p data-comment-anchor="about-bio-2">
              Mi fuerte es la <em>versatilidad</em>: pasé por bancos, restaurantes, apps y
              belleza, y aprendí a <span className="hl">adaptarme a cada marca</span> sin
              perder mi estilo.
            </p>
            <div className="about-niches">
              {NICHES.map((n) => (
                <div key={n.label} className="n"><i /> {n.label}</div>
              ))}
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

// ─── Servicios ────────────────────────────────────────────────────────
function Services() {
  return (
    <section className="s s-services" id="servicios" data-screen-label="04 Servicios">
      <div className="wrap">
        <div className="s-head s-head-services">
          <div className="s-num">02 — Servicios</div>
          <h2 className="s-title">Esto es lo que <em>creo</em> para tu marca.</h2>
          <div className="s-head-avatar">
            <img src="imagenes/lucia-services.webp" alt="Lucía en estudio" />
          </div>
        </div>
        <div className="svc-grid">
          {SERVICES.map((s) => (
            <div key={s.num} className={`svc-card ${s.featured || ""}`} data-comment-anchor={`svc-${s.num}`}>
              <div className="svc-num">{s.num}</div>
              <div>
                <h3>{s.title}</h3>
                <p>{s.desc}</p>
              </div>
              <div className="svc-arrow">→</div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

// ─── TikTok thumbnail fetcher ─────────────────────────────────────────
// Usa la API oEmbed pública de TikTok para traer el cover real del video.
// Si falla (CORS / sin conexión / link inválido), cae al placeholder animado.
const __tiktokThumbCache = new Map();
function useTikTokThumbnail(url) {
  const [thumb, setThumb] = React.useState(() =>
    url && __tiktokThumbCache.has(url) ? __tiktokThumbCache.get(url) : null
  );
  React.useEffect(() => {
    if (!url) { setThumb(null); return; }
    if (__tiktokThumbCache.has(url)) { setThumb(__tiktokThumbCache.get(url)); return; }
    let cancelled = false;
    fetch(`https://www.tiktok.com/oembed?url=${encodeURIComponent(url)}`)
      .then((r) => (r.ok ? r.json() : null))
      .then((d) => {
        if (cancelled) return;
        const t = d && d.thumbnail_url ? d.thumbnail_url : null;
        __tiktokThumbCache.set(url, t);
        setThumb(t);
      })
      .catch(() => {
        if (cancelled) return;
        __tiktokThumbCache.set(url, null);
        setThumb(null);
      });
    return () => { cancelled = true; };
  }, [url]);
  return thumb;
}

// ─── Lightbox player ──────────────────────────────────────────────────
// Extrae el ID de un link de TikTok ("https://www.tiktok.com/@user/video/1234..." → "1234...")
function getTikTokId(url) {
  if (!url) return null;
  const m = url.match(/\/video\/(\d+)/) || url.match(/\/v\/(\d+)/);
  return m ? m[1] : null;
}

// Extrae el shortcode de un link de Instagram ("https://instagram.com/p/ABC123/" → "ABC123")
function getInstagramCode(url) {
  if (!url) return null;
  const m = url.match(/instagram\.com\/(?:p|reel|reels|tv)\/([A-Za-z0-9_-]+)/);
  return m ? m[1] : null;
}

function Lightbox({ work, onClose, onPrev, onNext }) {
  // Esc para cerrar, flechas para navegar
  React.useEffect(() => {
    if (!work) return;
    const onKey = (e) => {
      if (e.key === "Escape") onClose();
      if (e.key === "ArrowLeft") onPrev();
      if (e.key === "ArrowRight") onNext();
    };
    document.body.style.overflow = "hidden";
    window.addEventListener("keydown", onKey);
    return () => {
      document.body.style.overflow = "";
      window.removeEventListener("keydown", onKey);
    };
  }, [work, onClose, onPrev, onNext]);

  if (!work) return null;

  const ttId = getTikTokId(work.tiktokUrl);
  const igCode = getInstagramCode(work.instagramUrl);
  const externalUrl = work.tiktokUrl || work.instagramUrl;
  const platform = work.instagramUrl ? "Instagram" : "TikTok";

  return (
    <div className="lb" onClick={onClose}>
      <button className="lb-close" onClick={onClose} aria-label="Cerrar">✕</button>
      <button className="lb-nav lb-prev" onClick={(e) => { e.stopPropagation(); onPrev(); }} aria-label="Anterior">‹</button>
      <button className="lb-nav lb-next" onClick={(e) => { e.stopPropagation(); onNext(); }} aria-label="Siguiente">›</button>

      <div className="lb-stage" onClick={(e) => e.stopPropagation()}>
        <div className={`lb-video ${ttId ? "lb-video-tt" : ""} ${igCode ? "lb-video-ig" : ""}`}>
          {ttId ? (
            <iframe
              key={ttId}
              src={`https://www.tiktok.com/embed/v2/${ttId}?lang=es`}
              allow="encrypted-media; fullscreen; picture-in-picture"
              allowFullScreen
              title={work.title}
            />
          ) : igCode ? (
            <iframe
              key={igCode}
              src={`https://www.instagram.com/p/${igCode}/embed`}
              allow="encrypted-media; fullscreen; picture-in-picture"
              allowFullScreen
              title={work.title}
            />
          ) : work.video ? (
            <video
              key={work.video}
              src={work.video}
              poster={work.poster || undefined}
              controls
              autoPlay
              playsInline
              preload="metadata"
            />
          ) : (
            <div className="lb-empty">
              <div className="lb-empty-glyph">
                {work.type === "ugc" ? "🎬" : "▶"}
              </div>
              <div className="lb-empty-title">
                {work.type === "ugc"
                  ? "Video disponible bajo solicitud"
                  : externalUrl
                    ? `Ver este video en ${platform}`
                    : "Video próximamente"}
              </div>
              <div className="lb-empty-sub">
                {work.type === "ugc" ? (
                  <>Algunos UGC son material exclusivo para marcas.<br />
                  Escribime a <strong>luciadistantecolabs@gmail.com</strong> para verlo.</>
                ) : externalUrl ? (
                  <>Tocá el botón de abajo para abrirlo en {platform} ↓</>
                ) : (
                  <>Estoy subiendo este video, vuelve pronto.</>
                )}
              </div>
            </div>
          )}
        </div>
        <div className="lb-info">
          <div className="lb-brand">{work.brand}</div>
          <div className="lb-title">{work.title}</div>
          <div className="lb-tags">
            <span>{work.tag}</span>
            <span>·</span>
            <span>{work.duration}</span>
            {work.type === "creator" && (
              <>
                <span>·</span>
                <span>{platform}</span>
              </>
            )}
          </div>
          {externalUrl && (
            <a
              href={externalUrl}
              target="_blank"
              rel="noopener"
              className="lb-tiktok-link"
              onClick={(e) => e.stopPropagation()}
            >
              Ver en {platform}
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
                <path d="M7 17L17 7M7 7h10v10" />
              </svg>
            </a>
          )}
          {work.type === "ugc" && !work.video && (
            <a
              href="mailto:luciadistantecolabs@gmail.com?subject=Quiero ver tu UGC"
              className="lb-tiktok-link lb-mail-link"
              onClick={(e) => e.stopPropagation()}
            >
              Solicitar acceso al video
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
                <path d="M7 17L17 7M7 7h10v10" />
              </svg>
            </a>
          )}
        </div>
      </div>
    </div>
  );
}

// ─── WorkCard ─────────────────────────────────────────────────────────
function WorkCard({ w, idx, type, palette, onClick }) {
  const tones = ["a", "b", "c", "d", "e"];
  const tiktokThumb = useTikTokThumbnail(w.tiktokUrl);
  const [imgFailed, setImgFailed] = React.useState(false);
  const igCode = getInstagramCode(w.instagramUrl);
  const igThumb = igCode ? `https://www.instagram.com/p/${igCode}/media/?size=l` : null;
  const cover = imgFailed ? null : (w.poster || tiktokThumb || igThumb);
  return (
    <button
      type="button"
      className="work-item"
      data-comment-anchor={`work-${type}-${idx}`}
      onClick={onClick}
      aria-label={`Ver ${w.title}`}
    >
      {cover ? (
        <img
          className="work-poster"
          src={cover}
          alt={w.title}
          loading="lazy"
          referrerPolicy="no-referrer"
          onError={() => setImgFailed(true)}
        />
      ) : (
        <DesignedCover w={w} idx={idx} palette={palette} />
      )}
      <div className="work-cover">
        <div className="work-top">
          <span className="work-brand">{w.brand}</span>
          <span className={`work-type-pill work-type-${w.type}`}>
            {w.type === "ugc"
              ? "UGC"
              : w.type === "vlog"
                ? w.brand.split("·")[0].trim()
                : w.instagramUrl
                  ? "Instagram"
                  : "TikTok"}
          </span>
        </div>
        <div className="work-meta">
          <div className="work-title">{w.title}</div>
          <div className="work-stats">
            <span>▶ {w.duration}</span>
          </div>
        </div>
      </div>
      <div className="work-play">
        <svg width="18" height="18" viewBox="0 0 24 24">
          <path d="M8 5v14l11-7z" />
        </svg>
      </div>
    </button>
  );
}

// Cover diseñado que no depende de imágenes externas — gradiente + iconografía
// + tipografía grande con el pilar y la marca. Se ve pro sin thumbnail.
function DesignedCover({ w, idx, palette }) {
  const tagColors = {
    Belleza: { bg: "linear-gradient(155deg, #2a1a26, #4a1d3f)", accent: palette[1] },
    Moda: { bg: "linear-gradient(155deg, #2a1a26, #4a2d1f)", accent: palette[1] },
    Comida: { bg: "linear-gradient(155deg, #2a1f14, #4a3018)", accent: palette[0] },
    Viajes: { bg: "linear-gradient(155deg, #14202a, #1a2f4a)", accent: palette[2] },
    Lifestyle: { bg: "linear-gradient(155deg, #1a2418, #283b25)", accent: palette[0] },
    Finanzas: { bg: "linear-gradient(155deg, #1a1828, #2d2548)", accent: palette[2] },
    Hogar: { bg: "linear-gradient(155deg, #241a1a, #3a2418)", accent: palette[0] },
  };
  const cfg = tagColors[w.tag] || tagColors.Lifestyle;
  return (
    <div
      className="dc"
      style={{
        background: cfg.bg,
        "--accent": cfg.accent,
      }}
    >
      <span className="dc-blob" />
      <span className="dc-grain" />
      <div className="dc-tag">{w.tag}</div>
      <div className="dc-num">{String(idx + 1).padStart(2, "0")}</div>
    </div>
  );
}

// ─── Trabajos ─────────────────────────────────────────────────────────
function Works({ palette }) {
  const [type, setType] = React.useState("ugc");
  const [filter, setFilter] = React.useState("Todos");
  const [activeIdx, setActiveIdx] = React.useState(null);

  const byType = WORKS.filter((w) => w.type === type);
  // Solo muestro pilares que existen en este tipo
  const availableTags = ["Todos", ...Array.from(new Set(byType.map((w) => w.tag)))];
  const items = filter === "Todos" ? byType : byType.filter((w) => w.tag === filter);
  const active = activeIdx == null ? null : items[activeIdx];
  const close = () => setActiveIdx(null);
  const prev = () => setActiveIdx((i) => (i == null ? null : (i - 1 + items.length) % items.length));
  const next = () => setActiveIdx((i) => (i == null ? null : (i + 1) % items.length));

  // Reset filtro al cambiar de pestaña si el filtro actual no aplica
  React.useEffect(() => {
    if (!availableTags.includes(filter)) setFilter("Todos");
  }, [type]);

  const activeTab = TYPE_TABS.find((t) => t.value === type);

  return (
    <section className="s s-works" id="trabajos" data-screen-label="05 Mis trabajos">
      <div className="wrap">
        <div className="s-head">
          <div className="s-num">03 — Mis trabajos</div>
          <h2 className="s-title">Selección de <em>piezas recientes</em>.</h2>
        </div>

        <div className="work-tabs" role="tablist">
          {TYPE_TABS.map((tab) => (
            <button
              key={tab.value}
              className={`work-tab ${type === tab.value ? "active" : ""}`}
              onClick={() => { setType(tab.value); setActiveIdx(null); }}
              role="tab"
              aria-selected={type === tab.value}
            >
              <span className="work-tab-label">{tab.label}</span>
              <span className="work-tab-count">{WORKS.filter((w) => w.type === tab.value).length}</span>
            </button>
          ))}
        </div>
        <p className="work-tab-desc">{activeTab.desc}</p>

        <div className="work-toolbar">
          {availableTags.map((f) => (
            <button
              key={f}
              className={`filter ${f === filter ? "active" : ""}`}
              onClick={() => { setFilter(f); setActiveIdx(null); }}
            >
              {f}
            </button>
          ))}
        </div>
        <div className="work-grid">
          {items.map((w, i) => (
            <WorkCard
              key={`${type}-${i}`}
              w={w}
              idx={i}
              type={type}
              palette={palette}
              onClick={() => setActiveIdx(i)}
            />
          ))}
        </div>
      </div>
      <Lightbox work={active} onClose={close} onPrev={prev} onNext={next} />
    </section>
  );
}

// ─── Por qué yo ───────────────────────────────────────────────────────
function Why() {
  return (
    <section className="s s-why" id="por-que" data-screen-label="06 ¿Por qué yo?">
      <div className="wrap">
        <div className="s-head">
          <div className="s-num">04 — ¿Por qué yo?</div>
          <h2 className="s-title">No solo grabo. <em>Pienso</em> el contenido.</h2>
        </div>
        <div className="why-grid">
          {WHY.map((w) => (
            <div key={w.n} className="why-item" data-comment-anchor={`why-${w.n}`}>
              <div className="why-num">{w.n}</div>
              <div>
                <h3>{w.title}</h3>
                <p>{w.desc}</p>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

// ─── Contacto ─────────────────────────────────────────────────────────
function Contact() {
  return (
    <section className="s s-contact" id="contacto" data-screen-label="07 Contacto">
      <div className="wrap">
        <div className="s-head">
          <div className="s-num">05 — Contacto</div>
          <h2 className="s-title">¿Charlamos sobre <em>tu próxima campaña</em>?</h2>
        </div>
        <div className="contact-grid">
          <div className="contact-photo" data-comment-anchor="contact-photo">
            <img src="imagenes/lucia-contact.webp" alt="Lucía lista para tu marca" />
          </div>
          <div className="contact-main">
            <p className="contact-headline">
              Tu marca <em>+ mis ideas =</em> contenido que la gente recuerda.
            </p>
            <a className="contact-mail" href="mailto:luciadistantecolabs@gmail.com" data-comment-anchor="contact-mail">
              luciadistantecolabs@gmail.com
              <span className="arrow">→</span>
            </a>
          </div>
          <div className="contact-list">
            <a className="row" href="https://instagram.com/ludienmadrid" target="_blank" rel="noopener" data-comment-anchor="contact-ig">
              <div>
                <div className="lbl">Instagram</div>
                <div className="val">@ludienmadrid</div>
              </div>
              <span>↗</span>
            </a>
            <a className="row" href="https://tiktok.com/@ludistante" target="_blank" rel="noopener" data-comment-anchor="contact-tt">
              <div>
                <div className="lbl">TikTok</div>
                <div className="val">@ludistante</div>
              </div>
              <span>↗</span>
            </a>
          </div>
        </div>
      </div>
    </section>
  );
}

// ─── Footer ───────────────────────────────────────────────────────────
function Footer() {
  return (
    <footer className="foot">
      <div className="wrap" style={{ display: "flex", justifyContent: "space-between", flexWrap: "wrap", gap: 16, width: "100%" }}>
        <div>© 2026 Lucía Agustina Di Stante · España</div>
        <div>Sitio diseñado con cariño · Última actualización: mayo 2026</div>
      </div>
    </footer>
  );
}

// ─── Nav ──────────────────────────────────────────────────────────────
function Nav() {
  return (
    <nav className="nav">
      <div className="nav-inner">
        <div className="nav-links">
          <a href="#sobre-mi">Sobre mí</a>
          <a href="#servicios">Servicios</a>
          <a href="#trabajos">Trabajos</a>
          <a href="#por-que">¿Por qué yo?</a>
        </div>
        <button className="nav-cta" onClick={() => {
          document.getElementById("contacto")?.scrollIntoView({ behavior: "smooth", block: "start" });
        }}>Trabajemos juntos →</button>
      </div>
    </nav>
  );
}

// ─── App ──────────────────────────────────────────────────────────────
function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // Apply CSS variables for palette
  React.useEffect(() => {
    const root = document.documentElement;
    root.style.setProperty("--c1", t.palette[0]);
    root.style.setProperty("--c2", t.palette[1]);
    root.style.setProperty("--c3", t.palette[2]);
    root.style.setProperty("--display", `"${t.displayFont}", system-ui, sans-serif`);
    root.setAttribute("data-accent", t.accent);
    root.setAttribute("data-density", t.density);
  }, [t]);

  return (
    <>
      <Nav />
      <Hero t={t} palette={t.palette} />
      {t.marquee && <Marquee />}
      <About palette={t.palette} />
      <Services />
      <Works palette={t.palette} />
      <Why />
      <Contact />
      <Footer />

      <TweaksPanel title="Tweaks">
        <TweakSection label="Paleta" />
        <TweakColor
          label="Acentos"
          value={t.palette}
          options={PALETTES}
          onChange={(v) => setTweak("palette", v)}
        />
        <TweakRadio
          label="Estilo"
          value={t.accent}
          options={["solid", "outline", "gradient"]}
          onChange={(v) => setTweak("accent", v)}
        />

        <TweakSection label="Tipografía" />
        <TweakSelect
          label="Fuente display"
          value={t.displayFont}
          options={DISPLAY_FONTS}
          onChange={(v) => setTweak("displayFont", v)}
        />

        <TweakSection label="Layout" />
        <TweakRadio
          label="Densidad"
          value={t.density}
          options={["cozy", "regular", "airy"]}
          onChange={(v) => setTweak("density", v)}
        />
        <TweakToggle
          label="Marquee de nichos"
          value={t.marquee}
          onChange={(v) => setTweak("marquee", v)}
        />
        <TweakToggle
          label="Stickers decorativos"
          value={t.stickers}
          onChange={(v) => setTweak("stickers", v)}
        />
      </TweaksPanel>
    </>
  );
}

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