// media.jsx — sección Fotografía + Audiovisual con producción/postproducción y galerías const { useState: __mes, useEffect: __mee, useRef: __mer } = React; /* ════════════════════════════════════════════════════════ MEDIA — wrapper con dos disciplinas ════════════════════════════════════════════════════════ */ function Media({ t }) { const [remote, setRemote] = __mes(null); // Carga del admin (media_items). Si falla, usamos el i18n como fallback. __mee(() => { let alive = true; fetch('api/media.php', { credentials: 'same-origin' }) .then(r => r.ok ? r.json() : null) .then(d => { if (!alive || !d || !d.ok || !d.data) return; const photoOk = Array.isArray(d.data.photo) && d.data.photo.length > 0; const videoOk = Array.isArray(d.data.video) && d.data.video.length > 0; if (photoOk || videoOk) setRemote(d.data); }) .catch(() => {}); return () => { alive = false; }; }, []); // Mezcla: si el admin tiene items, sobreescribe la galería del i18n const photoBlock = remote && remote.photo && remote.photo.length ? { ...t.photo, gallery: remote.photo } : t.photo; const videoBlock = remote && remote.video && remote.video.length ? { ...t.video, gallery: remote.video } : t.video; return (
{t.media_eye}

{t.media_title_1} {t.media_title_2}

{t.media_sub}

); } /* ════════════════════════════════════════════════════════ MEDIA DISCIPLINE — un bloque (fotografía o audiovisual) ════════════════════════════════════════════════════════ */ function MediaDiscipline({ block, kind }) { const accent = kind === 'photo' ? 'var(--magenta)' : 'var(--azure)'; const accentName = kind === 'photo' ? 'magenta' : 'azure'; return (
{/* Encabezado: kicker enorme + intro */}
{block.eyebrow}

{block.title}

{block.lead}

{/* Producción + Postproducción */}
{block.phases.map((p, i) => (
{p.tag}

{p.title}

{p.body}

    {p.items.map(it => (
  • {it}
  • ))}
))}
{/* Galería — solo se renderiza si hay items con imagen real */} {Array.isArray(block.gallery) && block.gallery.length > 0 && ( <>
{block.gallery_label}
{block.gallery_cta}
{block.gallery.map((g, i) => ( ))}
)}
); } /* ════════════════════════════════════════════════════════ MEDIA TILE — celda visual (placeholder generativo) Si llega item.image se usa la imagen; si no, gradiente animado. ════════════════════════════════════════════════════════ */ function MediaTile({ item, kind, index }) { const palettes = kind === 'photo' ? [ ['#FF3EA5', '#9D5BFF', '#4361FF'], ['#FFD93E', '#FF6B1A', '#FF3EA5'], ['#2DD4FF', '#4361FF', '#9D5BFF'], ['#C8FF3E', '#FFD93E', '#FF6B1A'], ['#FF3EA5', '#FF6B1A', '#FFD93E'], ['#9D5BFF', '#2DD4FF', '#C8FF3E'], ] : [ ['#0a1a3a', '#4361FF', '#2DD4FF'], ['#1a0a2a', '#9D5BFF', '#FF3EA5'], ['#2a0a1a', '#FF6B1A', '#FFD93E'], ['#0a2a1a', '#21C97A', '#C8FF3E'], ['#0a1a3a', '#2DD4FF', '#C8FF3E'], ['#1a0a2a', '#FF3EA5', '#FFD93E'], ]; const p = palettes[index % palettes.length]; const isWide = item.span === 'wide'; return ( {item.image ? ( {item.title ) : (
)} {/* Overlay con datos */}
{item.tag}
{item.title}
); } Object.assign(window, { Media });