/* EcoEsperanza — Website UI kit
   Interactive marketing-site recreation. Self-contained presentational
   components styled via the DS tokens (site.css). Router switches between
   Inicio / Proyectos / Educación / Contacto. */

const { useState, useEffect, useRef } = React;

/* ---- helpers ------------------------------------------------------------- */
/* Curated, verified Unsplash photos — content confirmed via contact sheet.
   Warm, hopeful, human-in-nature. Keys describe where each is used. */
const PHOTOS = {
  heroForest:   'photo-1441974231531-c6227db76b6e', // sunlit forest
  soilSeedling: 'photo-1532601224476-15c79f2f7a51', // wind turbines on green hills (monitoring/climate)
  birds:        'photo-1437622368342-7a3d73a34c8f', // sea turtle (biodiversity)
  treePlanting: 'photo-1591857177580-dc82b9ac4e1e', // urban community garden
  greenSun:     'photo-1500382017468-9049fed747ef', // wheat field at sunset
  handsPlant:   'photo-1473773508845-188df298d2d1', // aerial pine forest
  recycling:    'photo-1591193686104-fddba4d0e4d8', // baled recycled bottles
  kidsNature:   'photo-1542273917363-3b1817f69a2d', // misty green forest
  volunteers:   'photo-1560493676-04071c5f467b',    // crop field rows
  turbines:     'photo-1466611653911-95081537e5b7', // wind turbines at sunset
  leaves:       'photo-1518173946687-a4c8892bbd9f', // dewy green leaves
  riverForest:  'photo-1498925008800-019c7d59d903', // aerial forest + river
  canopy:       'photo-1497436072909-60f360e1d4b1', // aerial forest + turquoise river
  teaching:     'photo-1576085898323-218337e3e43c', // education workshop / talk
  forestPath:   'photo-1542601906990-b4d3fb778b09', // hands holding a seedling
};
const img = (key, w = 1200, h) =>
  `https://images.unsplash.com/${PHOTOS[key] || key}?auto=format&fit=crop&w=${w}${h ? `&h=${h}` : ''}`;
const Icon = ({ n, ...p }) => <i data-lucide={n} {...p}></i>;
function refreshIcons() { if (window.lucide) window.lucide.createIcons(); }

/* WhatsApp brand glyph (Lucide has no brand logos). Used in the floating
   bubble and the contact line. */
const WHATSAPP_NUMBER = '573164208654';
const WhatsAppGlyph = ({ size = 24 }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill="currentColor" aria-hidden="true">
    <path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.71.306 1.263.489 1.694.625.712.227 1.36.195 1.872.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.885-9.885 9.885M20.52 3.449C18.24 1.245 15.24 0 12.045 0 5.463 0 .103 5.359.1 11.892c0 2.096.546 4.142 1.588 5.945L0 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.337 11.892-11.893a11.821 11.821 0 00-3.366-8.452z" />
  </svg>
);
function FloatingWhatsApp() {
  return (
    <a className="wa-fab" href={`https://wa.me/${WHATSAPP_NUMBER}`} target="_blank" rel="noopener"
      aria-label="Escríbenos por WhatsApp" title="Escríbenos por WhatsApp">
      <WhatsAppGlyph size={30} />
      <span className="wa-fab__pulse" aria-hidden="true" />
    </a>
  );
}

const NAV = [
  { id: 'inicio', label: 'Inicio' },
  { id: 'proyectos', label: 'Proyectos' },
  { id: 'datos', label: 'Datos' },
  { id: 'educacion', label: 'Educación' },
  { id: 'contacto', label: 'Contacto' },
];

/* ---- IQAir / AirVisual live integration ---------------------------------
   The "Datos" page shows city-level air quality (US AQI) from IQAir's official
   AirVisual API. Paste your free Community API key below (get one at
   iqair.com/air-pollution-data-api) and it refreshes every few minutes.
   Without a key it gracefully shows the reference values seeded here.
   NOTE: in production, proxy the key through a small backend so it isn't
   exposed in the browser. Attribution to IQAir is required by their terms.
   --------------------------------------------------------------------------- */
const IQAIR_API = 'https://api.airvisual.com/v2';
const IQAIR_KEY = ''; // ← pega aquí tu API key gratuita de IQAir
// city/state/country must match IQAir's database exactly
const CITIES = [
  { label: 'Bogotá',       country: 'Colombia',  state: 'Bogota D.C.',        city: 'Bogota',       lat: 4.6097,   lng: -74.0817, aqi: 75, main: 'PM2.5', temp: 14, hum: 78 },
  { label: 'São Paulo',    country: 'Brazil',    state: 'Sao Paulo',          city: 'Sao Paulo',    lat: -23.5505, lng: -46.6333, aqi: 56, main: 'PM2.5', temp: 27, hum: 61 },
  { label: 'Valencia',     country: 'Spain',     state: 'Valencia',           city: 'Valencia',     lat: 39.4699,  lng: -0.3763,  aqi: 38, main: 'PM2.5', temp: 22, hum: 65 },
  { label: 'Provincia de Buenos Aires', country: 'Argentina', state: 'Buenos Aires F.D.',  city: 'Buenos Aires', lat: -34.6037, lng: -58.3816, aqi: 82, main: 'PM2.5', temp: 19, hum: 70 },
];

/* The 7 individual community stations (mirrors the monitor dashboard). Shown as
   points on the map; pm25 in µg/m³. Wire to OpenSenseMap box ids for live data. */
const MAP_STATIONS = [
  { name: 'Bogotá · Centro',         city: 'Bogotá',       lat: 4.6097,   lng: -74.0817, pm25: 22, temp: 14.2 },
  { name: 'Bogotá · Kennedy',        city: 'Bogotá',       lat: 4.6280,   lng: -74.1500, pm25: 31, temp: 15.1 },
  { name: 'São Paulo · Sé',          city: 'São Paulo',    lat: -23.5505, lng: -46.6333, pm25: 18, temp: 26.8 },
  { name: 'São Paulo · Pinheiros',   city: 'São Paulo',    lat: -23.5670, lng: -46.7020, pm25: 15, temp: 27.4 },
  { name: 'Valencia · Ciutat Vella', city: 'Valencia',     lat: 39.4699,  lng: -0.3763,  pm25: 9,  temp: 22.1 },
  { name: 'Valencia · Cabanyal',     city: 'Valencia',     lat: 39.4720,  lng: -0.3290,  pm25: 12, temp: 22.6 },
  { name: 'Provincia de Buenos Aires · Centro',   city: 'Provincia de Buenos Aires', lat: -34.6037, lng: -58.3816, pm25: 29, temp: 19.4 },
];
const IQAIR_POLLUTANT = { p2: 'PM2.5', p1: 'PM10', o3: 'O₃', n2: 'NO₂', s2: 'SO₂', co: 'CO' };
// US AQI categories
const aqiBand = (aqi) => aqi <= 50 ? { label: 'Buena', bg: 'var(--success-bg)', fg: 'var(--green-800)', dot: 'var(--success)' }
  : aqi <= 100 ? { label: 'Moderada', bg: 'var(--warning-bg)', fg: 'var(--gold-700)', dot: 'var(--warning)' }
  : aqi <= 150 ? { label: 'Dañina (sensibles)', bg: 'var(--danger-bg)', fg: 'var(--red-600)', dot: 'var(--gold-600)' }
  : { label: 'Dañina', bg: 'var(--danger-bg)', fg: 'var(--red-600)', dot: 'var(--danger)' };
async function fetchCity(c) {
  const url = `${IQAIR_API}/city?city=${encodeURIComponent(c.city)}&state=${encodeURIComponent(c.state)}&country=${encodeURIComponent(c.country)}&key=${IQAIR_KEY}`;
  const res = await fetch(url);
  if (!res.ok) throw new Error('iqair ' + res.status);
  const j = await res.json();
  if (j.status !== 'success') throw new Error('iqair ' + j.status);
  const p = j.data.current.pollution, w = j.data.current.weather;
  return { aqi: p.aqius, main: IQAIR_POLLUTANT[p.mainus] || p.mainus, temp: Math.round(w.tp), hum: w.hu };
}
function timeAgo(ts) {
  const s = Math.max(0, Math.round((Date.now() - ts) / 1000));
  if (s < 60) return `hace ${s}s`;
  const m = Math.round(s / 60);
  return m < 60 ? `hace ${m} min` : `hace ${Math.round(m / 60)} h`;
}

/* PM2.5 (µg/m³) → band + colour (WHO/EPA-ish thresholds). */
const pmBand = (pm) => pm <= 12 ? { label: 'Buena', hex: '#2BA557', fg: 'var(--green-800)', bg: 'var(--success-bg)' }
  : pm <= 35 ? { label: 'Moderada', hex: '#E9A81C', fg: 'var(--gold-700)', bg: 'var(--warning-bg)' }
  : pm <= 55 ? { label: 'Dañina (sensibles)', hex: '#C98A00', fg: 'var(--gold-700)', bg: 'var(--warning-bg)' }
  : { label: 'Dañina', hex: '#C0392B', fg: 'var(--red-600)', bg: 'var(--danger-bg)' };

/* Interactive Leaflet map of the individual community stations (OpenStreetMap
   tiles). Replaces an OpenSenseMap iframe — their headers block embedding.
   Markers are colour-coded by PM2.5; click for a popup with the reading. */
function StationMap({ stations }) {
  const ref = React.useRef(null);
  const mapRef = React.useRef(null);
  const layerRef = React.useRef(null);

  useEffect(() => {
    if (!window.L || !ref.current || mapRef.current) return;
    const map = window.L.map(ref.current, { scrollWheelZoom: false });
    window.L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      maxZoom: 18, attribution: '&copy; OpenStreetMap',
    }).addTo(map);
    mapRef.current = map;
    setTimeout(() => map.invalidateSize(), 200);
    return () => { map.remove(); mapRef.current = null; };
  }, []);

  useEffect(() => {
    const map = mapRef.current; if (!map || !window.L) return;
    if (layerRef.current) layerRef.current.remove();
    const group = window.L.featureGroup();
    stations.forEach(s => {
      const band = pmBand(s.pm25);
      const m = window.L.circleMarker([s.lat, s.lng], {
        radius: 10, color: '#fff', weight: 3, fillColor: band.hex, fillOpacity: 1,
      });
      m.bindPopup(
        `<strong style="font-size:15px">${s.name}</strong><br>` +
        `<span style="color:#4A5C50">${s.city}</span><br>` +
        `<b style="font-family:monospace">${s.pm25} µg/m³</b> · ${band.label}<br>` +
        `<span style="font-family:monospace;font-size:12px;color:#7B8A80">${s.temp}°C · PM2.5</span>`
      );
      m.addTo(group);
    });
    group.addTo(map);
    layerRef.current = group;
    const b = group.getBounds();
    if (b.isValid()) map.fitBounds(b, { padding: [50, 50], maxZoom: 5 });
  }, [stations]);

  return <div ref={ref} className="osm-map__frame"></div>;
}

/* ====================================================================== */
/* Header                                                                  */
/* ====================================================================== */
function Header({ view, go }) {
  const [scrolled, setScrolled] = useState(false);
  const [menuOpen, setMenuOpen] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 12);
    window.addEventListener('scroll', onScroll); onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  // Lock body scroll while the mobile drawer is open
  useEffect(() => {
    document.body.style.overflow = menuOpen ? 'hidden' : '';
    return () => { document.body.style.overflow = ''; };
  }, [menuOpen]);
  const navTo = (id) => { setMenuOpen(false); go(id); };
  return (
    <header className={`hdr${scrolled ? ' hdr--scrolled' : ''}`}>
      <div className="container hdr__row">
        <a className="hdr__logo" onClick={() => navTo('inicio')} style={{ cursor: 'pointer' }}>
          <img src="assets/logo-full.png" alt="EcoEsperanza" />
        </a>
        <nav className="hdr__nav">
          {NAV.map(n => (
            <span key={n.id}
              className={`hdr__link${view === n.id ? ' hdr__link--active' : ''}`}
              onClick={() => navTo(n.id)}>{n.label}</span>
          ))}
        </nav>
        <div className="hdr__cta">
          <button className="btn btn--accent btn--sm" onClick={() => navTo('contacto')}>
            <Icon n="sprout" />Únete ahora
          </button>
          <button className="hdr__burger" aria-label="Abrir menú" aria-expanded={menuOpen}
            onClick={() => setMenuOpen(v => !v)}>
            <Icon n={menuOpen ? 'x' : 'menu'} />
          </button>
        </div>
      </div>

      {/* Mobile drawer */}
      <div className={`drawer${menuOpen ? ' drawer--open' : ''}`} onClick={() => setMenuOpen(false)}>
        <nav className="drawer__panel" onClick={(e) => e.stopPropagation()}>
          {NAV.map(n => (
            <button key={n.id}
              className={`drawer__link${view === n.id ? ' drawer__link--active' : ''}`}
              onClick={() => navTo(n.id)}>
              {n.label}<Icon n="chevron-right" />
            </button>
          ))}
          <button className="btn btn--accent" style={{ marginTop: '.6rem' }} onClick={() => navTo('contacto')}>
            <Icon n="sprout" />Únete ahora
          </button>
          <a className="drawer__wa" href={`https://wa.me/${WHATSAPP_NUMBER}`} target="_blank" rel="noopener">
            <WhatsAppGlyph size={18} />Escríbenos por WhatsApp
          </a>
        </nav>
      </div>
    </header>
  );
}

/* ====================================================================== */
/* Shared bits                                                             */
/* ====================================================================== */
function SectionHead({ eyebrow, icon, title, lead, center, mod }) {
  return (
    <div className="reveal" style={{ maxWidth: center ? '46rem' : '42rem',
      marginInline: center ? 'auto' : 0, textAlign: center ? 'center' : 'left',
      display: 'flex', flexDirection: 'column', gap: '.4rem',
      alignItems: center ? 'center' : 'flex-start', marginBottom: '2.5rem' }}>
      {eyebrow && <span className={`eyebrow${mod ? ' ' + mod : ''}`}>{icon && <Icon n={icon} />}{eyebrow}</span>}
      <h2 className="h2">{title}</h2>
      {lead && <p className="lead" style={{ marginTop: '.4rem' }}>{lead}</p>}
    </div>
  );
}

function ProjectCard({ p, go }) {
  return (
    <article className="card reveal" onClick={() => go('proyectos')}>
      <div className="card__img">
        <img src={p.img} alt="" loading="lazy" />
        {p.badge && <span className="card__badge"><span className={`badge badge--${p.badge.tone}`}>
          {p.badge.dot && <span className="badge__dot" />}{p.badge.text}</span></span>}
      </div>
      <div className="card__body">
        <span className="card__eyebrow">{p.eyebrow}</span>
        <h3 className="card__title">{p.title}</h3>
        <p className="card__text">{p.text}</p>
        <span className="card__foot">Leer más <Icon n="arrow-right" /></span>
      </div>
    </article>
  );
}

function Faq({ items }) {
  // Independent open/close per item — opening or closing one never affects the
  // others. Items are always rendered (no scroll-reveal) so none can vanish.
  const [open, setOpen] = useState(() => new Set([0]));
  const toggle = (i) => setOpen(prev => {
    const next = new Set(prev);
    next.has(i) ? next.delete(i) : next.add(i);
    return next;
  });
  return (
    <div className="faq">
      {items.map((it, i) => {
        const isOpen = open.has(i);
        return (
          <div key={i} className={`acc${isOpen ? ' acc--open' : ''}`}>
            <button className="acc__q" aria-expanded={isOpen} onClick={() => toggle(i)}>
              <span>{it.q}</span>
              <span className="acc__ico"><Icon n="plus" /></span>
            </button>
            <div className="acc__panel"><div className="acc__inner"><p className="acc__a">{it.a}</p></div></div>
          </div>
        );
      })}
    </div>
  );
}

const FAQ_ITEMS = [
  { q: '¿Qué es EcoEsperanza?', a: 'EcoEsperanza es una organización sin fines de lucro dedicada a la protección del medio ambiente y la sostenibilidad a través de la educación, el monitoreo climático y la acción comunitaria.' },
  { q: '¿Cómo puedo involucrarme?', a: 'Puedes participar en nuestros programas de educación ambiental, voluntariado y proyectos comunitarios para restaurar el entorno natural.' },
  { q: '¿Qué proyectos realizan?', a: 'Realizamos proyectos de monitoreo climático, educación ambiental y acciones comunitarias para promover ecosistemas sostenibles y la participación ciudadana.' },
  { q: '¿Cómo se financian?', a: 'Nos financiamos a través de donaciones, subvenciones y colaboraciones con otras organizaciones y empresas comprometidas con el medio ambiente.' },
  { q: '¿Dónde están ubicados?', a: 'Trabajamos en colaboración con grupos locales en distintas comunidades —con estaciones activas en Bogotá, São Paulo y Valencia— para maximizar nuestro impacto ambiental.' },
];

/* ====================================================================== */
/* Footer + CTA band                                                       */
/* ====================================================================== */
function CtaBand({ go }) {
  return (
    <div className="container section" style={{ paddingTop: 0 }}>
      <div className="cta-band reveal">
        <span className="cta-band__sun" />
        <h2>Cada dato cuenta. Cada acción suma. Súmate a EcoEsperanza.</h2>
        <div style={{ display: 'flex', gap: '.9rem', position: 'relative', flexWrap: 'wrap' }}>
          <button className="btn btn--accent btn--lg" onClick={() => go('contacto')}><Icon n="hand-heart" />Únete ahora</button>
          <button className="btn btn--ondark btn--lg" onClick={() => go('proyectos')}>Ver proyectos</button>
        </div>
      </div>
    </div>
  );
}

function Footer({ go }) {
  return (
    <footer className="ftr">
      <div className="container">
        <div className="ftr__grid">
          <div className="ftr__about">
            <span className="ftr__word">Eco<b>Esperanza</b></span>
            <p style={{ margin: 0, lineHeight: 'var(--leading-relaxed)' }}>
              Protegiendo y restaurando el medio ambiente con tecnología, datos abiertos,
              ciencia ciudadana y educación. Desde Colombia para el mundo, desde 2017.
            </p>
          </div>
          <div>
            <h4>Navegación</h4>
            <div className="ftr__links">
              {NAV.map(n => <a key={n.id} onClick={() => go(n.id)}>{n.label}</a>)}
            </div>
          </div>
          <div>
            <h4>Contacto</h4>
            <div className="ftr__links">
              <a href="mailto:contacto@ecoesperanzaglobal.org"><Icon n="mail" />contacto@ecoesperanzaglobal.org</a>
              <a href="tel:+576019185309"><Icon n="phone" />+57 601 918 5309</a>
              <a href={`https://wa.me/${WHATSAPP_NUMBER}`} target="_blank" rel="noopener"><WhatsAppGlyph size={16} />+57 316 420 8654</a>
            </div>
          </div>
        </div>
        <div className="ftr__bottom">
          <span>© 2017 EcoEsperanza · Organización sin fines de lucro</span>
          <span>Conservación · Educación · Datos abiertos</span>
        </div>
      </div>
    </footer>
  );
}

/* ====================================================================== */
/* INICIO                                                                  */
/* ====================================================================== */
function HomeView({ go }) {
  const stats = [
    { ico: 'radio-tower', val: '7', lbl: 'Estaciones activas' },
    { ico: 'map-pin', val: '4', lbl: 'Ciudades en dos continentes' },
    { ico: 'calendar', val: '2017', lbl: 'Desde nuestro origen' },
    { ico: 'globe', val: '24/7', lbl: 'Datos abiertos en tiempo real' },
  ];
  const projects = [
    { eyebrow: 'Monitoreo', title: 'Red de Estaciones Climáticas Comunitarias', img: img('soilSeedling', 640, 400),
      text: 'Sensores que miden clima y calidad del aire y publican en abierto en OpenSenseMap.',
      badge: { tone: 'success', dot: true, text: 'Activa' } },
    { eyebrow: 'Biodiversidad', title: 'Observatorio de Biodiversidad Urbana', img: img('birds', 640, 400),
      text: 'Registro de flora y fauna con iNaturalist para mapear la vida de cada barrio.',
      badge: { tone: 'data', text: 'iNaturalist' } },
    { eyebrow: 'Comunidad', title: 'Educación y Acción Comunitaria', img: img('treePlanting', 640, 400),
      text: 'Talleres, huertos urbanos, reciclaje y jornadas de reforestación con vecinos.',
      badge: { tone: 'sun', text: 'Talleres' } },
  ];
  const gallery = ['greenSun', 'handsPlant', 'recycling', 'kidsNature', 'volunteers', 'turbines', 'leaves', 'riverForest'];
  return (
    <main>
      {/* Hero */}
      <section className="hero">
        <div className="hero__bg hero__bg--motion"><img src={img('heroForest', 1920)} alt="" /></div>
        <span className="hero__mist" aria-hidden="true" />
        <span className="hero__sun" />
        <div className="container hero__inner">
          <span className="eyebrow eyebrow--invert"><Icon n="sprout" />Conservación · Educación · Datos abiertos</span>
          <h1>Protegiendo el medio ambiente con tecnología y educación.</h1>
          <p className="hero__lead">Una red de ciencia ciudadana que monitorea el clima y restaura
            ecosistemas para construir un futuro sostenible.</p>
          <div className="hero__cta">
            <button className="btn btn--accent btn--lg" onClick={() => go('contacto')}><Icon n="hand-heart" />Únete ahora</button>
            <button className="btn btn--ondark btn--lg" onClick={() => go('proyectos')}>Ver proyectos <Icon n="arrow-right" /></button>
          </div>
        </div>
        <a className="hero__scroll" href="#sobre" aria-label="Desplázate"><Icon n="chevron-down" /></a>
      </section>

      {/* Stats */}
      <div className="container stats">
        <div className="stats__grid">
          {stats.map((s, i) => (
            <div className="stat reveal" key={i}>
              <div className="stat__top"><span className="stat__lbl">{s.lbl}</span>
                <span className="stat__ico"><Icon n={s.ico} /></span></div>
              <span className="stat__val">{s.val}</span>
            </div>
          ))}
        </div>
      </div>

      {/* Sobre nosotros */}
      <section className="section container" id="sobre">
        <div className="split">
          <div className="split__body reveal">
            <span className="eyebrow"><Icon n="leaf" />Sobre Nosotros</span>
            <h2 className="h2">Ciencia y comunidad al servicio del planeta</h2>
            <p>EcoEsperanza nació en Colombia en octubre de 2017 como respuesta a la creciente
              crisis medioambiental: deforestación, contaminación y pérdida de biodiversidad.</p>
            <p>Creemos que la información ambiental debe ser <strong>libre, accesible y útil</strong> para
              toda la sociedad. Por eso combinamos tecnología de bajo costo, datos abiertos y
              participación ciudadana para proteger y restaurar los ecosistemas.</p>
            <button className="btn btn--secondary" onClick={() => go('educacion')}>Conoce nuestra educación <Icon n="arrow-right" /></button>
          </div>
          <div className="collage reveal">
            <img src={img('treePlanting', 600, 800)} alt="" />
            <img src={img('soilSeedling', 600, 440)} alt="" />
            <img src={img('leaves', 600, 440)} alt="" />
          </div>
        </div>
      </section>

      {/* Misión / Visión */}
      <section className="section container" style={{ paddingTop: 0 }}>
        <div className="panel-green reveal">
          <span className="panel-green__sun" />
          <div className="mv-grid">
            <div className="mv">
              <span className="eyebrow eyebrow--invert"><Icon n="target" />Nuestra Misión</span>
              <h3>Proteger y restaurar el medio ambiente</h3>
              <p>En todo el mundo, mediante el uso de tecnología, datos abiertos y participación
                ciudadana, promoviendo la educación ambiental y fomentando acciones comunitarias que
                garanticen la sostenibilidad de los ecosistemas.</p>
            </div>
            <div className="mv">
              <span className="eyebrow eyebrow--invert"><Icon n="eye" />Nuestra Visión</span>
              <h3>Una referencia mundial en conservación</h3>
              <p>Conectar comunidades, ciencia y tecnología para mantener un presente resiliente y
                responsable, y crear un futuro consciente y en armonía con la naturaleza.</p>
            </div>
          </div>
        </div>
      </section>

      {/* Proyectos preview */}
      <section className="section container" style={{ paddingTop: 0 }}>
        <SectionHead eyebrow="Nuestros Proyectos" icon="radio-tower"
          title="Iniciativas para la conservación y la sostenibilidad"
          lead="Monitoreo, biodiversidad y acción comunitaria en cada ciudad donde operamos." center />
        <div className="cards">{projects.map((p, i) => <ProjectCard key={i} p={p} go={go} />)}</div>
      </section>

      {/* Galería */}
      <section className="section container" style={{ paddingTop: 0 }}>
        <SectionHead eyebrow="Galería EcoEsperanza" icon="camera"
          title="Nuestras acciones por un futuro sostenible" center />
        <div className="gallery">
          {gallery.map((key, i) => <a key={i} className="reveal"><img src={img(key, 400, 400)} alt="" loading="lazy" /></a>)}
        </div>
      </section>

      <CtaBand go={go} />
      <Footer go={go} />
    </main>
  );
}

/* ====================================================================== */
/* PROYECTOS                                                               */
/* ====================================================================== */
function ProyectosView({ go }) {
  const areas = [
    { ico: 'activity', title: 'Monitoreo Climático y Datos Abiertos',
      text: 'Redes de sensores que miden temperatura, humedad, presión, calidad del aire y lluvia, publicadas en abierto en OpenSenseMap.' },
    { ico: 'graduation-cap', title: 'Educación Ambiental',
      text: 'Talleres, charlas escolares, cursos en línea y guías didácticas para formar ciudadanía informada y comprometida.' },
    { ico: 'hand-heart', title: 'Acción Comunitaria Sostenible',
      text: 'Reforestaciones, limpiezas de ríos y playas, huertos urbanos y restauración de humedales, co-diseñados con la comunidad.' },
  ];
  return (
    <main>
      <section className="pagehero">
        <div className="pagehero__bg"><img src={img('riverForest', 1920)} alt="" /></div>
        <div className="container pagehero__inner">
          <span className="crumb"><a onClick={() => go('inicio')} style={{ cursor: 'pointer' }}>Inicio</a><Icon n="chevron-right" />Proyectos</span>
          <h1>Proyectos estratégicos de monitoreo y acción ambiental</h1>
          <p>Tecnología, ciencia ciudadana y participación comunitaria en distintas ciudades del mundo.</p>
        </div>
      </section>

      <section className="section container">
        <div className="proj reveal">
          <div className="proj__media"><img src={img('soilSeedling', 800, 600)} alt="" /></div>
          <div className="proj__body">
            <span className="eyebrow"><Icon n="radio-tower" />Monitoreo</span>
            <h3>Red de Estaciones Climáticas Comunitarias</h3>
            <p>Recopilamos datos en tiempo real sobre clima y calidad del aire en zonas urbanas
              vulnerables. La información se transmite a plataformas abiertas como OpenSenseMap.</p>
            <ul className="bullets">
              <li><Icon n="map-pin" /><span><strong>Bogotá, Colombia</strong> — 2 estaciones tras lluvias extremas y altos niveles de PM2.5.</span></li>
              <li><Icon n="map-pin" /><span><strong>São Paulo, Brasil</strong> — 2 estaciones por olas de calor e inundaciones repentinas.</span></li>
              <li><Icon n="map-pin" /><span><strong>Valencia, España</strong> — 2 estaciones tras tormentas intensas y contaminación urbana.</span></li>
              <li><Icon n="map-pin" /><span><strong>Provincia de Buenos Aires, Argentina</strong> — 1 estación por contaminación urbana.</span></li>
            </ul>
            <button className="btn btn--primary" onClick={() => go('contacto')}>Apadrina una estación <Icon n="arrow-right" /></button>
          </div>
        </div>
      </section>

      <section className="section container" style={{ paddingTop: 0 }}>
        <div className="proj proj--rev reveal">
          <div className="proj__media"><img src={img('birds', 800, 600)} alt="" /></div>
          <div className="proj__body">
            <span className="eyebrow"><Icon n="bird" />Biodiversidad</span>
            <h3>Observatorio de Biodiversidad Urbana</h3>
            <p>Promovemos el uso de iNaturalist para registrar especies de flora y fauna en las
              zonas donde operamos, conectando los datos climáticos con la salud de los ecosistemas.</p>
            <ul className="bullets">
              <li><Icon n="leaf" /><span>Documentar la biodiversidad local.</span></li>
              <li><Icon n="search" /><span>Identificar especies en riesgo o invasoras.</span></li>
              <li><Icon n="users" /><span>Concientizar sobre la riqueza natural del entorno.</span></li>
            </ul>
          </div>
        </div>
      </section>

      <section className="section" style={{ background: 'var(--color-surface)' }}>
        <div className="container">
          <SectionHead eyebrow="Áreas de Acción" icon="sprout"
            title="Iniciativas para un futuro sostenible y responsable" center />
          <div className="areas">
            {areas.map((a, i) => (
              <div className="area reveal" key={i}>
                <span className="area__ico"><Icon n={a.ico} /></span>
                <h3>{a.title}</h3><p>{a.text}</p>
              </div>
            ))}
          </div>
        </div>
      </section>

      <section className="section container">
        <SectionHead eyebrow="Preguntas Frecuentes" icon="help-circle" title="Resolvemos tus dudas" center />
        <Faq items={FAQ_ITEMS} />
      </section>

      <CtaBand go={go} />
      <Footer go={go} />
    </main>
  );
}

/* ====================================================================== */
/* EDUCACIÓN                                                               */
/* ====================================================================== */
function EducacionView({ go }) {
  const programs = [
    { ico: 'book-open', title: 'Talleres y charlas', text: 'Sesiones presenciales en escuelas, iglesias y comunidades sobre ecología y cambio climático.' },
    { ico: 'graduation-cap', title: 'Cursos en línea', text: 'Formación abierta sobre sostenibilidad, conservación y uso de herramientas de ciencia ciudadana.' },
    { ico: 'radio-tower', title: 'Tecnología para conservar', text: 'Aprende a usar sensores ambientales y aplicaciones como iNaturalist y OpenSenseMap.' },
    { ico: 'hand-heart', title: 'Voluntariado', text: 'Súmate a reforestaciones, huertos urbanos y jornadas de limpieza con tu comunidad.' },
  ];
  return (
    <main>
      <section className="pagehero">
        <div className="pagehero__bg"><img src={img('canopy', 1920)} alt="" /></div>
        <div className="container pagehero__inner">
          <span className="crumb"><a onClick={() => go('inicio')} style={{ cursor: 'pointer' }}>Inicio</a><Icon n="chevron-right" />Educación</span>
          <h1>Educación ambiental para restaurar el entorno natural</h1>
          <p>No se puede proteger lo que no se conoce. Formamos ciudadanía capaz de comprender los
            datos y actuar sobre ellos.</p>
        </div>
      </section>

      <section className="section container">
        <div className="split">
          <div className="split__body reveal">
            <span className="eyebrow"><Icon n="graduation-cap" />Nuestro enfoque</span>
            <h2 className="h2">Aprender, comprender y actuar</h2>
            <p>Desarrollamos programas educativos para distintos públicos —estudiantes, comunidades
              locales, iglesias y voluntariados— con talleres, charlas, cursos en línea y campañas
              de sensibilización.</p>
            <p>Los contenidos abarcan desde conceptos básicos de ecología y cambio climático hasta el
              uso de herramientas tecnológicas para la conservación.</p>
            <button className="btn btn--accent" onClick={() => go('contacto')}><Icon n="sprout" />Quiero participar</button>
          </div>
          <div className="proj__media reveal" style={{ aspectRatio: '4/3', borderRadius: 'var(--radius-xl)', overflow: 'clip', boxShadow: 'var(--shadow-md)' }}>
            <img src={img('teaching', 800, 600)} alt="Taller de educación ambiental" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
          </div>
        </div>
      </section>

      <section className="section" style={{ background: 'var(--color-surface)' }}>
        <div className="container">
          <SectionHead eyebrow="Programas" icon="book-open" title="Formación para todas las edades" center />
          <div className="cards" style={{ gridTemplateColumns: 'repeat(4,1fr)' }}>
            {programs.map((p, i) => (
              <div className="area reveal" key={i}>
                <span className="area__ico"><Icon n={p.ico} /></span>
                <h3 style={{ fontSize: 'var(--text-lg)' }}>{p.title}</h3><p>{p.text}</p>
              </div>
            ))}
          </div>
        </div>
      </section>

      <section className="section container">
        <SectionHead eyebrow="Preguntas Frecuentes" icon="help-circle" title="Sobre la educación ambiental" center />
        <Faq items={FAQ_ITEMS} />
      </section>

      <CtaBand go={go} />
      <Footer go={go} />
    </main>
  );
}

/* ====================================================================== */
/* CONTACTO                                                                */
/* ====================================================================== */
function ContactoView({ go }) {
  const [sent, setSent] = useState(false);
  return (
    <main>
      <section className="pagehero">
        <div className="pagehero__bg"><img src={img('forestPath', 1920)} alt="" /></div>
        <div className="container pagehero__inner">
          <span className="crumb"><a onClick={() => go('inicio')} style={{ cursor: 'pointer' }}>Inicio</a><Icon n="chevron-right" />Contacto</span>
          <h1>Contáctanos</h1>
          <p>Estamos aquí para ayudarte en la conservación ambiental. Escríbenos y súmate a la red.</p>
        </div>
      </section>

      <section className="section container">
        <div className="contact">
          <form className="form reveal" onSubmit={(e) => { e.preventDefault(); setSent(true); }}>
            {sent && <div className="toast"><Icon n="check-circle" />¡Gracias! Te responderemos pronto.</div>}
            <div className="field">
              <label>Nombre</label>
              <input className="input" placeholder="Tu nombre" />
            </div>
            <div className="field">
              <label>Correo electrónico <span className="req">*</span></label>
              <input className="input" type="email" required placeholder="tu@correo.com" />
            </div>
            <div className="field">
              <label>Mensaje <span className="req">*</span></label>
              <textarea className="input" required placeholder="Cuéntanos cómo quieres participar…"></textarea>
            </div>
            <button className="btn btn--primary btn--lg" type="submit" style={{ alignSelf: 'flex-start' }}>
              Enviar <Icon n="arrow-right" />
            </button>
          </form>

          <aside className="contact__info reveal">
            <span className="eyebrow"><Icon n="message-circle" />Datos de contacto</span>
            <a className="cinfo" href="mailto:contacto@ecoesperanzaglobal.org"><span className="cinfo__ico"><Icon n="mail" /></span>
              <div><b>Correo</b><span>contacto@ecoesperanzaglobal.org</span></div></a>
            <a className="cinfo" href="tel:+576019185309"><span className="cinfo__ico"><Icon n="phone" /></span>
              <div><b>Teléfono</b><span>+57 601 918 5309</span></div></a>
            <a className="cinfo" href={`https://wa.me/${WHATSAPP_NUMBER}`} target="_blank" rel="noopener"><span className="cinfo__ico cinfo__ico--wa"><WhatsAppGlyph size={20} /></span>
              <div><b>WhatsApp</b><span>+57 316 420 8654</span></div></a>
            <div className="cinfo"><span className="cinfo__ico"><Icon n="map-pin" /></span>
              <div><b>Estaciones</b><span style={{ fontFamily: 'var(--font-sans)' }}>Bogotá · São Paulo · Valencia · Provincia de Buenos Aires</span></div></div>
          </aside>
        </div>
      </section>

      <Footer go={go} />
    </main>
  );
}

/* ====================================================================== */
/* DATOS (en vivo)                                                         */
/* ====================================================================== */
function DatosView({ go }) {
  const [cities, setCities] = useState(CITIES);
  const [updated, setUpdated] = useState(Date.now());
  const [loading, setLoading] = useState(false);
  const [liveCount, setLiveCount] = useState(0);

  const refresh = React.useCallback(async () => {
    setLoading(true);
    let live = 0;
    const next = await Promise.all(CITIES.map(async (c) => {
      if (!IQAIR_KEY) return c;
      try {
        const d = await fetchCity(c);
        live++;
        return { ...c, aqi: d.aqi, main: d.main, temp: d.temp, hum: d.hum };
      } catch (e) { return c; }
    }));
    setCities(next); setLiveCount(live); setUpdated(Date.now()); setLoading(false);
  }, []);

  useEffect(() => {
    refresh();
    const t = setInterval(refresh, 180000); // auto-refresh every 3 min
    return () => clearInterval(t);
  }, [refresh]);

  const avgAqi = Math.round(cities.reduce((a, c) => a + c.aqi, 0) / cities.length);
  const worst = cities.reduce((a, c) => c.aqi > a.aqi ? c : a, cities[0]);
  const kpis = [
    { ico: 'building-2', val: String(cities.length), lbl: 'Ciudades monitoreadas' },
    { ico: 'wind', val: String(avgAqi), lbl: 'AQI (US) promedio de la red' },
    { ico: 'trending-up', val: String(worst.aqi), lbl: `AQI más alto · ${worst.label}` },
    { ico: 'building-2', val: '2', lbl: 'Continentes monitoreados' },
  ];
  return (
    <main>
      <section className="pagehero">
        <div className="pagehero__bg"><img src={img('mountain', 1920)} alt="" /></div>
        <div className="container pagehero__inner">
          <span className="crumb"><a onClick={() => go('inicio')} style={{ cursor: 'pointer' }}>Inicio</a><Icon n="chevron-right" />Datos en vivo</span>
          <h1>Calidad del aire, ciudad por ciudad</h1>
          <p>La información ambiental debe ser libre, accesible y útil para toda la sociedad.
            Mostramos el índice de calidad del aire (AQI) en tiempo real de las ciudades donde
            trabajamos, con datos de IQAir.</p>
        </div>
      </section>

      <section className="section container">
        <div className="stats" style={{ marginTop: 0 }}>
          <div className="stats__grid">
            {kpis.map((k, i) => (
              <div className="stat reveal" key={i}>
                <div className="stat__top"><span className="stat__lbl">{k.lbl}</span>
                  <span className="stat__ico"><Icon n={k.ico} /></span></div>
                <span className="stat__val">{k.val}</span>
              </div>
            ))}
          </div>
        </div>
      </section>

      <section className="section container" style={{ paddingTop: 0 }}>
        <div className="datos">
          <div className="datos__list panel-card">
            <div className="datos__head">
              <div>
                <span className="eyebrow"><Icon n="activity" />Calidad del aire en vivo</span>
                <h2 className="h2" style={{ fontSize: 'var(--text-2xl)' }}>Índice por ciudad (AQI US)</h2>
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: '.7rem' }}>
                <button className="datos__refresh" onClick={refresh} disabled={loading}
                  aria-label="Actualizar datos" title="Actualizar datos">
                  <Icon n="refresh-cw" className={loading ? 'spin' : ''} />
                </button>
                <span className="live"><span className="live__dot" />En vivo</span>
              </div>
            </div>
            <div className="datos__stations">
              {cities.map((c, i) => {
                const band = aqiBand(c.aqi);
                return (
                  <div className="dst reveal" key={i}>
                    <span className="dst__dot" style={{ background: band.dot }} />
                    <div className="dst__main">
                      <span className="dst__name">{c.label}</span>
                      <span className="dst__city">{c.country} · {c.temp}°C · {c.hum}% · {c.main}</span>
                    </div>
                    <span className="dst__pm" style={{ color: band.fg }}>{c.aqi}<span className="u"> AQI</span></span>
                    <span className="aqi" style={{ background: band.bg, color: band.fg }}>{band.label}</span>
                  </div>
                );
              })}
            </div>
            <div className="datos__foot">
              <span>{liveCount > 0
                ? <><Icon n="wifi" /> {liveCount} ciudad{liveCount === 1 ? '' : 'es'} en directo desde IQAir</>
                : <><Icon n="info" /> Mostrando valores de referencia · añade tu API key para datos en vivo</>}</span>
              <span>Actualizado {timeAgo(updated)}</span>
            </div>
          </div>
        </div>
      </section>

      {/* Mapa interactivo OpenSenseMap */}
      <section className="section container" style={{ paddingTop: 0 }}>
        <SectionHead eyebrow="Mapa abierto" icon="map"
          title="Explora la red de sensores en el mapa"
          lead="Las 7 estaciones comunitarias en 4 ciudades: acerca, mueve y toca cualquier punto para ver su PM2.5 y temperatura." />
        <div className="osm-map reveal">
          <StationMap stations={MAP_STATIONS} />
          <div className="osm-map__bar">
            <span><Icon n="globe" />7 estaciones · Mapa © OpenStreetMap</span>
            <a href="mapa.html">
              Abrir explorador de sensores <Icon n="arrow-up-right" />
            </a>
          </div>
        </div>
      </section>

      <CtaBand go={go} />
      <Footer go={go} />
    </main>
  );
}

/* ====================================================================== */
/* App                                                                     */
/* ====================================================================== */
function App() {
  const [view, setView] = useState('inicio');
  const go = (v) => { setView(v); window.scrollTo({ top: 0, behavior: 'instant' }); };

  // refresh icons + wire reveal-on-scroll whenever the view changes
  useEffect(() => {
    refreshIcons();
    const t = setTimeout(refreshIcons, 120);
    const els = document.querySelectorAll('.reveal');
    let io;
    if ('IntersectionObserver' in window) {
      io = new IntersectionObserver((entries) => {
        entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); } });
      }, { threshold: 0.12, rootMargin: '0px 0px -8% 0px' });
      els.forEach(el => io.observe(el));
    } else {
      els.forEach(el => el.classList.add('in'));
    }
    // Safety net: never leave content permanently hidden (non-scrolling
    // contexts, print/PDF export, capture tools). Reveal all after a beat.
    const safety = setTimeout(() => els.forEach(el => el.classList.add('in')), 1400);
    return () => { clearTimeout(t); clearTimeout(safety); if (io) io.disconnect(); };
  }, [view]);

  const View = { inicio: HomeView, proyectos: ProyectosView, datos: DatosView, educacion: EducacionView, contacto: ContactoView }[view];
  return (
    <>
      <Header view={view} go={go} />
      <View go={go} />
      <FloatingWhatsApp />
    </>
  );
}

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