// src/pages-gestores-aula.jsx — Aula virtual del Programa de Gestores
//
// AUTENTICACIÓN — MAGIC LINK (sin contraseñas), INDEPENDIENTE de la de
// colegios miembros: backend clonado en /plataforma/gestores-auth/ con
// cookie propia (lpde_gestor). La unidad de acceso es la PERSONA (alumno
// del programa), no el colegio: un mismo correo puede tener sesión aquí
// y en ?page=colegios-miembros a la vez sin conflicto.
//   login.php   → POST {correo}: si el alumno está activo, envía enlace
//   acceso.php  → el enlace del correo; setea cookie y vuelve aquí
//   session.php → ¿quién soy? {alumno:{nombre}, correo}
//   sesiones.php→ contenido del Sheet "Aula Gestores" (requiere sesión)
//   logout.php  → borra la cookie
// El alta/baja de alumnos se administra en la pestaña "Accesos" del Sheet.
//
// CONTENIDO
// ─────────
// Todo sale del Sheet (pestaña "Sesiones": una fila por sesión con módulo,
// video y hasta 3 materiales). Fallback local: la estructura pública de
// GESTORES_MODULOS/GESTORES_FECHAS (pages-rest.jsx) sin videos, para que
// el aula nunca aparezca vacía si el Sheet no responde.

const GESTORES_AUTH_API = 'https://lpdebate.org/plataforma/gestores-auth';

/* ── Fallback: programa 2026 desde la landing pública (sin videos) ── */
function aulaFallbackSessions() {
  const mods = window.GESTORES_MODULOS || [];
  const fechas = window.GESTORES_FECHAS || {};
  const out = [];
  for (const m of mods) {
    for (const s of m.sesiones) {
      out.push({
        n: s.n,
        modulo: m.code,
        modulo_titulo: m.title,
        title: s.title,
        speaker: s.resp,
        date: (fechas[s.n] ? fechas[s.n][0] : '') + (fechas[s.n] ? ' 2026' : ''),
        duration: '2 h',
        summary: s.desc,
        video: '',
        materials: [],
      });
    }
  }
  return out;
}

/* ── Filas del Sheet (objetos del backend) → sesiones del aula ── */
function rowsToAulaSessions(rows) {
  const out = [];
  for (const raw of rows || []) {
    const row = {};
    for (const k of Object.keys(raw || {})) row[k.trim().toLowerCase()] = raw[k];
    const get = (name) => ((row[name] === undefined || row[name] === null) ? '' : String(row[name]).trim());

    const n = parseInt(get('n'), 10);
    if (!n || !get('title')) continue;
    const pub = get('published').toLowerCase();
    if (pub === 'false' || pub === 'no' || pub === '0') continue;

    const materials = [];
    for (let i = 1; i <= 3; i++) {
      const url = get(`material_${i}_url`);
      if (url) materials.push({ label: get(`material_${i}_label`) || 'Material ' + i, url });
    }

    out.push({
      n,
      modulo: get('modulo'),
      modulo_titulo: get('modulo_titulo'),
      title: get('title'),
      speaker: get('speaker'),
      date: get('date'),
      duration: get('duration'),
      summary: get('summary'),
      video: get('video'),
      materials,
    });
  }
  out.sort((a, b) => a.n - b.n);
  return out;
}

/* ── Agrupar por módulo preservando el orden de las sesiones ── */
function aulaGroupByModulo(sessions) {
  const groups = [];
  const byCode = {};
  for (const s of sessions) {
    const code = s.modulo || 'Programa';
    if (!byCode[code]) {
      byCode[code] = { code, titulo: s.modulo_titulo || '', sesiones: [] };
      groups.push(byCode[code]);
    }
    if (!byCode[code].titulo && s.modulo_titulo) byCode[code].titulo = s.modulo_titulo;
    byCode[code].sesiones.push(s);
  }
  return groups;
}

/* ── Hook: sesiones desde sesiones.php (requiere cookie), fallback local ── */
function useAulaGestoresData() {
  const [sessions, setSessions] = React.useState(aulaFallbackSessions);
  const [status, setStatus] = React.useState('loading'); // loading | live | fallback
  React.useEffect(() => {
    let cancelled = false;
    fetch(`${GESTORES_AUTH_API}/sesiones.php`, { cache: 'no-store', credentials: 'include' })
      .then((r) => r.ok ? r.json() : Promise.reject('http ' + r.status))
      .then((data) => {
        if (cancelled) return;
        const parsed = rowsToAulaSessions(data && data.rows);
        if (parsed.length) { setSessions(parsed); setStatus('live'); }
        else { setStatus('fallback'); }
      })
      .catch((err) => {
        console.warn('[aula-gestores] sesiones.php failed, using fallback:', err);
        if (!cancelled) setStatus('fallback');
      });
    return () => { cancelled = true; };
  }, []);
  return { sessions, status };
}

/* ── Convertir URL de YouTube o Google Drive en URL embebible ── */
function aulaYtEmbedUrl(url) {
  if (!url) return null;
  const yt = url.match(/(?:youtu\.be\/|v=|\/embed\/|\/live\/)([A-Za-z0-9_-]{6,})/);
  if (yt) return `https://www.youtube-nocookie.com/embed/${yt[1]}?rel=0&modestbranding=1&playsinline=1&iv_load_policy=3`;
  const dr = url.match(/drive\.google\.com\/file\/d\/([A-Za-z0-9_-]{10,})/);
  if (dr) return `https://drive.google.com/file/d/${dr[1]}/preview`;
  return null;
}

/* ═══════════════════════════════════════════════════════════
   LOGIN
   ═══════════════════════════════════════════════════════════ */
const AulaGestoresLogin = ({ setPage }) => {
  const { t } = useLang();
  const [correo, setCorreo] = React.useState('');
  const [err, setErr] = React.useState('');
  const [sent, setSent] = React.useState(false);
  const [busy, setBusy] = React.useState(false);

  const submit = async (e) => {
    if (e) e.preventDefault();
    setErr('');
    const c = correo.trim().toLowerCase();
    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(c)) { setErr(t('Escribe el correo con el que te inscribiste al programa.', 'Enter the email you enrolled with.')); return; }
    setBusy(true);
    try {
      const r = await fetch(`${GESTORES_AUTH_API}/login.php`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify({ correo: c }),
      });
      const data = await r.json().catch(() => ({ ok: false }));
      if (data.ok && data.found) {
        setSent(true);
      } else if (data.ok && data.found === false) {
        setErr(t('Este correo no está registrado en el Programa de Gestores. Verifica que sea el correo con el que te inscribiste, o escríbenos a contacto@lpdebate.org.', 'This email isn’t registered in the program. Make sure it’s the one you enrolled with, or write to contacto@lpdebate.org.'));
      } else if (data.error === 'rate_limited') {
        setErr(t('Demasiados intentos seguidos. Espera unos minutos y vuelve a intentar.', 'Too many attempts in a row. Please wait a few minutes and try again.'));
      } else if (data.error === 'datos_no_disponibles') {
        setErr(t('No pudimos consultar el registro de alumnos en este momento. Intenta de nuevo en unos minutos.', 'We couldn’t check the student registry right now. Please try again in a few minutes.'));
      } else if (data.error === 'mail_failed') {
        setErr(t('No pudimos enviar el correo. Intenta de nuevo o escríbenos a contacto@lpdebate.org.', 'We couldn’t send the email. Try again or write to contacto@lpdebate.org.'));
      } else {
        setErr(t('No pudimos procesar la solicitud. Intenta de nuevo o escríbenos a contacto@lpdebate.org.', 'We couldn’t process your request. Try again or write to contacto@lpdebate.org.'));
      }
    } catch (e2) {
      setErr(t('No pudimos conectar con el servidor. Revisa tu conexión o escríbenos a contacto@lpdebate.org.', 'We couldn’t reach the server. Check your connection or write to contacto@lpdebate.org.'));
    } finally {
      setBusy(false);
    }
  };

  return (
    <section style={{ minHeight: '78vh', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '64px 24px', background: 'var(--bg-alt)' }}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 0, maxWidth: 880, width: '100%', background: 'var(--bg)', border: '1px solid var(--line)' }}>
        {/* Panel izquierdo — branding */}
        <div style={{ background: 'var(--ink)', color: '#fff', padding: 48, display: 'flex', flexDirection: 'column', justifyContent: 'space-between', position: 'relative', overflow: 'hidden' }}>
          <div aria-hidden="true" style={{ position: 'absolute', top: -40, right: -40, fontFamily: 'var(--serif)', fontSize: 320, lineHeight: 0.78, color: 'rgba(227,6,19,0.18)', fontStyle: 'italic', userSelect: 'none', pointerEvents: 'none' }}>G</div>
          <div style={{ position: 'relative', zIndex: 2 }}>
            <div style={{ fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--red)', fontWeight: 700 }}>{t('Aula virtual', 'Virtual classroom')}</div>
            <h1 className="display" style={{ color: '#fff', fontSize: 36, lineHeight: 1.05, marginTop: 12 }}>
              {t(<>Programa de<br /><em className="it">Gestores</em></>, <>Program<br />​<em className="it">Managers</em> course</>)}
            </h1>
          </div>
          <div style={{ position: 'relative', zIndex: 2, fontSize: 14, color: '#B8B8C0', lineHeight: 1.55 }}>
            {t('Las grabaciones de las 18 sesiones y el material complementario del programa, disponibles para los alumnos durante todo el curso.', 'Recordings of all 18 sessions and the program’s supporting materials, available to students throughout the course.')}
          </div>
        </div>

        {/* Panel derecho — form de correo (magic link) */}
        {sent
          ? <div style={{ padding: 48, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
              <div className="kicker" style={{ color: 'var(--red)', marginBottom: 12 }}>{t('Revisa tu correo', 'Check your inbox')}</div>
              <h2 className="display" style={{ fontSize: 28, lineHeight: 1.1, marginBottom: 12 }}>{t('Enlace en camino ✓', 'Link on its way ✓')}</h2>
              <p style={{ fontSize: 14, color: 'var(--ink-2)', lineHeight: 1.6 }}>
                {t(<>Enviamos un enlace de acceso a <strong>{correo.trim().toLowerCase()}</strong>.
                Ábrelo en este dispositivo y entrarás directo al aula.</>, <>We sent an access link to <strong>{correo.trim().toLowerCase()}</strong>.
                Open it on this device and you’ll go straight to the classroom.</>)}
              </p>
              <p style={{ fontSize: 13, color: 'var(--mute)', lineHeight: 1.55, marginTop: 14 }}>
                {t('¿No llega? Revisa la carpeta de spam, o escríbenos a contacto@lpdebate.org.', 'Didn’t get it? Check your spam folder, or write to contacto@lpdebate.org.')}
              </p>
              <button type="button" onClick={() => { setSent(false); setErr(''); }} className="btn btn-link" style={{ fontSize: 13, marginTop: 24, alignSelf: 'flex-start' }}>
                ← {t('Usar otro correo', 'Use a different email')}
              </button>
            </div>
          : <form onSubmit={submit} style={{ padding: 48 }}>
              <div className="kicker" style={{ color: 'var(--red)', marginBottom: 12 }}>{t('Ingreso de alumnos', 'Student log in')}</div>
              <h2 className="display" style={{ fontSize: 28, lineHeight: 1.1, marginBottom: 8 }}>{t('Entra con tu correo', 'Log in with your email')}</h2>
              <p style={{ fontSize: 13, color: 'var(--ink-2)', lineHeight: 1.55, marginBottom: 24 }}>
                {t('Sin contraseñas: escribe el correo con el que te inscribiste y te enviamos un enlace de acceso. La sesión dura 30 días en este navegador.', 'No passwords: enter the email you enrolled with and we’ll send you an access link. Your session stays active for 30 days in this browser.')}
              </p>

              <label style={{ display: 'block', fontSize: 11, fontFamily: 'var(--mono)', letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--mute)', marginBottom: 6 }}>{t('Tu correo', 'Your email')}</label>
              <input
                className="input"
                type="email"
                value={correo}
                onChange={(e) => { setCorreo(e.target.value); setErr(''); }}
                autoFocus
                autoComplete="email"
                placeholder={t('tucorreo@ejemplo.com', 'you@example.com')}
                style={{ width: '100%', marginBottom: err ? 8 : 20 }}
              />

              {err && <div style={{ fontSize: 13, color: 'var(--red)', marginBottom: 12, lineHeight: 1.5 }}>{err}</div>}

              <button type="submit" className="btn btn-red" disabled={busy} style={{ width: '100%', justifyContent: 'center' }}>
                {busy ? t('Enviando…', 'Sending…') : <>{t('Enviarme el enlace', 'Send me the link')} <Icon name="arrow" size={14} /></>}
              </button>

              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 24, paddingTop: 16, borderTop: '1px solid var(--line)' }}>
                <button type="button" onClick={() => setPage && setPage('gestores')} className="btn btn-link" style={{ fontSize: 13 }}>
                  {t('Sobre el programa', 'About the program')}
                </button>
                <button type="button" onClick={() => setPage && setPage('presentacion')} className="btn btn-link" style={{ fontSize: 13, color: 'var(--mute)' }}>
                  {t('Volver al inicio', 'Back to home')}
                </button>
              </div>
            </form>}
      </div>
    </section>
  );
};

/* ═══════════════════════════════════════════════════════════
   AULA — módulos con sus sesiones
   ═══════════════════════════════════════════════════════════ */
const AulaGestoresDashboard = ({ sess, onOpen, onLogout }) => {
  const { t } = useLang();
  const { sessions, status } = useAulaGestoresData();
  const modulos = aulaGroupByModulo(sessions);
  const disponibles = sessions.filter((s) => s.video).length;

  return (
    <>
      {/* Barra de sesión */}
      <section style={{ background: 'var(--ink)', color: '#fff', borderBottom: '1px solid #2A2A30' }}>
        <div className="shell" style={{ display: 'flex', alignItems: 'center', gap: 16, padding: '18px 0', flexWrap: 'wrap' }}>
          <div>
            <div style={{ fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.18em', textTransform: 'uppercase', color: 'var(--red)' }}>{t('Aula virtual · Programa de Gestores', 'Virtual classroom · Program managers')}</div>
            <div style={{ fontFamily: 'var(--serif)', fontSize: 22, marginTop: 4 }}>
              {t('Hola,', 'Hello,')} <em className="it" style={{ color: '#fff' }}>{sess.user}</em>
            </div>
          </div>
          <div style={{ flex: 1 }} />
          <button className="btn btn-light" style={{ padding: '8px 14px' }} onClick={onLogout}>{t('Cerrar sesión', 'Log out')}</button>
        </div>
      </section>

      {/* Header */}
      <section style={{ paddingTop: 56, paddingBottom: 32, borderBottom: '1px solid var(--line)' }}>
        <div className="shell">
          <div className="reveal">
            <span className="eyebrow">{t('Material del curso', 'Course materials')}</span>
            <h1 className="display" style={{ fontSize: 'clamp(40px, 6vw, 84px)', marginTop: 16 }}>
              {t(<>Tus <em className="it">sesiones</em></>, <>Your <em className="it">sessions</em></>)}
            </h1>
            <p style={{ fontSize: 16, color: 'var(--ink-2)', lineHeight: 1.55, marginTop: 12, maxWidth: 560 }}>
              {t('Las grabaciones y el material complementario se publican aquí después de cada sesión. Las sesiones sin video aún no se dictan.', 'Recordings and supporting materials are published here after each session. Sessions without a video haven’t been taught yet.')}
            </p>
            <p style={{ fontFamily: 'var(--mono)', fontSize: 12, letterSpacing: '0.06em', color: 'var(--mute)', marginTop: 16 }}>
              {disponibles} {t('de', 'of')} {sessions.length} {t('grabaciones disponibles', 'recordings available')}
            </p>
          </div>
        </div>
      </section>

      {/* Módulos */}
      {modulos.map((m, mi) => (
        <section key={m.code} className="section" style={{ paddingTop: 48, paddingBottom: 48, background: mi % 2 === 1 ? 'var(--bg-alt)' : 'var(--bg)', borderBottom: '1px solid var(--line)' }}>
          <div className="shell">
            <div style={{ display: 'flex', alignItems: 'baseline', gap: 16, marginBottom: 28, flexWrap: 'wrap' }}>
              <span style={{ padding: '4px 10px', background: 'var(--red)', color: '#fff', fontSize: 10, fontWeight: 700, letterSpacing: '0.14em', fontFamily: 'var(--mono)' }}>
                {t('MÓDULO', 'MODULE')} {mi + 1} · {m.code}
              </span>
              <h2 className="display" style={{ fontSize: 'clamp(24px, 3vw, 36px)' }}>{m.titulo}</h2>
            </div>

            <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
              {m.sesiones.map((s) => {
                const ready = !!s.video;
                return (
                  <article key={s.n}
                    onClick={() => onOpen(s)}
                    style={{
                      display: 'grid', gridTemplateColumns: '56px 1fr auto', gap: 20, alignItems: 'center',
                      background: 'var(--bg)', border: '1px solid var(--line)', padding: '18px 22px',
                      cursor: 'pointer', transition: 'all 220ms ease',
                    }}
                    onMouseEnter={(e) => { e.currentTarget.style.borderColor = 'var(--red)'; e.currentTarget.style.boxShadow = '0 10px 30px rgba(0,0,0,0.06)'; }}
                    onMouseLeave={(e) => { e.currentTarget.style.borderColor = 'var(--line)'; e.currentTarget.style.boxShadow = 'none'; }}
                  >
                    <div style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 30, color: ready ? 'var(--red)' : 'var(--mute)', textAlign: 'center' }}>
                      {String(s.n).padStart(2, '0')}
                    </div>
                    <div>
                      <h3 className="display" style={{ fontSize: 20, lineHeight: 1.2 }}>{s.title}</h3>
                      <div style={{ display: 'flex', gap: 14, flexWrap: 'wrap', marginTop: 6, fontSize: 12, color: 'var(--ink-2)', fontFamily: 'var(--mono)', letterSpacing: '0.04em' }}>
                        {s.speaker && <span>{t('con', 'with')} {s.speaker}</span>}
                        {s.date && <span>· {s.date}</span>}
                        {s.materials.length > 0 && <span>· ⬇ {s.materials.length} material{s.materials.length > 1 ? t('es', 's') : ''}</span>}
                      </div>
                    </div>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
                      <span style={{
                        padding: '5px 12px', borderRadius: 999, fontSize: 10, fontWeight: 700,
                        letterSpacing: '0.1em', fontFamily: 'var(--mono)', textTransform: 'uppercase',
                        background: ready ? 'var(--red-tint)' : 'var(--bg-alt)',
                        color: ready ? 'var(--red)' : 'var(--mute)',
                        border: '1px solid ' + (ready ? 'var(--red)' : 'var(--line)'),
                      }}>
                        {ready ? t('▶ Video disponible', '▶ Video available') : t('Próximamente', 'Coming soon')}
                      </span>
                      <Icon name="arrow" size={14} />
                    </div>
                  </article>
                );
              })}
            </div>
          </div>
        </section>
      ))}

      <section style={{ padding: '24px 0 48px' }}>
        <p style={{ fontSize: 12, color: 'var(--mute)', textAlign: 'center', fontFamily: 'var(--mono)', letterSpacing: '0.04em' }}>
          {status === 'live' ? t('sincronizado con el Sheet', 'live data') : status === 'loading' ? t('cargando…', 'loading…') : t('modo offline (programa local, sin videos)', 'offline mode (local program, no videos)')}
        </p>
      </section>
    </>
  );
};

/* ═══════════════════════════════════════════════════════════
   VISTA DE SESIÓN — video + descargables
   ═══════════════════════════════════════════════════════════ */
const AulaGestoresSessionView = ({ session, sess, onBack }) => {
  const { t } = useLang();
  const embed = aulaYtEmbedUrl(session.video);

  // Bloquear menú contextual sobre el reproductor (deterrent)
  const blockContext = (e) => { e.preventDefault(); return false; };

  return (
    <>
      {/* Barra de sesión */}
      <section style={{ background: 'var(--ink)', color: '#fff', borderBottom: '1px solid #2A2A30' }}>
        <div className="shell" style={{ display: 'flex', alignItems: 'center', gap: 16, padding: '14px 0', flexWrap: 'wrap' }}>
          <button onClick={onBack} className="btn btn-light" style={{ padding: '6px 14px' }}>
            ← {t('Volver al aula', 'Back to classroom')}
          </button>
          <div style={{ flex: 1 }} />
          <span style={{ fontFamily: 'var(--mono)', fontSize: 11, color: '#9C9AA0', letterSpacing: '0.06em' }}>
            {t('Sesión iniciada como', 'Logged in as')} <strong style={{ color: '#fff' }}>{sess.user}</strong>
          </span>
        </div>
      </section>

      {/* Encabezado de sesión */}
      <section style={{ paddingTop: 48, paddingBottom: 16 }}>
        <div className="shell">
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 16, flexWrap: 'wrap' }}>
            <span style={{ padding: '3px 9px', borderRadius: 3, background: 'var(--red)', color: '#fff', fontSize: 9, fontWeight: 700, letterSpacing: '0.14em', fontFamily: 'var(--mono)' }}>
              {t('SESIÓN', 'SESSION')} {String(session.n).padStart(2, '0')}
            </span>
            {session.modulo && <span className="kicker">{session.modulo} · {session.modulo_titulo}</span>}
            {session.date && <span className="kicker" style={{ color: 'var(--mute)' }}>· {session.date}</span>}
          </div>
          <h1 className="display" style={{ fontSize: 'clamp(36px, 5vw, 64px)', lineHeight: 1.05, maxWidth: '24ch' }}>
            {session.title}
          </h1>
          {session.speaker && (
            <p style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 22, color: 'var(--ink-2)', marginTop: 16 }}>
              {t('con', 'with')} {session.speaker}
            </p>
          )}
        </div>
      </section>

      {/* Layout principal: video + sidebar de materiales */}
      <section className="section" style={{ paddingTop: 32 }}>
        <div className="shell" style={{ display: 'grid', gridTemplateColumns: '2.4fr 1fr', gap: 40, alignItems: 'start' }}>
          {/* Video con watermark */}
          <div>
            {embed
              ? <div onContextMenu={blockContext}
                  style={{
                    position: 'relative', aspectRatio: '16/9', width: '100%',
                    background: '#000', border: '1px solid var(--line)', overflow: 'hidden',
                  }}>
                  <iframe
                    src={embed}
                    title={session.title}
                    allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
                    allowFullScreen
                    referrerPolicy="strict-origin-when-cross-origin"
                    style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', border: 0 }}
                  />
                  {/* Watermark — esquina inferior derecha */}
                  <div aria-hidden="true" style={{
                    position: 'absolute', bottom: 14, right: 16,
                    background: 'rgba(0,0,0,0.45)', color: 'rgba(255,255,255,0.78)',
                    padding: '4px 10px', borderRadius: 4,
                    fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.12em',
                    textTransform: 'uppercase', pointerEvents: 'none', userSelect: 'none', zIndex: 2,
                  }}>
                    LPDE · {sess.user}
                  </div>
                </div>
              : <div style={{ aspectRatio: '16/9', background: 'var(--bg-alt)', border: '1px dashed var(--line-strong)', display: 'flex', flexDirection: 'column', gap: 8, alignItems: 'center', justifyContent: 'center', color: 'var(--mute)', fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 22, textAlign: 'center', padding: 24 }}>
                  {t('La grabación se publicará después de la sesión', 'The recording will be published after the session')}
                  {session.date && <span style={{ fontFamily: 'var(--mono)', fontStyle: 'normal', fontSize: 12, letterSpacing: '0.08em' }}>{session.date} · {t('martes 7:00 – 9:00 p. m.', 'Tuesday 7:00 – 9:00 p.m.')}</span>}
                </div>}

            {session.summary && (
              <div style={{ marginTop: 32 }}>
                <span className="eyebrow">{t('Sobre esta sesión', 'About this session')}</span>
                <p style={{ fontSize: 17, lineHeight: 1.7, color: 'var(--ink-soft)', marginTop: 14 }}>
                  {session.summary}
                </p>
              </div>
            )}
          </div>

          {/* Sidebar — material descargable */}
          <aside style={{ position: 'sticky', top: 'calc(var(--nav-h) + 24px)' }}>
            <div style={{ background: 'var(--bg)', border: '1px solid var(--line)', padding: 24 }}>
              <div className="kicker" style={{ color: 'var(--red)', marginBottom: 16 }}>{t('Material complementario', 'Supporting materials')}</div>
              {Array.isArray(session.materials) && session.materials.length > 0
                ? <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                    {session.materials.map((m, i) => (
                      <a key={i} href={m.url} target="_blank" rel="noopener"
                        style={{ display: 'flex', alignItems: 'center', gap: 14, padding: '14px 16px', background: 'var(--bg-alt)', border: '1px solid var(--line)', textDecoration: 'none', color: 'var(--ink)', transition: 'all 200ms' }}
                        onMouseEnter={(e) => { e.currentTarget.style.borderColor = 'var(--red)'; e.currentTarget.style.background = 'var(--bg)'; }}
                        onMouseLeave={(e) => { e.currentTarget.style.borderColor = 'var(--line)'; e.currentTarget.style.background = 'var(--bg-alt)'; }}
                      >
                        <div style={{ width: 36, height: 36, background: 'var(--red)', color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                          <Icon name="download" size={16} />
                        </div>
                        <div style={{ flex: 1, minWidth: 0 }}>
                          <div style={{ fontFamily: 'var(--serif)', fontSize: 15, color: 'var(--ink)', lineHeight: 1.25 }}>{m.label}</div>
                        </div>
                        <Icon name="arrow-up-right" size={14} />
                      </a>
                    ))}
                  </div>
                : <p style={{ fontSize: 13, color: 'var(--mute)', fontStyle: 'italic' }}>
                    {t('Aún no se ha publicado material para esta sesión.', 'No materials have been published for this session yet.')}
                  </p>}
            </div>

            {/* Disclaimer privacidad */}
            <div style={{ marginTop: 16, padding: '16px 18px', background: 'var(--bg-alt)', border: '1px solid var(--line)', borderLeft: '3px solid var(--red)' }}>
              <div className="kicker" style={{ marginBottom: 6 }}>{t('Aviso de uso', 'Usage notice')}</div>
              <p style={{ fontSize: 12, color: 'var(--ink-2)', lineHeight: 1.55, margin: 0 }}>
                {t('Las grabaciones y el material son de uso personal de los alumnos del Programa de Gestores. No los compartas fuera del curso; cita a la LPDE como fuente cuando uses el material en tu institución.', 'Recordings and materials are for the personal use of program students. Don’t share them outside the course; credit LPDE as the source when using materials at your school.')}
              </p>
            </div>
          </aside>
        </div>
      </section>
    </>
  );
};

/* ═══════════════════════════════════════════════════════════
   ENTRY — orquesta login / aula / sesión
   ═══════════════════════════════════════════════════════════ */
const AulaGestoresPage = ({ setPage }) => {
  const { t } = useLang();
  const [sess, setSess] = React.useState(null);          // {user, correo}
  const [checking, setChecking] = React.useState(true);  // consultando session.php
  const [openSession, setOpenSession] = React.useState(null);

  // Al montar: ¿hay cookie de sesión válida?
  React.useEffect(() => {
    let cancelled = false;
    fetch(`${GESTORES_AUTH_API}/session.php`, { cache: 'no-store', credentials: 'include' })
      .then((r) => r.ok ? r.json() : Promise.reject('http ' + r.status))
      .then((data) => {
        if (cancelled) return;
        if (data.ok && data.correo) {
          setSess({ user: (data.alumno && data.alumno.nombre) || data.correo, correo: data.correo });
        }
      })
      .catch(() => {})
      .finally(() => { if (!cancelled) setChecking(false); });
    return () => { cancelled = true; };
  }, []);

  const logout = () => {
    fetch(`${GESTORES_AUTH_API}/logout.php`, { method: 'POST', credentials: 'include' }).catch(() => {});
    setSess(null);
    setOpenSession(null);
  };
  const openSess = (s) => { setOpenSession(s); window.scrollTo({ top: 0, behavior: 'smooth' }); };
  const backToAula = () => { setOpenSession(null); window.scrollTo({ top: 0, behavior: 'smooth' }); };

  if (checking) {
    return (
      <Page screen="Aula Gestores · Acceso">
        <section style={{ minHeight: '60vh', display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'var(--bg-alt)' }}>
          <p style={{ fontFamily: 'var(--serif)', fontStyle: 'italic', fontSize: 22, color: 'var(--mute)' }}>{t('Verificando acceso…', 'Verifying access…')}</p>
        </section>
      </Page>
    );
  }

  if (!sess) {
    return (
      <Page screen="Aula Gestores · Acceso">
        <AulaGestoresLogin setPage={setPage} />
      </Page>
    );
  }

  if (openSession) {
    return (
      <Page screen="Aula Gestores · Sesión">
        <AulaGestoresSessionView session={openSession} sess={sess} onBack={backToAula} />
      </Page>
    );
  }

  return (
    <Page screen="Aula Gestores · Dashboard">
      <AulaGestoresDashboard sess={sess} onOpen={openSess} onLogout={logout} />
    </Page>
  );
};

Object.assign(window, { AulaGestoresPage });
