/* global React, ReactDOM */ const { useState, useEffect, useRef, useMemo } = React; const { createRoot } = ReactDOM; const IG = 'https://www.instagram.com/project226_/'; const TIKTOK = 'https://www.tiktok.com/@project226_'; const WA_GROUP = 'https://chat.whatsapp.com/JDNINDfFGwi3MQ9QXjBpkN?mode=gi_t'; const WA_LINK = 'https://w.app/project226_'; const WA_PHONE = '5491132400743'; const WA_DIRECT = () => WA_LINK; const MAIL_TO = 'infoproject226@gmail.com'; const MAIL = (subject, body) => `mailto:${MAIL_TO}?subject=${encodeURIComponent(subject || 'Propuesta — Project 226')}&body=${encodeURIComponent(body || '')}`; // Formspree: ir a formspree.io → New Form → copiar el ID de la URL y pegarlo acá const FORMSPREE_ID = 'YOUR_FORM_ID'; // ← reemplazar, ej: 'xvgprdkz' /* ───────── METRICS / LIVE DATA ───────── Conectado a una capa de métricas (API stub). Para producción: reemplazar fetchLiveMetrics() con tu endpoint real (Phyllo, Modash, Iconosquare, o un cron a Instagram Graph API). */ // Semana 15 al 4-may-2026 → semana 1 = 26-ene-2026 (lunes). Mantener este lunes para que la cuenta sea exacta. const PROJECT_START = new Date('2026-01-26T00:00:00-03:00'); // semana 1 const RACE_DATE = new Date('2026-12-13T00:00:00-05:00'); // Ironman Florida function weekProgress() { const ms = Date.now() - PROJECT_START.getTime(); const week = Math.max(1, Math.min(46, Math.floor(ms / (7 * 24 * 3600 * 1000)) + 1)); return { week, total: 46 }; } function daysToRace() { return Math.max(0, Math.ceil((RACE_DATE.getTime() - Date.now()) / (24 * 3600 * 1000))); } // Capa de métricas en vivo. En producción: poner METRICS_ENDPOINT a tu API // (Phyllo, Modash, Iconosquare, o un cron propio que lea Instagram Graph API). // Mientras tanto, los números se manejan desde Tweaks y refrescan en pantalla. const METRICS_ENDPOINT = ''; // ej. 'https://api.tudominio.com/p226/metrics' async function fetchLiveMetrics(seed) { if (METRICS_ENDPOINT) { try { const r = await fetch(METRICS_ENDPOINT, { cache: 'no-store' }); if (r.ok) { const j = await r.json(); return { ...seed, ...j, _ts: Date.now() }; } } catch (_) {} } return { ...seed, _ts: Date.now() }; } /* ───────── TWEAKS DEFAULTS ───────── */ const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "followers": 10000, "engagement": 5.34, "viewsAvg": 5000, "members": 240, "posts": 293, "useAI": false, "accent": "#f6f4ee", "showTicker": true } /*EDITMODE-END*/; /* ───────────── NAV ───────────── */ function Nav({ openForm }) { const [scrolled, setScrolled] = useState(false); const [mobileOpen, setMobileOpen] = useState(false); useEffect(() => { const on = () => setScrolled(window.scrollY > 40); window.addEventListener('scroll', on, { passive: true });on(); return () => window.removeEventListener('scroll', on); }, []); useEffect(() => { document.body.style.overflow = mobileOpen ? 'hidden' : ''; }, [mobileOpen]); const close = () => setMobileOpen(false); return ( <> {mobileOpen && (
)} ); } /* ───────────── HERO ───────────── */ function Hero({ metrics, openForm }) { const { week, total } = weekProgress(); const [cd, setCd] = useState(() => { const ms = Math.max(0, RACE_DATE.getTime() - Date.now()); return { d: Math.floor(ms / (24 * 3600 * 1000)), h: Math.floor((ms % (24 * 3600 * 1000)) / (3600 * 1000)), m: Math.floor((ms % (3600 * 1000)) / (60 * 1000)), s: Math.floor((ms % (60 * 1000)) / 1000) }; }); useEffect(() => { const id = setInterval(() => { const ms = Math.max(0, RACE_DATE.getTime() - Date.now()); setCd({ d: Math.floor(ms / (24 * 3600 * 1000)), h: Math.floor((ms % (24 * 3600 * 1000)) / (3600 * 1000)), m: Math.floor((ms % (3600 * 1000)) / (60 * 1000)), s: Math.floor((ms % (60 * 1000)) / 1000) }); }, 1000); return () => clearInterval(id); }, []); return (
{/* Cinematic background video */} {/* Vignette overlay over video */}
{/* Top meta row */}
DESDE BUENOS AIRES · 2026 EN VIVO · SEMANA {String(week).padStart(2, '0')} / {total}
{/* Compact logo above wordmark */}
Project 226
{/* Wordmark below */}

PROJECT 226

{/* Claim */}

Dos amigos, un Ironman, nada inventado.

{/* CTAs */}
Sumate al grupo
{/* Live data strip */}
{/* Bottom ticker */}
{Array.from({ length: 3 }).map((_, g) =>
{['DOS AMIGOS', 'UN IRONMAN', '46 SEMANAS', 'NADA INVENTADO', 'TODO GRABADO', 'BUENOS AIRES → FLORIDA', '—', 'P226'].map((w, i) => {w} )}
)}
); } function LiveCell({ k, v, live, last }) { return (
{v}
{live && } {k}
); } function fmt(n) { if (n >= 1000) return (n / 1000).toFixed(1).replace('.0', '') + 'K'; return String(n); } /* ───────────── QUÉ ES ───────────── */ function About() { return (
01 / El proyecto 01 — 05

Una marca
que se construye
corriendo.

Somos dos pibes que arrancaron lesionados, sin saber nadar, y se metieron en algo grande: el Ironman 70.3 de Florida, el 13 de diciembre del 2026. 46 semanas de entreno. Todo, pero todo, lo subimos.

No somos una cuenta más ni un grupo de WhatsApp genérico. Es lo que pasa de verdad: los días que sale y los que no, las dudas, las recaídas, las pavadas. Una plataforma abierta para el que quiera meterse en algo grande y para marcas que cachan cuándo una historia vale la pena contarla.

); } /* ───────────── DIFERENCIALES ───────────── */ function Different() { const items = [ { n: '01', t: 'En vivo, sin filtro', d: 'Los entrenamientos que salen y los días que no querés saber nada. La duda también se publica.' }, { n: '02', t: 'Una historia, no un feed', d: 'Cada video es un capítulo. Tiene principio, desarrollo, y todavía no sabemos cómo termina.' }, { n: '03', t: 'Comunidad de verdad', d: 'Gente que se conoce, entrena junta y se cruza fuera de la pantalla. Sin seguidores fantasma.' }, { n: '04', t: 'Marcas que suman', d: 'Las marcas que encajan se meten en el proceso. No son un cartel pegado al final del reel.' }]; return (
02 / Cómo se ve 02 — 05

No somos una cuenta más.
Somos un proyecto con forma.

{items.map((x) =>

{x.t}

{x.d}

)}
); } /* ───────────── COMUNIDAD ───────────── */ function Community({ metrics }) { return (
04 / Comunidad 04 — 05
{/* Headline + single big visual */}

No es
una audiencia.
ES UNA COMUNIDAD.

Lo que arrancó como un grupo de WhatsApp se transformó en un grupo que entrena, se junta y se banca. Una marca no colabora con dos personas —colabora con todo lo que se mueve alrededor.

SIN NIVEL MÍNIMO · SI QUERÉS MOVERTE, YA SOS PARTE Entrar al grupo
); } /* ───────────── PARTNERS / MARCAS QUE CONFIARON ───────────── */ function Partners() { const trackRef = useRef(null); const pausedRef = useRef(false); useEffect(() => { const el = trackRef.current; if (!el) return; let raf; let last = performance.now(); const SPEED = 70; // px / sec (más rápido que antes) const tick = (now) => { const dt = (now - last) / 1000; last = now; if (!pausedRef.current && el) { el.scrollLeft += SPEED * dt; const half = el.scrollWidth / 2; if (el.scrollLeft >= half) el.scrollLeft -= half; if (el.scrollLeft < 0) el.scrollLeft += half; } raf = requestAnimationFrame(tick); }; raf = requestAnimationFrame(tick); const pause = () => {pausedRef.current = true;}; const resume = () => {pausedRef.current = false;}; el.addEventListener('mouseenter', pause); el.addEventListener('mouseleave', resume); el.addEventListener('touchstart', pause, { passive: true }); el.addEventListener('touchend', () => setTimeout(resume, 1500), { passive: true }); return () => { cancelAnimationFrame(raf); el.removeEventListener('mouseenter', pause); el.removeEventListener('mouseleave', resume); }; }, []); const nudge = (dir) => { const el = trackRef.current; if (!el) return; pausedRef.current = true; el.scrollBy({ left: dir * 320, behavior: 'smooth' }); setTimeout(() => {pausedRef.current = false;}, 1500); }; const brands = [ { name: 'RITUAL', tag: 'Café de especialidad', url: 'https://www.instagram.com/ritualcafe.arg/', handle: '@ritualcafe.arg' }, { name: 'GARMIN', tag: 'GPS & wearables', url: 'https://www.instagram.com/garminargentina/', handle: '@garminargentina' }, { name: 'LAS TRES NIÑAS', tag: 'Leche', url: 'https://www.instagram.com/lastresninasok/', handle: '@lastresninasok' }, { name: 'SUMA', tag: 'Hidratación', url: 'https://www.instagram.com/drink.suma/', handle: '@drink.suma' }, { name: 'PELOTÓN BIKES', tag: 'Bicis & equipamiento', url: 'https://www.instagram.com/peloton.bikes/', handle: '@peloton.bikes' }, { name: 'MARTHA', tag: 'Ropa y lifestyle', url: 'https://www.instagram.com/martha/', handle: '@martha' }, { name: 'BASSET', tag: 'Indumentaria', url: 'https://www.instagram.com/basset.arg/', handle: '@basset.arg' }, { name: 'SPORT TECH', tag: 'Deporte & tecnología', url: 'https://www.instagram.com/sportechstore.arg/', handle: '@sportechstore.arg' }, { name: 'THERABODY', tag: 'Recovery & bienestar', url: 'https://www.instagram.com/therabodyargentina/', handle: '@therabodyargentina' }, { name: 'INSTA360', tag: 'Productos de tecnología', url: 'https://www.instagram.com/insta360argentina/', handle: '@insta360argentina' }, { name: 'DAY BY DAY', tag: 'Productos fit', url: 'https://www.instagram.com/daybyday_arg/', handle: '@daybyday_arg' }, { name: "ZANNA'S", tag: 'Nutrición', url: 'https://www.instagram.com/zannas.ar/', handle: '@zannas.ar' }]; return (
Marcas que confiaron — se subieron temprano —

Marcas que ya
se subieron al barco.

{[...brands, ...brands].map((b, idx) =>
{b.name} {e.currentTarget.style.display = 'none';e.currentTarget.nextElementSibling.style.display = 'flex';}} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
{b.name}
{b.name}
{b.tag}
{b.handle}
)}

Tocá cualquier marca y te lleva a su Instagram · usá las flechas para volver · VER PROPUESTAS →

); } /* ───────────── VALORES ───────────── */ function Values() { const v = ['Disfrutar el proceso', 'Documentar todo', 'Crear comunidad', 'Ser genuino', 'Apuntar alto', 'No aflojar']; return (
Valores — P226 —
{v.map((w, i) =>
{`0${i + 1}`} {w}
)}
); } /* ───────────── PARA MARCAS ───────────── */ function Brands({ openForm }) { const tiers = [ { k: 'Producto', d: 'Nos mandás el producto, lo usamos en serio entrenando y aparece en la historia cuando suma. Sin guion armado, sin posteos hechos a medida — así se nota que es genuino y así convierte.', t: ['Te mandamos el producto', 'Lo integramos al día a día', 'Reels, stories y menciones orgánicas'] }, { k: 'Contenido a medida', d: 'Producimos contenido pensado para tu marca, con ustedes de protagonistas. Bajamos la idea, grabamos, editamos y lo subimos a nuestros canales y a los tuyos.', t: ['Concepto, guión y producción', 'Contenido corto, carruseles y contenido largo', 'Distribución en IG, TikTok y YouTube', 'Derechos de uso para tu marca'] }, { k: 'Largo plazo', d: 'Tu marca metida en el proyecto durante todo el camino al Ironman. Presencia sostenida, eventos y contenido todo el año.', t: ['Relación a largo plazo', 'Eventos y activaciones presenciales', 'Plan de contenido mensual'] }]; return (
03 / Para marcas 03 — 05

Estamos
construyendo algo grande.
Metéte.

Project 226 es una plataforma de marca en formación: audiencia que se compromete, una historia que se sostiene en el tiempo y producción con criterio. Buscamos aliados que entiendan el proyecto, no sponsors que pongan plata y se vayan.

{/* Tiers — horizontal list, minimal */}
{tiers.map((t, i) =>
{`0${i + 1}`}

{t.k}

{t.d}

    {t.t.map((x, j) =>
  • — {x}
  • )}
)}
{/* Industries */}
Industrias con las que trabajamos
{[ ['Indumentaria & gear', 'Lo que nos ponemos para entrenar 6 días por semana — desde la pileta hasta la ruta. Si te sirve para correr 90km en bici, sirve para cualquier audiencia activa.', 'Ej.: Basset · Martha · Sport Tech'], ['Nutrición & hidratación', 'Lo que comemos y tomamos antes, durante y después de cada sesión larga. Reseñas honestas — si no nos gusta, no lo mostramos. Punto.', 'Ej.: SUMA · Zanna\'s · Day by Day · Las Tres Niñas'], ['Tecnología & wearables', 'Relojes, GPS, sensores, plataformas de entrenamiento. Métricas reales en Strava y Garmin que validan cualquier producto técnico.', 'Ej.: Garmin · Insta360'], ['Recovery & wellness', 'Las marcas que nos mantienen enteros entre entrenos. El 80% del rendimiento pasa cuando no estamos en la cinta — y queremos contarlo bien.', 'Ej.: Therabody']]. map(([t, d, ex], i) =>
{String(i + 1).padStart(2, '0')}

{t}

{d}

{ex}
)}
{/* CTA removido */}
); } /* ───────────── FAQ ───────────── */ function FAQ() { const [open, setOpen] = useState(0); const faqs = [ { q: '¿Qué es Project 226?', a: 'Somos Doman y Frigo. Dos amigos que un día decidieron anotarse a un Ironman 70.3 sin tener experiencia, sin estar entrenados, y arrancando lesionados. 46 semanas de preparación, todo grabado, todo publicado — los días buenos y los que no. En el medio nació una comunidad de gente que entrena con nosotros desde cualquier parte del mundo.' }, { q: '¿Cómo me sumo a la comunidad?', a: 'Click en el botón de WhatsApp y listo. No te pedimos currículum de deportista profesional jajaj.' }, { q: '¿Hay que tener nivel?', a: 'Para nada. Hay gente que está saliendo a correr por primera vez y gente que ya hizo un Ironman entero. Todos en el mismo grupo.' }, { q: '¿Qué marcas encajan?', a: 'Marcas que estemos dispuestos a usar todos los días, aunque no nos pagasen. Si no lo usaríamos en nuestro entrenamiento real, no lo mostramos. Punto.' }, { q: '¿Cómo son las colaboraciones?', a: 'Tres formatos: producto (te recibimos y lo usamos), contenido a medida (lo producimos para vos) o largo plazo (vamos juntos al Ironman). Todo por escrito, entregables claros.' }, { q: '¿Cómo los contacto?', a: 'Mail a infoproject226@gmail.com o WhatsApp directo al +54 9 11 3240-0743. Te volvemos a escribir en menos de 24hs hábiles.' }]; return (
05 / FAQ 05 — 05

Lo que
nos preguntan.
Sin vueltas.

{faqs.map((f, i) => { const isOpen = open === i; return (
{f.a}
); })}
); } /* ───────────── FINAL CTA ───────────── */ function FinalCTA({ openForm }) { return (

SUMATE
O SUMA TU MARCA.

PARA PERSONAS ACTIVAS

Sumate al grupo.

Sumate al WhatsApp y entrená con gente que va para el mismo lado.

Entrar al grupo de WhatsApp
Para marcas

Hablemos.

Contanos qué marca son y en qué momento están. Te respondemos en menos de 24hs hábiles con una propuesta a medida.

); } /* ───────────── FOOTER ───────────── */ function Footer() { return ( ); } /* ───────────── TWEAKS PANEL ───────────── */ function TweaksPanel({ tweaks, setTweak, onClose }) { const ts = tweaks._ts ? new Date(tweaks._ts) : new Date(); return (
Tweaks · Métricas
{METRICS_ENDPOINT ? 'Conectado' : 'Manual'} · Actualizado {ts.toLocaleTimeString('es-AR', { hour: '2-digit', minute: '2-digit' })}
{[ ['followers', 'Seguidores IG'], ['engagement', 'Engagement %'], ['viewsAvg', 'Views promedio'], ['posts', 'Posts publicados']]. map(([k, lbl]) => )}
); } /* ───────────── PROPOSAL FORM ───────────── */ function ProposalForm({ onClose }) { const [form, setForm] = useState({ nombre: '', marca: '', email: '', web: '', tipo: 'Branded Content', timing: '1–3 meses', mensaje: '' }); const [sending, setSending] = useState(false); const [sent, setSent] = useState(false); const update = (k, v) => setForm((f) => ({ ...f, [k]: v })); const buildBody = () => { return [ `Nombre: ${form.nombre}`, `Marca: ${form.marca}`, `Email: ${form.email}`, form.web ? `Web / IG: ${form.web}` : null, `Tipo de colaboración: ${form.tipo}`, `Timing: ${form.timing}`, '', 'Mensaje:', form.mensaje]. filter(Boolean).join('\n'); }; const sendViaFormspree = async (e) => { e?.preventDefault?.(); if (!form.nombre || !form.marca || !form.email || !form.mensaje) return; if (FORMSPREE_ID === 'YOUR_FORM_ID') { // Fallback a mailto si aún no hay Formspree configurado const subject = `Propuesta — ${form.marca} × Project 226`; window.open(MAIL(subject, buildBody()), '_blank'); setSent(true); return; } setSending(true); try { const res = await fetch(`https://formspree.io/f/${FORMSPREE_ID}`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, body: JSON.stringify({ nombre: form.nombre, marca: form.marca, email: form.email, web: form.web || undefined, tipo: form.tipo, timing: form.timing, mensaje: form.mensaje, _subject: `Propuesta — ${form.marca} × Project 226`, _replyto: form.email }) }); if (res.ok) { setSent(true); } else { alert(`Error al enviar. Escribinos directo a ${MAIL_TO} o por WhatsApp.`); } } catch (_) { alert(`Sin conexión. Escribinos a ${MAIL_TO} o por WhatsApp.`); } finally { setSending(false); } }; const sendByWA = () => { if (!form.nombre || !form.marca || !form.mensaje) return; const txt = `Hola Project 226 👋\n\n${buildBody()}`; window.open(WA_DIRECT(txt), '_blank'); setSent(true); }; // ESC to close useEffect(() => { const onKey = (e) => {if (e.key === 'Escape') onClose();}; window.addEventListener('keydown', onKey); document.body.style.overflow = 'hidden'; return () => { window.removeEventListener('keydown', onKey); document.body.style.overflow = ''; }; }, []); const inputStyle = { width: '100%', padding: '14px 16px', background: 'transparent', border: '1px solid var(--line-2)', color: 'var(--fg)', fontFamily: 'inherit', fontSize: 15, outline: 'none' }; const labelStyle = { display: 'block', fontFamily: "'JetBrains Mono', monospace", fontSize: 11, letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--fg-dim)', marginBottom: 8 }; return (
e.stopPropagation()} onSubmit={sendViaFormspree} style={{ width: '100%', maxWidth: 640, background: '#0a0a0a', border: '1px solid var(--line-2)', padding: 'clamp(28px, 4vw, 48px)', position: 'relative' }}> Propuesta para marcas

Hablemos.

Contanos quiénes son y qué buscan. Te volvemos en menos de 24hs hábiles con una propuesta a medida.

{sent ?
✓ ENVIADO

Gracias por escribirnos.

Te respondemos en menos de 24hs hábiles.

: <>
update('nombre', e.target.value)} placeholder="Juan Pérez" />
update('marca', e.target.value)} placeholder="Nombre de la marca" />
update('email', e.target.value)} placeholder="vos@marca.com" />
update('web', e.target.value)} placeholder="@marca o marca.com" />
{['Producto', 'Contenido a medida', 'Largo plazo', 'Otro'].map((opt) => )}
{['Puntual', '1–3 meses', '3–6 meses', '6+ meses'].map((opt) => )}