// src/pages-main.jsx — Presentación, Equipo, Noticias

/* ── Diccionarios ES→EN para datos que viven en data.js ──
   (clave = string español exacto → inglés; si falta, se muestra el español) */
const STATS_LABELS_EN = {
  'Colegios miembros': 'Member schools',
  'Regiones del Perú': 'Regions of Peru',
  'Mundiales consecutivos': 'Consecutive world titles',
  'Año de fundación': 'Year founded',
};

const MARQUEE_EN = {
  'Tricampeones Mundiales': 'Three-Time World Champions',
  'Lima 2018 — fundación': 'Founded in Lima · 2018',
  '103 colegios miembros': '103 member schools',
  '11 regiones': '11 regions',
  'Selección Nacional': 'National Team',
  'Educación Continua': 'Continuing education',
  'Argumentar · Pensar · Convencer': 'Argue · Think · Persuade',
};

/* ═══════════════════════════════════════════════════════════
   PRESENTACIÓN (Home)
   ═══════════════════════════════════════════════════════════ */
const PresentacionPage = ({ setPage }) => {
  const D = window.LPDE_DATA;
  const { t, lang } = useLang();

  return (
    <Page screen="01 Presentación">
      {/* ─── HERO ──────────────────────────────────────── */}
      <section style={{ position: 'relative', minHeight: '88vh', overflow: 'hidden', background: 'var(--ink)' }}>
        <div
          className="photo dark"
          style={{
            position: 'absolute', inset: 0,
            backgroundImage: 'url(assets/portada/portada-lpde.jpg)',
            backgroundSize: 'cover', backgroundPosition: 'center 35%',
            filter: 'grayscale(0.25) contrast(1.05)'
          }} />
        
        <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(180deg, rgba(15,15,18,0.45) 0%, rgba(15,15,18,0.25) 50%, rgba(15,15,18,0.95) 100%)', zIndex: 1 }} />
        <div style={{ position: 'relative', zIndex: 2, minHeight: '88vh', display: 'flex', flexDirection: 'column', justifyContent: 'space-between', paddingTop: 140, paddingBottom: 72 }}>
          <div className="shell" style={{ width: '100%' }}>
            <div className="reveal" style={{ marginBottom: 56 }}>
              <span style={{ color: '#fff', fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.16em', textTransform: 'uppercase', display: 'inline-flex', alignItems: 'center', gap: 12 }}>
                <span style={{ width: 32, height: 1, background: 'var(--red)' }} />
                {t('Desde 2018 · Lima · Perú', 'Since 2018 · Lima · Peru')}
              </span>
            </div>
            <h1 className="display reveal d1" style={{ color: '#fff', fontSize: 'clamp(58px, 9vw, 148px)', maxWidth: '14ch' }}>
              {t('Argumentar', 'Argument')}<br />
              {t('da sentido al', 'gives meaning to')}<br />
              {t('mundo que ', 'the world we ')}<span className="it">{t('habitamos', 'inhabit')}</span>
            </h1>
          </div>
          <div className="shell" style={{ width: '100%', display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', flexWrap: 'wrap', gap: 32 }}>
            <p className="reveal d2" style={{ color: '#E0DED7', fontSize: 19, maxWidth: 480, lineHeight: 1.5 }}>
              {t('Somos la ', 'We are the ')}<strong style={{ color: '#fff' }}>{t('Liga Peruana de Debate Escolar', 'Peruvian School Debate League (LPDE)')}</strong>{t(' — la red más grande de debate académico del Perú. 103 colegios, 11 regiones, tres títulos mundiales consecutivos.', ' — Peru’s largest academic debate network. 103 schools, 11 regions, three consecutive world titles.')}
            </p>
            <div className="reveal d3" style={{ display: 'flex', gap: 12 }}>
              <button className="btn btn-red" onClick={() => setPage('admision')}>
                {t('Sé miembro', 'Become a member')} <Icon name="arrow" />
              </button>
              <button className="btn btn-light" onClick={() => setPage('tnde')}>
                {t('Conoce el TNDE', 'Discover the TNDE')}
              </button>
            </div>
          </div>
        </div>
      </section>

      {/* ─── Marquee ──────────────────────────────────── */}
      <Marquee items={lang === 'en' ? D.marquee.map((m) => MARQUEE_EN[m] || m) : D.marquee} />

      {/* ─── Stats ─────────────────────────────────────── */}
      <section className="section" style={{ background: 'var(--bg)' }}>
        <div className="shell">
          <div className="reveal" style={{ marginBottom: 64, display: 'flex', justifyContent: 'space-between', alignItems: 'end', flexWrap: 'wrap', gap: 24 }}>
            <div>
              <span className="eyebrow">{t('La Liga en números', 'The League in numbers')}</span>
              <h2 className="display" style={{ fontSize: 'clamp(40px, 5vw, 64px)', marginTop: 16, maxWidth: '16ch' }}>
                {t('Casi una década formando a las próximas ', 'Nearly a decade shaping Peru’s next generation of ')}<span className="it">{t('voces críticas', 'critical voices')}</span>{t(' del país.', '.')}
              </h2>
            </div>
            <p style={{ maxWidth: 360, color: 'var(--ink-2)', fontSize: 16 }}>
              {t('Datos actualizados a marzo 2026.', 'Data as of March 2026.')}
            </p>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 0, borderTop: '1px solid var(--line)' }}>
            {D.stats.map((s, i) =>
            <div key={i} className={`reveal d${i + 1}`} style={{ padding: '40px 24px', borderRight: i < 3 ? '1px solid var(--line)' : 'none' }}>
                <div className="stat-num">
                  {s.it ? <em className="it"><CountUp to={parseInt(s.num)} /></em> : <CountUp to={parseInt(s.num)} />}
                </div>
                <div className="stat-label" style={{ marginTop: 12 }}>{lang === 'en' ? (STATS_LABELS_EN[s.label] || s.label) : s.label}</div>
              </div>
            )}
          </div>
        </div>
      </section>

      {/* ─── Quiénes somos ─────────────────────────────── */}
      <section className="section bg-pale">
        <div className="shell">
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1.1fr', gap: 80, alignItems: 'center' }}>
            <div className="reveal">
              <div style={{ position: 'relative', aspectRatio: '4/5', borderRadius: 4, overflow: 'hidden', background: 'var(--ink)' }}>
                <img
                  src="assets/portada/comunidad-academica.jpg"
                  alt={t('Estudiantes en debate', 'Students debating')}
                  style={{ width: '100%', height: '100%', objectFit: 'cover', filter: 'contrast(1.04) saturate(0.85) sepia(0.22) brightness(1.03)' }} />
                {/* Máscara oscura para legibilidad del texto */}
                <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(180deg, rgba(15,15,18,0.0) 0%, rgba(15,15,18,0.35) 45%, rgba(15,15,18,0.88) 100%)' }} />
                <div style={{ position: 'absolute', bottom: 28, left: 28, right: 28, color: '#fff', zIndex: 2 }}>
                  <Icon name="quote" size={28} />
                  <p style={{ fontFamily: 'var(--serif)', fontSize: 22, lineHeight: 1.3, marginTop: 8, fontStyle: 'italic' }}>
                    {t('“Debatir nos enseña que podemos equivocarnos y que otros también tienen razones para pensar distinto.”', '“Debate teaches us that we can be wrong — and that others have their own reasons to think differently.”')}
                  </p>
                </div>
              </div>
            </div>
            <div className="reveal d1">
              <span className="eyebrow">{t('Quiénes somos', 'Who we are')}</span>
              <h2 className="display" style={{ fontSize: 'clamp(40px, 5vw, 64px)', marginTop: 16 }}>
                {t('Una comunidad ', 'An ')}<em className="it">{t('académica', 'academic')}</em>{t(', no un torneo.', ' community, not a tournament.')}
              </h2>
              <p style={{ fontSize: 19, lineHeight: 1.6, color: 'var(--ink-soft)', marginTop: 28, maxWidth: 540 }}>{t('Fundada en 2018 por una red de profesores y debatientes, la LPDE existe para algo más que competir: garantizar que cualquier estudiante peruano —sin importar su lugar de procedencia— pueda aprender a comprometerse con sus propias ideas.', 'Founded in 2018 by a network of teachers and debaters, the LPDE exists for more than competition: to ensure that every Peruvian student — wherever they come from — can learn to stand behind their own ideas.')}


              </p>
              <p style={{ fontSize: 16, lineHeight: 1.7, color: 'var(--ink-2)', marginTop: 18, maxWidth: 540 }}>{t('Operamos a través de Metadidactas, la consultora de la LPDE. Capacitamos a profesores, organizamos torneos abiertos, publicamos materiales gratuitos y representamos al Perú en el Mundial Escolar de Debate (MED).', 'We operate through Metadidactas, the LPDE’s consulting arm. We train teachers, run open tournaments, publish free materials and represent Peru at the Spanish-language World Schools Debating Championship (MED).')}

              </p>
              <div style={{ display: 'flex', gap: 24, marginTop: 36, flexWrap: 'wrap', alignItems: 'center' }}>
                <button className="btn btn-primary" onClick={() => setPage('equipo')}>{t('Conoce al equipo', 'Meet the team')} <Icon name="arrow" /></button>
                <button className="btn btn-link" onClick={() => setPage('noticias')} style={{ lineHeight: "1.4", fontSize: "15px" }}>{t('Leer la nota', 'Read the story')}</button>
              </div>
            </div>
          </div>
        </div>
      </section>

      {/* ─── Historia / timeline ───────────────────────── */}
      <section className="section bg-dots">
        <div className="shell">
          <div className="reveal" style={{ marginBottom: 56 }}>
            <span className="eyebrow">{t('Historia', 'Our history')}</span>
            <h2 className="display" style={{ fontSize: 'clamp(40px, 5vw, 64px)', marginTop: 16, maxWidth: '14ch' }}>
              {t('De la fundación al ', 'From our founding to ')}<em className="it">{t('tricampeonato mundial', 'three straight world titles')}</em>.
            </h2>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 0, borderTop: '1px solid var(--line)' }}>
            {[
            { y: '2018', t: t('Se funda la LPDE', 'The LPDE is founded'), d: t('Una red de profesores y debatientes firma el acta fundacional.', 'A network of teachers and debaters signs the founding charter.') },
            { y: '2021', t: t('TNDE en inglés', 'TNDE in English'), d: t('El TNDE incorpora oficialmente la división en inglés, junto a la categoría en español.', 'The TNDE officially adds an English division alongside the Spanish category.') },
            { y: '2023', t: t('Primer Descentralizado', 'First regional tournament'), d: t('La LPDE realiza su primer Torneo Descentralizado fuera de Lima, en Juliaca, Puno.', 'The LPDE holds its first Decentralized Tournament outside Lima, in Juliaca, Puno.') },
            { y: '2024', t: t('Se funda la SNDE', 'The SNDE is founded'), d: t('Nace la Selección Nacional de Debate Escolar como cuerpo permanente.', 'The National School Debate Team (SNDE) is established as a permanent body.') },
            { y: '2023—25', t: t('Tricampeonato MED', 'Three MED titles in a row'), d: t('San Clemente (2023), Selección Nacional en Panamá (2024) y en Chile (2025).', 'San Clemente (2023), the National Team in Panama (2024) and in Chile (2025).') }].
            map((e, i) => {
              const last = i === 4;
              return (
            <div key={i} className={`reveal d${(i % 4) + 1}`} style={{ padding: '40px 22px 0', borderRight: i < 4 ? '1px solid var(--line)' : 'none', position: 'relative' }}>
                <div style={{ position: 'absolute', top: -1, left: 0, width: i < 4 ? 'calc(100% + 1px)' : '100%', height: 3, background: last ? 'var(--red)' : 'transparent' }} />
                <div style={{ fontFamily: 'var(--mono)', fontSize: 12, letterSpacing: '0.12em', color: last ? 'var(--red)' : 'var(--mute)', marginBottom: 24 }}>
                  {e.y}
                </div>
                <h3 className="display" style={{ fontSize: 24, marginBottom: 12 }}>{e.t}</h3>
                <p style={{ fontSize: 14, color: 'var(--ink-2)', lineHeight: 1.55, paddingBottom: 24 }}>{e.d}</p>
              </div>
              );
            })}
          </div>
        </div>
      </section>

      {/* ─── Lo que hacemos ────────────────────────────── */}
      <section className="section" style={{ background: '#070709', color: '#fff' }}>
        <div className="shell">
          <div className="reveal" style={{ marginBottom: 56, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 80, alignItems: 'end' }}>
            <div>
              <span className="eyebrow" style={{ color: 'var(--red)' }}>{t('Lo que hacemos', 'What we do')}</span>
              <h2 className="display" style={{ color: '#fff', fontSize: 'clamp(40px, 5vw, 64px)', marginTop: 16 }}>
                {t('Cuatro frentes,', 'Four fronts,')}<br />{t('una misma ', 'one shared ')}<em className="it" style={{ color: 'var(--red)' }}>{t('misión', 'mission')}</em>
              </h2>
            </div>
            <p style={{ color: '#B8B8C0', fontSize: 17, lineHeight: 1.6 }}>
              {t('Construir, año tras año, una cancha donde cualquier estudiante peruano pueda jugar a pensar en serio.', 'To build, year after year, a playing field where every Peruvian student can practice serious thinking.')}
            </p>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 16 }}>
            {[
            { n: '01', t: t('Torneos', 'Tournaments'), tag: t('Competencia', 'Competition'), stat: t('Calidad', 'Quality'), statLabel: t('académica', 'academic'), d: t('TNDE, circuitos regionales y abiertos. Eventos presenciales y virtuales para todos.', 'The TNDE, regional circuits and open events. In person and online, open to everyone.'), cta: () => setPage('tnde'), variant: 'photo', img: 'https://images.unsplash.com/photo-1540575467063-178a50c2df87?w=1200&auto=format&q=80' },
            { n: '02', t: t('Selección Nacional', 'National Team'), tag: t('Comunidad', 'Community'), stat: '3×', statLabel: t('Tricampeones MED', 'Three-time MED champions'), d: t('Preparamos a los seis representantes peruanos para el Mundial Escolar de Debate (MED).', 'We prepare Peru’s six representatives for the Spanish-language World Schools Debating Championship (MED).'), cta: () => setPage('snde'), variant: 'red' },
            { n: '03', t: t('Formación', 'Training'), tag: 'Metadidactas', stat: '400+', statLabel: t('Egresados', 'Alumni'), d: t('Programa especializado para profesores y debatientes. Operado por Metadidactas.', 'Specialized programs for teachers and debaters, run by Metadidactas.'), cta: () => setPage('formacion'), variant: 'cream' },
            { n: '04', t: t('Publicaciones', 'Publications'), tag: t('Acceso libre', 'Open access'), stat: '∞', statLabel: t('Libre para todos', 'Free for everyone'), d: t('Información libre para todos: manuales del juez, guías curriculares y libros de argumentación.', 'Free knowledge for everyone: adjudication manuals, curriculum guides and books on argumentation.'), cta: () => setPage('noticias'), variant: 'outline' }].
            map((f, i) =>
            <FrentCard key={i} f={f} idx={i} />
            )}
          </div>
        </div>
      </section>

      {/* ─── TNDE spotlight ──────────────── */}
      <section style={{ background: 'var(--ink)', color: '#fff', padding: '80px 0', position: 'relative', overflow: 'hidden' }}>
        <div aria-hidden="true" style={{ position: 'absolute', top: '50%', right: '-8%', transform: 'translateY(-50%)', fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 'clamp(280px, 30vw, 480px)', lineHeight: 0.78, color: 'rgba(227,6,19,0.08)', letterSpacing: '-0.04em', pointerEvents: 'none', userSelect: 'none' }}>
          XII.
        </div>
        <div className="shell" style={{ position: 'relative' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 32 }} className="reveal">
            <span style={{ width: 8, height: 8, borderRadius: 999, background: 'var(--red)', boxShadow: '0 0 0 4px rgba(227,6,19,0.2)', animation: 'pulse 2s ease-in-out infinite' }}/>
            <span style={{ fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.18em', textTransform: 'uppercase', color: 'var(--red)' }}>{t('Próximo evento', 'Next event')}</span>
            <div style={{ flex: 1, height: 1, background: '#2A2A30' }}/>
            <img src={D.tnde.emblemWhite} alt={t('Emblema TNDE', 'TNDE emblem')} style={{ height: 56, width: 'auto', opacity: 0.95 }}/>
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: '1.1fr 1.4fr 0.9fr', gap: 56, alignItems: 'center' }}>
            {/* Date block */}
            <div className="reveal d1">
              <div style={{ display: 'inline-block', padding: '4px 10px', borderRadius: 999, background: 'var(--red)', color: '#fff', fontFamily: 'var(--sans)', fontSize: 10, fontWeight: 700, letterSpacing: '0.16em', textTransform: 'uppercase', marginBottom: 20 }}>
                {t('TNDE · XII Edición', 'TNDE · 12th Edition')}
              </div>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 16 }}>
                <div style={{ fontFamily: 'var(--serif)', fontWeight: 400, fontSize: 'clamp(96px, 11vw, 180px)', lineHeight: 0.8, color: '#fff', letterSpacing: '-0.03em' }}>
                  8–11
                </div>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
                  <span style={{ fontFamily: 'var(--mono)', fontSize: 16, fontWeight: 700, letterSpacing: '0.14em', color: 'var(--red)' }}>{t('AGO', 'AUG')}</span>
                  <span style={{ fontFamily: 'var(--mono)', fontSize: 14, color: '#9C9AA0' }}>2026</span>
                </div>
              </div>
              <div style={{ marginTop: 16, fontFamily: 'var(--mono)', fontSize: 13, color: '#B8B8C0', letterSpacing: '0.05em' }}>
                {t('SÁB → MAR · 8, 9, 10 y 11 AGO', 'SAT → TUE · AUG 8, 9, 10 & 11')}
              </div>
            </div>

            {/* Title + description */}
            <div className="reveal d2" style={{ paddingLeft: 32, borderLeft: '1px solid #2A2A30' }}>
              <h2 className="display" style={{ color: '#fff', fontSize: 'clamp(40px, 5vw, 64px)', lineHeight: 0.98, marginBottom: 20 }}>
                {t('Torneo Nacional', 'National School')}<br/>{t('de ', '')}<em className="it" style={{ color: 'var(--red)' }}>{t('Debate Escolar', 'Debate Tournament')}</em>
              </h2>
              <p style={{ color: '#B8B8C0', fontSize: 17, lineHeight: 1.55, marginBottom: 24, maxWidth: 520 }}>
                {t('La XII edición del torneo bandera de la LPDE. Cuatro días con cientos de adolescentes de todo el país pensando juntos en problemas del mundo real, en español y en inglés.', 'The 12th edition of the LPDE’s flagship tournament. Four days of hundreds of teenagers from across Peru thinking together about real-world problems, in Spanish and in English.')}
              </p>
              <div style={{ display: 'flex', gap: 32, flexWrap: 'wrap', paddingTop: 20, borderTop: '1px solid #2A2A30' }}>
                <div>
                  <div className="kicker" style={{ color: '#9C9AA0', marginBottom: 4 }}>{t('Sede', 'Venue')}</div>
                  <div style={{ fontFamily: 'var(--serif)', fontSize: 18, color: '#fff', fontStyle: 'italic' }}>TBA</div>
                </div>
                <div>
                  <div className="kicker" style={{ color: '#9C9AA0', marginBottom: 4 }}>{t('Formato', 'Format')}</div>
                  <div style={{ fontFamily: 'var(--serif)', fontSize: 18, color: '#fff' }}>{t('WSDC · presencial', 'WSDC · in person')}</div>
                </div>
                <div>
                  <div className="kicker" style={{ color: '#9C9AA0', marginBottom: 4 }}>{t('Vacantes', 'Slots')}</div>
                  <div style={{ fontFamily: 'var(--serif)', fontSize: 18, color: 'var(--red)', fontStyle: 'italic' }}>TBA</div>
                </div>
              </div>
            </div>

            {/* CTA + emblema grande */}
            <div className="reveal d3" style={{ display: 'flex', flexDirection: 'column', gap: 20, alignItems: 'center' }}>
              <div style={{ padding: 16, display: 'flex', alignItems: 'center', justifyContent: 'center', width: '100%' }}>
                <img src={D.tnde.emblemWhite} alt={t('Emblema TNDE', 'TNDE emblem')} style={{ width: '100%', height: 'auto', maxHeight: 220, maxWidth: 220 }}/>
              </div>
              <button className="btn btn-red" style={{ justifyContent: 'center', width: '100%' }} onClick={() => setPage('tnde')}>
                {t('Conoce el TNDE', 'Discover the TNDE')} <Icon name="arrow"/>
              </button>
              <button className="btn btn-light" style={{ justifyContent: 'center', width: '100%' }} onClick={() => setPage('calendario')}>
                {t('Ver calendario completo', 'View full calendar')}
              </button>
            </div>
          </div>
        </div>
      </section>

      {/* ─── Calendario · próximos eventos (dinámico) ──── */}
      <CalendarioSnippet setPage={setPage} />

      {/* ─── Colegios miembros (teaser) ─────────────────── */}
      <section className="section">
        <div className="shell">
          <div className="reveal" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 64, alignItems: 'center' }}>
            {/* Left: copy */}
            <div>
              <span className="eyebrow">{t('Colegios miembros', 'Member schools')}</span>
              <h2 className="display" style={{ fontSize: 'clamp(40px, 5vw, 72px)', marginTop: 16, maxWidth: '14ch' }}>
                {t('Cien colegios.', 'One hundred schools.')}<br/>{t('Un solo ', 'One shared ')}<em className="it">{t('campo de juego', 'playing field')}</em>
              </h2>
              <p style={{ fontSize: 17, color: 'var(--ink-2)', lineHeight: 1.6, marginTop: 24, maxWidth: 500 }}>
                {t('Desde colegios privados en Lima Metropolitana hasta escuelas públicas en la sierra centro, los Andes del sur y la costa norte. La red de la LPDE reúne hoy a colegios de ', 'From private schools in Metropolitan Lima to public schools in the central highlands, the southern Andes and the northern coast. The LPDE network now brings together schools from ')}<strong style={{ color: 'var(--ink)' }}>{t('11 regiones', '11 regions')}</strong>{t(' y ', ' and ')}<strong style={{ color: 'var(--ink)' }}>{t('44 ciudades y distritos', '44 cities and districts')}</strong>{t(' del país.', ' across Peru.')}
              </p>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 24, marginTop: 36, paddingTop: 24, borderTop: '1px solid var(--line)' }}>
                <div>
                  <div className="stat-num" style={{ fontSize: 56 }}><CountUp to={103}/></div>
                  <div className="kicker" style={{ marginTop: 4 }}>{t('Miembros', 'Members')}</div>
                </div>
                <div>
                  <div className="stat-num" style={{ fontSize: 56 }}><CountUp to={11}/></div>
                  <div className="kicker" style={{ marginTop: 4 }}>{t('Regiones', 'Regions')}</div>
                </div>
                <div>
                  <div className="stat-num" style={{ fontSize: 56, color: 'var(--red)' }}><em className="it"><CountUp to={44}/></em></div>
                  <div className="kicker" style={{ marginTop: 4 }}>{t('Públicos', 'Public')}</div>
                </div>
              </div>
              <button className="btn btn-primary" style={{ marginTop: 36 }} onClick={() => setPage('colegios')}>
                {t('Ver el mapa completo', 'Explore the full map')} <Icon name="arrow"/>
              </button>
            </div>

            {/* Right: stylized preview map */}
            <div onClick={() => setPage('colegios')}
              style={{ cursor: 'pointer', background: 'var(--bg-alt)', border: '1px solid var(--line)', padding: 32, position: 'relative', transition: 'all 280ms ease' }}
              onMouseEnter={(e) => { e.currentTarget.style.transform = 'translateY(-4px)'; e.currentTarget.style.boxShadow = '0 16px 40px rgba(0,0,0,0.08)'; }}
              onMouseLeave={(e) => { e.currentTarget.style.transform = 'translateY(0)'; e.currentTarget.style.boxShadow = 'none'; }}
            >
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 16 }}>
                <div className="kicker">{t('Mapa interactivo · vista previa', 'Interactive map · preview')}</div>
                <span style={{ width: 32, height: 32, borderRadius: 999, background: 'var(--ink)', color: '#fff', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
                  <Icon name="arrow-up-right" size={14}/>
                </span>
              </div>
              <div style={{ aspectRatio: '4/5', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
                <svg viewBox="0 0 100 130" style={{ width: '100%', height: '100%' }}>
                  <path
                    d="M22,18 L26,14 L34,16 L40,22 L46,18 L54,22 L58,28 L62,32 L62,42 L58,46 L60,52 L56,58 L54,64 L58,68 L62,72 L66,78 L68,84 L64,92 L60,98 L54,104 L48,108 L42,114 L36,118 L30,116 L26,110 L22,102 L20,94 L24,86 L26,78 L22,72 L20,64 L24,56 L22,48 L18,42 L14,34 L18,26 Z"
                    fill="var(--bg)"
                    stroke="var(--line-strong)"
                    strokeWidth="0.4"
                  />
                  {[
                    { x: 28, y: 56, r: 13 }, { x: 56, y: 68, r: 5 }, { x: 50, y: 82, r: 5 },
                    { x: 30, y: 32, r: 3 }, { x: 20, y: 22, r: 3 }, { x: 42, y: 56, r: 3 },
                    { x: 24, y: 30, r: 3 }, { x: 30, y: 24, r: 3 }, { x: 56, y: 18, r: 2 },
                    { x: 62, y: 76, r: 2 }, { x: 32, y: 70, r: 2 }, { x: 30, y: 42, r: 2 },
                  ].map((c, i) => (
                    <g key={i}>
                      <circle cx={c.x} cy={c.y} r={c.r + 2} fill="var(--red)" opacity="0.15"/>
                      <circle cx={c.x} cy={c.y} r={c.r * 0.5} fill="var(--red)" opacity="0.9">
                        <animate attributeName="opacity" values="0.9;0.5;0.9" dur="3s" begin={`${i * 0.2}s`} repeatCount="indefinite"/>
                      </circle>
                    </g>
                  ))}
                </svg>
              </div>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 16, paddingTop: 16, borderTop: '1px solid var(--line)' }}>
                <span style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 20, color: 'var(--ink)' }}>Lima · 78</span>
                <span style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 20, color: 'var(--red)' }}>{t('Provincia · 25', 'Outside Lima · 25')}</span>
              </div>
            </div>
          </div>
        </div>
      </section>

      {/* ─── Metadidactas spotlight ──────────────────── */}
      <section className="section" style={{ background: '#0F0F12', color: '#fff', position: 'relative', overflow: 'hidden' }}>
        <div className="shell">
          <div className="reveal" style={{ marginBottom: 56 }}>
            <span className="eyebrow" style={{ color: 'var(--red)' }}>{t('Proyecto hermano', 'Sister project')}</span>
            <h2 className="display" style={{ color: '#fff', fontSize: 'clamp(40px, 5vw, 64px)', marginTop: 16, maxWidth: '20ch' }}>
              {t('La plataforma de ', 'The LPDE’s ')}<em className="it" style={{ color: 'var(--red)' }}>e-learning</em>{t(' de la LPDE', ' platform')}
            </h2>
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1.3fr', gap: 0, border: '1px solid #2A2A30' }}>
            {/* Left — branded visual */}
            <div className="reveal d1" style={{ background: 'var(--red)', color: '#fff', padding: 56, display: 'flex', flexDirection: 'column', justifyContent: 'space-between', minHeight: 440, position: 'relative', overflow: 'hidden' }}>
              {/* Giant M */}
              <div aria-hidden="true" style={{ position: 'absolute', top: -40, right: -40, fontFamily: 'var(--serif)', fontSize: 520, lineHeight: 0.78, color: 'rgba(255,255,255,0.18)', fontWeight: 900, fontStyle: 'italic', userSelect: 'none', pointerEvents: 'none' }}>M</div>

              <div style={{ position: 'relative', zIndex: 2 }}>
                <div style={{ display: 'inline-flex', alignItems: 'center', gap: 12, padding: '6px 14px', background: 'rgba(255,255,255,0.15)', border: '1px solid rgba(255,255,255,0.25)', borderRadius: 999, fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase' }}>
                  <span style={{ width: 8, height: 8, borderRadius: 999, background: '#fff' }}/>
                  {t('Consultora de la LPDE', 'The LPDE’s consulting arm')}
                </div>
              </div>

              <div style={{ position: 'relative', zIndex: 2 }}>
                <div style={{ fontFamily: 'var(--serif)', fontSize: 'clamp(48px, 5vw, 72px)', lineHeight: 0.95, color: '#fff', fontWeight: 700 }}>
                  meta<br/><span style={{ color: 'rgba(255,255,255,0.5)' }}>didactas</span>
                </div>
                <p style={{ fontSize: 14, color: 'rgba(255,255,255,0.85)', marginTop: 16, maxWidth: '32ch', lineHeight: 1.55 }}>
                  {t('Plataforma de educación continua en argumentación, debate y pensamiento crítico para Latinoamérica.', 'A continuing education platform in argumentation, debate and critical thinking for Latin America.')}
                </p>
                <div style={{ marginTop: 24, paddingTop: 20, borderTop: '1px solid rgba(255,255,255,0.2)', display: 'flex', alignItems: 'center', gap: 10, fontFamily: 'var(--mono)', fontSize: 11, color: 'rgba(255,255,255,0.85)', letterSpacing: '0.05em' }}>
                  {t('Metadidactas · Educación continua', 'Metadidactas · Continuing education')} <Icon name="arrow-up-right" size={12}/>
                </div>
              </div>
            </div>

            {/* Right — story + ramas + CTAs */}
            <div className="reveal d2" style={{ background: '#15151A', padding: 56, display: 'flex', flexDirection: 'column', gap: 28 }}>
              <p style={{ fontFamily: 'var(--serif)', fontSize: 24, lineHeight: 1.4, color: '#fff', fontStyle: 'italic' }}>
                {t('“Lo que aprendimos formando debatientes durante años, hoy lo enseñamos a profesores y estudiantes.”', '“What we learned over years of training debaters, we now teach to teachers and students.”')}
              </p>
              <p style={{ fontSize: 15, lineHeight: 1.65, color: '#B8B8C0' }}>
                {t('Metadidactas nace de la LPDE como plataforma de educación continua. Un equipo interdisciplinario —debatientes, filósofos, comunicadores, abogados, politólogos, pedagogos— diseña sus contenidos. No solo trabajamos debate: también filosofía y emprendimiento.', 'Metadidactas grew out of the LPDE as a continuing education platform. An interdisciplinary team — debaters, philosophers, communicators, lawyers, political scientists, educators — designs its content. We go beyond debate: we also teach philosophy and entrepreneurship.')}
              </p>

              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12, paddingTop: 24, borderTop: '1px solid #2A2A30' }}>
                {[
                  { label: 'Debate', sub: t('Argumentación, retórica, juzgamiento', 'Argumentation, rhetoric, adjudication') },
                  { label: 'FiloNautas', sub: t('Filosofía para escolares', 'Philosophy for school students') },
                  { label: 'Impulso', sub: t('Emprendimiento y proyectos', 'Entrepreneurship and projects') },
                ].map((r, i) => (
                  <div key={i} style={{ padding: '16px 14px', background: 'rgba(227,6,19,0.06)', border: '1px solid rgba(227,6,19,0.25)' }}>
                    <div style={{ fontFamily: 'var(--serif)', fontSize: 22, lineHeight: 1.1, color: '#fff' }}>{r.label}</div>
                    <div style={{ fontSize: 11, color: '#9C9AA0', marginTop: 6, lineHeight: 1.4 }}>{r.sub}</div>
                  </div>
                ))}
              </div>

              <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', marginTop: 'auto' }}>
                <button className="btn btn-red" onClick={() => setPage('formacion')}>
                  {t('Ver oferta académica', 'See our programs')} <Icon name="arrow"/>
                </button>
                <a href="https://cidedidactica.org/metadidactas/" target="_blank" rel="noopener" className="btn btn-light">
                  {t('Ir a Metadidactas', 'Go to Metadidactas')}
                </a>
              </div>
            </div>
          </div>
        </div>
      </section>

      {/* ─── Aliados ───────────────────────────────────── */}
      <section className="section" style={{ background: '#fff' }}>
        <div className="shell">
          <div className="reveal" style={{ textAlign: 'center', marginBottom: 48 }}>
            <span className="eyebrow muted">{t('Aliados institucionales', 'Institutional partners')}</span>
            <h2 className="display" style={{ fontSize: 'clamp(28px, 3vw, 40px)', marginTop: 16, color: 'var(--ink)' }}>
              {t('Universidades y colegios que ', 'Universities and schools that ')}<em className="it">{t('apuestan', 'believe')}</em>{t(' por el debate.', ' in debate.')}
            </h2>
          </div>
          <div className="reveal d1" style={{
            display: 'grid',
            gridTemplateColumns: 'repeat(6, 1fr)',
            gap: '32px 48px',
            padding: '40px 24px',
            borderTop: '1px solid var(--line)',
            borderBottom: '1px solid var(--line)',
            alignItems: 'center',
            justifyItems: 'center',
          }}>
            {[
              { src: 'assets/aliados/pucp.webp', name: 'PUCP' },
              { src: 'assets/aliados/ulima.webp', name: 'Universidad de Lima' },
              { src: 'assets/aliados/upc.webp', name: 'UPC' },
              { src: 'assets/aliados/esan.webp', name: 'ESAN' },
              { src: 'assets/aliados/markham2023.webp', name: 'Colegio Markham' },
              { src: 'assets/aliados/salcantay.webp', name: 'Colegio Salcantay' },
              { src: 'assets/aliados/trener.webp', name: 'Colegio Trener' },
              { src: 'assets/aliados/aleph.webp', name: 'Colegio Áleph' },
              { src: 'assets/aliados/cpl.webp', name: 'CPL' },
              { src: 'assets/aliados/fil.webp', name: 'FIL' },
              { src: 'assets/aliados/bicentenario.webp', name: 'Bicentenario Perú' },
              { src: 'assets/aliados/logo.webp', name: t('Aliado institucional', 'Institutional partner') },
            ].map((a, i) => (
              <div key={i} title={a.name} style={{
                width: '100%',
                maxWidth: 140,
                height: 72,
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                transition: 'all 280ms ease',
              }}
                onMouseEnter={(e) => { e.currentTarget.querySelector('img').style.filter = 'grayscale(0) opacity(1)'; e.currentTarget.querySelector('img').style.transform = 'scale(1.05)'; }}
                onMouseLeave={(e) => { e.currentTarget.querySelector('img').style.filter = 'grayscale(1) opacity(0.65)'; e.currentTarget.querySelector('img').style.transform = 'scale(1)'; }}
              >
                <img src={a.src} alt={a.name} style={{
                  maxWidth: '100%',
                  maxHeight: '100%',
                  objectFit: 'contain',
                  filter: 'grayscale(1) opacity(0.65)',
                  transition: 'filter 280ms ease, transform 280ms ease',
                }}/>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* ─── CTA banner ────────────────────────────────── */}
      <section style={{ background: 'var(--red)', color: '#fff', padding: '80px 0' }}>
        <div className="shell" style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 48, alignItems: 'center' }}>
          <div>
            <h2 className="display" style={{ color: '#fff', fontSize: 'clamp(36px, 4.5vw, 56px)' }}>
              {t('¿Eres profesor, estudiante o colegio?', 'Are you a teacher, a student or a school?')}
            </h2>
            <p style={{ color: 'rgba(255,255,255,0.85)', fontSize: 18, marginTop: 16, maxWidth: 520 }}>
              {t('La participación en la LPDE está abierta todo el año. Te explicamos cómo puedes participar y qué beneficios puedes obtener.', 'Participation in the LPDE is open year-round. We’ll walk you through how to join and what you stand to gain.')}
            </p>
          </div>
          <div style={{ textAlign: 'right' }}>
            <button className="btn" style={{ background: '#fff', color: 'var(--red)' }} onClick={() => setPage('admision')}>
              {t('Cómo ser miembro', 'How to become a member')} <Icon name="arrow" />
            </button>
          </div>
        </div>
      </section>
    </Page>);

};

/* ═══════════════════════════════════════════════════════════
   EQUIPO
   ═══════════════════════════════════════════════════════════ */
/* Traducciones EN de los datos del equipo (window.LPDE_DATA.team vive en data.js
   y se mantiene en español; aquí solo se sobreescribe al renderizar en inglés). */
const TEAM_EN = {
  'Evangelina Beierbach': {
    role: 'Wellbeing Coordinator',
    short: 'Looks after the wellbeing and conduct of the National Team’s students and designs non-academic debate training sessions.',
    bio: 'Communication teacher at Colegio Trener since 2005. She entered the world of debate in 2012 and has accompanied the Trener Debate Society since 2014. Part of the LPDE since its early days, she helped launch the World Schools Debate Council and now serves on its General Secretariat. She supports the SNDE in the area of holistic development.',
  },
  'Felipe Zenteno Pacheco': {
    role: 'Academic Director',
    short: 'Leads the LPDE’s academic team. Designs and delivers training, coaching and consulting programs in school debate.',
    bio: 'Holds a bachelor’s degree in Philosophy from U.N.M.S.M. Debate teacher at Colegio Aleph and argumentation teacher at Colegio San Clemente. Coached the 2023 MED champion team and the 2023 TNDE champion.',
  },
  'Dante León Saavedra': {
    role: 'Operations Director',
    short: 'Leads the LPDE’s operations. Manages the finances, staff and logistics that sustain our programs and tournaments.',
    bio: 'Holds a degree in Pedagogy and is pursuing a master’s in Education at Tecnológico de Monterrey. Debate coach at St. George’s and teacher of Debate and Entrepreneurship at Colegio Salcantay. He also teaches at ESAN University (Extended Learning).',
    cvLabel: 'View LinkedIn',
  },
  'Sofía Pacheco': {
    role: 'Partnerships Director',
    short: 'Leads the LPDE’s institutional partnerships. Builds relationships with schools, universities, and public and private organizations.',
    bio: 'Lawyer from ESAN University and legal analyst at OEFA. Manager of school debate education projects. Served as Team Manager of the national team that won the 2024 and 2025 MED titles.',
  },
  'Nataly Vásquez Cabellos': {
    role: 'SNDE Coordinator',
    short: 'Coordinates the SNDE development team (students in grades 6 to 8).',
    bio: 'Psychologist from Universidad Peruana Cayetano Heredia, with experience in community social work. Holds graduate diplomas in Sexuality, Human Rights and Health, and in Education Policy (UPCH, 2025) and in University Teaching (UPCH, 2026). Works on the planning and delivery of educational projects in human rights, gender equality and climate change. Directs the Cayetano Heredia Debate Society — national runner-up in debate and national champion in speech — and is a co-founder of the consultancy SAMI: Salud Mental Integrada.',
    cvLabel: 'View LinkedIn',
  },
  'Mauricio Jarufe Caballero': {
    role: 'SNDE Coordinator',
    short: 'Coordinates the SNDE team (students in grades 9 to 11).',
    bio: 'Anthropologist from PUCP and film critic. Teaches debate at Colegio Alpamayo and Markham College. Three-time world champion in Spanish-language debate and best EFL speaker at the English-language world championship. Coach of Team Peru at WSDC and of the top-ranked team at the 2025 MED.',
  },
  'Luis Valverde': {
    role: 'Research Team',
    short: 'Leads research at the League. Produces diagnostics and data visualizations on the school debate circuit.',
    bio: 'Holds a degree in Political Science and Government from PUCP. Researcher at GIES PUCP with experience in academic research centers and consulting for public and private organizations. His research focuses on electoral behavior, institutional performance and education policy related to debate.',
  },
};

/* Etiquetas EN de los grupos de filtro (la lógica sigue usando las claves en español) */
const TEAM_GROUPS_EN = {
  'Todos': 'All',
  'Dirección': 'Leadership',
  'Académico': 'Academic',
  'Operaciones': 'Operations',
  'Comunicaciones': 'Communications',
};

const EquipoPage = () => {
  const D = window.LPDE_DATA;
  const { t, lang } = useLang();
  const [selected, setSelected] = React.useState(null);
  const [filter, setFilter] = React.useState('Todos');
  const localize = (m) => (lang === 'en' && TEAM_EN[m.name]) ? { ...m, ...TEAM_EN[m.name] } : m;
  const groupFor = (role) => {
    if (role.includes('Director') || role.includes('Dir.')) return 'Dirección';
    if (role.includes('Académic') || role.includes('Coach') || role.includes('Educación') || role.includes('Jueces')) return 'Académico';
    if (role.includes('Coordinador') || role.includes('Torneos') || role.includes('Regional')) return 'Operaciones';
    if (role.includes('Comunic')) return 'Comunicaciones';
    return 'Académico';
  };
  // Solo mostramos filtros con al menos un miembro (evita pestañas vacías con tarjetas "Por anunciar")
  const groups = ['Todos', ...['Dirección', 'Académico', 'Operaciones', 'Comunicaciones'].filter((g) => D.team.some((m) => groupFor(m.role) === g))];
  const visible = filter === 'Todos' ? D.team : D.team.filter((m) => groupFor(m.role) === filter);

  return (
    <Page screen="02 Equipo">
      {/* Hero */}
      <section style={{ paddingTop: 80, paddingBottom: 64, borderBottom: '1px solid var(--line)' }}>
        <div className="shell">
          <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 64, alignItems: 'end' }}>
            <div className="reveal">
              <span className="eyebrow">{t('Conoce al equipo', 'Meet the team')}</span>
              <h1 className="display" style={{ fontSize: 'clamp(56px, 8vw, 120px)', marginTop: 20, maxWidth: '14ch' }}>
                {t('Las personas detrás de la ', 'The people behind the ')}<em className="it">{t('liga', 'League')}</em>
              </h1>
            </div>
            <p className="reveal d1" style={{ fontSize: 17, color: 'var(--ink-2)', lineHeight: 1.6 }}>
              {t('Profesionales —debatientes, profesores, abogados, politólogos, filósofos, comunicadores— sostienen la operación diaria de la LPDE. Haz clic en cualquier nombre para ver bio, CV y datos de contacto.', 'Professionals — debaters, teachers, lawyers, political scientists, philosophers, communicators — keep the LPDE running every day. Click on any name to see their bio, CV and contact details.')}
            </p>
          </div>
        </div>
      </section>

      {/* Filters */}
      <section style={{ padding: '32px 0', borderBottom: '1px solid var(--line)', position: 'sticky', top: 'var(--nav-h)', background: 'rgba(255,255,255,0.9)', backdropFilter: 'blur(8px)', zIndex: 50 }}>
        <div className="shell" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 16 }}>
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
            {groups.map((g) =>
            <button key={g} onClick={() => setFilter(g)} style={{
              padding: '8px 16px', borderRadius: 999,
              background: filter === g ? 'var(--ink)' : 'transparent',
              color: filter === g ? '#fff' : 'var(--ink-soft)',
              border: '1px solid ' + (filter === g ? 'var(--ink)' : 'var(--line)'),
              fontSize: 13, fontWeight: 600, fontFamily: 'var(--sans)',
              transition: 'all 180ms'
            }}>{lang === 'en' ? (TEAM_GROUPS_EN[g] || g) : g}</button>
            )}
          </div>
          <div className="kicker">{visible.length}{t(' miembros', ' members')}</div>
        </div>
      </section>

      {/* Grid */}
      <section className="section" style={{ paddingTop: 64 }}>
        <div className="shell">
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 32 }}>
            {visible.map((m, i) =>
            <TeamCard key={m.name} member={localize(m)} onClick={() => setSelected(m)} idx={i} />
            )}
            {visible.length < 4 && Array.from({ length: 4 - visible.length }).map((_, i) => (
              <div key={`tba-${i}`} className={`reveal d${(visible.length + i) % 4 + 1}`} style={{ position: 'relative' }}>
                <div style={{ aspectRatio: '3/4', overflow: 'hidden', background: 'var(--bg-alt)', border: '1px dashed var(--line-strong)', position: 'relative', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                  <span style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 64, color: 'var(--line-strong)' }}>?</span>
                </div>
                <div style={{ paddingTop: 20 }}>
                  <div className="kicker" style={{ color: 'var(--mute)', marginBottom: 6 }}>{t('Por anunciar', 'To be announced')}</div>
                  <h3 className="display" style={{ fontSize: 26, lineHeight: 1.1, color: 'var(--mute)', fontStyle: 'italic' }}>TBA</h3>
                  <p style={{ fontSize: 14, color: 'var(--mute)', marginTop: 10, lineHeight: 1.5, fontStyle: 'italic' }}>{t('Iremos publicando al resto del equipo en las próximas semanas.', 'We’ll be introducing the rest of the team in the coming weeks.')}</p>
                </div>
              </div>
            ))}
          </div>
        </div>
      </section>

      <TeamModal member={selected && localize(selected)} onClose={() => setSelected(null)} />
    </Page>);

};

const TeamCard = ({ member, onClick, idx }) =>
<div className={`reveal d${idx % 4 + 1}`} onClick={onClick} style={{ cursor: 'pointer', position: 'relative' }}
onMouseEnter={(e) => {
  e.currentTarget.querySelector('.tc-img').style.transform = 'scale(1.04)';
  e.currentTarget.querySelector('.tc-arrow').style.transform = 'translate(4px, -4px)';
}}
onMouseLeave={(e) => {
  e.currentTarget.querySelector('.tc-img').style.transform = 'scale(1)';
  e.currentTarget.querySelector('.tc-arrow').style.transform = 'translate(0, 0)';
}}>
  
    <div style={{ aspectRatio: '3/4', overflow: 'hidden', background: 'var(--bg-alt)', position: 'relative' }}>
      <img className="tc-img" src={member.img} alt={member.name}
    style={{ width: '100%', height: '100%', objectFit: 'cover', transition: 'transform 600ms ease', filter: 'contrast(1.04) saturate(0.85) sepia(0.22) brightness(1.03)' }} />
    
      <div className="tc-arrow" style={{ position: 'absolute', top: 16, right: 16, width: 36, height: 36, borderRadius: 999, background: 'rgba(255,255,255,0.92)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--ink)', transition: 'transform 280ms ease' }}>
        <Icon name="arrow-up-right" size={16} />
      </div>
    </div>
    <div style={{ paddingTop: 20 }}>
      <div className="kicker" style={{ color: 'var(--red)', marginBottom: 6 }}>{member.role}</div>
      <h3 className="display" style={{ fontSize: 26, lineHeight: 1.1 }}>{member.name}</h3>
      <p style={{ fontSize: 14, color: 'var(--ink-2)', marginTop: 10, lineHeight: 1.5 }}>{member.short}</p>
    </div>
  </div>;


const TeamModal = ({ member, onClose }) => {
  const { t } = useLang();
  if (!member) return null;
  return (
    <Modal open={!!member} onClose={onClose}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1.2fr', minHeight: 480 }}>
        <div style={{ position: 'relative', background: 'var(--ink)' }}>
          <img src={member.img} alt={member.name} style={{ width: '100%', height: '100%', objectFit: 'cover', filter: 'contrast(1.04) saturate(0.85) sepia(0.22) brightness(1.03)' }} />
          <button onClick={onClose} style={{ position: 'absolute', top: 16, left: 16, width: 36, height: 36, borderRadius: 999, background: 'rgba(255,255,255,0.92)', border: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <Icon name="close" size={16} />
          </button>
        </div>
        <div style={{ padding: 48, display: 'flex', flexDirection: 'column' }}>
          <div className="kicker" style={{ color: 'var(--red)', marginBottom: 12 }}>{member.role}</div>
          <h2 className="display" style={{ fontSize: 44, lineHeight: 1.05, marginBottom: 24 }}>{member.name}</h2>
          <div className="rule-red" style={{ marginBottom: 24 }} />
          <p style={{ fontSize: 16, lineHeight: 1.65, color: 'var(--ink-soft)', marginBottom: 32 }}>{member.bio}</p>

          <div style={{ borderTop: '1px solid var(--line)', paddingTop: 24, marginTop: 'auto' }}>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 24 }}>
              {member.email && (
                <div>
                  <div className="kicker" style={{ marginBottom: 6 }}>{t('Correo', 'Email')}</div>
                  <a href={`mailto:${member.email}`} style={{ fontSize: 15, color: 'var(--ink)', borderBottom: '1px solid var(--ink)', paddingBottom: 1 }}>{member.email}</a>
                </div>
              )}
              {member.cv && member.cv !== '#' && (
                <div>
                  <div className="kicker" style={{ marginBottom: 6 }}>{member.cvLabel ? t('Perfil', 'Profile') : t('Documentos', 'Documents')}</div>
                  <a href={member.cv} target="_blank" rel="noopener" className="btn btn-link" style={{ display: 'inline-flex', gap: 8, alignItems: 'center' }}>
                    {member.cvLabel || t('Descargar CV', 'Download CV')} <Icon name={member.cvLabel ? 'arrow-up-right' : 'download'} size={14} />
                  </a>
                </div>
              )}
            </div>
          </div>
        </div>
      </div>
    </Modal>);

};

/* ═══════════════════════════════════════════════════════════
   NOTICIAS
   ═══════════════════════════════════════════════════════════ */
/* ── Noticias: almacenamiento (localStorage) + utilidades ───
   El sitio es estático: la semilla pública vive en data.js y el admin
   trabaja sobre una copia en localStorage (por navegador). "Exportar JSON"
   permite publicar luego ese contenido para todos. */
const NEWS_LS_KEY = 'lpde_news_v1';
const NEWS_ADMIN_KEY = 'lpde_news_admin';
const NEWS_ADMIN_PASS = 'lpde2026';

function loadNews() {
  try {
    const raw = localStorage.getItem(NEWS_LS_KEY);
    if (raw) { const arr = JSON.parse(raw); if (Array.isArray(arr) && arr.length) return arr; }
  } catch (e) {}
  return (window.LPDE_DATA && window.LPDE_DATA.news) || [];
}
function saveNews(list) {
  try { localStorage.setItem(NEWS_LS_KEY, JSON.stringify(list)); }
  catch (e) { window.alert('No se pudo guardar en este navegador (probable límite por imágenes muy pesadas). Usa imágenes más livianas o exporta el JSON.'); }
}
function newsUid() { return 'n' + Date.now().toString(36) + Math.random().toString(36).slice(2, 6); }

const newsCtlBtn = { padding: '5px 11px', borderRadius: 999, background: 'rgba(255,255,255,0.96)', border: '1px solid var(--line)', fontSize: 11, fontWeight: 700, fontFamily: 'var(--sans)', cursor: 'pointer', boxShadow: '0 2px 8px rgba(0,0,0,0.12)', color: 'var(--ink)' };

const NewsAdminControls = ({ onEdit, onDelete }) =>
  <div style={{ position: 'absolute', top: 10, right: 10, zIndex: 5, display: 'flex', gap: 6 }}>
    <button onClick={onEdit} style={newsCtlBtn}>Editar</button>
    <button onClick={onDelete} style={{ ...newsCtlBtn, color: 'var(--red)' }}>Borrar</button>
  </div>;

/* ── Crédito de autoría: "Equipo X — Nombre · Nombre" (o solo nombres) ── */
const newsByline = (news) => {
  const names = Array.isArray(news.authors) ? news.authors.filter(Boolean) : [];
  if (!names.length && !news.authorGroup) return null;
  return { group: news.authorGroup || '', names };
};

const NewsByline = ({ news, variant = 'inline' }) => {
  const b = newsByline(news);
  if (!b) return null;
  const namesStr = b.names.join(' · ');
  if (variant === 'mini') {
    return (
      <div style={{ fontSize: 12, color: 'var(--mute)', fontFamily: 'var(--mono)', letterSpacing: '0.02em', marginTop: 8 }}>
        {b.group ? <span>{b.group}{namesStr ? ' · ' : ''}</span> : null}
        {namesStr}
      </div>
    );
  }
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 4, padding: '14px 0', borderTop: '1px solid var(--line)', borderBottom: '1px solid var(--line)', margin: '20px 0 28px' }}>
      {b.group && <div className="kicker" style={{ color: 'var(--red)' }}>{b.group}</div>}
      {namesStr && <div style={{ fontFamily: 'var(--serif)', fontSize: 18, color: 'var(--ink)' }}>{namesStr}</div>}
    </div>
  );
};

/* ── Render de un bloque de cuerpo (vista de lectura) ── */
const NewsBlock = ({ b }) => {
  if (!b) return null;
  if (b.t === 'h') return <h3 className="display" style={{ fontSize: 26, lineHeight: 1.15, margin: '36px 0 14px' }}>{b.text}</h3>;
  if (b.t === 'p') return <p style={{ fontSize: 17, lineHeight: 1.7, color: 'var(--ink-soft)', margin: '0 0 18px' }}>{b.text}</p>;
  if (b.t === 'stat') return (
    <div style={{ border: '1px solid var(--line)', borderLeft: '3px solid var(--red)', background: 'var(--bg-alt)', padding: '16px 20px', margin: '0 0 16px' }}>
      <div style={{ fontFamily: 'var(--serif)', fontSize: 34, lineHeight: 1, color: 'var(--red)' }}>{b.value}</div>
      <div style={{ fontSize: 13, color: 'var(--ink-2)', marginTop: 6 }}>{b.label}</div>
    </div>
  );
  if (b.t === 'list') return (
    <ul style={{ margin: '0 0 18px', padding: 0, listStyle: 'none', display: 'flex', flexDirection: 'column', gap: 12 }}>
      {(b.items || []).map((it, i) =>
        <li key={i} style={{ display: 'flex', gap: 12, fontSize: 16, lineHeight: 1.6, color: 'var(--ink-soft)' }}>
          <span style={{ color: 'var(--red)', flexShrink: 0, marginTop: 3 }}><Icon name="arrow" size={15} /></span>{it}
        </li>
      )}
    </ul>
  );
  if (b.t === 'img') return (
    <figure style={{ margin: '0 0 24px' }}>
      <img src={b.src} alt={b.caption || ''} style={{ width: '100%', borderRadius: 4, border: '1px solid var(--line)', display: 'block' }} />
      {b.caption && <figcaption style={{ fontSize: 12, color: 'var(--mute)', marginTop: 8, fontFamily: 'var(--mono)', letterSpacing: '0.02em', lineHeight: 1.5 }}>{b.caption}</figcaption>}
    </figure>
  );
  return null;
};

/* ── Lector de noticia (vista de visitante) ── */
const NewsReader = ({ news, onClose }) => {
  const { t } = useLang();
  if (!news) return null;
  return (
    <Modal open={!!news} onClose={onClose}>
      <div style={{ position: 'relative' }}>
        <button onClick={onClose} aria-label={t('Cerrar', 'Close')} style={{ position: 'absolute', top: 16, right: 16, zIndex: 3, width: 38, height: 38, borderRadius: 999, background: 'rgba(255,255,255,0.92)', border: '1px solid var(--line)', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}><Icon name="close" size={16} /></button>
        {news.cover &&
          <div style={{ aspectRatio: '16/9', overflow: 'hidden', background: 'var(--bg-alt)' }}>
            <img src={news.cover} alt={news.title} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
          </div>}
        <div style={{ padding: 'clamp(24px, 4vw, 48px)' }}>
          <div style={{ display: 'flex', gap: 12, alignItems: 'center', marginBottom: 16 }}>
            <span className="tag red">{news.tag}</span>
            <span className="kicker">{news.date}</span>
          </div>
          <h2 className="display" style={{ fontSize: 'clamp(30px, 4vw, 48px)', lineHeight: 1.05, marginBottom: 16 }}>{news.title}</h2>
          {news.excerpt && <p style={{ fontSize: 19, lineHeight: 1.6, color: 'var(--ink-2)', marginBottom: 24, fontStyle: 'italic' }}>{news.excerpt}</p>}
          <NewsByline news={news} />
          {(news.body || []).map((b, i) => <NewsBlock key={i} b={b} />)}
          {(!news.body || news.body.length === 0) && <p style={{ color: 'var(--mute)' }}>{t('Esta noticia aún no tiene contenido.', 'This article has no content yet.')}</p>}
        </div>
      </div>
    </Modal>
  );
};

/* ── Editor de noticia (vista de administrador) ── */
const NewsEditor = ({ item, onSave, onClose }) => {
  const blank = { tag: 'NOTICIA', date: '', title: '', excerpt: '', cover: '', featured: false, authorGroup: '', authors: [], body: [] };
  const [d, setD] = React.useState(() => item ? JSON.parse(JSON.stringify(item)) : blank);
  const set = (k, v) => setD((s) => ({ ...s, [k]: v }));
  const readImage = (file, cb) => { if (!file) return; const r = new FileReader(); r.onload = () => cb(r.result); r.readAsDataURL(file); };
  const addBlock = (t) => {
    const base = t === 'stat' ? { t, value: '', label: '' } : t === 'list' ? { t, items: [''] } : t === 'img' ? { t, src: '', caption: '' } : { t, text: '' };
    setD((s) => ({ ...s, body: [...(s.body || []), base] }));
  };
  const updBlock = (i, patch) => setD((s) => ({ ...s, body: s.body.map((b, j) => j === i ? { ...b, ...patch } : b) }));
  const moveBlock = (i, dir) => setD((s) => { const a = [...s.body]; const j = i + dir; if (j < 0 || j >= a.length) return s; [a[i], a[j]] = [a[j], a[i]]; return { ...s, body: a }; });
  const delBlock = (i) => setD((s) => ({ ...s, body: s.body.filter((_, j) => j !== i) }));
  const submit = () => { if (!d.title.trim()) { window.alert('La noticia necesita un título.'); return; } onSave({ ...d, title: d.title.trim() }); };

  const lbl = { display: 'block', fontSize: 11, fontFamily: 'var(--mono)', letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--mute)', marginBottom: 6 };
  const iconBtn = { width: 36, height: 36, borderRadius: 999, background: 'var(--bg-alt)', border: '1px solid var(--line)', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' };
  const miniBtn = { width: 28, height: 28, borderRadius: 6, background: 'var(--bg-alt)', border: '1px solid var(--line)', cursor: 'pointer', fontSize: 13, lineHeight: 1, color: 'var(--ink-soft)' };
  const blockLabels = { h: 'Subtítulo', p: 'Párrafo', stat: 'Dato', list: 'Lista', img: 'Imagen' };

  return (
    <Modal open onClose={onClose}>
      <div style={{ padding: 'clamp(20px, 3vw, 36px)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 24 }}>
          <h2 className="display" style={{ fontSize: 30 }}>{item ? 'Editar noticia' : 'Nueva noticia'}</h2>
          <button onClick={onClose} aria-label="Cerrar" style={iconBtn}><Icon name="close" size={16} /></button>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, marginBottom: 16 }}>
          <div><label style={lbl}>Etiqueta</label><input className="input" value={d.tag} onChange={(e) => set('tag', e.target.value)} placeholder="INVESTIGACIÓN" /></div>
          <div><label style={lbl}>Fecha</label><input className="input" value={d.date} onChange={(e) => set('date', e.target.value)} placeholder="FEB 2025" /></div>
        </div>
        <div style={{ marginBottom: 16 }}><label style={lbl}>Título</label><input className="input" value={d.title} onChange={(e) => set('title', e.target.value)} placeholder="Título de la noticia" /></div>
        <div style={{ marginBottom: 16 }}><label style={lbl}>Extracto</label><textarea className="input" rows={3} style={{ borderRadius: 16, resize: 'vertical' }} value={d.excerpt} onChange={(e) => set('excerpt', e.target.value)} placeholder="Resumen breve que se ve en la tarjeta" /></div>

        <div style={{ marginBottom: 20 }}>
          <label style={lbl}>Imagen de portada</label>
          <div style={{ display: 'flex', gap: 16, alignItems: 'center' }}>
            <div style={{ width: 120, height: 80, background: 'var(--bg-alt)', border: '1px solid var(--line)', overflow: 'hidden', flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--mute)' }}>
              {d.cover ? <img src={d.cover} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} /> : <span style={{ fontSize: 11 }}>Sin foto</span>}
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8, alignItems: 'flex-start' }}>
              <input type="file" accept="image/*" onChange={(e) => readImage(e.target.files[0], (data) => set('cover', data))} style={{ fontSize: 13 }} />
              {d.cover && <button className="btn btn-link" style={{ fontSize: 13 }} onClick={() => set('cover', '')}>Quitar portada</button>}
            </div>
          </div>
        </div>

        <label style={{ display: 'flex', gap: 10, alignItems: 'center', marginBottom: 24, fontSize: 14, cursor: 'pointer' }}>
          <input type="checkbox" checked={!!d.featured} onChange={(e) => set('featured', e.target.checked)} style={{ accentColor: 'var(--red)' }} />
          Destacar (aparece grande arriba)
        </label>

        <div style={{ borderTop: '1px solid var(--line)', paddingTop: 20, marginBottom: 24 }}>
          <h3 style={{ fontFamily: 'var(--serif)', fontSize: 22, marginBottom: 16 }}>Autoría</h3>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr', gap: 14 }}>
            <div>
              <label style={lbl}>Equipo o área (opcional)</label>
              <input className="input" value={d.authorGroup || ''} onChange={(e) => set('authorGroup', e.target.value)} placeholder="Equipo de Investigación de la LPDE" />
            </div>
            <div>
              <label style={lbl}>Autor(es) · uno por línea</label>
              <textarea className="input" rows={3} style={{ borderRadius: 12, resize: 'vertical' }}
                value={(d.authors || []).join('\n')}
                onChange={(e) => set('authors', e.target.value.split('\n').map((s) => s.trim()).filter((s) => s !== ''))}
                placeholder={'Luis Valverde\nHideki Harada'} />
              <div style={{ fontSize: 11, color: 'var(--mute)', marginTop: 4 }}>Se mostrarán separados por "·" debajo del título.</div>
            </div>
          </div>
        </div>

        <div style={{ borderTop: '1px solid var(--line)', paddingTop: 20 }}>
          <h3 style={{ fontFamily: 'var(--serif)', fontSize: 22, marginBottom: 16 }}>Contenido</h3>
          {(d.body || []).map((b, i) =>
            <div key={i} style={{ border: '1px solid var(--line)', borderRadius: 6, padding: 14, marginBottom: 12, background: 'var(--bg)' }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
                <span className="kicker">{blockLabels[b.t] || b.t}</span>
                <div style={{ display: 'flex', gap: 6 }}>
                  <button onClick={() => moveBlock(i, -1)} style={miniBtn} title="Subir">↑</button>
                  <button onClick={() => moveBlock(i, 1)} style={miniBtn} title="Bajar">↓</button>
                  <button onClick={() => delBlock(i)} style={{ ...miniBtn, color: 'var(--red)' }} title="Eliminar">✕</button>
                </div>
              </div>
              {(b.t === 'h' || b.t === 'p') &&
                <textarea className="input" rows={b.t === 'h' ? 2 : 4} style={{ borderRadius: 12, resize: 'vertical' }} value={b.text || ''} onChange={(e) => updBlock(i, { text: e.target.value })} placeholder={b.t === 'h' ? 'Subtítulo' : 'Escribe el párrafo...'} />}
              {b.t === 'stat' &&
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 2fr', gap: 10 }}>
                  <input className="input" value={b.value || ''} onChange={(e) => updBlock(i, { value: e.target.value })} placeholder="408 pts" />
                  <input className="input" value={b.label || ''} onChange={(e) => updBlock(i, { label: e.target.value })} placeholder="Descripción del dato" />
                </div>}
              {b.t === 'list' &&
                <textarea className="input" rows={4} style={{ borderRadius: 12, resize: 'vertical' }} value={(b.items || []).join('\n')} onChange={(e) => updBlock(i, { items: e.target.value.split('\n').filter((x) => x.trim() !== '') })} placeholder="Un punto por línea" />}
              {b.t === 'img' &&
                <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
                  {b.src && <img src={b.src} alt="" style={{ maxHeight: 160, width: 'auto', alignSelf: 'flex-start', border: '1px solid var(--line)' }} />}
                  <input type="file" accept="image/*" onChange={(e) => readImage(e.target.files[0], (data) => updBlock(i, { src: data }))} style={{ fontSize: 13 }} />
                  <input className="input" value={b.caption || ''} onChange={(e) => updBlock(i, { caption: e.target.value })} placeholder="Pie de imagen (opcional)" />
                </div>}
            </div>
          )}
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginTop: 8 }}>
            {[['p', '+ Párrafo'], ['h', '+ Subtítulo'], ['stat', '+ Dato'], ['list', '+ Lista'], ['img', '+ Imagen']].map(([t, l]) =>
              <button key={t} onClick={() => addBlock(t)} className="btn btn-ghost" style={{ padding: '8px 14px', fontSize: 13 }}>{l}</button>
            )}
          </div>
        </div>

        <div style={{ display: 'flex', gap: 12, justifyContent: 'flex-end', marginTop: 28, borderTop: '1px solid var(--line)', paddingTop: 20 }}>
          <button className="btn btn-ghost" onClick={onClose}>Cancelar</button>
          <button className="btn btn-red" onClick={submit}>Guardar noticia <Icon name="check" size={14} /></button>
        </div>
      </div>
    </Modal>
  );
};

/* ─── Newsletter: form conectado al Web App de Apps Script ───
   Reusa el mismo endpoint de consultas (rama tipo:'newsletter',
   guarda en la pestaña "Newsletter" del Sheet de consultas). */
const NEWSLETTER_WEBAPP_URL = 'https://script.google.com/macros/s/AKfycbxSrnPxbP_8F6MYfG_MDlhD34ayGQUxZOYYC809p-PX4bu-k4r6LGaNNnvijPVOJOUk/exec';

const NewsletterForm = () => {
  const { t } = useLang();
  const [correo, setCorreo] = React.useState('');
  const [status, setStatus] = React.useState(null); // {kind:'sending'|'ok'|'error', msg}
  const sending = status && status.kind === 'sending';

  const submit = async (e) => {
    e.preventDefault();
    if (sending) return;
    const c = correo.trim();
    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(c)) {
      setStatus({ kind: 'error', msg: t('Escribe un correo válido.', 'Please enter a valid email.') });
      return;
    }
    setStatus({ kind: 'sending', msg: t('Suscribiendo…', 'Subscribing…') });
    try {
      // text/plain evita el preflight CORS (mismo truco que el form de Admisión)
      const r = await fetch(NEWSLETTER_WEBAPP_URL, {
        method: 'POST',
        headers: { 'Content-Type': 'text/plain;charset=utf-8' },
        body: JSON.stringify({ tipo: 'newsletter', correo: c, fuente: 'noticias', ua: navigator.userAgent }),
      });
      const data = await r.json().catch(() => ({ ok: false }));
      if (!data.ok) throw new Error(data.error || 'server_error');
      setCorreo('');
      setStatus({ kind: 'ok', msg: data.duplicate ? t('Ese correo ya estaba suscrito. Todo en orden.', 'That email is already subscribed. You’re all set.') : t('¡Listo! Te llegará el próximo número.', 'Done! The next issue is on its way.') });
    } catch (err) {
      setStatus({ kind: 'error', msg: t('No se pudo completar la suscripción. Escríbenos a contacto@lpdebate.org y te agregamos.', 'We couldn’t complete your subscription. Email us at contacto@lpdebate.org and we’ll add you.') });
    }
  };

  return (
    <form onSubmit={submit}>
      <div className="kicker" style={{ marginBottom: 12 }}>{t('Tu correo', 'Your email')}</div>
      <div style={{ display: 'flex', gap: 8 }}>
        <input
          className="input"
          type="email"
          value={correo}
          onChange={(e) => { setCorreo(e.target.value); if (status && status.kind !== 'sending') setStatus(null); }}
          placeholder={t('nombre@colegio.edu.pe', 'name@school.edu')}
          disabled={sending}
          style={{ background: '#15151A', borderColor: '#2A2A30', color: '#fff', flex: 1 }}
        />
        <button type="submit" className="btn btn-red" disabled={sending} style={sending ? { opacity: 0.6, cursor: 'wait' } : undefined}>
          {sending ? t('Enviando…', 'Sending…') : <>{t('Suscribirme', 'Subscribe')} <Icon name="arrow" /></>}
        </button>
      </div>
      {status && status.kind !== 'sending' &&
        <p style={{ fontSize: 13, marginTop: 14, fontWeight: 600, color: status.kind === 'ok' ? '#7DD87D' : '#FF8A8A' }}>{status.msg}</p>}
      <p style={{ fontSize: 12, color: '#9C9AA0', marginTop: status ? 8 : 14 }}>{t('Al suscribirte aceptas nuestra política de privacidad. Puedes darte de baja cuando quieras.', 'By subscribing you accept our privacy policy. You can unsubscribe at any time.')}</p>
    </form>
  );
};

const NoticiasPage = () => {
  const D = window.LPDE_DATA;
  const { t } = useLang();
  const [news] = React.useState(loadNews);
  const [filter, setFilter] = React.useState('Todos');
  const [query, setQuery] = React.useState('');
  // Deep link a una nota: ?page=noticias&nota=<id> abre el lector al llegar
  const [reading, setReadingState] = React.useState(() => {
    try {
      const id = new URLSearchParams(window.location.search).get('nota');
      if (id) return news.find((n) => String(n.id) === id) || null;
    } catch (e) {}
    return null;
  });
  // Mantiene &nota= en la URL mientras el lector está abierto (link copiable)
  const setReading = (n) => {
    setReadingState(n);
    try {
      const url = new URL(window.location);
      if (n && n.id) url.searchParams.set('nota', n.id);
      else url.searchParams.delete('nota');
      window.history.replaceState(window.history.state, '', url);
    } catch (e) {}
  };

  const types = ['Todos', ...Array.from(new Set(news.map((n) => n.tag).filter(Boolean)))];
  const visible = news.filter((n) =>
    (filter === 'Todos' || n.tag === filter) &&
    (query.trim() === '' || ((n.title || '') + ' ' + (n.excerpt || '')).toLowerCase().includes(query.trim().toLowerCase()))
  );
  const ordered = visible.slice().sort((a, b) => (b.featured === true) - (a.featured === true));
  const [featured, ...rest] = ordered;

  return (
    <Page screen="03 Noticias">
      {/* Header */}
      <section style={{ paddingTop: 64, paddingBottom: 48, borderBottom: '1px solid var(--line)' }}>
        <div className="shell">
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'end', flexWrap: 'wrap', gap: 32 }}>
            <div className="reveal">
              <span className="eyebrow">{t('Noticias & Publicaciones', 'News & Publications')}</span>
              <h1 className="display" style={{ fontSize: 'clamp(48px, 7vw, 100px)', marginTop: 20 }}>
                {t('Lo que ', 'What’s ')}<em className="it">{t('pasa', 'happening')}</em>{t(' en la Liga', ' at the League')}
              </h1>
            </div>
            <div className="reveal d1" style={{ display: 'flex', alignItems: 'center', gap: 12, background: 'var(--bg-alt)', padding: '8px 8px 8px 18px', borderRadius: 999, border: '1px solid var(--line)' }}>
              <Icon name="search" size={16} />
              <input className="input" placeholder={t('Buscar...', 'Search…')} value={query} onChange={(e) => setQuery(e.target.value)} style={{ border: 'none', background: 'transparent', padding: '6px 0', width: 240 }} />
            </div>
          </div>
        </div>
      </section>

      {/* Filters */}
      <section style={{ padding: '24px 0', borderBottom: '1px solid var(--line)' }}>
        <div className="shell" style={{ display: 'flex', gap: 4, flexWrap: 'wrap' }}>
          {types.map((tg) =>
          <button key={tg} onClick={() => setFilter(tg)} style={{
            padding: '8px 16px', borderRadius: 999,
            background: filter === tg ? 'var(--red)' : 'transparent',
            color: filter === tg ? '#fff' : 'var(--ink-soft)',
            border: '1px solid ' + (filter === tg ? 'var(--red)' : 'transparent'),
            fontSize: 13, fontWeight: 500, fontFamily: 'var(--sans)', transition: 'all 180ms'
          }}>{tg === 'Todos' ? t('Todos', 'All') : tg}</button>
          )}
        </div>
      </section>

      {/* Editorial grid */}
      {ordered.length === 0
        ? <section className="section"><div className="shell" style={{ textAlign: 'center', padding: '40px 0' }}>
            <p style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 22, color: 'var(--mute)' }}>
              {query ? t('No hay noticias para tu búsqueda.', 'No news matches your search.') : t('Aún no hay noticias publicadas.', 'No news published yet.')}
            </p>
          </div></section>
        : <section className="section">
          <div className="shell">
            {/* Featured */}
            {featured &&
            <article className="reveal" style={{ position: 'relative', display: 'grid', gridTemplateColumns: '1.3fr 1fr', gap: 56, marginBottom: 80, cursor: 'pointer' }} onClick={() => setReading(featured)}>
              <div style={{ aspectRatio: '4/3', overflow: 'hidden', background: 'var(--bg-alt)' }}>
                {featured.cover
                  ? <img src={featured.cover} alt={featured.title} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
                  : <div style={{ width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--line-strong)', fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 48 }}>LPDE</div>}
              </div>
              <div style={{ alignSelf: 'center' }}>
                <div style={{ display: 'flex', gap: 12, alignItems: 'center', marginBottom: 20 }}>
                  <span className="tag red">{featured.tag}</span>
                  <span className="kicker">{featured.date}</span>
                </div>
                <h2 className="display" style={{ fontSize: 'clamp(36px, 4vw, 56px)', lineHeight: 1.05 }}>{featured.title}</h2>
                <p style={{ fontSize: 18, color: 'var(--ink-soft)', lineHeight: 1.55, marginTop: 20 }}>{featured.excerpt}</p>
                <NewsByline news={featured} variant="mini" />
                <button className="btn btn-link" style={{ marginTop: 28 }} onClick={(e) => { e.stopPropagation(); setReading(featured); }}>{t('Leer la nota', 'Read the story')} <Icon name="arrow" size={14} /></button>
              </div>
            </article>}

            {/* Rest — mixed grid */}
            {rest.length > 0 &&
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)', gap: 32, gridAutoRows: 'minmax(200px, auto)' }}>
              {rest.map((n, i) =>
                <NewsCard key={n.id || i} news={n} idx={i} onOpen={setReading} />
              )}
            </div>}
          </div>
        </section>
      }

      <NewsReader news={reading} onClose={() => setReading(null)} />

      {/* Newsletter */}
      <section style={{ background: 'var(--ink)', color: '#fff', padding: '96px 0' }}>
        <div className="shell">
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 80, alignItems: 'center' }}>
            <div>
              <span className="eyebrow" style={{ color: 'var(--red)' }}>{t('Newsletter mensual', 'Monthly newsletter')}</span>
              <h2 className="display" style={{ color: '#fff', fontSize: 'clamp(40px, 5vw, 72px)', marginTop: 16 }}>
                {t('Suscríbete al ', 'Subscribe to the ')}<em className="it" style={{ color: 'var(--red)' }}>newsletter</em>.
              </h2>
              <p style={{ color: '#B8B8C0', fontSize: 17, lineHeight: 1.6, marginTop: 20 }}>
                {t('Una vez al mes: torneos, becas, mociones recomendadas y la columna del director. Sin spam, sin marketing.', 'Once a month: tournaments, scholarships, recommended motions and the director’s column. No spam, no marketing.')}
              </p>
            </div>
            <NewsletterForm />
          </div>
        </div>
      </section>

      {/* Publicaciones */}
      <section id="publicaciones" className="section" style={{ background: 'var(--bg-alt)', scrollMarginTop: 'var(--nav-h)' }}>
        <div className="shell">
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'end', marginBottom: 48, flexWrap: 'wrap', gap: 24 }} className="reveal">
            <div>
              <span className="eyebrow">{t('Publicaciones LPDE', 'LPDE Publications')}</span>
              <h2 className="display" style={{ fontSize: 'clamp(36px, 4.5vw, 56px)', marginTop: 16 }}>{t('Materiales gratuitos para profesores y debatientes.', 'Free materials for teachers and debaters.')}</h2>
              <p style={{ fontSize: 16, color: 'var(--ink-2)', lineHeight: 1.55, marginTop: 16, maxWidth: 640 }}>
                {t('Manuales, guías y nuestra revista ', 'Manuals, guides and our magazine ')}<em style={{ fontStyle: 'italic' }}>Dialógica</em>{t('. Acceso abierto — sin pago, sin registro.', '. Open access — no fees, no sign-up.')}
              </p>
            </div>
            <a href="https://lpdebate.org/lpde/publicaciones/" className="btn btn-ghost" target="_blank" rel="noopener">{t('Ver en lpdebate.org', 'View on lpdebate.org')} <Icon name="arrow-up-right" size={14} /></a>
          </div>

          {/* ─── Revista Dialógica ─── */}
          <div className="reveal" style={{ marginBottom: 48 }}>
            <div style={{ display: 'flex', alignItems: 'baseline', gap: 16, marginBottom: 20 }}>
              <h3 className="display" style={{ fontSize: 28 }}>{t('Revista ', '')}<em className="it">Dialógica</em>{t('', ' magazine')}</h3>
              <span className="kicker" style={{ color: 'var(--mute)' }}>{(D.publications.dialogica || []).length}{t(' ediciones', ' issues')}</span>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: 16 }}>
              {(D.publications.dialogica || []).map((p, i) => (
                <a key={i} href={p.url} target="_blank" rel="noopener"
                  className={`reveal d${i % 4 + 1}`}
                  style={{ background: 'var(--bg)', border: '1px solid var(--line)', padding: '24px 22px', textDecoration: 'none', color: 'var(--ink)', display: 'flex', flexDirection: 'column', gap: 12, transition: 'all 220ms ease', minHeight: 180 }}
                  onMouseEnter={(e) => { e.currentTarget.style.transform = 'translateY(-3px)'; e.currentTarget.style.boxShadow = '0 12px 32px rgba(0,0,0,0.06)'; e.currentTarget.style.borderColor = 'var(--red)'; }}
                  onMouseLeave={(e) => { e.currentTarget.style.transform = 'translateY(0)'; e.currentTarget.style.boxShadow = 'none'; e.currentTarget.style.borderColor = 'var(--line)'; }}
                >
                  <div style={{ fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.14em', color: 'var(--red)', fontWeight: 700 }}>{p.num}</div>
                  <div style={{ flex: 1 }}>
                    <div style={{ fontFamily: 'var(--serif)', fontSize: 22, lineHeight: 1.15, color: 'var(--ink)' }}>{p.title}</div>
                    <div style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 16, color: 'var(--ink-2)', marginTop: 6 }}>{p.edition}</div>
                  </div>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', paddingTop: 12, borderTop: '1px solid var(--line)' }}>
                    <span className="kicker">{t('Leer', 'Read')}{p.host ? t(` en ${p.host}`, ` on ${p.host}`) : ''}</span>
                    <Icon name="arrow-up-right" size={14} />
                  </div>
                </a>
              ))}
            </div>
          </div>

          {/* ─── Otras publicaciones ─── */}
          <div className="reveal d1">
            <div style={{ display: 'flex', alignItems: 'baseline', gap: 16, marginBottom: 20 }}>
              <h3 className="display" style={{ fontSize: 28 }}>{t('Otras publicaciones', 'Other publications')}</h3>
              <span className="kicker" style={{ color: 'var(--mute)' }}>{(D.publications.otras || []).length}{t(' materiales', ' resources')}</span>
            </div>
            <div style={{ background: 'var(--bg)', border: '1px solid var(--line)' }}>
              {(D.publications.otras || []).map((p, i) => (
                <a key={i} href={p.url} target="_blank" rel="noopener"
                  style={{ display: 'grid', gridTemplateColumns: '60px 1fr 130px 32px', alignItems: 'center', gap: 20, padding: '20px 28px', borderTop: i > 0 ? '1px solid var(--line)' : 'none', textDecoration: 'none', color: 'var(--ink)', transition: 'background 200ms' }}
                  onMouseEnter={(e) => { e.currentTarget.style.background = 'var(--bg-alt)'; }}
                  onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }}
                >
                  <div style={{ fontFamily: 'var(--mono)', fontSize: 12, color: 'var(--mute)' }}>{p.num}</div>
                  <h4 style={{ fontFamily: 'var(--serif)', fontSize: 19, fontWeight: 400, color: 'var(--ink)', lineHeight: 1.3 }}>{p.title}</h4>
                  <div className="kicker" style={{ color: 'var(--ink-2)' }}>{p.type}</div>
                  <div style={{ textAlign: 'right', color: 'var(--mute)' }}><Icon name="arrow-up-right" size={16} /></div>
                </a>
              ))}
            </div>
          </div>
        </div>
      </section>
    </Page>);

};

const NewsCard = ({ news, idx, onOpen }) => {
  const { t } = useLang();
  // varied sizes for editorial feel
  const layouts = [
  { cols: 'span 3', big: true },
  { cols: 'span 3', big: false },
  { cols: 'span 2', big: false },
  { cols: 'span 2', big: false },
  { cols: 'span 2', big: false }];

  const layout = layouts[idx % layouts.length];
  return (
    <article className={`reveal d${idx % 4 + 1}`} style={{ gridColumn: layout.cols, position: 'relative', cursor: 'pointer', display: 'flex', flexDirection: 'column' }}
      onClick={() => onOpen(news)}>

      {news.cover &&
      <div style={{ aspectRatio: layout.big ? '16/10' : '4/3', overflow: 'hidden', background: 'var(--bg-alt)', marginBottom: 20 }}>
          <img src={news.cover} alt={news.title} style={{ width: '100%', height: '100%', objectFit: 'cover', transition: 'transform 500ms ease' }}
        onMouseEnter={(e) => {e.currentTarget.style.transform = 'scale(1.03)';}}
        onMouseLeave={(e) => {e.currentTarget.style.transform = 'scale(1)';}} />
        </div>
      }
      <div style={{ display: 'flex', gap: 10, alignItems: 'center', marginBottom: 10 }}>
        <span className="tag">{news.tag}</span>
        <span className="kicker">{news.date}</span>
      </div>
      <h3 className="display" style={{ fontSize: layout.big ? 30 : 22, lineHeight: 1.1, marginBottom: 8 }}>{news.title}</h3>
      <p style={{ fontSize: 14, color: 'var(--ink-2)', lineHeight: 1.55 }}>{news.excerpt}</p>
      <NewsByline news={news} variant="mini" />
      <div className="kicker" style={{ marginTop: 12, color: 'var(--red)' }}>{t('Leer la nota →', 'Read the story →')}</div>
    </article>);

};

/* ═══════════════════════════════════════════════════════════
   NOTICIAS · ADMINISTRADOR (vista privada — CRUD + login)
   Ruta: ?admin=noticias  o  navegar a 'noticias-admin'
   ═══════════════════════════════════════════════════════════ */
const NewsAdminLogin = ({ onOk }) => {
  const [pass, setPass] = React.useState('');
  const [err, setErr] = React.useState(false);
  const submit = (e) => {
    e && e.preventDefault();
    if (pass === NEWS_ADMIN_PASS) {
      try { localStorage.setItem(NEWS_ADMIN_KEY, '1'); } catch (e) {}
      onOk();
    } else { setErr(true); }
  };
  return (
    <section style={{ minHeight: '70vh', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '64px 24px', background: 'var(--bg-alt)' }}>
      <form onSubmit={submit} style={{ width: '100%', maxWidth: 420, background: 'var(--bg)', border: '1px solid var(--line)', padding: 40 }}>
        <div className="kicker" style={{ color: 'var(--red)', marginBottom: 12 }}>Acceso restringido</div>
        <h1 className="display" style={{ fontSize: 32, lineHeight: 1.1, marginBottom: 8 }}>Administración de noticias</h1>
        <p style={{ fontSize: 14, color: 'var(--ink-2)', lineHeight: 1.55, marginBottom: 24 }}>
          Esta vista es solo para el equipo editorial de la LPDE. Ingresa la clave para gestionar las noticias del sitio.
        </p>
        <label style={{ display: 'block', fontSize: 11, fontFamily: 'var(--mono)', letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--mute)', marginBottom: 6 }}>Clave</label>
        <input
          className="input"
          type="password"
          value={pass}
          onChange={(e) => { setPass(e.target.value); setErr(false); }}
          autoFocus
          placeholder="••••••••"
          style={{ width: '100%', marginBottom: err ? 8 : 20 }}
        />
        {err && <div style={{ fontSize: 13, color: 'var(--red)', marginBottom: 12 }}>Clave incorrecta.</div>}
        <button type="submit" className="btn btn-red" style={{ width: '100%', justifyContent: 'center' }}>
          Entrar <Icon name="arrow" size={14} />
        </button>
      </form>
    </section>
  );
};

const NoticiasAdminPage = ({ setPage }) => {
  const D = window.LPDE_DATA;
  const [authed, setAuthed] = React.useState(() => { try { return localStorage.getItem(NEWS_ADMIN_KEY) === '1'; } catch (e) { return false; } });
  const [news, setNews] = React.useState(loadNews);
  const [editing, setEditing] = React.useState(null);
  const [preview, setPreview] = React.useState(null);

  const commit = (list) => { setNews(list); saveNews(list); };
  const exit = () => { try { localStorage.removeItem(NEWS_ADMIN_KEY); } catch (e) {} setAuthed(false); };
  const saveItem = (item) => {
    const exists = item.id && news.some((n) => n.id === item.id);
    const list = exists
      ? news.map((n) => n.id === item.id ? item : n)
      : [{ ...item, id: item.id || newsUid() }, ...news];
    commit(list); setEditing(null);
  };
  const deleteItem = (id) => { if (window.confirm('¿Eliminar esta noticia? No se puede deshacer.')) commit(news.filter((n) => n.id !== id)); };
  const resetSeed = () => {
    if (window.confirm('¿Restaurar las noticias publicadas y descartar los cambios locales de este navegador?')) {
      try { localStorage.removeItem(NEWS_LS_KEY); } catch (e) {}
      setNews(D.news);
    }
  };
  const exportJSON = () => {
    const blob = new Blob([JSON.stringify(news, null, 2)], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a'); a.href = url; a.download = 'noticias-lpde.json'; a.click();
    URL.revokeObjectURL(url);
  };

  if (!authed) {
    return <Page screen="03 Noticias · Admin"><NewsAdminLogin onOk={() => setAuthed(true)} /></Page>;
  }

  return (
    <Page screen="03 Noticias · Admin">
      {/* Barra superior */}
      <section style={{ background: 'var(--ink)', color: '#fff', borderBottom: '1px solid #2A2A30' }}>
        <div className="shell" style={{ display: 'flex', alignItems: 'center', gap: 16, padding: '20px 0', flexWrap: 'wrap' }}>
          <div>
            <div style={{ fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.18em', textTransform: 'uppercase', color: 'var(--red)' }}>Modo administrador</div>
            <h1 className="display" style={{ color: '#fff', fontSize: 26, lineHeight: 1.1, marginTop: 4 }}>Noticias · gestión editorial</h1>
          </div>
          <div style={{ flex: 1 }} />
          <button className="btn btn-red" style={{ padding: '10px 16px' }} onClick={() => setEditing({ _new: true })}>
            <Icon name="plus" size={14} /> Nueva noticia
          </button>
          <button className="btn btn-light" style={{ padding: '10px 16px' }} onClick={exportJSON}>Exportar JSON</button>
          <button className="btn btn-light" style={{ padding: '10px 16px' }} onClick={resetSeed}>Restaurar publicadas</button>
          <button className="btn btn-light" style={{ padding: '10px 16px' }} onClick={() => setPage && setPage('noticias')}>Ver sitio público</button>
          <button className="btn btn-light" style={{ padding: '10px 16px' }} onClick={exit}>Cerrar sesión</button>
        </div>
      </section>

      {/* Info de almacenamiento */}
      <section style={{ background: 'var(--bg-alt)', borderBottom: '1px solid var(--line)' }}>
        <div className="shell" style={{ padding: '14px 0', fontSize: 13, color: 'var(--ink-2)', display: 'flex', gap: 16, flexWrap: 'wrap', alignItems: 'center' }}>
          <span><strong style={{ color: 'var(--ink)' }}>{news.length}</strong> noticia{news.length !== 1 ? 's' : ''} en este navegador.</span>
          <span style={{ color: 'var(--mute)' }}>Los cambios se guardan en localStorage. Para publicarlos al sitio público, exporta el JSON y reemplaza la semilla en <code style={{ fontFamily: 'var(--mono)', fontSize: 12, background: 'var(--bg)', padding: '2px 6px', border: '1px solid var(--line)' }}>data.js</code>.</span>
        </div>
      </section>

      {/* Lista de noticias */}
      <section className="section">
        <div className="shell">
          {news.length === 0
            ? <div style={{ textAlign: 'center', padding: '64px 24px', border: '1px dashed var(--line-strong)', background: 'var(--bg)' }}>
                <p style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 22, color: 'var(--mute)', marginBottom: 20 }}>Aún no hay noticias.</p>
                <button className="btn btn-red" onClick={() => setEditing({ _new: true })}><Icon name="plus" size={14} /> Crear la primera</button>
              </div>
            : <div style={{ border: '1px solid var(--line)', background: 'var(--bg)' }}>
                {/* Header */}
                <div style={{ display: 'grid', gridTemplateColumns: '80px 1.6fr 1fr 110px 100px 220px', alignItems: 'center', gap: 16, padding: '12px 20px', borderBottom: '1px solid var(--line)', background: 'var(--bg-alt)', fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--mute)' }}>
                  <div>Portada</div>
                  <div>Título</div>
                  <div>Autoría</div>
                  <div>Fecha</div>
                  <div>Estado</div>
                  <div style={{ textAlign: 'right' }}>Acciones</div>
                </div>
                {news.map((n, i) => {
                  const by = newsByline(n);
                  return (
                    <div key={n.id || i} style={{ display: 'grid', gridTemplateColumns: '80px 1.6fr 1fr 110px 100px 220px', alignItems: 'center', gap: 16, padding: '16px 20px', borderBottom: i < news.length - 1 ? '1px solid var(--line)' : 'none' }}>
                      <div style={{ width: 64, height: 48, background: 'var(--bg-alt)', border: '1px solid var(--line)', overflow: 'hidden', flexShrink: 0 }}>
                        {n.cover
                          ? <img src={n.cover} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
                          : <div style={{ width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: 'var(--serif)', fontStyle: 'italic', color: 'var(--mute)', fontSize: 16 }}>—</div>}
                      </div>
                      <div>
                        <div style={{ display: 'inline-block', padding: '2px 8px', background: 'var(--bg-alt)', border: '1px solid var(--line)', fontSize: 10, fontFamily: 'var(--mono)', letterSpacing: '0.1em', color: 'var(--ink-2)', marginBottom: 6 }}>{n.tag || '—'}</div>
                        <div style={{ fontFamily: 'var(--serif)', fontSize: 18, lineHeight: 1.2, color: 'var(--ink)' }}>{n.title || <span style={{ color: 'var(--mute)', fontStyle: 'italic' }}>(sin título)</span>}</div>
                      </div>
                      <div style={{ fontSize: 13, color: 'var(--ink-2)', lineHeight: 1.4 }}>
                        {by
                          ? <>
                              {by.group && <div style={{ fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--red)' }}>{by.group}</div>}
                              {by.names.length > 0 && <div>{by.names.join(' · ')}</div>}
                            </>
                          : <span style={{ color: 'var(--mute)', fontStyle: 'italic' }}>Sin autor</span>}
                      </div>
                      <div style={{ fontFamily: 'var(--mono)', fontSize: 12, color: 'var(--ink-soft)' }}>{n.date || '—'}</div>
                      <div>
                        {n.featured
                          ? <span style={{ padding: '4px 10px', background: 'var(--red)', color: '#fff', fontSize: 10, fontFamily: 'var(--mono)', letterSpacing: '0.12em', textTransform: 'uppercase', fontWeight: 700 }}>Destacada</span>
                          : <span style={{ padding: '4px 10px', background: 'var(--bg-alt)', border: '1px solid var(--line)', color: 'var(--ink-2)', fontSize: 10, fontFamily: 'var(--mono)', letterSpacing: '0.12em', textTransform: 'uppercase' }}>Publicada</span>}
                      </div>
                      <div style={{ display: 'flex', gap: 6, justifyContent: 'flex-end', flexWrap: 'wrap' }}>
                        <button className="btn btn-ghost" style={{ padding: '6px 12px', fontSize: 12 }} onClick={() => setPreview(n)}>Ver</button>
                        <button className="btn btn-ghost" style={{ padding: '6px 12px', fontSize: 12 }} onClick={() => setEditing(n)}>Editar</button>
                        <button className="btn btn-ghost" style={{ padding: '6px 12px', fontSize: 12, color: 'var(--red)', borderColor: 'var(--red)' }} onClick={() => deleteItem(n.id)}>Borrar</button>
                      </div>
                    </div>
                  );
                })}
              </div>
          }
        </div>
      </section>

      {/* Modales */}
      {editing && <NewsEditor item={editing._new ? null : editing} onSave={saveItem} onClose={() => setEditing(null)} />}
      <NewsReader news={preview} onClose={() => setPreview(null)} />
    </Page>
  );
};


/* ═══════════════════════════════════════════════════════════
   CALENDARIO — snippet (en home) + página completa
   Live fetch del Sheet con fallback al snapshot en data.js
   ═══════════════════════════════════════════════════════════ */

const MONTH_SHORT = ['ENE','FEB','MAR','ABR','MAY','JUN','JUL','AGO','SEP','OCT','NOV','DIC'];
const MONTH_LONG = ['Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'];
const MONTH_SHORT_EN = ['JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'];
const MONTH_LONG_EN = ['January','February','March','April','May','June','July','August','September','October','November','December'];

/* Etiquetas EN del chrome del calendario (tags de evento + filtros; las claves
   en español siguen mandando en la lógica y en los datos vivos del Sheet) */
const EVENT_TAG_EN = {
  'SEMINARIO': 'SEMINAR',
  'INTERNACIONAL': 'INTERNATIONAL',
  'EXTERNO': 'EXTERNAL',
  'PASADO': 'PAST',
};
const CAL_FILTERS_EN = {
  'Todos': 'All',
  'Externos': 'External',
  'Virtual': 'Online',
  'Presencial': 'In person',
  'Internacional': 'International',
  'Seminarios': 'Seminars',
};

const _CAL_MES_MAP = {
  enero: 1, febrero: 2, marzo: 3, abril: 4, mayo: 5, junio: 6,
  julio: 7, agosto: 8, septiembre: 9, octubre: 10, noviembre: 11, diciembre: 12,
};
const CALENDAR_CSV_URL = 'https://docs.google.com/spreadsheets/d/1zeV3ASYhwPq5nIEEpz8NX4nH6TOOaF9I6BuZOYQIA0E/export?format=csv';

function _parseCalCSVLine(line) {
  const cols = []; let cur = '', inQ = false;
  for (let i = 0; i < line.length; i++) {
    const ch = line[i];
    if (ch === '"') { inQ = !inQ; }
    else if (ch === ',' && !inQ) { cols.push(cur); cur = ''; }
    else cur += ch;
  }
  cols.push(cur);
  return cols.map(c => c ? c.replace(/^"|"$/g, '').trim() : '');
}

// Divide el CSV en filas respetando saltos de línea dentro de celdas entrecomilladas
// (el Sheet tiene \n embebidos en "contacto"/"dirigido"; un split('\n') simple rompe 7 eventos).
function _splitCalCSVRows(text) {
  const rows = []; let cur = '', inQ = false;
  for (let i = 0; i < text.length; i++) {
    const ch = text[i];
    if (ch === '"') { inQ = !inQ; cur += ch; }
    else if (ch === '\n' && !inQ) { rows.push(cur); cur = ''; }
    else cur += ch;
  }
  if (cur.trim()) rows.push(cur);
  return rows;
}

function parseCalendarCSV(text) {
  const rows = _splitCalCSVRows(text.replace(/\r/g, ''));
  if (rows.length < 2) return [];
  const out = [];
  for (let r = 1; r < rows.length; r++) {
    if (!rows[r].trim()) continue;
    const c = _parseCalCSVLine(rows[r]);
    const id = parseInt(c[0], 10);
    if (!id) continue;
    const fecha = c[3] || '';
    const mes = c[2] || '';
    const fechaLow = fecha.toLowerCase();
    const mesLow = mes.toLowerCase();
    let mesNum = _CAL_MES_MAP[mesLow] || null;
    if (!mesNum) {
      for (const k of Object.keys(_CAL_MES_MAP)) {
        if (fechaLow.includes(k)) { mesNum = _CAL_MES_MAP[k]; break; }
      }
    }
    const isTba = fechaLow.includes('anuncio') || fechaLow.includes('tba') || !fechaLow.trim();
    const nums = fecha.match(/\d+/g) || [];
    const day = (!isTba && nums.length) ? parseInt(nums[0], 10) : null;
    const isRange = nums.length > 1;
    out.push({
      id, name: c[1] || '', mes, mesNum: mesNum || 12,
      fecha, day, isRange, tba: isTba,
      horario: c[5] || '', ubicacion: c[6] || '', org: c[7] || '',
      contacto: (c[8] || '').replace(/\n/g, ' ').trim(),
      dirigido: (c[9] || '').replace(/\n/g, ' ').trim(),
      cats: c[10] || '',
      lpde: c[11] === 'TRUE',
      ext: c[12] === 'TRUE',
      virtual: c[13] === 'TRUE',
      presencial: c[14] === 'TRUE',
      intl: c[15] === 'TRUE',
      seminario: c[16] === 'TRUE',
    });
  }
  return out.sort((a, b) => (a.mesNum - b.mesNum) || ((a.day || 99) - (b.day || 99)));
}

function useCalendarEvents() {
  const D = window.LPDE_DATA;
  const [events, setEvents] = React.useState(D.calendarEvents);
  React.useEffect(() => {
    let cancelled = false;
    fetch(`${CALENDAR_CSV_URL}&t=${Date.now()}`, { cache: 'no-store' })
      .then(r => r.ok ? r.text() : Promise.reject('http ' + r.status))
      .then(text => {
        if (cancelled) return;
        const parsed = parseCalendarCSV(text);
        if (parsed.length) setEvents(parsed);
      })
      .catch(err => console.warn('[calendario] fetch failed, using snapshot:', err));
    return () => { cancelled = true; };
  }, []);
  return events;
}

const isPastEvent = (ev) => {
  if (ev.tba || !ev.day) return false;
  const today = new Date();
  const year = today.getFullYear();
  if (year > 2026) return true;
  if (year < 2026) return false;
  const m = today.getMonth() + 1;
  const d = today.getDate();
  if (ev.mesNum < m) return true;
  if (ev.mesNum === m && ev.day < d) return true;
  return false;
};

const eventTag = (ev) => {
  if (ev.id === 10) return 'TNDE';
  if (ev.seminario) return 'SEMINARIO';
  if (ev.intl) return 'INTERNACIONAL';
  if (ev.lpde) return 'LPDE';
  return 'EXTERNO';
};

const CalendarioSnippet = ({ setPage }) => {
  const events = useCalendarEvents();
  const { t, lang } = useLang();
  const MS = lang === 'en' ? MONTH_SHORT_EN : MONTH_SHORT;

  // Próximos 4 eventos (no pasados, con fecha definida)
  const upcoming = events.filter(e => !isPastEvent(e) && e.day != null).slice(0, 4);

  return (
    <section className="section bg-pale">
      <div className="shell">
        <div className="reveal" style={{ marginBottom: 56, display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 64, alignItems: 'end' }}>
          <div>
            <span className="eyebrow">{t('Calendario 2026', '2026 Calendar')}</span>
            <h2 className="display" style={{ fontSize: 'clamp(40px, 5vw, 72px)', marginTop: 16, maxWidth: '14ch' }}>
              {t('Lo que se viene en los ', 'What’s ahead in the ')}<em className="it">{t('próximos meses', 'coming months')}</em>
            </h2>
          </div>
          <p style={{ fontSize: 17, color: 'var(--ink-2)', lineHeight: 1.6, maxWidth: 460 }}>
            {t('Torneos LPDE, encuentros amistosos, seminarios virtuales y campeonatos internacionales. Los eventos LPDE aparecen marcados en oscuro; el TNDE en rojo.', 'LPDE tournaments, friendly meets, online seminars and international championships. LPDE events are shown in dark gray; the TNDE in red.')}
          </p>
        </div>

        {/* Year strip — 12 meses dinámicos */}
        <div className="reveal d1" style={{ background: 'var(--bg)', border: '1px solid var(--line)', padding: '20px 24px', marginBottom: 40 }}>
          <div className="kicker" style={{ marginBottom: 12 }}>{t('Vista anual · 2026', 'Year at a glance · 2026')}</div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(12, 1fr)', gap: 6 }}>
            {MS.map((m, i) => {
              const monthEvents = events.filter(e => e.mesNum === i + 1);
              const isAug = (i + 1) === 8;
              return (
                <div key={i} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6 }}>
                  <div style={{ fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.08em', color: isAug ? 'var(--red)' : 'var(--mute)', fontWeight: isAug ? 700 : 400 }}>{m}</div>
                  <div style={{ display: 'flex', gap: 3, height: 14, minHeight: 14 }}>
                    {monthEvents.map((ev, j) => {
                      const isTnde = ev.id === 10;
                      return (
                        <div key={j} style={{
                          width: 6, height: 14,
                          background: isTnde ? 'var(--red)' : (ev.lpde ? 'var(--ink)' : 'var(--line-strong)'),
                          opacity: isPastEvent(ev) ? 0.35 : 1,
                        }}/>
                      );
                    })}
                    {monthEvents.length === 0 && <div style={{ width: 6, height: 14, background: 'var(--bg-alt)' }}/>}
                  </div>
                </div>
              );
            })}
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 24, marginTop: 16, paddingTop: 12, borderTop: '1px solid var(--line)', fontSize: 11, fontFamily: 'var(--mono)', color: 'var(--mute)' }}>
            <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}><span style={{ width: 8, height: 8, background: 'var(--red)' }}/>TNDE</span>
            <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}><span style={{ width: 8, height: 8, background: 'var(--ink)' }}/>LPDE</span>
            <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}><span style={{ width: 8, height: 8, background: 'var(--line-strong)' }}/>{t('Externo', 'External')}</span>
            <span style={{ marginLeft: 'auto' }}>{events.length}{t(' eventos planificados', ' events planned')}</span>
          </div>
        </div>

        {/* Próximos 4 eventos */}
        <div className="kicker reveal d2" style={{ marginBottom: 16 }}>{t('Próximos eventos', 'Upcoming events')}</div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 16 }}>
          {upcoming.map((ev, i) => {
            const isTnde = ev.id === 10;
            const tag = eventTag(ev);
            return (
              <article key={ev.id} className={`reveal d${i + 1}`}
                style={{
                  background: isTnde ? 'var(--ink)' : 'var(--bg)',
                  color: isTnde ? '#fff' : 'var(--ink)',
                  border: '1px solid ' + (isTnde ? 'var(--ink)' : 'var(--line)'),
                  padding: 24,
                  display: 'flex', flexDirection: 'column', gap: 14,
                  cursor: 'pointer',
                  transition: 'all 280ms ease',
                }}
                onMouseEnter={(e2) => { e2.currentTarget.style.transform = 'translateY(-4px)'; e2.currentTarget.style.boxShadow = '0 16px 40px rgba(0,0,0,0.08)'; }}
                onMouseLeave={(e2) => { e2.currentTarget.style.transform = 'translateY(0)'; e2.currentTarget.style.boxShadow = 'none'; }}
                onClick={() => setPage('calendario')}
              >
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
                  <div>
                    <div style={{ fontFamily: 'var(--serif)', fontWeight: 400, fontSize: 'clamp(48px, 5vw, 72px)', lineHeight: 0.85 }}>
                      {ev.day}{ev.isRange ? '+' : ''}
                    </div>
                    <div style={{ display: 'flex', alignItems: 'baseline', gap: 6, marginTop: 4 }}>
                      <span style={{ fontFamily: 'var(--mono)', fontSize: 12, fontWeight: 700, letterSpacing: '0.1em', color: 'var(--red)' }}>{MS[ev.mesNum - 1]}</span>
                    </div>
                  </div>
                  <span style={{ padding: '3px 9px', borderRadius: 3, background: isTnde ? 'rgba(255,255,255,0.14)' : 'var(--bg-alt)', color: isTnde ? '#fff' : 'var(--ink-soft)', fontSize: 9, fontWeight: 700, letterSpacing: '0.14em', fontFamily: 'var(--mono)', border: isTnde ? '1px solid rgba(255,255,255,0.2)' : '1px solid var(--line)' }}>
                    {lang === 'en' ? (EVENT_TAG_EN[tag] || tag) : tag}
                  </span>
                </div>
                <div style={{ flex: 1 }}>
                  <h3 style={{ fontFamily: 'var(--serif)', fontSize: 18, lineHeight: 1.2, marginBottom: 10 }}>
                    {ev.name}
                  </h3>
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 6, fontSize: 11, color: isTnde ? '#B8B8C0' : 'var(--ink-2)' }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}><Icon name="map" size={12}/> {ev.ubicacion}</div>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                      <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>
                      {ev.horario}
                    </div>
                  </div>
                </div>
              </article>
            );
          })}
        </div>

        <div className="reveal d3" style={{ marginTop: 32, textAlign: 'center' }}>
          <button className="btn btn-ghost" onClick={() => setPage('calendario')}>
            {t('Ver calendario completo', 'View full calendar')} <Icon name="arrow-up-right" size={14}/>
          </button>
        </div>
      </div>
    </section>
  );
};


/* ─── Descarga de evento como JPG (canvas 1080×1350, estilo editorial) ───
   El layout se MIDE antes de dibujar y baja de escala hasta caber:
   garantiza que la imagen nunca salga cortada. */
const _wrapCanvasText = (ctx, text, maxWidth) => {
  const words = [];
  String(text || '').split(/\s+/).filter(Boolean).forEach((w) => {
    // trocea palabras más anchas que la caja (URLs, correos largos)
    while (ctx.measureText(w).width > maxWidth && w.length > 4) {
      let cut = w.length - 1;
      while (cut > 1 && ctx.measureText(w.slice(0, cut)).width > maxWidth) cut--;
      words.push(w.slice(0, cut));
      w = w.slice(cut);
    }
    words.push(w);
  });
  const lines = [];
  let line = '';
  words.forEach((w) => {
    const probe = line ? line + ' ' + w : w;
    if (ctx.measureText(probe).width > maxWidth && line) { lines.push(line); line = w; }
    else line = probe;
  });
  if (line) lines.push(line);
  return lines;
};

// Como _wrapCanvasText pero limita líneas y cierra con "…" si truncó
const _fitCanvasLines = (ctx, text, maxWidth, maxLines) => {
  const lines = _wrapCanvasText(ctx, text, maxWidth);
  if (lines.length <= maxLines) return lines;
  const kept = lines.slice(0, maxLines);
  let last = kept[maxLines - 1] + '…';
  while (ctx.measureText(last).width > maxWidth && last.length > 2) last = last.slice(0, -2) + '…';
  kept[maxLines - 1] = last;
  return kept;
};

const downloadEventJPG = (ev, lang) => {
  const css = getComputedStyle(document.body);
  const RED = (css.getPropertyValue('--red') || '#E30613').trim();
  const INK = (css.getPropertyValue('--ink') || '#0F0F12').trim();
  const CREAM = (css.getPropertyValue('--bg-alt') || '#F7F5EF').trim();
  const dark = ev.id === 10; // tarjeta TNDE en oscuro, como en la web
  const W = 1080, H = 1350, M = 90, CW = W - M * 2;
  const SERIF = '"Instrument Serif", Georgia, serif';
  const SANS = '"Source Sans 3", Arial, sans-serif';
  const MONO = '"JetBrains Mono", monospace';
  const bg = dark ? INK : CREAM;
  const fg = dark ? '#FFFFFF' : INK;
  const sub = dark ? '#C9C9D0' : '#4B4B53';
  const mute = dark ? '#9C9AA0' : '#6B7280';
  const past = isPastEvent(ev);
  const baseTag = eventTag(ev);
  const eventTagLabel = lang === 'en' ? (EVENT_TAG_EN[baseTag] || baseTag) : baseTag;
  const ML = lang === 'en' ? MONTH_LONG_EN : MONTH_LONG;

  const draw = (logoImg) => {
    const canvas = document.createElement('canvas');
    canvas.width = W; canvas.height = H;
    const ctx = canvas.getContext('2d');
    const CONTENT_TOP = 282;
    const CONTENT_BOTTOM = H - 210; // el pie es fijo; nada puede invadirlo
    const monthName = (ML[(ev.mesNum || 12) - 1] || '').toUpperCase();
    const fechaTxt = ev.fecha || (lang === 'en' ? 'Date TBA' : 'Fecha por anunciar');
    const L = (es, en) => (lang === 'en' ? en : es);

    // Dibuja (o solo mide, con dry=true) el contenido a una escala S. Devuelve la y final.
    const render = (S, dry) => {
      const fecha = Math.round(60 * S);
      const title = Math.round(74 * S), titleLH = Math.round(82 * S);
      const val = Math.round(33 * S), valLH = Math.round(43 * S);
      const gap = Math.round(34 * S);
      const maxTitle = S >= 0.9 ? 3 : 4;
      let y = CONTENT_TOP;

      // Chips: categoría (+ PASADO si aplica, sin perder la categoría)
      ctx.font = '500 23px ' + MONO;
      let chipX = M;
      const chips = past ? [eventTagLabel, L('PASADO', 'PAST')] : [eventTagLabel];
      chips.forEach((c, ci) => {
        const w = ctx.measureText(c).width + 44;
        if (!dry) {
          ctx.fillStyle = ci === 0 && !past ? RED : (ci === 0 ? RED : (dark ? '#2A2A30' : '#D4D2CC'));
          if (ctx.roundRect) { ctx.beginPath(); ctx.roundRect(chipX, y, w, 48, 6); ctx.fill(); }
          else ctx.fillRect(chipX, y, w, 48);
          ctx.fillStyle = ci === 0 ? '#FFFFFF' : (dark ? '#C9C9D0' : '#4B4B53');
          ctx.fillText(c, chipX + 22, y + 33);
        }
        chipX += w + 14;
      });
      y += 48 + Math.round(44 * S);

      // Mes (kicker) + fecha (serif itálica roja)
      if (!dry) {
        ctx.fillStyle = mute;
        ctx.font = '500 24px ' + MONO;
        ctx.fillText(monthName, M, y + 24);
      }
      y += 24 + Math.round(26 * S);
      ctx.font = 'italic 400 ' + fecha + 'px ' + SERIF;
      const fechaLines = _fitCanvasLines(ctx, fechaTxt, CW, 1);
      if (!dry) {
        ctx.fillStyle = RED;
        ctx.fillText(fechaLines[0], M, y + fecha * 0.78);
      }
      y += fecha + gap;

      // Título
      ctx.font = '900 ' + title + 'px ' + SANS;
      const titleLines = _fitCanvasLines(ctx, ev.name, CW, maxTitle);
      titleLines.forEach((l) => {
        if (!dry) { ctx.fillStyle = fg; ctx.fillText(l, M, y + title * 0.78); }
        y += titleLH;
      });
      y += gap;

      // Regla corta roja entre título y datos
      if (!dry) { ctx.fillStyle = RED; ctx.fillRect(M, y, 56, 4); }
      y += Math.round(40 * S);

      // Detalles: Ubicación + Horario en dos columnas; el resto a lo ancho
      const colW = Math.floor((CW - 48) / 2);
      const block = (label, value, x, width, maxLines) => {
        if (!value) return 0;
        let by = 0;
        if (!dry) {
          ctx.fillStyle = mute;
          ctx.font = '500 21px ' + MONO;
          ctx.fillText(label.toUpperCase(), x, y + by + 21);
        }
        by += 21 + 16;
        ctx.font = '400 ' + val + 'px ' + SANS;
        const lines = _fitCanvasLines(ctx, value, width, maxLines);
        lines.forEach((l) => {
          if (!dry) { ctx.fillStyle = sub; ctx.fillText(l, x, y + by + val * 0.78); }
          by += valLH;
        });
        return by;
      };
      const h1 = block(L('Ubicación', 'Location'), ev.ubicacion, M, colW, 2);
      const h2 = block(L('Horario', 'Time'), ev.horario, M + colW + 48, colW, 2);
      if (h1 || h2) y += Math.max(h1, h2) + gap;
      const h3 = block(L('Organiza', 'Hosted by'), ev.org, M, CW, 1);
      if (h3) y += h3 + gap;
      const h4 = block(L('Dirigido a', 'For'), ev.dirigido, M, CW, S >= 0.85 ? 3 : 2);
      if (h4) y += h4 + gap;
      const h5 = block(L('Contacto', 'Contact'), ev.contacto, M, CW, S >= 0.85 ? 2 : 1);
      if (h5) y += h5;
      return y;
    };

    // 1) Pasada de medición: baja la escala hasta que el contenido cabe
    const scales = [1, 0.92, 0.84, 0.76, 0.68];
    let S = scales[scales.length - 1];
    for (const s of scales) {
      if (render(s, true) <= CONTENT_BOTTOM) { S = s; break; }
    }

    // 2) Pasada real
    ctx.fillStyle = bg;
    ctx.fillRect(0, 0, W, H);
    try { ctx.letterSpacing = '3px'; } catch (e) {}

    // Cabecera fija: logo + kicker + línea
    if (logoImg) {
      const lh = 54, lw = lh * (logoImg.width / logoImg.height);
      ctx.drawImage(logoImg, M, M - 6, lw, lh);
    } else {
      ctx.fillStyle = RED;
      ctx.font = '900 44px ' + SANS;
      ctx.fillText('LPDE', M, M + 38);
    }
    ctx.fillStyle = mute;
    ctx.font = '500 22px ' + MONO;
    ctx.textAlign = 'right';
    ctx.fillText(lang === 'en' ? '2026 CALENDAR' : 'CALENDARIO 2026', W - M, M + 34);
    ctx.textAlign = 'left';
    ctx.strokeStyle = dark ? '#2A2A30' : '#D4D2CC';
    ctx.lineWidth = 2;
    ctx.beginPath(); ctx.moveTo(M, 206); ctx.lineTo(W - M, 206); ctx.stroke();

    render(S, false);

    // Pie fijo
    ctx.strokeStyle = dark ? '#2A2A30' : '#D4D2CC';
    ctx.beginPath(); ctx.moveTo(M, H - 150); ctx.lineTo(W - M, H - 150); ctx.stroke();
    ctx.fillStyle = RED;
    ctx.fillRect(M, H - 150, 64, 4);
    ctx.fillStyle = mute;
    ctx.font = '500 23px ' + MONO;
    ctx.fillText('lpdebate.org', M, H - 88);
    ctx.textAlign = 'right';
    ctx.fillText(lang === 'en' ? 'Peruvian School Debate League' : 'Liga Peruana de Debate Escolar', W - M, H - 88);
    ctx.textAlign = 'left';

    canvas.toBlob((blob) => {
      if (!blob) return;
      const a = document.createElement('a');
      const slug = String(ev.name || 'evento').toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '').replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '').slice(0, 60);
      a.href = URL.createObjectURL(blob);
      a.download = `lpde-${slug}.jpg`;
      a.click();
      setTimeout(() => URL.revokeObjectURL(a.href), 4000);
    }, 'image/jpeg', 0.92);
  };

  const start = () => {
    const logo = new Image();
    logo.onload = () => draw(logo);
    logo.onerror = () => draw(null);
    logo.src = dark ? 'assets/logo-lpde-white.png' : 'assets/logo-lpde-red.png';
  };
  if (document.fonts && document.fonts.ready) document.fonts.ready.then(start);
  else start();
};

const CalendarioPage = ({ setPage }) => {
  const events = useCalendarEvents();
  const { t, lang } = useLang();
  const ML = lang === 'en' ? MONTH_LONG_EN : MONTH_LONG;
  const [filter, setFilter] = React.useState('Todos');
  const [hidePast, setHidePast] = React.useState(false);
  const filters = ['Todos', 'LPDE', 'Externos', 'Virtual', 'Presencial', 'Internacional', 'Seminarios'];

  const matchFilter = (e) => {
    if (filter === 'Todos') return true;
    if (filter === 'LPDE') return e.lpde;
    if (filter === 'Externos') return e.ext;
    if (filter === 'Virtual') return e.virtual;
    if (filter === 'Presencial') return e.presencial;
    if (filter === 'Internacional') return e.intl;
    if (filter === 'Seminarios') return e.seminario;
    return true;
  };

  const visible = events.filter(matchFilter).filter((e) => !hidePast || !isPastEvent(e));

  // Agrupar por mes
  const byMonth = {};
  visible.forEach(e => {
    const k = e.mesNum;
    if (!byMonth[k]) byMonth[k] = [];
    byMonth[k].push(e);
  });

  return (
    <Page screen="08 Calendario">
      {/* Hero */}
      <section style={{ paddingTop: 80, paddingBottom: 64, borderBottom: '1px solid var(--line)' }}>
        <div className="shell">
          <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 64, alignItems: 'end' }}>
            <div className="reveal">
              <span className="eyebrow">{t('Calendario 2026', '2026 Calendar')}</span>
              <h1 className="display" style={{ fontSize: 'clamp(56px, 8vw, 120px)', marginTop: 20, maxWidth: '14ch' }}>
                {t('Todo lo que se viene en la ', 'Everything coming up at the ')}<em className="it">{t('Liga', 'League')}</em>
              </h1>
            </div>
            <p className="reveal d1" style={{ fontSize: 17, color: 'var(--ink-2)', lineHeight: 1.6 }}>
              {events.length}{t(' eventos planificados para 2026: torneos LPDE, encuentros amistosos, seminarios virtuales, campeonatos externos e internacionales. Usa los filtros para ver solo lo que te interesa.', ' events planned for 2026: LPDE tournaments, friendly meets, online seminars, and external and international championships. Use the filters to see only what interests you.')}
            </p>
          </div>
        </div>
      </section>

      {/* Filtros sticky */}
      <section style={{ padding: '24px 0', borderBottom: '1px solid var(--line)', position: 'sticky', top: 'var(--nav-h)', background: 'rgba(255,255,255,0.92)', backdropFilter: 'blur(8px)', zIndex: 50 }}>
        <div className="shell" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 16 }}>
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
            {filters.map(f =>
              <button key={f} onClick={() => setFilter(f)} style={{
                padding: '8px 16px', borderRadius: 999,
                background: filter === f ? 'var(--ink)' : 'transparent',
                color: filter === f ? '#fff' : 'var(--ink-soft)',
                border: '1px solid ' + (filter === f ? 'var(--ink)' : 'var(--line)'),
                fontSize: 13, fontWeight: 600, fontFamily: 'var(--sans)',
                cursor: 'pointer', transition: 'all 180ms',
              }}>{lang === 'en' ? (CAL_FILTERS_EN[f] || f) : f}</button>
            )}
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
            <button onClick={() => setHidePast(!hidePast)} aria-pressed={hidePast} style={{
              display: 'inline-flex', alignItems: 'center', gap: 8,
              padding: '8px 16px', borderRadius: 999,
              background: hidePast ? 'var(--red)' : 'transparent',
              color: hidePast ? '#fff' : 'var(--ink-soft)',
              border: '1px solid ' + (hidePast ? 'var(--red)' : 'var(--line)'),
              fontSize: 13, fontWeight: 600, fontFamily: 'var(--sans)',
              cursor: 'pointer', transition: 'all 180ms',
            }}>
              {hidePast && <Icon name="check" size={13}/>}
              {t('Ocultar pasados', 'Hide past events')}
            </button>
            <div className="kicker">{visible.length}{t(' evento', ' event')}{visible.length !== 1 ? 's' : ''}</div>
          </div>
        </div>
      </section>

      {/* Eventos agrupados por mes */}
      <section className="section">
        <div className="shell">
          {Object.keys(byMonth).sort((a, b) => parseInt(a) - parseInt(b)).map(monthKey => {
            const month = parseInt(monthKey);
            const list = byMonth[monthKey];
            return (
              <div key={monthKey} style={{ marginBottom: 56 }}>
                <div className="reveal" style={{ display: 'flex', alignItems: 'baseline', gap: 18, marginBottom: 28, paddingBottom: 14, borderBottom: '1px solid var(--line)' }}>
                  <span style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 22, color: 'var(--red)' }}>{String(month).padStart(2, '0')}</span>
                  <h2 className="display" style={{ fontSize: 36 }}>{ML[month - 1]}</h2>
                  <div className="kicker" style={{ marginLeft: 'auto' }}>{list.length}{t(' evento', ' event')}{list.length > 1 ? 's' : ''}</div>
                </div>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(320px, 1fr))', gap: 16 }}>
                  {list.map((ev, i) => {
                    const past = isPastEvent(ev);
                    const isTnde = ev.id === 10;
                    const tag = past ? 'PASADO' : eventTag(ev);
                    return (
                      <article key={ev.id} className={`reveal d${(i % 4) + 1}`}
                        style={{
                          background: isTnde ? 'var(--ink)' : 'var(--bg)',
                          color: isTnde ? '#fff' : 'var(--ink)',
                          border: '1px solid ' + (isTnde ? 'var(--ink)' : 'var(--line)'),
                          padding: 22,
                          display: 'flex', flexDirection: 'column', gap: 14,
                          opacity: past ? 0.55 : 1,
                          transition: 'all 280ms ease',
                        }}
                        onMouseEnter={(e) => { e.currentTarget.style.transform = 'translateY(-3px)'; e.currentTarget.style.boxShadow = '0 12px 32px rgba(0,0,0,0.06)'; }}
                        onMouseLeave={(e) => { e.currentTarget.style.transform = 'translateY(0)'; e.currentTarget.style.boxShadow = 'none'; }}
                      >
                        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 10 }}>
                          <div style={{ fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.08em', color: isTnde ? '#fff' : 'var(--ink-soft)' }}>
                            {ev.fecha}
                          </div>
                          <span style={{ padding: '3px 8px', borderRadius: 3, background: isTnde ? 'rgba(255,255,255,0.14)' : 'var(--bg-alt)', color: isTnde ? '#fff' : 'var(--ink-soft)', fontSize: 9, fontWeight: 700, letterSpacing: '0.14em', fontFamily: 'var(--mono)', whiteSpace: 'nowrap' }}>
                            {lang === 'en' ? (EVENT_TAG_EN[tag] || tag) : tag}
                          </span>
                        </div>
                        <h3 style={{ fontFamily: 'var(--serif)', fontSize: 19, lineHeight: 1.25 }}>
                          {ev.name}
                        </h3>
                        <div style={{ display: 'flex', flexDirection: 'column', gap: 6, fontSize: 12, color: isTnde ? '#B8B8C0' : 'var(--ink-2)' }}>
                          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}><Icon name="map" size={12}/> {ev.ubicacion}</div>
                          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>
                            {ev.horario}
                          </div>
                          <div style={{ fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.06em', textTransform: 'uppercase', marginTop: 4, color: isTnde ? '#9C9AA0' : 'var(--mute)' }}>
                            {t('Organiza · ', 'Hosted by · ')}{ev.org}
                          </div>
                          <div style={{ fontSize: 12 }}>
                            {t('Dirigido a: ', 'For: ')}{ev.dirigido}
                          </div>
                        </div>
                        {ev.contacto && (
                          <div style={{ paddingTop: 12, borderTop: '1px solid ' + (isTnde ? '#2A2A30' : 'var(--line)'), fontSize: 11, color: isTnde ? '#9C9AA0' : 'var(--mute)', fontFamily: 'var(--mono)' }}>
                            {ev.contacto}
                          </div>
                        )}
                        <div style={{ marginTop: 'auto', paddingTop: 10, display: 'flex', justifyContent: 'flex-end' }}>
                          <button
                            onClick={(e) => { e.stopPropagation(); downloadEventJPG(ev, lang); }}
                            title={t('Descarga esta tarjeta como imagen JPG', 'Download this card as a JPG image')}
                            style={{
                              display: 'inline-flex', alignItems: 'center', gap: 6,
                              background: 'none', border: 'none', cursor: 'pointer',
                              fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.1em', textTransform: 'uppercase',
                              color: isTnde ? '#9C9AA0' : 'var(--mute)', padding: '4px 0',
                            }}
                            onMouseEnter={(e) => { e.currentTarget.style.color = 'var(--red)'; }}
                            onMouseLeave={(e) => { e.currentTarget.style.color = isTnde ? '#9C9AA0' : 'var(--mute)'; }}
                          >
                            <Icon name="download" size={12}/> {t('Descargar JPG', 'Download JPG')}
                          </button>
                        </div>
                      </article>
                    );
                  })}
                </div>
              </div>
            );
          })}
        </div>
      </section>

      {/* CTA back to home */}
      <section style={{ background: 'var(--bg-alt)', padding: '64px 0', borderTop: '1px solid var(--line)' }}>
        <div className="shell" style={{ textAlign: 'center' }}>
          <p style={{ fontFamily: 'var(--serif)', fontSize: 20, fontStyle: 'italic', color: 'var(--ink-soft)', marginBottom: 20 }}>
            {t('Información actualizada desde el calendario oficial LPDE.', 'Information updated live from the official LPDE calendar.')}
          </p>
          <button className="btn btn-primary" onClick={() => setPage('presentacion')}>
            {t('Volver al inicio', 'Back to home')} <Icon name="arrow" size={14}/>
          </button>
        </div>
      </section>
    </Page>
  );
};

Object.assign(window, { PresentacionPage, EquipoPage, NoticiasPage, NoticiasAdminPage, CalendarioSnippet, CalendarioPage, TEAM_EN, TeamCard, TeamModal });

/* FrentCard — distinct visual treatment per frente */
const FrentCard = ({ f, idx }) => {
  const base = {
    position: 'relative', overflow: 'hidden', cursor: 'pointer',
    padding: '40px 40px 36px', minHeight: 360,
    display: 'flex', flexDirection: 'column', justifyContent: 'space-between',
    transition: 'transform 320ms ease',
  };
  const variants = {
    photo: {
      ...base, background: '#0B0B0E', color: '#fff',
      backgroundImage: `linear-gradient(135deg, rgba(11,11,14,0.86) 0%, rgba(11,11,14,0.55) 100%), url(${f.img})`,
      backgroundSize: 'cover', backgroundPosition: 'center',
    },
    red: { ...base, background: 'var(--red)', color: '#fff' },
    cream: { ...base, background: '#F4F1E8', color: 'var(--ink)' },
    outline: { ...base, background: '#0B0B0E', color: '#fff', border: '1px solid #2A2A30' },
  };
  const numColor = {
    photo: 'rgba(255,255,255,0.96)',
    red: '#fff',
    cream: 'var(--red)',
    outline: 'var(--red)',
  }[f.variant];
  const tagStyle = {
    photo: { background: 'rgba(255,255,255,0.14)', color: '#fff', border: '1px solid rgba(255,255,255,0.2)' },
    red: { background: 'rgba(255,255,255,0.18)', color: '#fff', border: '1px solid rgba(255,255,255,0.25)' },
    cream: { background: 'var(--ink)', color: '#fff', border: '1px solid var(--ink)' },
    outline: { background: 'transparent', color: 'var(--red)', border: '1px solid var(--red)' },
  }[f.variant];
  const descColor = {
    photo: 'rgba(255,255,255,0.78)',
    red: 'rgba(255,255,255,0.86)',
    cream: 'var(--ink-2)',
    outline: '#A0A0A8',
  }[f.variant];
  const statLabelColor = {
    photo: 'rgba(255,255,255,0.55)',
    red: 'rgba(255,255,255,0.7)',
    cream: 'var(--ink-2)',
    outline: '#7A7A82',
  }[f.variant];

  return (
    <div className={`reveal d${idx + 1}`} onClick={f.cta} style={variants[f.variant]}
      onMouseEnter={(e) => { e.currentTarget.style.transform = 'translateY(-6px)'; }}
      onMouseLeave={(e) => { e.currentTarget.style.transform = 'translateY(0)'; }}
    >
      {/* Giant editorial number watermark */}
      <div aria-hidden="true" style={{
        position: 'absolute', top: -20, right: -24,
        fontFamily: 'var(--serif)', fontStyle: 'italic', fontWeight: 400,
        fontSize: 'clamp(180px, 22vw, 320px)', lineHeight: 0.78,
        letterSpacing: '-0.06em', color: numColor,
        opacity: f.variant === 'cream' ? 0.18 : (f.variant === 'red' ? 0.28 : 0.14),
        pointerEvents: 'none', userSelect: 'none',
      }}>{f.n}</div>

      {/* Top row: tag */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', position: 'relative', zIndex: 2 }}>
        <span style={{ ...tagStyle, display: 'inline-flex', alignItems: 'center', padding: '5px 12px', borderRadius: 999, fontSize: 10, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', fontFamily: 'var(--sans)' }}>
          {f.tag}
        </span>
        <span style={{ width: 36, height: 36, borderRadius: 999, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', background: f.variant === 'cream' ? 'var(--ink)' : 'rgba(255,255,255,0.12)', color: f.variant === 'cream' ? '#fff' : 'currentColor', border: f.variant === 'cream' ? 'none' : '1px solid rgba(255,255,255,0.18)' }}>
          <Icon name="arrow-up-right" size={14} />
        </span>
      </div>

      {/* Bottom block */}
      <div style={{ position: 'relative', zIndex: 2 }}>
        <h3 className="display" style={{ fontSize: 'clamp(36px, 3.4vw, 52px)', color: 'inherit', lineHeight: 1, marginBottom: 14 }}>
          {f.t}
        </h3>
        <p style={{ color: descColor, fontSize: 15, lineHeight: 1.55, maxWidth: '32ch', marginBottom: 28 }}>{f.d}</p>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 14, paddingTop: 20, borderTop: '1px solid ' + (f.variant === 'cream' ? 'rgba(0,0,0,0.12)' : 'rgba(255,255,255,0.14)') }}>
          <div style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 'clamp(40px, 4vw, 56px)', lineHeight: 0.9, color: f.variant === 'cream' ? 'var(--red)' : (f.variant === 'red' ? '#fff' : 'var(--red)') }}>
            {f.stat}
          </div>
          <div style={{ fontFamily: 'var(--mono)', fontSize: 10.5, letterSpacing: '0.14em', textTransform: 'uppercase', color: statLabelColor, lineHeight: 1.3 }}>
            {f.statLabel}
          </div>
        </div>
      </div>
    </div>
  );
};

Object.assign(window, { FrentCard });