// Panel de Microapps con IA. Cuatro vistas sobre los mismos tres RPC:
//   Hoy      — el pulso: qué pasó hoy y qué necesita atención.
//   Embudo   — de la visita a la venta, escalón por escalón, contra el período anterior.
//   Ventas   — el dinero real: neto después del fee de Hotmart, reembolsos, geografía, precios.
//   Horas    — cuándo se vende, hasta dónde aguanta el VSL, qué titular convierte.
//
// Toda la aritmética de negocio vive en los RPC (regla heredada del admin de
// Skalah). Aquí solo se derivan tasas de dos números que ya vienen calculados.
function ScreenMicroapps() {
  const { Panel, Card, Button, Badge, StatusDot, MetricTile, Sparkline, DataTable,
          Tabs, SegmentedControl, Callout, EmptyState, Spinner, StatDelta } = window.EG;
  const A = window.MicroappsAPI;

  const [vista, setVista] = React.useState('hoy');
  const [rango, setRango] = React.useState('30');
  const [datos, setDatos] = React.useState(null);
  const [horas, setHoras] = React.useState(null);
  const [ret, setRet] = React.useState(null);
  const [error, setError] = React.useState(null);
  const [cargando, setCargando] = React.useState(true);

  const desde = rango === 'hoy' ? A.hoyBogota() : A.haceDias(Number(rango) - 1);
  const hasta = A.hoyBogota();

  React.useEffect(() => {
    let vivo = true;
    setCargando(true); setError(null);
    Promise.all([
      A.panel(desde, hasta),
      A.horas(A.haceDias(89), hasta),
      A.retencion(desde, hasta),
    ]).then(([p, h, r]) => {
      if (!vivo) return;
      setDatos(p); setHoras(h); setRet(r); setCargando(false);
    }).catch(e => {
      if (!vivo) return;
      setError(e.message || String(e)); setCargando(false);
    });
    return () => { vivo = false; };
  }, [desde, hasta]);

  if (error) {
    return (
      <div className="ws-pad">
        <Callout tone="danger" title="No se pudo leer el panel" icon="error">{error}</Callout>
      </div>
    );
  }
  if (cargando || !datos) {
    return <div className="ws-pad" style={{ display: 'grid', placeItems: 'center', minHeight: 320 }}><Spinner /></div>;
  }

  const R = datos.resumen;
  const salud = datos.salud;
  const serie = (datos.diaria || []);
  const sinDatos = R.ordenes === 0 && serie.every(d => d.visitas === 0);

  // ── cabecera: rango + estado de la ingesta ────────────────────────────────
  const cabecera = (
    <div className="ws-row" style={{ justifyContent: 'space-between', alignItems: 'flex-end', flexWrap: 'wrap', gap: 16 }}>
      <div>
        <span className="eg-eyebrow">Microapps con IA que Venden</span>
        <h1 className="ws-h1" style={{ marginTop: 10 }}>Panel del embudo</h1>
      </div>
      <div className="ws-row" style={{ gap: 10, flexWrap: 'wrap' }}>
        <SegmentedControl size="sm" value={rango} onChange={setRango}
          options={[{ value: 'hoy', label: 'Hoy' }, { value: '7', label: '7 d' },
                    { value: '30', label: '30 d' }, { value: '90', label: '90 d' }]} />
        <Badge tone={salud.ingesta_activa === false ? 'danger' : salud.ultimo_evento ? 'success' : 'warning'}
               icon={salud.ingesta_activa === false ? 'pause_circle' : 'sensors'}>
          {salud.ingesta_activa === false ? 'Ingesta pausada'
            : salud.ultimo_evento ? `Hotmart · ${A.fFecha(salud.ultimo_evento)}` : 'Sin eventos de Hotmart'}
        </Badge>
      </div>
    </div>
  );

  // ── avisos que valen la pena antes que cualquier número ───────────────────
  const avisos = [];
  if (salud.ingesta_activa === false) {
    avisos.push(['danger', 'La ingesta de Hotmart está pausada',
      'Los eventos se están guardando en crudo pero no se procesan, y el webhook responde 503 para que Hotmart reintente. Nada se pierde; los números de abajo están congelados hasta que se reactive.']);
  }
  if (salud.eventos_sin_procesar > 0) {
    avisos.push(['warning', `${A.fInt(salud.eventos_sin_procesar)} eventos de Hotmart sin procesar`,
      'Llegaron y quedaron guardados, pero algo falló al asentarlos. El dinero de esas órdenes no está contado aquí.']);
  }
  if (!salud.ultimo_beacon) {
    avisos.push(['info', 'El embudo todavía no manda medición',
      'Las ventas de Hotmart sí se ven, pero sin beacon no hay visitas ni conversión: falta desplegar el sitio con beaconUrl configurado.']);
  }
  if (R.reembolsos > 0) {
    avisos.push(['warning', `${A.fInt(R.reembolsos)} reembolso(s) en el período`,
      `${A.fUsd(R.reembolsos_usd)} devueltos. Ya están descontados del neto de arriba.`]);
  }

  // ── VISTA · HOY ───────────────────────────────────────────────────────────
  const vistaHoy = () => {
    const dNeto = A.delta(R.neto, R.neto_prev);
    const dComp = A.delta(R.compradores, R.compradores_prev);
    const dOrd  = A.delta(R.ordenes, R.ordenes_prev);
    const pts = serie.map(d => Number(d.neto) || 0);
    const ptsC = serie.map(d => Number(d.compradores) || 0);
    const ptsV = serie.map(d => Number(d.visitas) || 0);

    return (
      <div className="ws-stack">
        {avisos.map(([tono, titulo, texto]) => (
          <Callout key={titulo} tone={tono} title={titulo}>{texto}</Callout>
        ))}

        <div className="ws-grid-3">
          <MetricTile label="Neto en el período" value={A.fUsd0(R.neto)}
            delta={dNeto && dNeto.texto} deltaDirection={dNeto ? dNeto.dir : 'up'}
            chart={pts.length > 1 ? <Sparkline points={pts} width={140} height={26} tone="accent" /> : null} />
          <MetricTile label="Compradores nuevos" value={A.fInt(R.compradores)}
            delta={dComp && dComp.texto} deltaDirection={dComp ? dComp.dir : 'up'}
            chart={ptsC.length > 1 ? <Sparkline points={ptsC} width={140} height={26} tone="signal" /> : null} />
          <MetricTile label="Órdenes (todas las piezas)" value={A.fInt(R.ordenes)}
            delta={dOrd && dOrd.texto} deltaDirection={dOrd ? dOrd.dir : 'up'}
            chart={ptsV.length > 1 ? <Sparkline points={ptsV} width={140} height={26} tone="accent" /> : null} />
        </div>

        <div className="ws-grid-3">
          <Card padding="15px 16px">
            <span className="eg-eyebrow">Ticket medio por comprador</span>
            <p style={{ font: 'var(--type-h3)', margin: '10px 0 4px' }}>{A.fUsd(R.ticket_medio)}</p>
            <p style={{ font: 'var(--type-body-sm)', color: 'var(--text-tertiary)', margin: 0 }}>
              Neto total ÷ compradores de entrada. Incluye bump y Gold.
            </p>
          </Card>
          <Card padding="15px 16px">
            <span className="eg-eyebrow">Se queda Hotmart</span>
            <p style={{ font: 'var(--type-h3)', margin: '10px 0 4px' }}>{A.fUsd(R.fee)}</p>
            <p style={{ font: 'var(--type-body-sm)', color: 'var(--text-tertiary)', margin: 0 }}>
              Fee real del payload, no estimado · bruto {A.fUsd(R.bruto)}
            </p>
          </Card>
          <Card padding="15px 16px">
            <span className="eg-eyebrow">Renovaciones</span>
            <p style={{ font: 'var(--type-h3)', margin: '10px 0 4px' }}>{A.fInt(R.renovaciones)}</p>
            <p style={{ font: 'var(--type-body-sm)', color: 'var(--text-tertiary)', margin: 0 }}>
              Cobros posteriores al primero. No cuentan como conversión.
            </p>
          </Card>
        </div>

        <Panel title="Últimas órdenes" eyebrow="En vivo, desde el webhook de Hotmart">
          <DataTable
            emptyLabel="Todavía no ha entrado ninguna orden."
            columns={[
              { key: 'cuando', label: 'Cuándo', render: r => A.fFecha(r.cuando) },
              { key: 'pieza', label: 'Pieza', render: r => (
                <Badge variant="quiet" tone={r.pieza === 'entrada' ? 'accent' : r.pieza === 'bump' ? 'neutral' : 'signal'}>
                  {A.PIEZAS[r.pieza] || r.pieza}
                </Badge>) },
              { key: 'correo', label: 'Comprador', render: r => r.correo || '—' },
              { key: 'pais', label: 'País', render: r => r.pais || '—' },
              { key: 'lane', label: 'Carril', muted: true, render: r => A.CARRILES[r.lane] || r.lane },
              { key: 'neto', label: 'Neto', align: 'right', mono: true, render: r => A.fUsd(r.neto) },
              { key: 'estado', label: 'Estado', render: r => (
                <StatusDot state={['approved', 'complete'].includes(r.estado) ? 'success'
                  : ['refunded', 'chargeback'].includes(r.estado) ? 'error' : 'idle'}
                  label={r.estado} />) },
            ]}
            rows={(datos.ultimas || []).map((o, i) => ({ id: o.transaction || i, ...o }))} />
        </Panel>
      </div>
    );
  };

  // ── VISTA · EMBUDO ────────────────────────────────────────────────────────
  const vistaEmbudo = () => {
    const pasos = datos.pasos || [];
    const base = pasos.length ? Number(pasos[0].actual) || 0 : 0;
    // Cada escalón se compara con el anterior (paso a paso) y con la cima
    // (acumulado): las dos lecturas dicen cosas distintas y las dos importan.
    return (
      <div className="ws-stack">
        {sinDatos && (
          <Callout tone="info" title="Sin tráfico todavía">
            El embudo se llena cuando el sitio empiece a emitir el beacon y entren las primeras órdenes.
          </Callout>
        )}
        <Panel title="De la visita a la venta" eyebrow={`${datos.desde} → ${datos.hasta} · contra los ${datos.dias} días anteriores`}>
          <div className="ws-stack" style={{ gap: 2 }}>
            {pasos.map((p, i) => {
              const prev = i === 0 ? null : Number(pasos[i - 1].actual) || 0;
              const act = Number(p.actual) || 0;
              const tPaso = i === 0 ? null : A.tasa(act, prev);
              const tCima = i === 0 ? null : A.tasa(act, base);
              const d = A.delta(p.actual, p.previo);
              const ancho = base > 0 ? Math.max((act / base) * 100, act > 0 ? 2 : 0) : 0;
              return (
                <div key={p.id} style={{ padding: '11px 0', borderBottom: '1px solid var(--border-subtle)' }}>
                  <div className="ws-row" style={{ justifyContent: 'space-between', gap: 12, flexWrap: 'wrap' }}>
                    <span style={{ font: 'var(--type-body)', minWidth: 190 }}>{p.label}</span>
                    <div className="ws-row" style={{ gap: 14, flexWrap: 'wrap' }}>
                      {tPaso != null && (
                        <span style={{ font: 'var(--type-mono-sm)', color: 'var(--text-tertiary)' }}
                              title="Del escalón inmediatamente anterior">
                          paso {A.fPct(tPaso)}
                        </span>
                      )}
                      {tCima != null && (
                        <span style={{ font: 'var(--type-mono-sm)', color: 'var(--text-muted)' }}
                              title="De todos los que entraron al embudo">
                          total {A.fPct(tCima, 2)}
                        </span>
                      )}
                      <span style={{ font: 'var(--type-mono)', fontVariantNumeric: 'tabular-nums', minWidth: 60, textAlign: 'right' }}>
                        {A.fInt(act)}
                      </span>
                      {d ? <StatDelta value={d.texto} direction={d.dir} /> : <span style={{ width: 48 }} />}
                    </div>
                  </div>
                  <div style={{ marginTop: 8, height: 6, borderRadius: 3, background: 'var(--surface-3)', overflow: 'hidden' }}>
                    <div style={{
                      width: `${ancho}%`, height: '100%', borderRadius: 3,
                      background: i >= 4 ? 'var(--accent)' : 'var(--signal, var(--accent))',
                      opacity: 1 - i * 0.07,
                      transition: 'width var(--dur-slow, .4s) var(--ease-move, ease)',
                    }} />
                  </div>
                </div>
              );
            })}
          </div>
        </Panel>

        <div className="ws-grid-2" style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(320px, 1fr))', gap: 16 }}>
          <Panel title="Carriles" eyebrow="De dónde vienen los que compran (sck)">
            <DataTable emptyLabel="Sin ventas atribuidas todavía."
              columns={[
                { key: 'lane', label: 'Carril', render: r => A.CARRILES[r.lane] || r.lane },
                { key: 'compradores', label: 'Compradores', align: 'right', mono: true, render: r => A.fInt(r.compradores) },
                { key: 'neto', label: 'Neto', align: 'right', mono: true, render: r => A.fUsd(r.neto) },
              ]}
              rows={(datos.carriles || []).map((c, i) => ({ id: c.lane || i, ...c }))} />
          </Panel>

          <Panel title="Test de precio" eyebrow="57 · 67 · 77 — cuál gana de verdad">
            <DataTable emptyLabel="Sin checkouts todavía."
              columns={[
                { key: 'precio', label: 'Precio', render: r => `US$ ${A.fInt(r.precio)}` },
                { key: 'checkouts', label: 'Checkouts', align: 'right', mono: true, render: r => A.fInt(r.checkouts) },
                { key: 'compradores', label: 'Compras', align: 'right', mono: true, render: r => A.fInt(r.compradores) },
                { key: 'conv', label: 'Conversión', align: 'right', mono: true,
                  render: r => A.fPct(A.tasa(r.compradores, r.checkouts)) },
                { key: 'neto', label: 'Neto', align: 'right', mono: true, render: r => A.fUsd(r.neto) },
              ]}
              rows={(datos.precios || []).map((p, i) => ({ id: p.precio || i, ...p }))} />
            <p style={{ font: 'var(--type-body-sm)', color: 'var(--text-tertiary)', margin: '12px 0 0' }}>
              El ganador es el de más <strong>neto</strong>, no el de más conversión: 77 convierte menos y puede facturar más.
            </p>
          </Panel>
        </div>

        <Panel title="Día a día" eyebrow="Visitas, compradores y neto">
          <DataTable dense emptyLabel="Sin actividad en el período."
            columns={[
              { key: 'dia', label: 'Día' },
              { key: 'visitas', label: 'Visitas', align: 'right', mono: true, render: r => A.fInt(r.visitas) },
              { key: 'compradores', label: 'Compradores', align: 'right', mono: true, render: r => A.fInt(r.compradores) },
              { key: 'conv', label: 'Conv.', align: 'right', mono: true,
                render: r => A.fPct(A.tasa(r.compradores, r.visitas), 2) },
              { key: 'ordenes', label: 'Órdenes', align: 'right', mono: true, render: r => A.fInt(r.ordenes) },
              { key: 'neto', label: 'Neto', align: 'right', mono: true, render: r => A.fUsd(r.neto) },
            ]}
            rows={serie.slice().reverse().map(d => ({ id: d.dia, ...d }))} />
        </Panel>
      </div>
    );
  };

  // ── VISTA · VENTAS ────────────────────────────────────────────────────────
  const vistaVentas = () => (
    <div className="ws-stack">
      <div className="ws-grid-3">
        <MetricTile label="Bruto" value={A.fUsd0(R.bruto)} />
        <MetricTile label="Fee de Hotmart" value={A.fUsd0(R.fee)}
          delta={R.bruto > 0 ? A.fPct(A.tasa(R.fee, R.bruto)) : null} deltaDirection="down" deltaTone="neutral" />
        <MetricTile label="Neto para ti" value={A.fUsd0(R.neto)} />
      </div>

      {R.reembolsos > 0 && (
        <Callout tone="warning" title={`${A.fInt(R.reembolsos)} reembolso(s) · ${A.fUsd(R.reembolsos_usd)}`}>
          Un reembolso conserva su fee y su neto originales en la base — solo cambia de estado.
          Así se puede medir cuánto costó de verdad la devolución.
        </Callout>
      )}

      <Panel title="Países" eyebrow="Compradores de la membresía">
        <DataTable emptyLabel="Sin compradores todavía."
          columns={[
            { key: 'pais', label: 'País' },
            { key: 'compradores', label: 'Compradores', align: 'right', mono: true, render: r => A.fInt(r.compradores) },
            { key: 'neto', label: 'Neto', align: 'right', mono: true, render: r => A.fUsd(r.neto) },
          ]}
          rows={(datos.geo || []).map((g, i) => ({ id: g.pais || i, ...g }))} />
      </Panel>

      <Panel title="Todas las órdenes recientes" eyebrow="Las 25 últimas, con su estado actual">
        <DataTable dense emptyLabel="Sin órdenes."
          columns={[
            { key: 'cuando', label: 'Cuándo', render: r => A.fFecha(r.cuando) },
            { key: 'transaction', label: 'Transacción', mono: true, muted: true },
            { key: 'pieza', label: 'Pieza', render: r => A.PIEZAS[r.pieza] || r.pieza },
            { key: 'precio', label: 'Precio', align: 'right', mono: true, render: r => r.precio ? A.fUsd(r.precio) : '—' },
            { key: 'recurrencia', label: 'Cobro #', align: 'right', mono: true },
            { key: 'neto', label: 'Neto', align: 'right', mono: true, render: r => A.fUsd(r.neto) },
            { key: 'estado', label: 'Estado' },
          ]}
          rows={(datos.ultimas || []).map((o, i) => ({ id: o.transaction || i, ...o }))} />
      </Panel>
    </div>
  );

  // ── VISTA · HORAS ─────────────────────────────────────────────────────────
  const DOW = ['Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb', 'Dom'];
  const BLOQUES = ['00–03', '03–06', '06–09', '09–12', '12–15', '15–18', '18–21', '21–24'];

  // Intensidad relativa al promedio de la ventana, en un solo hue.
  const alpha = (n, prom) => {
    if (prom <= 0 || n <= 0) return 0.04;
    const r = n / prom;
    return r <= 0.5 ? 0.08 : r <= 0.8 ? 0.18 : r <= 1.2 ? 0.32 : r <= 2 ? 0.5 : 0.72;
  };

  const vistaHoras = () => {
    const celdas = new Map();
    (horas && horas.celdas || []).forEach(c => celdas.set(`${c.dow}-${c.block}`, c.count));
    const visitas = new Map();
    (horas && horas.visitas || []).forEach(c => visitas.set(`${c.dow}-${c.block}`, c.count));
    const total = Number(horas && horas.total) || 0;
    const prom = total > 0 ? total / 56 : 0;

    const curva = (ret && ret.curva) || [];
    const basePlay = Number(ret && ret.base_play) || 0;

    return (
      <div className="ws-stack">
        <Panel title="Horas calientes"
          eyebrow={`Ventas por día y franja · últimos 90 días · ${horas ? horas.zona : 'America/Bogota'}`}>
          {total === 0 ? (
            <EmptyState icon="schedule" title="Sin ventas que repartir todavía"
              description="El mapa se dibuja con las primeras órdenes reales. Cada celda cuenta compras nuevas, no renovaciones." />
          ) : (
            <>
              <p style={{ font: 'var(--type-body-sm)', color: 'var(--text-tertiary)', margin: '0 0 14px' }}>
                {A.fInt(total)} ventas analizadas · promedio {prom.toFixed(1)} por celda ·
                el número pequeño es cuánta gente <em>visitó</em> en esa franja.
              </p>
              <div style={{ overflowX: 'auto' }}>
                <table style={{ borderCollapse: 'separate', borderSpacing: 4, minWidth: 620 }}>
                  <thead>
                    <tr>
                      <th style={{ font: 'var(--type-mono-sm)', color: 'var(--text-muted)', textAlign: 'left', padding: '0 6px' }}>Franja</th>
                      {DOW.map(d => (
                        <th key={d} style={{ font: 'var(--type-mono-sm)', color: 'var(--text-muted)', padding: '0 6px' }}>{d}</th>
                      ))}
                    </tr>
                  </thead>
                  <tbody>
                    {BLOQUES.map((etq, b) => (
                      <tr key={etq}>
                        <td style={{ font: 'var(--type-mono-sm)', color: 'var(--text-tertiary)', whiteSpace: 'nowrap', padding: '0 6px' }}>{etq}</td>
                        {DOW.map((_, i) => {
                          const n = celdas.get(`${i + 1}-${b}`) || 0;
                          const v = visitas.get(`${i + 1}-${b}`) || 0;
                          return (
                            <td key={i} style={{ padding: 0 }}>
                              <div title={`${n} venta(s) · ${v} visita(s)`}
                                style={{
                                  minWidth: 56, height: 42, display: 'grid', placeItems: 'center',
                                  borderRadius: 8, border: '1px solid var(--border-subtle)',
                                  background: `rgba(75, 9, 249, ${alpha(n, prom)})`,
                                  font: 'var(--type-mono)', fontVariantNumeric: 'tabular-nums',
                                }}>
                                <span>{n}</span>
                                {v > 0 && <span style={{ font: 'var(--type-mono-sm)', color: 'var(--text-muted)' }}>{v}</span>}
                              </div>
                            </td>
                          );
                        })}
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              <p style={{ font: 'var(--type-body-sm)', color: 'var(--text-muted)', margin: '14px 0 0' }}>
                Intensidad relativa al promedio (≤50 % · 50–80 · 80–120 · 120–200 · &gt;200).
                Una celda oscura con muchas visitas es una franja que trae gente y no vende.
              </p>
            </>
          )}
        </Panel>

        <Panel title="Retención del VSL" eyebrow={`${A.fInt(basePlay)} personas le dieron play en el período`}>
          {curva.length === 0 ? (
            <EmptyState icon="play_circle" title="El VSL todavía no reporta"
              description="La curva se dibuja cuando el player de VTurb empiece a emitir hitos de reproducción." />
          ) : (
            <div className="ws-stack" style={{ gap: 6 }}>
              {curva.map(p => {
                const pct = A.tasa(p.espectadores, basePlay);
                return (
                  <div key={p.percent} className="ws-row" style={{ gap: 12 }}>
                    <span style={{ font: 'var(--type-mono-sm)', color: 'var(--text-tertiary)', minWidth: 44 }}>{p.percent} %</span>
                    <div style={{ flex: 1, height: 10, borderRadius: 5, background: 'var(--surface-3)', overflow: 'hidden' }}>
                      <div style={{ width: `${pct || 0}%`, height: '100%', background: 'var(--accent)', borderRadius: 5 }} />
                    </div>
                    <span style={{ font: 'var(--type-mono)', fontVariantNumeric: 'tabular-nums', minWidth: 100, textAlign: 'right' }}>
                      {A.fInt(p.espectadores)} · {A.fPct(pct)}
                    </span>
                  </div>
                );
              })}
              <p style={{ font: 'var(--type-body-sm)', color: 'var(--text-tertiary)', margin: '10px 0 0' }}>
                El pitch está en el minuto 38 de ~40, o sea cerca del 95 %. Lo que sobreviva hasta ahí
                es el techo real de ventas del VSL principal.
              </p>
            </div>
          )}
        </Panel>

        <Panel title="Titulares" eyebrow="Variantes ?h= del banco de headlines">
          <DataTable emptyLabel="Sin visitas con variante asignada."
            columns={[
              { key: 'titular', label: 'Variante' },
              { key: 'visitas', label: 'Visitas', align: 'right', mono: true, render: r => A.fInt(r.visitas) },
              { key: 'pitch', label: 'Llegan a la oferta', align: 'right', mono: true, render: r => A.fInt(r.pitch) },
              { key: 'tasa', label: '% que llega', align: 'right', mono: true,
                render: r => A.fPct(A.tasa(r.pitch, r.visitas)) },
              { key: 'checkout', label: 'Checkout', align: 'right', mono: true, render: r => A.fInt(r.checkout) },
            ]}
            rows={((ret && ret.titulares) || []).map((t, i) => ({ id: t.titular || i, ...t }))} />
        </Panel>
      </div>
    );
  };

  return (
    <div className="ws-pad ws-stack">
      {cabecera}
      <Tabs variant="line" activeId={vista} onChange={setVista}
        tabs={[{ id: 'hoy', label: 'Hoy' }, { id: 'embudo', label: 'Embudo' },
               { id: 'ventas', label: 'Ventas' }, { id: 'horas', label: 'Horas y VSL' }]} />
      {vista === 'hoy' ? vistaHoy()
        : vista === 'embudo' ? vistaEmbudo()
        : vista === 'ventas' ? vistaVentas()
        : vistaHoras()}
    </div>
  );
}
