/* global React, ReactDOM */
const { useState, useEffect, useRef, useMemo } = React;

// 🔗 URL DE DESCARGA — SGA-Setup.exe en Google Drive
const DOWNLOAD_URL = "https://drive.google.com/uc?export=download&id=1_Z6PgfI1iI4txSrBpD2ofM60WuzlTspL";

// ---------- Tweakable defaults ----------
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "heroVariant": "cursor",
  "tagline": "Mil archivos.\nUn plan. Cero sustos."
}/*EDITMODE-END*/;

// ---------- Helpers ----------
const cx = (...xs) => xs.filter(Boolean).join(" ");

function useInView(options = { threshold: 0.15, rootMargin: "0px 0px -10% 0px" }) {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    if (!ref.current) return;
    const obs = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) {
        setInView(true);
        obs.disconnect();
      }
    }, options);
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);
  return [ref, inView];
}

function Reveal({ children, delay = 0, as: Tag = "div", className = "", style = {} }) {
  const [ref, inView] = useInView();
  useEffect(() => {
    if (inView && ref.current && typeof anime !== "undefined") {
      anime({
        targets: ref.current,
        translateY: [20, 0],
        opacity: [0, 1],
        duration: 800,
        delay: delay,
        easing: "easeOutElastic(1, .8)"
      });
    }
  }, [inView, delay]);
  return (
    <Tag
      ref={ref}
      className={cx("reveal", className)}
      style={{ opacity: 0, ...style }}
    >
      {children}
    </Tag>
  );
}

// ---------- Logo SGA (SVG inline) ----------
function SgaLogo({ size = 32 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 180 180" fill="none" xmlns="http://www.w3.org/2000/svg" aria-label="SGA Logo">
      {/* Outer gear/circle ring */}
      <circle cx="90" cy="90" r="80" stroke="#3272E3" strokeWidth="6" fill="none" opacity="0.3"/>
      {/* Inner S-curve inspired by the actual SGA paths */}
      <path
        d="M60 55 C60 42 72 35 85 38 C105 42 118 55 115 72 C112 85 98 90 88 94 C75 99 62 107 65 122 C68 137 82 145 96 142 C112 138 122 125 118 110"
        stroke="#2569DF" strokeWidth="10" strokeLinecap="round" fill="none"
      />
      <path
        d="M62 57 C62 44 74 37 87 40 C107 44 120 57 117 74 C114 87 100 92 90 96 C77 101 64 109 67 124 C70 139 84 147 98 144 C114 140 124 127 120 112"
        stroke="#095FF9" strokeWidth="4" strokeLinecap="round" fill="none" opacity="0.6"
      />
      {/* Top arc accent */}
      <path d="M55 50 Q90 20 125 50" stroke="#3272E3" strokeWidth="5" strokeLinecap="round" fill="none" opacity="0.4"/>
      {/* Bottom arc accent */}
      <path d="M60 130 Q90 160 120 130" stroke="#095FF9" strokeWidth="5" strokeLinecap="round" fill="none" opacity="0.4"/>
    </svg>
  );
}

// ---------- Logo / Wordmark ----------
function Wordmark({ size = 22 }) {
  return (
    <div className="wordmark" style={{ fontSize: size }}>
      <SgaLogo size={size + 10} />
      <span>SGA</span>
      <span className="wordmark__suffix">Desktop</span>
    </div>
  );
}

// ---------- Nav ----------
function Nav() {
  const [scrolled, setScrolled] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 12);
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  return (
    <header className={cx("nav", scrolled && "nav--scrolled")}>
      <div className="nav__inner">
        <Wordmark />
        <nav className="nav__links">
          <a href="#producto">Producto</a>
          <a href="#comparativa">Comparativa</a>
          <a href="#precios">Precios</a>
          <a href="#docs">Docs</a>
        </nav>
        <div className="nav__cta">
          <a href="https://www.instagram.com/sga_saas?igsh=d2Fnb3V6eTVjajl0" target="_blank" rel="noopener noreferrer" className="link-muted" style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="2" y="2" width="20" height="20" rx="5" ry="5"></rect><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"></path><line x1="17.5" y1="6.5" x2="17.51" y2="6.5"></line></svg>
            Instagram
          </a>
          <a href={DOWNLOAD_URL} target="_blank" rel="noopener noreferrer" className="btn btn--primary btn--sm">
            Descargar
            <span className="btn__suffix">Windows</span>
          </a>
        </div>
      </div>
    </header>
  );
}

// ---------- HERO ----------
function Hero({ variant, tagline }) {
  const lines = tagline.split("\n");
  return (
    <section className="hero">
      <div className="hero__bg" aria-hidden="true">
        <div className="hero__grid" />
        <div className="hero__glow hero__glow--a" />
        <div className="hero__glow hero__glow--b" />
      </div>

      <div className="hero__inner">
        <Reveal className="hero__eyebrow">
          <span className="dot dot--live" />
          <span>v3.0 · Windows · .NET 8</span>
        </Reveal>

        <Reveal delay={80} as="h1" className="hero__title">
          {lines.map((l, i) => (
            <span key={i} className="hero__line">
              <span className="hero__line-inner">{l}</span>
            </span>
          ))}
        </Reveal>

        <Reveal delay={180} className="hero__sub">
          La app de gestión masiva de archivos para Windows que <em>simula</em> cada
          lote antes de tocar un solo byte — y lo <em>deshace</em> si algo no encaja.
        </Reveal>

        <Reveal delay={260} className="hero__cta">
          <a href={DOWNLOAD_URL} target="_blank" rel="noopener noreferrer" className="btn btn--primary btn--lg">
            <DownloadGlyph />
            Descargar para Windows
            <span className="btn__suffix">.NET 8 · 64‑bit</span>
          </a>
          <a href="#producto" className="btn btn--ghost btn--lg">
            <PlayGlyph />
            Ver demo silenciosa
          </a>
        </Reveal>

        <Reveal delay={340} className="hero__trust">
          <TrustItem icon={<ShieldGlyph />} label="Sin telemetría" />
          <TrustItem icon={<DiskGlyph />} label="100% local" />
          <TrustItem icon={<UndoGlyph />} label="Deshacer por diario" />
          <TrustItem icon={<TerminalGlyph />} label="Open source kernel" />
        </Reveal>
      </div>

      <div className="hero__stage">
        {variant === "cursor" && <AppMockupCursor />}
        {variant === "pipeline" && <PipelineHero />}
        {variant === "kinetic" && <KineticHero tagline={tagline} />}
      </div>
    </section>
  );
}

function TrustItem({ icon, label }) {
  return (
    <div className="trust-item">
      <span className="trust-item__icon">{icon}</span>
      <span>{label}</span>
    </div>
  );
}

// ---------- Hero variant A: App mockup with cursor demo ----------
const DEMO_FILES = [
  { name: "IMG_0341.HEIC",       size: "4.1 MB",  kind: "Imagen" },
  { name: "IMG_0342.HEIC",       size: "3.8 MB",  kind: "Imagen" },
  { name: "IMG_0343.HEIC",       size: "4.5 MB",  kind: "Imagen" },
  { name: "IMG_0344.HEIC",       size: "3.2 MB",  kind: "Imagen" },
  { name: "presupuesto-q3.docx", size: "182 KB",  kind: "Documento" },
  { name: "presupuesto-q4.docx", size: "195 KB",  kind: "Documento" },
  { name: "factura_2025_001.pdf",size: "412 KB",  kind: "PDF" },
  { name: "factura_2025_002.pdf",size: "388 KB",  kind: "PDF" },
  { name: "demo-final-v7-FINAL.mov", size: "104 MB", kind: "Vídeo" },
  { name: "screen recording.webm",   size: "62 MB",  kind: "Vídeo" },
];

const RENAMED = (n, idx) => {
  if (n.endsWith(".HEIC")) return `viaje-2025-${String(idx).padStart(3, "0")}.jpg`;
  if (n.endsWith(".docx")) return n.replace(/^presupuesto-/, "FIN_2025_Presupuesto_");
  if (n.endsWith(".pdf"))  return n.replace(/^factura_/, "FAC_");
  if (n.endsWith(".mov") || n.endsWith(".webm"))
    return n.replace(/(.*)/, `media-archive-${String(idx).padStart(3, "0")}.mp4`);
  return n;
};

function AppMockupCursor() {
  // Phases: idle → select → addAction → simulate → review → execute → done → reset
  const PHASES = [
    { id: "intro",    dur: 600,  cursor: { x: 6, y: 18 } },
    { id: "select",   dur: 1500, cursor: { x: 48, y: 38 } },
    { id: "addRule",  dur: 1500, cursor: { x: 78, y: 30 } },
    { id: "simulate", dur: 2200, cursor: { x: 78, y: 88 } },
    { id: "review",   dur: 2000, cursor: { x: 50, y: 62 } },
    { id: "execute",  dur: 1800, cursor: { x: 92, y: 88 } },
    { id: "done",     dur: 1800, cursor: { x: 50, y: 50 } },
  ];
  const [phaseIdx, setPhaseIdx] = useState(0);
  useEffect(() => {
    const t = setTimeout(
      () => setPhaseIdx(p => (p + 1) % PHASES.length),
      PHASES[phaseIdx].dur
    );
    return () => clearTimeout(t);
  }, [phaseIdx]);
  const phase = PHASES[phaseIdx].id;

  const fileSelected = ["select", "addRule", "simulate", "review", "execute", "done"].includes(phase);
  const ruleAdded   = ["addRule", "simulate", "review", "execute", "done"].includes(phase);
  const simulating  = phase === "simulate";
  const simulated   = ["review", "execute", "done"].includes(phase);
  const executing   = phase === "execute";
  const executed    = phase === "done";

  return (
    <div className="mock">
      <div className="mock__chrome">
        <div className="mock__traffic">
          <span /><span /><span />
        </div>
        <div className="mock__title">SGA Desktop — Lote sin nombre</div>
        <div className="mock__chrome-r">
          <span className="mock__pill">●&nbsp;Local</span>
        </div>
      </div>

      <div className="mock__body">
        <aside className="mock__side">
          <div className="mock__side-section">Lote actual</div>
          <ul className="mock__side-list">
            <li className="active"><FolderGlyph /> Sin nombre <span className="badge">{DEMO_FILES.length}</span></li>
            <li><ClockGlyph /> Hist. 12 may</li>
            <li><ClockGlyph /> Hist. 09 may</li>
          </ul>
          <div className="mock__side-section">Presets</div>
          <ul className="mock__side-list">
            <li><PresetGlyph /> Fotos viaje → JPG</li>
            <li><PresetGlyph /> Facturas → archivar</li>
            <li><PresetGlyph /> Vídeos → MP4</li>
          </ul>
        </aside>

        <main className="mock__main">
          <div className="mock__tabs">
            <button className={cx("mock__tab", !simulated && "active")}>Lote</button>
            <button className={cx("mock__tab", simulated && "active")}>
              Plan de ejecución {simulated && <span className="dot dot--accent" />}
            </button>
            <button className="mock__tab">Workflows</button>
            <button className="mock__tab">Diario</button>
          </div>

          <div className="mock__toolbar">
            <button className={cx("chip", ruleAdded && "chip--active")}>
              <PlusGlyph /> Renombrar
            </button>
            <button className="chip"><ConvertGlyph /> Convertir</button>
            <button className="chip"><MoveGlyph /> Mover</button>
            <button className="chip"><ZipGlyph /> Comprimir</button>
            <span className="mock__sep" />
            <button className={cx("chip chip--ghost", simulating && "chip--working")}>
              {simulating ? <SpinnerGlyph /> : <PlayGlyph small />}
              Simular
            </button>
            <button className={cx("chip chip--primary", executing && "chip--working", !simulated && "chip--disabled")}>
              {executing ? <SpinnerGlyph /> : <BoltGlyph />}
              Ejecutar
            </button>
          </div>

          {ruleAdded && (
            <div className="rule-card">
              <div className="rule-card__head">
                <span className="rule-card__pill">REGLA · 01</span>
                <span className="rule-card__name">Renombrar &amp; Convertir</span>
                <span className="rule-card__delete">×</span>
              </div>
              <div className="rule-card__body">
                <span className="kbd">SI</span>
                <span className="rule-card__expr">extensión <em>= .HEIC</em></span>
                <span className="kbd">ENTONCES</span>
                <span className="rule-card__expr">renombrar a <em>viaje‑2025‑{"{n:03}"}.jpg</em></span>
                <span className="kbd">+</span>
                <span className="rule-card__expr">convertir a <em>JPEG q90</em></span>
              </div>
            </div>
          )}

          <div className={cx("mock__table", simulated && "mock__table--planned")}>
            <div className="mock__row mock__row--head">
              <span>Archivo</span>
              <span>Tipo</span>
              <span>Tamaño</span>
              <span>{simulated ? "→ Resultado simulado" : "Estado"}</span>
            </div>
            {DEMO_FILES.map((f, i) => {
              const willChange = simulated && f.name !== RENAMED(f.name, i + 1);
              return (
                <div
                  key={f.name}
                  className={cx(
                    "mock__row",
                    fileSelected && "mock__row--checked",
                    willChange && "mock__row--planned"
                  )}
                  style={{ animationDelay: `${i * 60}ms` }}
                >
                  <span className="mock__cell mock__cell--name">
                    <span className="mock__check" data-on={fileSelected}>
                      <CheckGlyph />
                    </span>
                    <FileGlyph kind={f.kind} />
                    {executed && willChange ? RENAMED(f.name, i + 1) : f.name}
                  </span>
                  <span className="mock__cell muted">{f.kind}</span>
                  <span className="mock__cell mono muted">{f.size}</span>
                  <span className="mock__cell mock__cell--state">
                    {!simulated && (
                      <span className="status status--idle">listo</span>
                    )}
                    {simulated && willChange && !executed && (
                      <span className="status status--plan">
                        <ArrowGlyph /> {RENAMED(f.name, i + 1)}
                      </span>
                    )}
                    {simulated && !willChange && !executed && (
                      <span className="status status--keep">sin cambios</span>
                    )}
                    {executed && willChange && (
                      <span className="status status--ok">
                        <CheckGlyph /> ejecutado
                      </span>
                    )}
                    {executed && !willChange && (
                      <span className="status status--keep">sin cambios</span>
                    )}
                  </span>
                </div>
              );
            })}
          </div>

          <div className="mock__footer">
            <div className="mock__footer-l">
              {!simulated && (
                <span className="muted">{DEMO_FILES.length} archivos · 184 MB</span>
              )}
              {simulating && (
                <span className="muted"><SpinnerGlyph /> Simulando lote sin tocar el disco…</span>
              )}
              {phase === "review" && (
                <span className="ok">
                  <CheckGlyph /> Plan validado · 8 cambios · 2 sin tocar · 0 conflictos
                </span>
              )}
              {executing && (
                <span className="muted"><SpinnerGlyph /> Ejecutando · respaldando al diario…</span>
              )}
              {executed && (
                <span className="ok">
                  <CheckGlyph /> Ejecutado en 1.2s · respaldo guardado · pulsa ⌘Z para deshacer
                </span>
              )}
            </div>
            <div className="mock__footer-r mono">
              <span className="muted">cpu 6%</span>
              <span className="muted">·</span>
              <span className="muted">mem 184 MB</span>
              <span className="muted">·</span>
              <span className="ok">índice ✓</span>
            </div>
          </div>
        </main>
      </div>

      <Cursor x={PHASES[phaseIdx].cursor.x} y={PHASES[phaseIdx].cursor.y} clicking={["select","addRule","simulate","execute"].includes(phase)} />

      <div className="mock__caption mono">
        <span className="dot dot--live" /> demo en bucle · simulación → ejecución → deshacer
      </div>
    </div>
  );
}

function Cursor({ x, y, clicking }) {
  return (
    <div
      className={cx("cursor", clicking && "cursor--click")}
      style={{ left: `${x}%`, top: `${y}%` }}
    >
      <svg viewBox="0 0 18 22" width="18" height="22" aria-hidden>
        <path d="M2 2 L2 18 L6.5 14 L9.5 20 L12 19 L9 13 L15 13 Z" fill="#fff" stroke="#000" strokeWidth="1.2" strokeLinejoin="round" />
      </svg>
      <span className="cursor__ring" />
    </div>
  );
}

// ---------- Hero variant B: Pipeline ----------
function PipelineHero() {
  return (
    <div className="pipeline-hero">
      <PipelineCanvas />
      <div className="pipeline-hero__legend mono">
        <span><span className="dot dot--idle" /> entrada</span>
        <span><span className="dot dot--accent" /> simulación</span>
        <span><span className="dot dot--ok" /> ejecución</span>
      </div>
    </div>
  );
}

function PipelineCanvas() {
  const ref = useRef(null);
  useEffect(() => {
    const c = ref.current;
    if (!c) return;
    const ctx = c.getContext("2d");
    let raf;
    const dpr = Math.min(window.devicePixelRatio || 1, 2);
    const resize = () => {
      const w = c.clientWidth, h = c.clientHeight;
      c.width = w * dpr; c.height = h * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    };
    resize();
    window.addEventListener("resize", resize);

    const tracks = 6;
    const particles = [];
    const seed = () => {
      for (let i = 0; i < tracks; i++) {
        particles.push({
          track: i,
          t: Math.random(),
          speed: 0.0008 + Math.random() * 0.0006,
          phase: 0,
        });
      }
    };
    seed();

    const draw = (now) => {
      const w = c.clientWidth, h = c.clientHeight;
      ctx.clearRect(0, 0, w, h);

      // grid lines
      ctx.strokeStyle = "rgba(255,255,255,0.04)";
      ctx.lineWidth = 1;
      for (let i = 0; i < tracks; i++) {
        const y = (h / (tracks + 1)) * (i + 1);
        ctx.beginPath();
        ctx.moveTo(40, y); ctx.lineTo(w - 40, y); ctx.stroke();
      }

      // gates
      const gateA = w * 0.38, gateB = w * 0.7;
      ctx.strokeStyle = "rgba(59,130,246,0.5)";
      ctx.beginPath(); ctx.moveTo(gateA, 30); ctx.lineTo(gateA, h - 30); ctx.stroke();
      ctx.strokeStyle = "rgba(34,211,238,0.5)";
      ctx.beginPath(); ctx.moveTo(gateB, 30); ctx.lineTo(gateB, h - 30); ctx.stroke();

      ctx.font = "11px 'Geist Mono', monospace";
      ctx.fillStyle = "rgba(255,255,255,0.4)";
      ctx.fillText("SIMULAR", gateA - 28, 22);
      ctx.fillText("EJECUTAR", gateB - 32, 22);

      particles.forEach(p => {
        p.t += p.speed;
        if (p.t > 1) { p.t = 0; }
        const y = (h / (tracks + 1)) * (p.track + 1);
        const x = 40 + (w - 80) * p.t;
        const inSim = x > gateA && x < gateB;
        const done = x > gateB;
        const color = done ? "rgba(74,222,128,1)" : inSim ? "rgba(59,130,246,1)" : "rgba(255,255,255,0.6)";
        ctx.fillStyle = color;
        ctx.beginPath(); ctx.arc(x, y, 3, 0, Math.PI * 2); ctx.fill();
        ctx.fillStyle = color.replace("1)", "0.18)");
        ctx.beginPath(); ctx.arc(x, y, 8, 0, Math.PI * 2); ctx.fill();
      });

      raf = requestAnimationFrame(draw);
    };
    raf = requestAnimationFrame(draw);
    return () => { cancelAnimationFrame(raf); window.removeEventListener("resize", resize); };
  }, []);
  return <canvas ref={ref} className="pipeline-canvas" />;
}

// ---------- Hero variant C: Kinetic typography ----------
function KineticHero({ tagline }) {
  const words = tagline.replace(/\n/g, " ").split(" ");
  return (
    <div className="kinetic">
      <div className="kinetic__inner">
        {words.map((w, i) => (
          <span key={i} className="kinetic__word" style={{ animationDelay: `${i * 200}ms` }}>
            {w}
          </span>
        ))}
      </div>
      <div className="kinetic__loop mono">simular → ejecutar → deshacer · simular → ejecutar → deshacer ·&nbsp;</div>
    </div>
  );
}

// ---------- Cómo funciona ----------
function HowItWorks() {
  const steps = [
    {
      kicker: "01 · Cargas",
      title: "Lote",
      body: "Arrastra carpetas, selecciona desde el menú contextual de Windows o lanza una Quick Action. SGA construye tu lote en memoria — el disco no se ha tocado todavía.",
      visual: <StepBatch />,
    },
    {
      kicker: "02 · Pruebas",
      title: "Simular",
      body: "Aplica reglas IF…THEN, presets o acciones rápidas. SGA genera un Plan de Ejecución completo: qué cambia, qué se mantiene, qué da conflicto. Sin escribir nada.",
      visual: <StepSimulate />,
    },
    {
      kicker: "03 · Confirmas",
      title: "Ejecutar",
      body: "Solo cuando dices que sí, el kernel de transformaciones cancela‑con‑gracia, respalda al diario y aplica los cambios. Todo en transacción.",
      visual: <StepExecute />,
    },
    {
      kicker: "04 · Si hay duda",
      title: "Deshacer",
      body: "Cada lote ejecutado se respalda en el diario. Un atajo y vuelve al estado anterior — bytes idénticos, hash verificado.",
      visual: <StepUndo />,
    },
  ];
  return (
    <section id="producto" className="how">
      <div className="section-head">
        <Reveal className="kicker">El flujo</Reveal>
        <Reveal delay={80} as="h2" className="section-title">
          Cuatro tiempos. Ningún archivo se mueve hasta que tú lo decidas.
        </Reveal>
        <Reveal delay={160} className="section-sub">
          SGA está construido sobre una sola idea: <em>simular → ejecutar → deshacer</em>.
          Los pasos son inmutables; lo que cambia es lo que pones en cada uno.
        </Reveal>
      </div>

      <div className="how__grid">
        {steps.map((s, i) => (
          <Reveal delay={i * 100} key={s.title} className="how__card">
            <div className="how__visual">{s.visual}</div>
            <div className="how__meta mono">{s.kicker}</div>
            <h3 className="how__title">{s.title}</h3>
            <p className="how__body">{s.body}</p>
          </Reveal>
        ))}
      </div>
    </section>
  );
}

// Step visuals
function StepBatch() {
  return (
    <div className="step-vis step-batch">
      {Array.from({ length: 12 }).map((_, i) => (
        <span key={i} className="step-batch__file" style={{ animationDelay: `${i * 90}ms` }}>
          <span className="step-batch__icon" />
        </span>
      ))}
      <div className="step-batch__tray" />
    </div>
  );
}

function StepSimulate() {
  return (
    <div className="step-vis step-sim">
      <div className="step-sim__col">
        <div className="step-sim__row" />
        <div className="step-sim__row" />
        <div className="step-sim__row" />
      </div>
      <div className="step-sim__arrow">→</div>
      <div className="step-sim__col step-sim__col--out">
        <div className="step-sim__row step-sim__row--ok" />
        <div className="step-sim__row step-sim__row--ok" />
        <div className="step-sim__row step-sim__row--keep" />
      </div>
      <span className="step-sim__seal mono">PLAN ✓</span>
    </div>
  );
}

function StepExecute() {
  return (
    <div className="step-vis step-exec">
      <div className="step-exec__bar"><span /></div>
      <div className="step-exec__bar"><span style={{ animationDelay: "200ms" }} /></div>
      <div className="step-exec__bar"><span style={{ animationDelay: "400ms" }} /></div>
      <div className="step-exec__bar"><span style={{ animationDelay: "600ms" }} /></div>
      <span className="step-exec__seal mono">⚡ COMMIT</span>
    </div>
  );
}

function StepUndo() {
  return (
    <div className="step-vis step-undo">
      <span className="step-undo__arc" />
      <span className="step-undo__pin step-undo__pin--a" />
      <span className="step-undo__pin step-undo__pin--b" />
      <span className="step-undo__label mono">⌘Z</span>
    </div>
  );
}

// ---------- Demo "video" ----------
function DemoVideo() {
  const [ref, inView] = useInView({ threshold: 0.3 });
  return (
    <section ref={ref} className={cx("demo", inView && "demo--in")}>
      <div className="demo__bg">
        <div className="demo__bg-glow" />
      </div>
      <div className="section-head">
        <Reveal className="kicker">Cinco mil archivos en directo</Reveal>
        <Reveal delay={80} as="h2" className="section-title">
          El kernel hace el trabajo pesado.<br />Tú miras la barra avanzar.
        </Reveal>
      </div>
      <Reveal className="demo__frame" delay={120}>
        <DemoFakeVideo active={inView} />
      </Reveal>
      <div className="demo__captions">
        <Caption k="01" t="Discovery cooperativo" b="Recorre subárboles enteros con cancelación real. Sin enumerar dos veces." />
        <Caption k="02" t="Conversión por kernel" b="Providers especializados (imagen, doc, vídeo). Stream a stream, con cancelación por chunk." />
        <Caption k="03" t="ZIP de un solo paso" b="Comprime mientras lee. Sin relectura, sin tmp inflados." />
        <Caption k="04" t="Diario reversible" b="Cada commit deja un respaldo verificable. Deshacer = restaurar bytes, no rehacer planes." />
      </div>
    </section>
  );
}

function Caption({ k, t, b }) {
  return (
    <Reveal className="caption">
      <span className="caption__k mono">{k}</span>
      <h4 className="caption__t">{t}</h4>
      <p className="caption__b">{b}</p>
    </Reveal>
  );
}

function DemoFakeVideo({ active }) {
  const [t, setT] = useState(0);
  useEffect(() => {
    if (!active) return;
    let raf;
    const start = performance.now();
    const tick = (now) => {
      const elapsed = (now - start) / 1000;
      setT(elapsed % 18);
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [active]);

  // 0..18s loop
  const phase = t < 4 ? "scan" : t < 9 ? "plan" : t < 14 ? "commit" : "done";
  const total = 5247;
  const scanned = Math.min(total, Math.round((t / 4) * total));
  const planned = phase === "scan" ? 0 : Math.min(total, Math.round(((t - 4) / 5) * total));
  const committed = phase === "commit"
    ? Math.min(total, Math.round(((t - 9) / 5) * total))
    : phase === "done" ? total : 0;

  return (
    <div className="dfv">
      <div className="dfv__chrome">
        <div className="mock__traffic"><span /><span /><span /></div>
        <span className="mono dfv__name">SGA Desktop · Lote “Archivo de fotos 2018‑2024”</span>
        <span className="mono dfv__time">{t.toFixed(1)}s</span>
      </div>
      <div className="dfv__body">
        <div className="dfv__metrics">
          <Metric label="Detectados" value={scanned} of={total} active={phase === "scan"} />
          <Metric label="En plan"     value={planned} of={total} active={phase === "plan"}  tone="accent" />
          <Metric label="Ejecutados"  value={committed} of={total} active={phase === "commit"} tone="ok" />
        </div>
        <div className="dfv__viz">
          <DfvVisualization phase={phase} t={t} />
        </div>
        <div className="dfv__bar">
          <span className="dfv__bar-track">
            <span className="dfv__bar-fill" style={{ width: `${(t / 18) * 100}%` }} />
            <span className="dfv__bar-mark" style={{ left: "22%" }} />
            <span className="dfv__bar-mark" style={{ left: "50%" }} />
            <span className="dfv__bar-mark" style={{ left: "78%" }} />
          </span>
          <span className="dfv__phase mono">
            {phase === "scan" && "01 · descubriendo archivos"}
            {phase === "plan" && "02 · construyendo plan"}
            {phase === "commit" && "03 · ejecutando · respaldando al diario"}
            {phase === "done" && "04 · listo · pulsa ⌘Z para deshacer"}
          </span>
        </div>
      </div>
    </div>
  );
}

function Metric({ label, value, of, active, tone = "" }) {
  const pct = Math.round((value / of) * 100);
  return (
    <div className={cx("metric", active && "metric--active", tone && `metric--${tone}`)}>
      <span className="metric__label mono">{label}</span>
      <span className="metric__value">
        <span className="metric__num">{value.toLocaleString("es-ES")}</span>
        <span className="metric__of mono">/ {of.toLocaleString("es-ES")}</span>
      </span>
      <span className="metric__bar"><span style={{ width: `${pct}%` }} /></span>
    </div>
  );
}

function DfvVisualization({ phase, t }) {
  // Grid of "files" that animate through phases
  const cols = 60, rows = 14;
  const total = cols * rows;
  const scanProgress = Math.min(1, t / 4);
  const planProgress = Math.min(1, Math.max(0, (t - 4) / 5));
  const commitProgress = Math.min(1, Math.max(0, (t - 9) / 5));

  return (
    <div
      className="dfv-grid"
      style={{ gridTemplateColumns: `repeat(${cols}, 1fr)`, gridTemplateRows: `repeat(${rows}, 1fr)` }}
    >
      {Array.from({ length: total }).map((_, i) => {
        const norm = i / total;
        const scanned = norm < scanProgress;
        const planned = norm < planProgress && phase !== "scan";
        const committed = norm < commitProgress && (phase === "commit" || phase === "done");
        let cls = "dfv-cell";
        if (committed) cls += " dfv-cell--commit";
        else if (planned) cls += " dfv-cell--plan";
        else if (scanned) cls += " dfv-cell--scan";
        return <span key={i} className={cls} />;
      })}
    </div>
  );
}

// ---------- Comparativa ----------
function Comparativa() {
  const [t, setT] = useState(0);
  useEffect(() => {
    let raf;
    const start = performance.now();
    const tick = (now) => {
      setT(((now - start) / 1000) % 8);
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);

  return (
    <section id="comparativa" className="vs">
      <div className="section-head">
        <Reveal className="kicker">Antes / después</Reveal>
        <Reveal delay={80} as="h2" className="section-title">
          PowerShell te deja escribir cualquier cosa.<br />SGA te deja <em>deshacer</em>la.
        </Reveal>
        <Reveal delay={160} className="section-sub">
          La misma tarea — renombrar 5 247 fotos, convertir HEIC → JPG y archivar por mes — desde dos ángulos.
        </Reveal>
      </div>

      <div className="vs__grid">
        <Reveal className="vs__col vs__col--bad">
          <div className="vs__head">
            <span className="vs__tag">PowerShell · script de turno</span>
            <span className="vs__warn mono">⚠ irreversible</span>
          </div>
          <pre className="vs__code"><code>{powershellSnippet(t)}</code></pre>
          <ul className="vs__list">
            <li><X /> Sin simulación: cada Run es un commit.</li>
            <li><X /> Sin diario: si Move‑Item falla a mitad, te toca el rescate manual.</li>
            <li><X /> Sin cancelación: Ctrl+C deja el árbol de archivos en estado indefinido.</li>
            <li><X /> Sin contexto: el script no sabe que esa foto se llama IMG_0341 desde 2019.</li>
          </ul>
        </Reveal>

        <Reveal delay={120} className="vs__col vs__col--good">
          <div className="vs__head">
            <span className="vs__tag vs__tag--good">SGA · Plan de ejecución</span>
            <span className="vs__ok mono">✓ reversible</span>
          </div>
          <div className="vs__sga">
            <VsSGAMock t={t} />
          </div>
          <ul className="vs__list">
            <li><Check /> Plan revisable antes de tocar el disco.</li>
            <li><Check /> Diario verificable + Deshacer atómico por lote.</li>
            <li><Check /> Cancel cooperativo en cada chunk del kernel.</li>
            <li><Check /> Reglas IF…THEN guardables como preset y reutilizables.</li>
          </ul>
        </Reveal>
      </div>
    </section>
  );
}

function powershellSnippet(t) {
  const cursor = Math.floor(t * 14) % 240;
  const full = `# Renombrar y convertir 5247 fotos
Get-ChildItem -Path "D:\\Fotos" -Recurse -Filter *.HEIC |
  ForEach-Object {
    $i++
    $new = "viaje-2025-{0:D3}.jpg" -f $i
    magick convert $_.FullName "$($_.DirectoryName)\\$new" -quality 90
    Remove-Item $_.FullName -Force        # ← sin red de seguridad
    Move-Item "$($_.DirectoryName)\\$new" \`
              "D:\\Archive\\$($_.LastWriteTime.ToString('yyyy-MM'))"
  }
# Si algo falla aquí, suerte.`;
  return full.slice(0, Math.max(40, cursor)) + (cursor < full.length ? "█" : "");
}

function VsSGAMock({ t }) {
  const phase = (t % 8) < 3 ? "plan" : (t % 8) < 6 ? "exec" : "done";
  return (
    <div className="vs-sga">
      <div className="vs-sga__head mono">
        <span className="vs-sga__step" data-on={true}>① simular</span>
        <span className="vs-sga__step" data-on={phase !== "plan"}>② ejecutar</span>
        <span className="vs-sga__step" data-on={phase === "done"}>③ deshacer</span>
      </div>
      <div className="vs-sga__rows">
        {[
          ["IMG_0341.HEIC", "viaje-2025-001.jpg"],
          ["IMG_0342.HEIC", "viaje-2025-002.jpg"],
          ["IMG_0343.HEIC", "viaje-2025-003.jpg"],
          ["IMG_0344.HEIC", "viaje-2025-004.jpg"],
          ["IMG_0345.HEIC", "viaje-2025-005.jpg"],
          ["IMG_0346.HEIC", "viaje-2025-006.jpg"],
        ].map(([a, b], i) => (
          <div key={a} className="vs-sga__row" style={{ animationDelay: `${i * 50}ms` }}>
            <span className="mono muted">{a}</span>
            <span className="vs-sga__arrow">
              <ArrowGlyph />
            </span>
            <span className={cx("mono", phase !== "plan" && "ok")}>{b}</span>
            <span className="vs-sga__state mono">
              {phase === "plan" && <em className="muted">en plan</em>}
              {phase === "exec" && <em className="accent">aplicando…</em>}
              {phase === "done" && <em className="ok">✓ commit · respaldo</em>}
            </span>
          </div>
        ))}
      </div>
      <div className="vs-sga__foot mono">
        diario.sga · 6 entradas · 184 MB respaldados
      </div>
    </div>
  );
}

// ---------- Pricing ----------
function Pricing() {
  const tiers = [
    {
      name: "Solo",
      price: "Gratis",
      sub: "para siempre",
      blurb: "Lo esencial para gestionar tus archivos sin trampas.",
      features: [
        "Lotes ilimitados, hasta 1.000 archivos",
        "Simular · Ejecutar · Deshacer",
        "Quick Actions desde Explorer",
        "Presets locales · 3 reglas IF…THEN",
        "Diario de 7 días",
      ],
      cta: "Descargar",
      tone: "ghost",
    },
    {
      name: "Pro",
      price: "9 €",
      sub: "/ mes · facturación anual",
      blurb: "Para profesionales que mueven archivos en serio.",
      features: [
        "Lotes ilimitados, sin tope de archivos",
        "Workflows IF…THEN ilimitados",
        "Índice 3.0 con tags, auditoría y duplicados",
        "Kernel de transformaciones completo",
        "Diario ilimitado + integridad por hash",
      ],
      cta: "Empezar 14 días gratis",
      tone: "primary",
      featured: true,
    },
    {
      name: "Team",
      price: "29 €",
      sub: "/ asiento · mes",
      blurb: "Equipos de IT y agencias con flujos compartidos.",
      features: [
        "Todo lo de Pro",
        "Presets y workflows compartidos",
        "Gateway local SaaS · loopback con API key",
        "Despliegue por GPO · MSI firmado",
        "SLA de 8h y soporte humano",
      ],
      cta: "Hablar con el equipo",
      tone: "ghost",
    },
  ];
  return (
    <section id="precios" className="pricing">
      <div className="section-head">
        <Reveal className="kicker">Precios</Reveal>
        <Reveal delay={80} as="h2" className="section-title">
          Una licencia por dispositivo.<br />Sin límites artificiales en el plan que pagas.
        </Reveal>
        <Reveal delay={160} className="section-sub">
          Todos los planes incluyen el motor completo: nada de telemetría, nada de subscripciones a la nube ajena.
        </Reveal>
      </div>
      <div className="pricing__grid">
        {tiers.map((tier, i) => (
          <Reveal delay={i * 100} key={tier.name} className={cx("tier", tier.featured && "tier--featured")}>
            {tier.featured && <span className="tier__badge mono">Recomendado</span>}
            <div className="tier__head">
              <h3 className="tier__name">{tier.name}</h3>
              <p className="tier__blurb">{tier.blurb}</p>
            </div>
            <div className="tier__price">
              <span className="tier__amount">{tier.price}</span>
              <span className="tier__sub mono">{tier.sub}</span>
            </div>
            <a href="#download" className={cx("btn btn--lg btn--block", `btn--${tier.tone}`)}>
              {tier.cta}
            </a>
            <ul className="tier__features">
              {tier.features.map(f => (
                <li key={f}><Check /> {f}</li>
              ))}
            </ul>
          </Reveal>
        ))}
      </div>
      <Reveal className="pricing__foot mono">
        Estudiantes y proyectos open‑source: Pro gratis con verificación · escríbenos a hola@sga.app
      </Reveal>
    </section>
  );
}

// ---------- CTA ----------
function FinalCTA() {
  return (
    <section id="download" className="cta">
      <div className="cta__bg">
        <div className="cta__glow" />
      </div>
      <Reveal as="h2" className="cta__title">
        Tu próximo lote no debería darte miedo.
      </Reveal>
      <Reveal delay={80} className="cta__sub">
        Descarga SGA Desktop, simula tu primer lote y deshazlo solo para ver cómo se siente.
      </Reveal>
      <Reveal delay={160} className="cta__buttons">
        <a className="btn btn--primary btn--lg" href="#">
          <DownloadGlyph /> Descargar para Windows
          <span className="btn__suffix">.NET 8 · 184 MB</span>
        </a>
        <a className="btn btn--ghost btn--lg" href="#">
          <TerminalGlyph /> Probar el kernel · open source
        </a>
      </Reveal>
      <Reveal delay={240} className="cta__hash mono">
        sha256 · 4f1c…b29d · firma Authenticode válida hasta 2027
      </Reveal>
    </section>
  );
}

// ---------- Footer ----------
function Footer() {
  return (
    <footer className="foot">
      <div className="foot__top">
        <div className="foot__brand">
          <Wordmark size={20} />
          <p className="foot__pitch">
            Software de gestión masiva de archivos para Windows. Construido en Madrid sobre .NET 8 con la idea
            de que ningún archivo merece moverse sin un plan.
          </p>
        </div>
        <FootCol title="Producto" items={["Descargar", "Changelog", "Roadmap", "Estado del kernel"]} />
        <FootCol title="Documentación" items={["Guía rápida", "Workflows IF…THEN", "API local", "ShellIntegration"]} />
        <FootCol title="Empresa" items={["Sobre", "Privacidad", "Licencia EULA", "Contacto"]} />
      </div>
      <div className="foot__bottom mono">
        <span>© 2026 SGA · Software local, sin telemetría, sin cuentas obligatorias.</span>
        <span>v3.0.4 · build 24871 · firmado</span>
      </div>
    </footer>
  );
}

function FootCol({ title, items }) {
  return (
    <div className="foot__col">
      <h5 className="foot__title mono">{title}</h5>
      <ul>
        {items.map(i => <li key={i}><a href="#">{i}</a></li>)}
      </ul>
    </div>
  );
}

// ---------- Glyphs ----------
function DownloadGlyph(){return(<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 1v8m0 0L4 6m3 3 3-3M2 11h10" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"/></svg>);}
function PlayGlyph({small}){return(<svg width={small?12:14} height={small?12:14} viewBox="0 0 14 14"><path d="M3 2v10l9-5z" fill="currentColor"/></svg>);}
function ShieldGlyph(){return(<svg width="13" height="13" viewBox="0 0 14 14" fill="none"><path d="M7 1l5 2v4c0 3-2 5-5 6-3-1-5-3-5-6V3z" stroke="currentColor" strokeWidth="1.3"/></svg>);}
function DiskGlyph(){return(<svg width="13" height="13" viewBox="0 0 14 14" fill="none"><circle cx="7" cy="7" r="5.5" stroke="currentColor" strokeWidth="1.3"/><circle cx="7" cy="7" r="1.5" fill="currentColor"/></svg>);}
function UndoGlyph(){return(<svg width="13" height="13" viewBox="0 0 14 14" fill="none"><path d="M2 6h7a3 3 0 010 6H6M2 6l3-3M2 6l3 3" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round"/></svg>);}
function TerminalGlyph(){return(<svg width="13" height="13" viewBox="0 0 14 14" fill="none"><rect x="1.5" y="2.5" width="11" height="9" rx="1" stroke="currentColor" strokeWidth="1.2"/><path d="M4 6l2 1.5L4 9M7 9h3" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round"/></svg>);}
function FolderGlyph(){return(<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M1.5 4a1 1 0 011-1h3l1 1.5h5a1 1 0 011 1V11a1 1 0 01-1 1h-9a1 1 0 01-1-1V4z" stroke="currentColor" strokeWidth="1.2"/></svg>);}
function ClockGlyph(){return(<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><circle cx="7" cy="7" r="5.5" stroke="currentColor" strokeWidth="1.2"/><path d="M7 4v3l2 1.5" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round"/></svg>);}
function PresetGlyph(){return(<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 3h8M3 7h5M3 11h8" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round"/></svg>);}
function PlusGlyph(){return(<svg width="11" height="11" viewBox="0 0 11 11"><path d="M5.5 1v9M1 5.5h9" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round"/></svg>);}
function ConvertGlyph(){return(<svg width="11" height="11" viewBox="0 0 12 12" fill="none"><path d="M2 4h6l-2-2M10 8H4l2 2" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round"/></svg>);}
function MoveGlyph(){return(<svg width="11" height="11" viewBox="0 0 12 12" fill="none"><path d="M2 6h8m-2-2 2 2-2 2" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round"/></svg>);}
function ZipGlyph(){return(<svg width="11" height="11" viewBox="0 0 12 12" fill="none"><rect x="2" y="2" width="8" height="8" rx="1" stroke="currentColor" strokeWidth="1.2"/><path d="M6 2v8" stroke="currentColor" strokeWidth="1" strokeDasharray="1.5 1.2"/></svg>);}
function BoltGlyph(){return(<svg width="11" height="11" viewBox="0 0 12 12"><path d="M7 1L2 7h3l-1 4 5-6H6l1-4z" fill="currentColor"/></svg>);}
function SpinnerGlyph(){return(<svg width="11" height="11" viewBox="0 0 12 12" className="spin"><circle cx="6" cy="6" r="4.5" stroke="currentColor" strokeWidth="1.4" strokeDasharray="6 22" fill="none"/></svg>);}
function CheckGlyph(){return(<svg width="11" height="11" viewBox="0 0 12 12" fill="none"><path d="M2 6.5l3 3 5-6" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/></svg>);}
function ArrowGlyph(){return(<svg width="11" height="11" viewBox="0 0 12 12" fill="none"><path d="M2 6h8m-3-3 3 3-3 3" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round"/></svg>);}
function FileGlyph({kind}){
  const color = kind==="Imagen" ? "#22d3ee" : kind==="Vídeo" ? "#a78bfa" : kind==="PDF" ? "#f97316" : "#94a3b8";
  return(<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 2h6l3 3v7a1 1 0 01-1 1H3a1 1 0 01-1-1V3a1 1 0 011-1z" stroke={color} strokeWidth="1.2"/></svg>);
}
function X(){return(<span className="x"><svg width="10" height="10" viewBox="0 0 10 10"><path d="M2 2l6 6M8 2l-6 6" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/></svg></span>);}
function Check(){return(<span className="ck"><svg width="10" height="10" viewBox="0 0 10 10"><path d="M2 5.5l2 2 4-5" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" fill="none"/></svg></span>);}

// ---------- Tweaks ----------
function TweaksUI({ tweaks, setTweak }) {
  const { TweaksPanel, TweakSection, TweakRadio, TweakText } = window;
  if (!TweaksPanel) return null;
  return (
    <TweaksPanel title="Tweaks · SGA">
      <TweakSection label="Hero" />
      <TweakRadio
        label="Variante"
        value={tweaks.heroVariant}
        onChange={v => setTweak("heroVariant", v)}
        options={["cursor", "pipeline", "kinetic"]}
      />
      <TweakText
        label="Tagline"
        value={tweaks.tagline.replace(/\n/g, " · ")}
        onChange={v => setTweak("tagline", v.replace(/ · /g, "\n"))}
      />
    </TweaksPanel>
  );
}

// ---------- App ----------
function InteractiveCursor() {
  const cursorRef = useRef(null);
  useEffect(() => {
    if (!cursorRef.current || typeof anime === 'undefined') return;
    const updateCursor = (e) => {
      anime({
        targets: cursorRef.current,
        translateX: e.clientX - 10,
        translateY: e.clientY - 10,
        duration: 250,
        easing: 'easeOutQuad'
      });
    };
    window.addEventListener('mousemove', updateCursor);
    return () => window.removeEventListener('mousemove', updateCursor);
  }, []);

  return (
    <div 
      ref={cursorRef}
      style={{
        position: 'fixed',
        top: 0,
        left: 0,
        width: '20px',
        height: '20px',
        borderRadius: '50%',
        backgroundColor: 'rgba(50, 114, 227, 0.4)',
        boxShadow: '0 0 20px rgba(50, 114, 227, 0.6)',
        pointerEvents: 'none',
        zIndex: 9999,
        mixBlendMode: 'screen'
      }}
    />
  );
}

function App() {
  const [tweaks, setTweak] = window.useTweaks
    ? window.useTweaks(TWEAK_DEFAULTS)
    : [TWEAK_DEFAULTS, () => {}];

  return (
    <>
      <InteractiveCursor />
      <Nav />
      <main>
        <Hero variant={tweaks.heroVariant} tagline={tweaks.tagline} />
        <HowItWorks />
        <DemoVideo />
        <Comparativa />
        <DocsSection />
        <Pricing />
        <FinalCTA />
      </main>
      <Footer />
      <TweaksUI tweaks={tweaks} setTweak={setTweak} />
    </>
  );
}

// ---------- Docs Section ----------
function DocsSection() {
  return (
    <section id="docs" className="docs">
      <div className="section-head">
        <Reveal className="kicker">Arquitectura Open Source</Reveal>
        <Reveal delay={80} as="h2" className="section-title">
          100% C# .NET 8. Cero Dependencias Externas.
        </Reveal>
        <Reveal delay={160} className="section-sub">
          Descubre cómo funciona el kernel bajo el capó.
        </Reveal>
      </div>
      <div className="how__grid" style={{ gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))' }}>
        <Reveal delay={0} className="how__card">
          <div className="how__meta mono">01 · Baterías Incluidas</div>
          <h3 className="how__title">Embedded Engines Architecture</h3>
          <p className="how__body">SGA Desktop pesa alrededor de 1GB porque empaqueta los motores open-source más potentes (Poppler, QPDF, LibreOffice Headless) directamente en su instalador. Funciona out-of-the-box sin pedir descargas a tus usuarios.</p>
        </Reveal>
        <Reveal delay={100} className="how__card">
          <div className="how__meta mono">02 · UI Premium</div>
          <h3 className="how__title">Glassmorphism nativo en WPF</h3>
          <p className="how__body">Las interfaces de SGA están construidas utilizando aceleración por hardware pura en Windows Presentation Foundation (WPF). Sin Anime.js ni overhead de JS, con Storyboards nativos que aplican curvas CubicEase fluidas para animar estados y transiciones.</p>
        </Reveal>
        <Reveal delay={200} className="how__card">
          <div className="how__meta mono">03 · Privacidad 100%</div>
          <h3 className="how__title">Seguridad Offline</h3>
          <p className="how__body">Cada byte procesado se queda en tu RAM y tu SSD. Sin telemetría, sin llamadas ocultas a APIs. Transformamos archivos PDF, comprimimos y convertimos localmente, asegurando cumplimiento extremo de protección de datos.</p>
        </Reveal>
      </div>

      <div className="section-head" style={{ paddingTop: '80px', paddingBottom: '32px' }}>
        <Reveal delay={100} as="h3" className="section-title" style={{ fontSize: '28px' }}>
          Cumplimiento Normativo Auditado
        </Reveal>
      </div>
      <div className="how__grid" style={{ gridTemplateColumns: 'repeat(auto-fit, minmax(320px, 1fr))' }}>
        <Reveal delay={150} className="how__card">
          <div className="how__meta mono">GESTIÓN DE SEGURIDAD</div>
          <h3 className="how__title">ISO/IEC 27001</h3>
          <p className="how__body">El Kernel de SGA implementa directrices estrictas de gestión de seguridad de la información. Al operar 100% en entorno local y no transmitir datos a la nube, garantiza la soberanía de los datos, previene fugas de información corporativa y cumple con los estándares más altos de seguridad de la información definidos por la Organización Internacional de Normalización.</p>
        </Reveal>
        <Reveal delay={250} className="how__card">
          <div className="how__meta mono">CALIDAD Y TRAZABILIDAD</div>
          <h3 className="how__title">ISO 9001</h3>
          <p className="how__body">Nuestra arquitectura garantiza trazabilidad absoluta de las transformaciones gracias al <em>Undo Journal</em>. Cada operación sobre lotes de archivos genera un historial determinista que permite auditar y revertir modificaciones (rollback), cumpliendo con los estándares de control de calidad, procesos medibles y gestión documental exigidos por la norma ISO 9001.</p>
        </Reveal>
      </div>
    </section>
  );
}

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