/* global React, CATALOGO, CAT_LABELS, CAT_TOTALS, PATRONES, detectarPatron, ICONOS_INFO,
   Placeholder, Eyebrow, Arr, HeartIcon, Reveal, useWishlist, useUI, waLink */
const { useState, useMemo, useEffect } = React;

/* ─── Portada del catálogo — polaroids por categoría ─── */
function CatalogPortada({ onSelect }) {
  const isMob = typeof window !== "undefined" && window.innerWidth < 760;

  const CATS = [
    { id: "mecedoras",  bg: "#ede4d4" },
    { id: "sillas",     bg: "#dde8e0" },
    { id: "comedores",  bg: "#dde4ee" },
    { id: "combos",     bg: "#f0e4d4" },
    { id: "mesas",      bg: "#e8e4da" },
    { id: "sofas",      bg: "#ead8e4" },
    { id: "percheros",  bg: "#d4e8d4" },
    { id: "sillas-bar", bg: "#f0ddd8" },
  ].filter(c => (CATALOGO||[]).some(p => p.categoria === c.id));

  const CAT_HERO_LOCAL_P = { sofas: "guajira-lineal", "sillas-bar": "diamante-precolombino-3" };
  const getPhoto = (catId) => {
    const ovr = CAT_HERO_LOCAL_P[catId] || (window.CAT_HERO_OVERRIDES||{})[catId];
    if (ovr) { const p = (CATALOGO||[]).find(x => (x.id === ovr || x.slug === ovr) && x.foto); if (p) return p.foto; }
    return (CATALOGO||[]).find(p => p.categoria === catId && p.foto)?.foto || null;
  };

  const minPrecio = (catId) => {
    const ps = (CATALOGO||[]).filter(p => p.categoria === catId && p.precio).map(p => p.precio);
    return ps.length ? Math.min(...ps).toLocaleString("es-CO") : null;
  };

  return (
    <div style={{ minHeight:"100vh", background:"#1b1813", padding: isMob ? "108px 16px 64px" : "108px clamp(40px,7vw,120px) 88px" }}>
      <style>{`
        @keyframes pol-in { from{opacity:0;transform:translateY(28px) rotate(var(--rot))} to{opacity:1;transform:translateY(0) rotate(var(--rot))} }
        .pol-card { --rot:0deg; transform:rotate(var(--rot)); animation:pol-in .65s cubic-bezier(.2,.7,.2,1) both; cursor:pointer; will-change:transform; transition:transform .38s cubic-bezier(.2,.7,.2,1), box-shadow .38s; }
        .pol-card:hover { transform:rotate(0deg) translateY(-10px) scale(1.04) !important; }
        .pol-card:nth-child(1){--rot:-2.2deg;animation-delay:.06s}
        .pol-card:nth-child(2){--rot: 1.5deg;animation-delay:.12s}
        .pol-card:nth-child(3){--rot:-1.2deg;animation-delay:.18s}
        .pol-card:nth-child(4){--rot: 2.0deg;animation-delay:.24s}
        .pol-card:nth-child(5){--rot:-0.8deg;animation-delay:.30s}
        .pol-card:nth-child(6){--rot: 1.8deg;animation-delay:.36s}
        .pol-card:nth-child(7){--rot:-1.8deg;animation-delay:.42s}
        .pol-card:nth-child(8){--rot: 2.5deg;animation-delay:.48s}
        .pol-card .pol-frame { background:#fff; border-radius:2px; }
        .pol-card .pol-photo { overflow:hidden; display:flex; align-items:center; justify-content:center; }
        .pol-card .pol-photo img { width:100%; height:100%; object-fit:contain; display:block; transition:transform .55s cubic-bezier(.2,.7,.2,1); }
        .pol-card:hover .pol-photo img { transform:scale(1.06); }
        .pol-verTodo { background:none; border:1.5px solid rgba(247,242,234,.22); color:rgba(247,242,234,.6); font-size:12px; letter-spacing:.14em; text-transform:uppercase; padding:14px 32px; border-radius:2px; cursor:pointer; transition:all .25s; }
        .pol-verTodo:hover { border-color:rgba(247,242,234,.55); color:#F7F2EA; }
      `}</style>

      {/* Header */}
      <div style={{ marginBottom: isMob ? 40 : 52 }}>
        <div style={{ fontSize:10, letterSpacing:"0.28em", textTransform:"uppercase", color:"#C8901A", fontWeight:500, marginBottom:14 }}>El catálogo · DAVA'S · 2026</div>
        <h1 style={{ fontFamily:"var(--f-display,'Fraunces',serif)", fontWeight:400, fontSize: isMob?"clamp(28px,8vw,38px)":"clamp(36px,4vw,58px)", lineHeight:1.0, letterSpacing:"-1px", color:"#F7F2EA", margin:"0 0 14px" }}>
          ¿Qué espacio vas<br/><span style={{ fontStyle:"italic", color:"#C8901A" }}>a transformar?</span>
        </h1>
        <p style={{ fontSize: isMob?14:15, color:"rgba(247,242,234,.55)", maxWidth:400 }}>
          Elige tu categoría y encuentra la pieza que va a vivir contigo.
        </p>
      </div>

      {/* Grid de polaroids */}
      <div style={{ display:"grid", gridTemplateColumns: isMob ? "1fr 1fr" : "repeat(3,1fr)", gap: isMob ? "clamp(20px,5vw,28px)" : "clamp(28px,4vw,52px)" }}>
        {CATS.map((c) => {
          const photo  = getPhoto(c.id);
          const label  = (CAT_LABELS?.combos && c.id === 'combos' ? 'Conjuntos' : null) || CAT_LABELS[c.id] || c.id;
          const count  = (CATALOGO||[]).filter(p => p.categoria === c.id).length;
          const desde  = minPrecio(c.id);
          const pad    = isMob ? 9 : 13;
          const bot    = isMob ? 36 : 48;

          return (
            <div key={c.id} className="pol-card" onClick={() => onSelect(c.id)}
              style={{ boxShadow:"0 20px 56px rgba(0,0,0,.5)" }}>
              <div className="pol-frame" style={{ padding:`${pad}px ${pad}px ${bot}px` }}>
                <div className="pol-photo" style={{ background:"#ffffff", aspectRatio:"1/1" }}>
                  {photo
                    ? <img src={photo} alt={label} />
                    : <div style={{ width:"55%", height:"55%", background:"rgba(0,0,0,.10)", borderRadius:2 }} />
                  }
                </div>
                <div style={{ textAlign:"center", paddingTop: isMob ? 6 : 10 }}>
                  <div style={{ fontFamily:"'Caveat','Segoe Script',cursive", fontSize: isMob?18:26, fontWeight:600, color:"#1b1813", lineHeight:1 }}>{label}</div>
                  <div style={{ fontSize: isMob?10.5:11.5, color:"#9a8878", marginTop: isMob?4:5 }}>
                    {count} piezas{desde ? ` · desde $${desde}` : ""}
                  </div>
                </div>
              </div>
            </div>
          );
        })}
      </div>

      {/* Ver todo */}
      <div style={{ textAlign:"center", marginTop: isMob ? 44 : 60 }}>
        <button className="pol-verTodo" onClick={() => onSelect("__all__")}>
          Ver todo el catálogo →
        </button>
      </div>
    </div>
  );
}

/* ─── Tarjeta de producto — estilo polaroid ─── */
// Productos sin foto no se muestran al público
function CatProd({ p, onOpen, onModelo }) {
  if (!p.foto) return null;
  const wl = useWishlist();
  const isOn = wl.has(p.id);
  return (
    <div className="cat-prod"
      onClick={() => onOpen(p)}
      style={{ background:"#fff", padding:"10px 10px 44px", boxShadow:"0 12px 32px rgba(0,0,0,.13)", cursor:"pointer", position:"relative", transition:"transform .32s cubic-bezier(.2,.7,.2,1), box-shadow .32s", borderRadius:2 }}>
      <style>{`
        .cat-prod:hover { transform:translateY(-6px) rotate(0deg) !important; box-shadow:0 22px 48px rgba(0,0,0,.2) !important; }
        .cat-prod:hover .pol-photo img { transform:scale(1.05); }
        .pol-photo img { transition:transform .55s cubic-bezier(.2,.7,.2,1); }
      `}</style>
      {/* Foto */}
      <div className="pol-photo" style={{ background:"#ffffff", aspectRatio:"1/1", overflow:"hidden", display:"flex", alignItems:"center", justifyContent:"center", position:"relative" }}>
        <img src={p.foto} alt={p.nombre} loading="lazy" style={{ width:"100%", height:"100%", objectFit:"contain", display:"block" }} />
        <button
          className={`heart ${isOn ? "is-on" : ""}`}
          aria-label={isOn ? "Quitar" : "Guardar"}
          onClick={(e) => { e.stopPropagation(); wl.toggle({ id:p.id, name:p.nombre, family:CAT_LABELS[p.categoria], pattern:detectarPatron(p.variante), price:p.precio.toLocaleString("es-CO") }); }}
          style={{ position:"absolute", top:8, right:8 }}>
          <HeartIcon filled={isOn} size={14} stroke={isOn ? "var(--bone)" : "var(--ink)"} />
        </button>
      </div>
      {/* Nombre a mano + precio */}
      <div style={{ paddingTop:10, textAlign:"center" }}>
        <div style={{ fontFamily:"'Caveat','Segoe Script',cursive", fontSize:18, fontWeight:600, color:"#1b1813", lineHeight:1.1 }}>{p.nombre}</div>
        <div style={{ fontSize:11.5, color:"#9a917f", marginTop:5 }}>$ {p.precio.toLocaleString("es-CO")}</div>
      </div>
    </div>
  );
}

function Catalog({ initialFilter, setPage, openModelo, openFicha }) {
  const initial = { cat: "all", modelo: "all", patron: "all", q: "", sort: "destacado", ...(initialFilter || {}) };
  const [f, setF] = useState(initial);
  const [drawerOpen, setDrawerOpen] = useState(false);

  // "portada" = grid de polaroids | "list" = catálogo filtrado
  const startMode = (initialFilter?.cat && initialFilter.cat !== "all") ? "list" : "portada";
  const [viewMode, setViewMode] = useState(startMode);

  const set = (k, v) => { setF((x) => ({ ...x, [k]: v })); setViewMode("list"); };
  const clearAll = () => { setF({ cat: "all", modelo: "all", patron: "all", q: "", sort: "destacado" }); setViewMode("portada"); };

  // ── Todos los hooks SIEMPRE (reglas de React) ──
  // Bloqueo scroll cuando drawer abierto
  useEffect(() => {
    document.body.style.overflow = drawerOpen ? "hidden" : "";
    return () => { document.body.style.overflow = ""; };
  }, [drawerOpen]);

  useEffect(() => { window.scrollTo({ top: 0, behavior: "instant" }); }, [initialFilter?.cat]);

  // Reporta al header cuánto mide el banner de categoría (con foto), para que
  // sepa hasta dónde ir en blanco/transparente y desde dónde pasar a oscuro.
  // Si no hay categoría activa (f.cat === "all") no hay banner → 0.
  const bannerRef = React.useRef(null);
  useEffect(() => {
    if (f.cat === "all") {
      document.documentElement.style.setProperty("--dark-zone-h", "0px");
      return;
    }
    const el = bannerRef.current;
    if (!el) { document.documentElement.style.setProperty("--dark-zone-h", "0px"); return; }
    const update = () => document.documentElement.style.setProperty("--dark-zone-h", el.offsetHeight + "px");
    update();
    const ro = new ResizeObserver(update);
    ro.observe(el);
    window.addEventListener("resize", update);
    return () => { ro.disconnect(); window.removeEventListener("resize", update); };
  }, [f.cat]);

  // Sync cuando cambia initialFilter desde afuera (ej. clic en categoría del home)
  useEffect(() => {
    if (initialFilter?.cat && initialFilter.cat !== "all") {
      setF(prev => ({ ...prev, ...(initialFilter||{}) }));
      setViewMode("list");
    }
  }, [initialFilter?.cat]);

  // Modelos derivados del catálogo
  const modelos = useMemo(() => {
    const counts = {};
    CATALOGO.forEach((p) => { counts[p.nombre] = (counts[p.nombre] || 0) + 1; });
    return Object.entries(counts).sort((a, b) => b[1] - a[1]).map(([name, n]) => ({ name, n }));
  }, []);

  // Filtrado
  const filtered = useMemo(() => {
    let out = CATALOGO.slice();
    if (f.cat !== "all") out = out.filter((p) => p.categoria === f.cat);
    if (f.modelo !== "all") out = out.filter((p) => p.nombre === f.modelo);
    if (f.patron !== "all") out = out.filter((p) => detectarPatron(p.variante) === f.patron);
    if (f.q) {
      const q = f.q.toLowerCase();
      out = out.filter((p) =>
        p.nombre.toLowerCase().includes(q) ||
        (p.variante || "").toLowerCase().includes(q) ||
        p.id.toLowerCase().includes(q)
      );
    }
    if (f.sort === "destacado") out.sort((a, b) => (b.destacado - a.destacado));
    if (f.sort === "precio-asc") out.sort((a, b) => a.precio - b.precio);
    if (f.sort === "precio-desc") out.sort((a, b) => b.precio - a.precio);
    if (f.sort === "nombre") out.sort((a, b) => a.nombre.localeCompare(b.nombre));
    return out;
  }, [f]);

  const activeChips = [];
  if (f.cat !== "all") activeChips.push({ key: "cat", label: CAT_LABELS[f.cat], kind: "Categoría" });
  if (f.modelo !== "all") activeChips.push({ key: "modelo", label: f.modelo, kind: "Modelo" });
  if (f.patron !== "all") activeChips.push({ key: "patron", label: f.patron, kind: "Patrón" });
  if (f.q) activeChips.push({ key: "q", label: `"${f.q}"`, kind: "Buscar" });

  // ── Portada de categorías (early return DESPUÉS de todos los hooks) ──
  if (viewMode === "portada") {
    return (
      <CatalogPortada
        onSelect={(catId) => {
          if (catId === "__all__") { setViewMode("list"); }
          else { set("cat", catId); }
        }}
      />
    );
  }

  // ── Vista de lista/catálogo ──
  // Banners diseñados por categoría (desktop + mobile)
  // Banners horizontales — funcionan para desktop y mobile con object-fit:cover
  const CAT_BANNERS = {
    sillas:       { desk: "/banner_sillas_desk.jpg",    mob: "/banner_sillas_desk.jpg" },
    mecedoras:    { desk: "/banner_mecedoras_desk.jpg", mob: "/banner_mecedoras_desk.jpg" },
    combos:       { desk: "/banner_combos_desk.jpg",    mob: "/banner_combos_desk.jpg" },
    comedores:    { desk: "/banner_comedores_desk.jpg", mob: "/banner_comedores_desk.jpg" },
    mesas:        { desk: "/banner_mesas_desk.jpg",     mob: "/banner_mesas_desk.jpg" },
    sofas:        { desk: "/banner_sofas_desk.jpg",     mob: "/banner_sofas_desk.jpg" },
    percheros:    { desk: "/banner_percheros_desk.jpg", mob: "/banner_percheros_desk.jpg" },
    "sillas-bar": { desk: "/banner_sillabar_desk.jpg",  mob: "/banner_sillabar_desk.jpg" },
  };
  // Display names override (combos → Conjuntos)
  const CAT_DISPLAY = { ...CAT_LABELS, combos: "Conjuntos" };
  // Local hero overrides por slug (sofás y sillas-bar)
  const CAT_HERO_LOCAL = { sofas: "guajira-lineal", "sillas-bar": "diamante-precolombino-3" };

  const isMob2 = typeof window !== "undefined" && window.innerWidth < 760;
  const getCatHero = (catId) => {
    const ovr = CAT_HERO_LOCAL[catId] || (window.CAT_HERO_OVERRIDES||{})[catId];
    if (ovr) { const p = CATALOGO.find(x => (x.id === ovr || x.slug === ovr) && x.foto); if (p) return p; }
    return CATALOGO.find(p => p.categoria === catId && p.foto) || null;
  };
  const CAT_COPIES = {
    mecedoras:    { copy:"Hecha para quedarte.\nHecha para ti.",          sub:"Hierro forjado, madera noble y tejido a mano. Una mecedora que es tuya desde el primer movimiento." },
    sillas:       { copy:"La silla que\ndefine el espacio.",              sub:"Cada silla lleva horas de tejido artesanal y una estructura en hierro fundida en nuestro taller." },
    comedores:    { copy:"Alrededor de esta\nmesa pasan cosas.",          sub:"Comedores tejidos a mano para las reuniones que importan. Hierro y madera noble, sin atajos." },
    combos:       { copy:"El conjunto\nque transforma el espacio.",       sub:"Dos sillas, una mesa y un tejido que las une. Diseñados para vivir juntos, tejidos a mano en nuestro taller." },
    comedores:    { copy:"La mesa que hace\nque nadie quiera irse.",          sub:"Comedores tejidos a mano para las reuniones que importan. Hierro y madera noble, sin atajos." },
    mesas:        { copy:"La base de\ncada historia.",                    sub:"Hierro forjado en nuestro taller, integrado con madera noble. Sin tornillos escondidos." },
    sofas:        { copy:"Donde la tarde\nse vuelve larga.",              sub:"Sofás tejidos hilo a hilo, construidos para el uso real. No para la foto." },
    percheros:    { copy:"Lo primero que\nves al llegar a casa.",         sub:"Hierro y tejido artesanal en un solo objeto. El detalle que eleva cualquier entrada." },
    "sillas-bar": { copy:"Para las noches\nque no tienen prisa.",         sub:"Sillas de bar con tejido artesanal y hierro. Para bares, restaurantes y casas con barra." },
  };

  return (
    <div className="cat-page">
      <style>{`
        @keyframes cban-in{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:translateY(0)}}
        .cban-t1{animation:cban-in .5s cubic-bezier(.2,.7,.2,1) .08s both}
        .cban-t2{animation:cban-in .5s cubic-bezier(.2,.7,.2,1) .18s both}
        .cban-t3{animation:cban-in .5s cubic-bezier(.2,.7,.2,1) .28s both}
        .cban-t4{animation:cban-in .5s cubic-bezier(.2,.7,.2,1) .38s both}
        .cat-tab{padding:14px 18px;font-size:12.5px;letter-spacing:.05em;border:none;background:none;cursor:pointer;border-bottom:2px solid transparent;color:#6b6356;white-space:nowrap;transition:color .2s,border-color .2s}
        .cat-tab.on{color:#1b1813;border-bottom-color:#7E1232;font-weight:600}
        .cat-tab:hover:not(.on){color:#1b1813}
      `}</style>

      {/* ── Banner editorial cuando hay categoría activa ── */}
      {f.cat !== "all" && (() => {
        const banners = CAT_BANNERS[f.cat];
        const hero = getCatHero(f.cat);
        const { copy, sub } = CAT_COPIES[f.cat] || { copy: CAT_LABELS[f.cat] || f.cat, sub:"" };
        const count = CATALOGO.filter(p => p.categoria === f.cat).length;

        // Si hay banner diseñado, usarlo con overlay de copie
        if (banners) {
          const { copy: banCopy } = CAT_COPIES[f.cat] || {};
          return (
            <div ref={bannerRef} style={{ position:"relative", lineHeight:0, overflow:"hidden" }}>
              <img src={isMob2 ? banners.mob : banners.desk} alt={CAT_LABELS[f.cat]}
                style={{ width:"100%", display:"block", maxHeight: isMob2 ? "88vw" : 440, objectFit:"cover", objectPosition:"center" }} />
              {/* Gradiente + overlay texto */}
              <div style={{ position:"absolute", inset:0, background:"linear-gradient(90deg, rgba(10,6,4,.72) 0%, rgba(10,6,4,.38) 55%, rgba(10,6,4,.05) 100%)" }} />
              <div style={{ position:"absolute", top:0, left:0, bottom:0, display:"flex", flexDirection:"column", justifyContent:"center", padding: isMob2 ? "88px 24px 24px" : "0 56px", maxWidth: isMob2 ? "90%" : "52%" }}>
                <div style={{ fontSize:10, letterSpacing:"0.28em", textTransform:"uppercase", color:"#E2B25C", fontWeight:500, marginBottom:14 }}>
                  {CAT_DISPLAY[f.cat] || CAT_LABELS[f.cat]} · {count} piezas
                </div>
                {banCopy && (
                  <h2 style={{ fontFamily:"var(--f-display,'Fraunces',serif)", fontWeight:400, fontSize: isMob2?"clamp(22px,6vw,28px)":"clamp(28px,2.8vw,42px)", lineHeight:1.08, letterSpacing:"-0.8px", color:"#F7F2EA", whiteSpace:"pre-line", margin:"0 0 18px", textShadow:"0 2px 24px rgba(0,0,0,.5)" }}>
                    {banCopy}
                  </h2>
                )}
                <button onClick={clearAll}
                  style={{ alignSelf:"flex-start", background:"none", border:"1.5px solid rgba(247,242,234,.4)", color:"rgba(247,242,234,.8)", fontSize:11, letterSpacing:"0.12em", textTransform:"uppercase", padding:"10px 20px", borderRadius:2, cursor:"pointer", transition:"all .22s" }}
                  onMouseEnter={e=>{e.currentTarget.style.borderColor="#fff";e.currentTarget.style.color="#fff";}}
                  onMouseLeave={e=>{e.currentTarget.style.borderColor="rgba(247,242,234,.4)";e.currentTarget.style.color="rgba(247,242,234,.8)";}}>
                  ← Todas las categorías
                </button>
              </div>
            </div>
          );
        }

        // Banner generado por código (fallback)
        return (
          <div ref={bannerRef} style={{ background:"#1b1813", display:"grid", gridTemplateColumns: isMob2 ? "1fr" : "1fr 1fr", minHeight: isMob2 ? "auto" : 380 }}>
            <div style={{ padding: isMob2 ? "44px 24px 32px" : "52px 44px 52px 60px", display:"flex", flexDirection:"column", justifyContent:"space-between", gap:20 }}>
              <div>
                <div className="cban-t1" style={{ display:"flex", alignItems:"center", gap:10, fontSize:10, letterSpacing:"0.28em", textTransform:"uppercase", color:"#C8901A", fontWeight:500, marginBottom:18 }}>
                  <span style={{ width:20, height:1, background:"#C8901A" }} />
                  {CAT_DISPLAY[f.cat] || CAT_LABELS[f.cat]} · {count} piezas
                </div>
                <h2 className="cban-t2" style={{ fontFamily:"var(--f-display,'Fraunces',serif)", fontWeight:400, fontSize: isMob2?"clamp(26px,7.5vw,36px)":"clamp(30px,3vw,46px)", lineHeight:1.05, letterSpacing:"-0.8px", color:"#F7F2EA", whiteSpace:"pre-line", margin:"0 0 16px" }}>{copy}</h2>
                <p className="cban-t3" style={{ fontSize: isMob2?13:14.5, lineHeight:1.72, color:"rgba(247,242,234,.62)", maxWidth:380 }}>{sub}</p>
              </div>
              <button className="cban-t4" onClick={clearAll}
                style={{ alignSelf:"flex-start", background:"none", border:"1.5px solid rgba(247,242,234,.22)", color:"rgba(247,242,234,.55)", fontSize:11.5, letterSpacing:"0.12em", textTransform:"uppercase", padding:"10px 20px", borderRadius:2, cursor:"pointer", transition:"all .22s" }}
                onMouseEnter={e=>{e.currentTarget.style.borderColor="rgba(247,242,234,.5)";e.currentTarget.style.color="#F7F2EA";}}
                onMouseLeave={e=>{e.currentTarget.style.borderColor="rgba(247,242,234,.22)";e.currentTarget.style.color="rgba(247,242,234,.55)";}}>
                ← Todas las categorías
              </button>
            </div>
            <div style={{ background:"#231a14", display:"flex", alignItems:"center", justifyContent:"center", padding: isMob2 ? "8px 24px 44px" : "36px 44px" }}>
              {hero?.foto && <img src={hero.foto} alt={hero.nombre} className="cban-t2" style={{ maxWidth: isMob2?"min(240px,75vw)":"min(320px,32vw)", maxHeight: isMob2?220:300, width:"100%", height:"auto", objectFit:"contain", filter:"drop-shadow(0 20px 44px rgba(0,0,0,.55))" }} />}
            </div>
          </div>
        ); // end fallback banner
      })()}

      {/* ── Tabs de categoría (scroll normal con la página, sin recortarse) ── */}
      {f.cat !== "all" && (
        <div style={{ background:"var(--bone,#F7F2EA)", borderBottom:"1px solid rgba(27,24,19,.1)", padding:"6px clamp(16px,4vw,48px)", display:"flex", flexWrap:"wrap", gap:"2px 4px" }}>
          {Object.entries(CAT_LABELS).map(([k, label]) => (
            <button key={k} className={`cat-tab${f.cat===k?" on":""}`} onClick={() => set("cat", k)}>{label}</button>
          ))}
        </div>
      )}

      {/* Hero original solo cuando no hay categoría */}
      {f.cat === "all" && <section className="cat-hero">
        <div className="crumb">Inicio  ·  Catálogo</div>
        <div className="top">
          <h1>{filtered.length}<br /><em>piezas</em>.</h1>
          <div className="lead">
            <Eyebrow>Tejido a mano · entrega en 15 días</Eyebrow>
            <p style={{ marginTop: 14 }}>Filtra por categoría, modelo o patrón. Toca cualquier pieza para verla en grande y pedirla por WhatsApp.</p>
          </div>
        </div>
        <div className="chips-row">
          <span className="chip-label">Filtros activos:</span>
          {activeChips.length === 0 ? (
            <span style={{ fontFamily:"var(--f-mono)", fontSize:11, letterSpacing:"0.14em", color:"var(--ink-mute)" }}>— ninguno · mostrando todo el catálogo</span>
          ) : (<>
            {activeChips.map((c) => (
              <button key={c.key} className="chip is-on" onClick={() => set(c.key, c.key==="q"?"":"all")}>
                <span className="kind">{c.kind} ·</span> {c.label} <span className="x">×</span>
              </button>
            ))}
            <button className="chip-clear" onClick={clearAll}>Limpiar todo</button>
          </>)}
        </div>
      </section>}

      <div className="cat-layout">
        <aside className="cat-side">
          <input
            type="search"
            className="search"
            placeholder="Buscar nombre, código…"
            value={f.q}
            onChange={(e) => set("q", e.target.value)}
          />
          <h4>Categoría</h4>
          <div className="opt" onClick={() => set("cat", "all")} data-on={f.cat === "all"}>
            <span>Todas</span>
            <span className="n">{CATALOGO.length}</span>
          </div>
          {Object.entries(CAT_LABELS).map(([k, label]) => {
            const n = CATALOGO.filter((p) => p.categoria === k).length;
            return (
              <div key={k} className={`opt ${f.cat === k ? "is-on" : ""}`} onClick={() => set("cat", k)}>
                <span>{label}</span>
                <span className="n">{n}</span>
              </div>
            );
          })}

          <h4>Modelo</h4>
          <div className={`opt ${f.modelo === "all" ? "is-on" : ""}`} onClick={() => set("modelo", "all")}>
            <span>Todos</span>
            <span className="n">{modelos.length}</span>
          </div>
          {modelos.slice(0, 14).map((m) => (
            <div key={m.name} className={`opt ${f.modelo === m.name ? "is-on" : ""}`} onClick={() => set("modelo", m.name)}>
              <span>{m.name}</span>
              <span className="n">{m.n}</span>
            </div>
          ))}

          <h4>Patrón</h4>
          <div className={`opt ${f.patron === "all" ? "is-on" : ""}`} onClick={() => set("patron", "all")}>
            <span>Todos</span>
            <span className="n">—</span>
          </div>
          {PATRONES.map((p) => {
            const n = CATALOGO.filter((x) => detectarPatron(x.variante) === p).length;
            if (n === 0) return null;
            return (
              <div key={p} className={`opt ${f.patron === p ? "is-on" : ""}`} onClick={() => set("patron", p)}>
                <span>{p}</span>
                <span className="n">{n}</span>
              </div>
            );
          })}
        </aside>

        <div>
          <div className="cat-toolbar" style={{ position: "static !important", top: "auto !important" }}>
            <span>{filtered.length} resultados</span>
            <span>
              Ordenar
              <select value={f.sort} onChange={(e) => set("sort", e.target.value)} style={{ marginLeft: 10 }}>
                <option value="destacado">Destacados</option>
                <option value="precio-asc">Precio · menor</option>
                <option value="precio-desc">Precio · mayor</option>
                <option value="nombre">Nombre A — Z</option>
              </select>
            </span>
          </div>

          {filtered.length === 0 ? (
            <div className="cat-empty">— Sin resultados con esos filtros.</div>
          ) : (
            <div className="cat-grid">
              {filtered.map((p) => (
                <CatProd key={p.id} p={p} onOpen={openFicha} onModelo={openModelo} />
              ))}
            </div>
          )}
        </div>
      </div>

      {/* MOBILE: FAB de filtros */}
      <button className="mobile-filter-fab" onClick={() => setDrawerOpen(true)}>
        <span>Filtros</span>
        {activeChips.length > 0 ? <span className="badge">{activeChips.length}</span> : null}
        <span className="arrow">↑</span>
      </button>

      {/* MOBILE: drawer de filtros */}
      <div className={`mobile-filter-drawer-back ${drawerOpen ? "is-open" : ""}`} onClick={() => setDrawerOpen(false)} />
      <aside className={`mobile-filter-drawer ${drawerOpen ? "is-open" : ""}`}>
        <div className="mobile-filter-drawer-handle" />
        <div className="mobile-filter-drawer-top">
          <h3>Filtros</h3>
          {activeChips.length > 0 ? (
            <button className="clear" onClick={clearAll}>Limpiar todo</button>
          ) : null}
        </div>
        <div className="mobile-filter-drawer-body">
          <div className="mobile-filter-section">
            <h4>¿Qué buscas?</h4>
            <div className="mobile-filter-chips">
              <button className={`mobile-filter-chip ${f.cat === "all" ? "is-on" : ""}`} onClick={() => set("cat", "all")}>
                Todas <span className="n">{CATALOGO.length}</span>
              </button>
              {Object.entries(CAT_LABELS).map(([k, label]) => {
                const n = CATALOGO.filter((p) => p.categoria === k).length;
                if (n === 0) return null;
                return (
                  <button key={k} className={`mobile-filter-chip ${f.cat === k ? "is-on" : ""}`} onClick={() => set("cat", k)}>
                    {label} <span className="n">{n}</span>
                  </button>
                );
              })}
            </div>
          </div>
        </div>

        <div className="mobile-filter-drawer-foot">
          <button className="mobile-filter-apply" onClick={() => setDrawerOpen(false)}>
            Ver {filtered.length} {filtered.length === 1 ? "resultado" : "resultados"} →
          </button>
        </div>
      </aside>
    </div>
  );
}

window.Catalog = Catalog;
window.CatProd = CatProd;
