// sections.jsx — content overlays for each section.
// The 3D art is rendered by three-scene.js as a global background; these
// components only draw the text/buttons/lists that sit on top.

const { useState, useEffect, useLayoutEffect, useRef, useCallback, useMemo } = React;

// ── Emit gold sparks at a screen point ──────────────────────
function emitSparks(x, y, count = 8) {
  const layer = document.getElementById('sparks');
  if (!layer) return;
  for (let i = 0; i < count; i++) {
    const s = document.createElement('div');
    s.className = 'spark';
    s.style.left = x + 'px';
    s.style.top = y + 'px';
    const angle = Math.random() * Math.PI * 2;
    const dist = 40 + Math.random() * 80;
    s.style.setProperty('--dx', Math.cos(angle) * dist + 'px');
    s.style.setProperty('--dy', Math.sin(angle) * dist + 'px');
    layer.appendChild(s);
    setTimeout(() => s.remove(), 850);
  }
}
window.emitSparks = emitSparks;

// ── Glitch / scramble reveal text ───────────────────────────
function GlitchText({ text, className, style, delay = 0, duration = 700, active = true }) {
  const [out, setOut] = useState('');
  useEffect(() => {
    if (!active) {setOut(text);return;}
    const chars = '!<>-_\\/[]{}—=+*^?#█▓▒░·';
    let start = performance.now() + delay;
    let raf;
    const tick = (now) => {
      const p = Math.max(0, Math.min(1, (now - start) / duration));
      if (p <= 0) {setOut('');raf = requestAnimationFrame(tick);return;}
      let s = '';
      for (let i = 0; i < text.length; i++) {
        const cp = i / text.length;
        if (p > cp + 0.05) s += text[i];else
        if (p > cp - 0.05) s += chars[Math.floor(Math.random() * chars.length)];else
        s += ' ';
      }
      setOut(s);
      if (p < 1) raf = requestAnimationFrame(tick);else
      setOut(text);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [text, delay, duration, active]);
  return <span className={className} style={style}>{out || '\u00A0'}</span>;
}

// ── Hover/click spark wrapper ───────────────────────────────
function Sparkly({ children }) {
  const onClick = (e) => {
    emitSparks(e.clientX, e.clientY, 14);
    if (window.__pulseFlash) window.__pulseFlash();
    if (children.props.onClick) children.props.onClick(e);
  };
  return React.cloneElement(children, { onClick });
}

// ── Magnetic button (subtle pull toward cursor) ─────────────
function Magnetic({ children, strength = 14 }) {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let raf;
    let tx = 0,ty = 0,cx = 0,cy = 0;
    const onMove = (e) => {
      const r = el.getBoundingClientRect();
      const cxR = r.left + r.width / 2;
      const cyR = r.top + r.height / 2;
      const dist = Math.hypot(e.clientX - cxR, e.clientY - cyR);
      if (dist < 160) {
        const k = (1 - dist / 160) * strength;
        tx = (e.clientX - cxR) / r.width * k;
        ty = (e.clientY - cyR) / r.height * k;
      } else {
        tx = 0;ty = 0;
      }
    };
    const onLeave = () => {tx = 0;ty = 0;};
    const loop = () => {
      cx += (tx - cx) * 0.18;
      cy += (ty - cy) * 0.18;
      el.style.transform = `translate3d(${cx}px, ${cy}px, 0)`;
      raf = requestAnimationFrame(loop);
    };
    window.addEventListener('pointermove', onMove);
    window.addEventListener('pointerleave', onLeave);
    loop();
    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener('pointermove', onMove);
      window.removeEventListener('pointerleave', onLeave);
    };
  }, [strength]);
  return <div ref={ref} style={{ display: 'inline-block' }}>{children}</div>;
}

// ── Live ticker stats ───────────────────────────────────────
function useTicker(interval = 50) {
  const [n, setN] = useState(0);
  useEffect(() => {
    const t = setInterval(() => setN((x) => x + 1), interval);
    return () => clearInterval(t);
  }, [interval]);
  return n;
}

// ── Hero ↔ About transition phase ───────────────────────────
// Subscribes to the global `hxtransition` event dispatched by three-scene.js.
// Returns `{ phase, variant }` where phase is:
//   'active'   — transition is running (3D effect + content animating)
//   'settling' — 3D done, give about's entry animation a beat to complete
//   null       — idle
function useTransitionPhase() {
  const [data, setData] = useState({ phase: null, variant: null });
  useEffect(() => {
    let settleTimer;
    const onT = (e) => {
      const { phase, variant } = e.detail || {};
      if (phase === 'start') {
        clearTimeout(settleTimer);
        setData({ phase: 'active', variant });
      } else if (phase === 'end') {
        setData((d) => ({ phase: 'settling', variant: d.variant || variant }));
        clearTimeout(settleTimer);
        settleTimer = setTimeout(() => setData({ phase: null, variant: null }), 700);
      }
    };
    window.addEventListener('hxtransition', onT);
    return () => {
      window.removeEventListener('hxtransition', onT);
      clearTimeout(settleTimer);
    };
  }, []);
  return data;
}

// ═══════════════════════════════════════════════════════════
// 01 — HERO
// ═══════════════════════════════════════════════════════════
function Hero({ active }) {
  const { phase: tPhase, variant: tVariant } = useTransitionPhase();
  const exiting = !!tPhase; // active or settling — keep exited until idle
  return (
    <section className="screen" data-screen-label="01 Hero">
      <div className={`screen-inner hx-content ${exiting ? 'hx-exit' : ''}`}
      data-hx-variant={tVariant || undefined}>
        <div className="eyebrow">
          <span className="num">// INICIO</span>
          <span></span>
          <span className="sec-tag">hx.node.01</span>
        </div>

        <div style={{
          marginTop: 'auto', marginBottom: 'auto',
          display: 'flex', flexDirection: 'column', gap: 36,
          maxWidth: 'min(700px, 60vw)'
        }}>
          <div style={{
            display: 'flex', gap: 10, alignItems: 'center',
            color: 'var(--text-dim)',
            fontSize: 11, letterSpacing: '0.3em', textTransform: 'uppercase',
            fontFamily: 'var(--font-mono)'
          }}>
            <span style={{
              width: 10, height: 10, background: 'var(--accent)',
              boxShadow: '0 0 12px var(--accent)',
              animation: 'pulse 1.6s ease-in-out infinite'
            }}></span>
            <GlitchText text="SEÑAL ADQUIRIDA" active={active} />
          </div>

          <h1 className="h-display" style={{ fontSize: 'clamp(58px, 11vw, 168px)' }}>
            <span style={{ color: 'var(--text)' }}>hecs</span><span style={{ color: 'var(--accent)' }}>trim</span>
          </h1>

          <p style={{
            margin: 0,
            color: 'var(--text-dim)',
            fontSize: 'clamp(16px, 1.6vw, 22px)',
            lineHeight: 1.45,
            maxWidth: 580,
            fontWeight: 300
          }}>
            Hector. Creador de contenido, constructor de agentes.<br />
            <span style={{ color: 'var(--text)' }}>
              IA, automatización y ruido digital con propósito.
            </span>
          </p>

          <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap' }}>
            <Magnetic>
              <Sparkly><button className="btn primary">
                entrar al lab <span className="arrow">→</span>
              </button></Sparkly>
            </Magnetic>
            <Magnetic strength={8}>
              <Sparkly><button className="btn">MATERIALES DESCARGABLES

                </button></Sparkly>
            </Magnetic>
          </div>
        </div>

        <div style={{
          display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end',
          fontFamily: 'var(--font-mono)',
          color: 'var(--text-faint)',
          fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase'
        }}>
          <div>
            <div style={{ color: 'var(--text-dim)' }}>scroll ↓ · acerca el cursor</div>
            <div style={{ marginTop: 6 }}>loop activo · ↻</div>
          </div>
          <div style={{ textAlign: 'right' }}>
            <div>lat 40.4168 · lon −3.7038</div>
            <div style={{ color: 'var(--text-dim)' }}>render · 60 fps · webgl2</div>
          </div>
        </div>
      </div>
    </section>);

}

// ═══════════════════════════════════════════════════════════
// HectorCard — 3D vertical card body with real Y-axis rotation.
// The card has front face (photo), back face (data), and four thin
// edge slabs that give the body genuine thickness. Three variants:
//   'showcase' → continuous slow 360° Y-spin, museum display feel
//   'reveal'   → step-rotate: 180° flip, pause, 180° flip, pause
//   'magnet'   → idle slow spin + cursor X pushes rotation speed
// ═══════════════════════════════════════════════════════════
// ═══════════════════════════════════════════════════════════
// HectorCard — 3D vertical card body. Front face always faces the
// viewer with a gentle Y-axis sway, biased by cursor position
// (pointer adds yaw + slight pitch). Yaw never exceeds ~±30°.
// ═══════════════════════════════════════════════════════════
function HectorCard() {
  const wrapRef = useRef(null);
  const cardRef = useRef(null); // the rotating body
  const shadowRef = useRef(null); // ground shadow

  // Card sizing — kept identical across variants
  const CARD_W = 'min(340px, 78%)';
  const CARD_AR = '5 / 7';
  const THICK = 12; // px, half-depth of the card body (full thickness = 24px)

  // Ground shadow: breathes with the float cycle (used by all variants)
  useEffect(() => {
    const shadow = shadowRef.current;
    if (!shadow) return;
    let raf;
    const start = performance.now();
    const period = 5200;
    const tick = () => {
      const t = (performance.now() - start) / period;
      const lift = Math.sin(t * Math.PI * 2);
      const s = 1 + lift * 0.12;
      const o = 0.42 + lift * 0.18;
      shadow.style.transform = `translateX(-50%) scale(${s.toFixed(3)}, 1)`;
      shadow.style.opacity = o.toFixed(3);
      raf = requestAnimationFrame(tick);
    };
    tick();
    return () => cancelAnimationFrame(raf);
  }, []);

  // Idle Y-axis sway + cursor parallax. Front face stays visible at all times
  // (yaw stays well within ±30°). Cursor X biases the yaw; cursor Y biases X-tilt.
  useEffect(() => {
    const wrap = wrapRef.current;
    const card = cardRef.current;
    if (!wrap || !card) return;
    let targetYawBias = 0; // deg, from cursor X
    let targetPitch = 0; // deg, from cursor Y
    let yawBias = 0,pitch = 0;
    let raf;
    const t0 = performance.now();

    const onMove = (e) => {
      const r = wrap.getBoundingClientRect();
      const cx = r.left + r.width / 2;
      const cy = r.top + r.height / 2;
      // Normalize cursor distance from card center to viewport scale
      const nx = (e.clientX - cx) / (window.innerWidth * 0.5);
      const ny = (e.clientY - cy) / (window.innerHeight * 0.5);
      // Cap effect
      targetYawBias = Math.max(-1, Math.min(1, nx)) * 18; // ± 18°
      targetPitch = Math.max(-1, Math.min(1, ny)) * -10; // ± 10° (inverted)
    };
    const onLeave = () => {targetYawBias = 0;targetPitch = 0;};

    const tick = (now) => {
      const elapsed = (now - t0) / 1000;
      // Idle yaw oscillation: ± 12°, 6 s period
      const idleYaw = Math.sin(elapsed * (Math.PI * 2) / 6) * 12;
      // Smooth toward cursor targets
      yawBias += (targetYawBias - yawBias) * 0.06;
      pitch += (targetPitch - pitch) * 0.06;
      const yaw = idleYaw + yawBias;
      card.style.transform = `rotateY(${yaw.toFixed(2)}deg) rotateX(${pitch.toFixed(2)}deg)`;
      raf = requestAnimationFrame(tick);
    };

    window.addEventListener('pointermove', onMove);
    window.addEventListener('pointerleave', onLeave);
    raf = requestAnimationFrame(tick);
    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener('pointermove', onMove);
      window.removeEventListener('pointerleave', onLeave);
    };
  }, []);

  // Inline keyframes for the vertical float bob
  const KEYFRAMES = `
    @keyframes hxFloatA {
      0%, 100% { transform: translateY(-6px); }
      50%      { transform: translateY(8px); }
    }
  `;

  // Corner radius applied to all six surfaces of the body.
  const RADIUS = 24;

  // The card body. Front face holds the photo (framed with margin), back face
  // holds the persona data, and four edge slabs give the body real thickness.
  // Edge slabs are inset from the rounded corners so they don't poke past them.
  const renderBody = () =>
  <>
      {/* FRONT face — photo framed by margin, rounded corners */}
      <div style={{
      position: 'absolute', inset: 0,
      backfaceVisibility: 'hidden',
      transform: `translateZ(${THICK}px)`,
      background: 'var(--bg-2)',

      borderRadius: RADIUS,
      padding: 18,
      display: 'flex', flexDirection: 'column', gap: 14,
      boxShadow: `
          0 0 0 1px rgba(255,242,0,0.18),
          0 36px 80px rgba(0,0,0,0.7),
          0 0 60px rgba(255,242,0,0.10)
        `, border: "1px solid rgb(244, 244, 240)"
    }}>
        {/* image area — inset from the card edge with its own rounded corners */}
        <div style={{
        flex: 1,
        position: 'relative',
        borderRadius: 14,
        overflow: 'hidden',
        border: '1px solid rgba(255,242,0,0.18)',
        minHeight: 0
      }}>
          <img src="assets/hector.png" alt="Hector"
        draggable="false"
        style={{
          position: 'absolute', inset: 0,
          width: '100%', height: '100%',
          objectFit: 'cover',
          filter: 'contrast(1.04) saturate(1.05)'
        }} />
          {/* scanlines */}
          <div style={{
          position: 'absolute', inset: 0,
          background: 'repeating-linear-gradient(0deg, rgba(0,0,0,0.16) 0 1px, transparent 1px 3px)',
          mixBlendMode: 'multiply', opacity: 0.35, pointerEvents: 'none'
        }}></div>
          {/* header overlay on top of image */}
          <div style={{
          position: 'absolute', top: 12, left: 14, right: 14,
          display: 'flex', justifyContent: 'space-between',
          fontFamily: 'var(--font-mono)',
          fontSize: 9, letterSpacing: '0.24em', textTransform: 'uppercase',
          color: '#fff200',
          textShadow: '0 0 8px rgba(255,242,0,0.45)'
        }}>
            <span></span>
            <span></span>
          </div>
        </div>
        {/* footer — sits in the frame margin below the image */}
        <div style={{
        padding: '2px 6px 0',
        display: 'flex', flexDirection: 'column', gap: 3
      }}>
          <div style={{
          fontFamily: 'var(--font-mono)', fontSize: 9,
          letterSpacing: '0.24em', textTransform: 'uppercase', color: "rgb(203, 249, 255)"
        }}>PERSONAJE</div>
          <div style={{
          fontFamily: 'var(--font-sans)', fontWeight: 500, fontSize: 18,
          color: 'var(--text)', letterSpacing: '-0.01em'
        }}> <span style={{ color: "rgb(255, 255, 255)" }}>·</span> hecstrim</div>
          <div style={{
          fontFamily: 'var(--font-mono)', fontSize: 10,
          color: 'var(--text-dim)'
        }}>Ingeniero IA · Creador de contenido</div>
        </div>
      </div>

      {/* BACK face — closes the body, gray surface matching the edge slabs.
      Reserved for the personal brand logo (to come). */}
      <div style={{
      position: 'absolute', inset: 0,
      backfaceVisibility: 'hidden',
      transform: `rotateY(180deg) translateZ(${THICK}px)`,
      background: `
          linear-gradient(135deg, var(--bg-3) 0%, var(--bg-2) 60%, var(--bg-1) 100%)
        `,
      border: '1px solid #fff200',
      borderRadius: RADIUS,
      boxShadow: `
          0 0 0 1px rgba(255,242,0,0.18),
          0 36px 80px rgba(0,0,0,0.7),
          inset 0 0 40px rgba(0,0,0,0.45)
        `
    }}></div>

      {/* EDGE slabs — inset from rounded corners so they don't poke out */}
      {/* top edge */}
      <div style={{
      position: 'absolute', left: RADIUS, right: RADIUS, top: 0,
      height: THICK * 2,
      transform: `translateY(-${THICK}px) rotateX(90deg)`,
      transformOrigin: '50% 100%',
      background: 'linear-gradient(90deg, var(--bg-0), var(--bg-3) 50%, var(--bg-0))'
    }}></div>
      {/* bottom edge */}
      <div style={{
      position: 'absolute', left: RADIUS, right: RADIUS, bottom: 0,
      height: THICK * 2,
      transform: `translateY(${THICK}px) rotateX(-90deg)`,
      transformOrigin: '50% 0%',
      background: 'linear-gradient(90deg, var(--bg-0), var(--bg-3) 50%, var(--bg-0))'
    }}></div>
      {/* left edge */}
      <div style={{
      position: 'absolute', top: RADIUS, bottom: RADIUS, left: 0,
      width: THICK * 2,
      transform: `translateX(-${THICK}px) rotateY(-90deg)`,
      transformOrigin: '100% 50%',
      background: 'linear-gradient(180deg, var(--bg-0), var(--bg-3) 50%, var(--bg-0))'
    }}></div>
      {/* right edge */}
      <div style={{
      position: 'absolute', top: RADIUS, bottom: RADIUS, right: 0,
      width: THICK * 2,
      transform: `translateX(${THICK}px) rotateY(90deg)`,
      transformOrigin: '0% 50%',
      background: 'linear-gradient(180deg, var(--bg-0), var(--bg-3) 50%, var(--bg-0))'
    }}></div>
    </>;


  // The wrapper sits inside the section column; everything sits in a perspective stage.
  return (
    <div ref={wrapRef} style={{
      position: 'relative',
      width: '100%', height: '100%',
      minHeight: 520,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      perspective: '1600px',
      perspectiveOrigin: '50% 40%'
    }}>
      <style>{KEYFRAMES}</style>

      {/* ground shadow */}
      <div ref={shadowRef} style={{
        position: 'absolute', bottom: '10%', left: '50%',
        width: '46%', height: 18,
        transform: 'translateX(-50%)',
        background: 'radial-gradient(ellipse, rgba(0,0,0,0.55), transparent 70%)',
        filter: 'blur(14px)'
      }}></div>

      {/* outer floater: handles the vertical bob */}
      <div style={{
        width: CARD_W,
        aspectRatio: CARD_AR,
        animation: 'hxFloatA 5.4s ease-in-out infinite'
      }}>
        {/* inner rotator: the actual 3D body */}
        <div ref={cardRef} style={{
          position: 'relative',
          width: '100%', height: '100%',
          transformStyle: 'preserve-3d',
          willChange: 'transform'
        }}>
          {renderBody()}
        </div>
      </div>
    </div>);

}

// ═══════════════════════════════════════════════════════════
// 02 — ABOUT
// ═══════════════════════════════════════════════════════════
function About({ active }) {
  const { phase: tPhase, variant: tVariant } = useTransitionPhase();
  // Two-step entry. The transition fires the SAME tick that .hx-transitioning
  // pins About as a fixed full-viewport overlay — so if About paints at its
  // settled state for even one frame, the user sees the content flash into the
  // center BEFORE it snaps to the displaced start state. That's the
  // "bajan-suben-bajan" glitch.
  //
  // Fix: useLayoutEffect runs AFTER React commits but BEFORE the browser
  // paints. setState inside it triggers a synchronous re-render that is
  // flushed before paint, so the very first paint already shows About at
  // hx-enter-start (translateY 60px, opacity 0, snapped via
  // transition-duration:0s). No center flash, no extra "down" movement.
  //
  // Then useEffect (post-paint) schedules a 2-rAF beat to flip to hx-enter so
  // the CSS transition fires and About slides up to its settled position once,
  // smoothly.
  const [enterClass, setEnterClass] = useState('');
  useLayoutEffect(() => {
    if (tPhase === 'active') {
      setEnterClass('hx-enter-start');
    } else if (tPhase === null) {
      setEnterClass('');
    }
    // 'settling' — leave enterClass at 'hx-enter' so it stays settled
  }, [tPhase]);
  useEffect(() => {
    if (enterClass !== 'hx-enter-start') return;
    // Hold About at the displaced/invisible state until AFTER the 3D warp
    // (1.6s) fully resolves, so the dive does the visual heavy lifting
    // alone and the content arrives as a follow-up beat — not concurrent.
    const ENTER_HOLD_MS = 1800;
    const timer = setTimeout(() => setEnterClass('hx-enter'), ENTER_HOLD_MS);
    return () => clearTimeout(timer);
  }, [enterClass]);

  const stats = [
  ['focus.areas', 'IA · Automation · Storytelling'],
  ['based.in', 'Madrid · everywhere online'],
  ['stack', 'LLMs · Python · Next · Three'],
  ['status', 'shipping daily · open to collab']];

  return (
    <section className="screen" data-screen-label="02 About">
      <div className={`screen-inner hx-content ${enterClass}`}
      data-hx-variant={tVariant || undefined}>
        <div className="eyebrow">
          <span className="num">//</span>
          <span style={{ color: "rgb(230, 230, 230)" }}>PERFIL</span>
          <span className="sec-tag"></span>
        </div>

        <div style={{
          marginTop: 'auto', marginBottom: 'auto',
          display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 'clamp(40px, 6vw, 100px)',
          alignItems: 'center'
        }}>
          {/* Left — title spans into the 3D portrait area */}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 24 }}>
            <h2 className="h-display" style={{ fontSize: 'clamp(48px, 6vw, 96px)' }}>
              <span style={{ color: 'var(--text-dim)' }}>Este es</span><br />
              <span style={{ color: 'var(--text)' }}>HECTOR</span><span style={{ color: 'var(--accent)' }}>.</span>
            </h2>
            <p style={{
              margin: 0,
              color: 'var(--text-dim)',
              fontSize: 'clamp(15px, 1.4vw, 18px)',
              lineHeight: 1.55,
              fontWeight: 300,
              maxWidth: 480
            }}>Ingeniero y maker de IA que ayuda a otras personas en su camino con la IA, a través de materiales, formación en inteligencia artificial y tecnología.


            </p>
            <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', marginTop: 8 }}>
              {['ingeniero-ia', 'creador', 'investigador', 'open-source'].map((tag) =>
              <span key={tag} className="chip" style={{ borderColor: "rgb(244, 244, 241)", color: "rgb(244, 244, 241)" }}>#{tag}</span>
              )}
            </div>
          </div>

          {/* Right — 3D levitating card with portrait */}
          <HectorCard />
        </div>

        <div style={{
          fontFamily: 'var(--font-mono)', fontSize: 10,
          color: 'var(--text-faint)', letterSpacing: '0.22em', textTransform: 'uppercase'
        }}>
          // las partículas regresan cuando dejas de perseguirlas
        </div>
      </div>
    </section>);

}

// ═══════════════════════════════════════════════════════════
// 03 — DELIVERABLES
// ═══════════════════════════════════════════════════════════
const DELIVERABLES = [
{ cmd: 'wget', path: '/prompts/agent-system-v3.md', label: 'Prompts de sistema para agentes · v3', size: '12 KB', tag: 'gratis', kind: '.md' },
{ cmd: 'git clone', path: 'github.com/hecstrim/llm-toolkit', label: 'Toolkit LLM · helpers en Python, evals, fixtures', size: '2.4 MB', tag: 'gratis', kind: 'repo' },
{ cmd: 'curl -O', path: '/packs/voice-clone-recipe.zip', label: 'Receta clon de voz · pipeline completo', size: '48 MB', tag: '€19', kind: '.zip' },
{ cmd: 'wget', path: '/prompts/cinematic-shorts.json', label: 'Cortos cinematográficos · 40 prompts de vídeo', size: '36 KB', tag: '€9', kind: '.json' },
{ cmd: 'git clone', path: 'github.com/hecstrim/notion-ops', label: 'Notion Ops · plantilla segundo cerebro', size: '1.1 MB', tag: 'gratis', kind: 'repo' },
{ cmd: 'curl -O', path: '/skills/diffusion-finetune.pdf', label: 'Fine-tune de difusión · manual de 32 páginas', size: '8.2 MB', tag: '€14', kind: '.pdf' }];


function DelivRow({ item, idx, focused, onFocus }) {
  const isPaid = item.tag.startsWith('€');
  return (
    <div
      onMouseEnter={() => onFocus(idx)}
      onClick={(e) => {emitSparks(e.clientX, e.clientY, 12);window.__pulseFlash && window.__pulseFlash();}}
      style={{
        display: 'grid',
        gridTemplateColumns: '36px 110px 1fr auto auto',
        gap: 16,
        alignItems: 'center',
        padding: '16px 22px',
        cursor: 'pointer',
        borderBottom: '1px solid var(--line-soft)',
        background: focused ?
        'linear-gradient(90deg, var(--accent-soft), transparent 60%)' :
        'transparent',
        transition: 'background 0.22s, padding 0.22s',
        paddingLeft: focused ? 32 : 22
      }}>
      
      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-faint)' }}>
        {String(idx + 1).padStart(2, '0')}
      </span>
      <span style={{
        fontFamily: 'var(--font-mono)', fontSize: 12,
        color: focused ? 'var(--accent)' : 'var(--text-dim)',
        letterSpacing: '0.1em'
      }}>$ {item.cmd}</span>
      <span style={{
        fontFamily: 'var(--font-mono)', fontSize: 13,
        color: 'var(--text)',
        minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap'
      }}>{item.path}</span>
      <span style={{
        fontFamily: 'var(--font-mono)', fontSize: 10,
        color: 'var(--text-faint)', letterSpacing: '0.18em'
      }}>{item.size}</span>
      <span style={{
        fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.22em',
        textTransform: 'uppercase',
        color: isPaid ? 'var(--bg-0)' : 'var(--accent)',
        background: isPaid ? 'var(--accent)' : 'transparent',
        border: '1px solid var(--accent)',
        padding: '5px 12px',
        minWidth: 64, textAlign: 'center'
      }}>{item.tag}</span>
    </div>);

}

function Deliverables({ active }) {
  const [focused, setFocused] = useState(0);
  const item = DELIVERABLES[focused];
  return (
    <section className="screen" data-screen-label="03 Deliverables">
      <div className="screen-inner">
        <div className="eyebrow">
          <span className="num">//</span>
          <span>payloads.registry</span>
          <span className="sec-tag">{DELIVERABLES.length} entries</span>
        </div>

        <div style={{
          display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
          flexWrap: 'wrap', gap: 16, marginBottom: 28
        }}>
          <h2 className="h-display" style={{ fontSize: 'clamp(36px, 5vw, 72px)' }}>
            <span style={{ color: 'var(--text)' }}>Descargables</span>
            <span style={{ color: 'var(--accent)' }}>.</span>
          </h2>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-dim)', letterSpacing: '0.14em' }}>
            <span style={{ color: 'var(--accent)' }}>{DELIVERABLES.filter((d) => d.tag === 'gratis').length}</span> gratis
            &nbsp;·&nbsp;
            <span style={{ color: 'var(--accent)' }}>{DELIVERABLES.filter((d) => d.tag !== 'gratis').length}</span> de pago
            &nbsp;·&nbsp; actualizado semanalmente
          </div>
        </div>

        <div className="card" style={{
          flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0
        }}>
          <div style={{
            padding: '12px 22px',
            borderBottom: '1px solid var(--line)',
            display: 'flex', justifyContent: 'space-between', alignItems: 'center',
            fontFamily: 'var(--font-mono)', fontSize: 10,
            color: 'var(--text-faint)', letterSpacing: '0.22em', textTransform: 'uppercase'
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <span style={{ width: 6, height: 6, borderRadius: 3, background: 'var(--accent)' }}></span>
              hector@hecstrim:~/descargables
            </div>
            <div>tab ⌥ para explorar</div>
          </div>
          <div style={{ flex: 1, overflowY: 'auto', overflowX: 'hidden' }}>
            {DELIVERABLES.map((d, i) =>
            <DelivRow key={i} idx={i} item={d} focused={focused === i} onFocus={setFocused} />
            )}
          </div>
          <div style={{
            display: 'grid', gridTemplateColumns: '1fr auto',
            padding: '14px 22px', borderTop: '1px solid var(--line)',
            background: 'rgba(20,20,26,0.55)',
            fontFamily: 'var(--font-mono)', fontSize: 13,
            color: 'var(--text-dim)'
          }}>
            <div>
              <span style={{ color: 'var(--accent)' }}>›</span>{' '}
              <span style={{ color: 'var(--text)' }}>{item.label}</span>
              <span style={{ marginLeft: 12, color: 'var(--text-faint)', fontSize: 10, letterSpacing: '0.18em', textTransform: 'uppercase' }}>
                · {item.kind} · {item.size}
              </span>
            </div>
            <Sparkly><button className="btn" style={{ padding: '8px 16px', fontSize: 10 }}>
              {item.tag === 'gratis' ? '↓ descargar' : `↓ desbloquear ${item.tag}`}
            </button></Sparkly>
          </div>
        </div>
      </div>
    </section>);

}

// ═══════════════════════════════════════════════════════════
// 04 — SHOP
// ═══════════════════════════════════════════════════════════
const SHOP_DIGITAL = [
{ name: 'AGENT.PACK', sub: '120 prompts de sistema para builders de agentes', price: '€29' },
{ name: 'CINEMA.JSON', sub: 'Biblioteca de prompts para pipelines de vídeo IA', price: '€19' },
{ name: 'NOTION.OS', sub: 'Plantilla segundo cerebro + automatizaciones', price: '€14' },
{ name: 'VOICE.KIT', sub: 'Recetas de clon de voz + audio de referencia', price: '€39' }];

const SHOP_PHYSICAL = [
{ name: 'TEE · hxnode', sub: 'Algodón pesado negro · estampado de acento', price: '€34' },
{ name: 'HOODIE · terminal', sub: 'Corte boxy, cursor bordado', price: '€68' },
{ name: 'STICKER PACK', sub: '8 vinilos troquelados · resistentes al agua', price: '€9' },
{ name: 'POSTER · A2', sub: 'Risografía, manifiesto en píxeles', price: '€22' }];


function ProductCard({ p }) {
  const ref = useRef(null);
  return (
    <div
      ref={ref}
      className="card"
      onClick={(e) => {emitSparks(e.clientX, e.clientY, 12);window.__pulseFlash && window.__pulseFlash();}}
      style={{
        padding: 22,
        display: 'flex', flexDirection: 'column', gap: 12,
        cursor: 'pointer',
        minHeight: 220
      }}
      onMouseMove={(e) => {
        const r = ref.current.getBoundingClientRect();
        const x = ((e.clientX - r.left) / r.width - 0.5) * 8;
        const y = ((e.clientY - r.top) / r.height - 0.5) * -8;
        ref.current.style.transform = `perspective(800px) rotateX(${y}deg) rotateY(${x}deg) translateY(-2px)`;
      }}
      onMouseLeave={() => {ref.current.style.transform = '';}}>
      
      <div style={{
        height: 80,
        background: `
          repeating-linear-gradient(0deg, rgba(255,255,255,0.04) 0 1px, transparent 1px 12px),
          radial-gradient(circle at 30% 30%, var(--accent-soft), transparent 70%)
        `,
        border: '1px solid var(--line)',
        position: 'relative',
        display: 'flex', alignItems: 'flex-end',
        padding: 10
      }}>
        <span style={{
          fontFamily: 'var(--font-mono)', fontSize: 9,
          color: 'var(--text-faint)', letterSpacing: '0.22em', textTransform: 'uppercase'
        }}>{p.name.split(' ')[0]}</span>
        <span style={{
          position: 'absolute', top: 8, right: 10,
          width: 8, height: 8, background: 'var(--accent)',
          boxShadow: '0 0 8px var(--accent)'
        }}></span>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text)', letterSpacing: '0.04em' }}>
          {p.name}
        </div>
        <div style={{ fontSize: 13, color: 'var(--text-dim)', lineHeight: 1.4 }}>{p.sub}</div>
      </div>
      <div style={{
        marginTop: 'auto',
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        paddingTop: 8, borderTop: '1px solid var(--line-soft)'
      }}>
        <span style={{ fontFamily: 'var(--font-mono)', fontSize: 14, color: 'var(--accent)', fontWeight: 700 }}>
          {p.price}
        </span>
        <span style={{
          fontFamily: 'var(--font-mono)', fontSize: 10,
          letterSpacing: '0.22em', textTransform: 'uppercase',
          color: 'var(--text-dim)'
        }}>añadir ↗</span>
      </div>
    </div>);

}

function Shop({ active }) {
  const [mode, setMode] = useState('digital');
  const items = mode === 'digital' ? SHOP_DIGITAL : SHOP_PHYSICAL;
  const modeLabel = mode === 'digital' ? 'digital' : 'física';
  return (
    <section className="screen" data-screen-label="04 Shop">
      <div className="screen-inner">
        <div className="eyebrow">
          <span className="num">// 03</span>
          <span>tienda.{modeLabel}</span>
          <span className="sec-tag">{items.length} sku</span>
        </div>

        <div style={{
          display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end',
          flexWrap: 'wrap', gap: 24, marginBottom: 28
        }}>
          <h2 className="h-display" style={{ fontSize: 'clamp(36px, 5vw, 72px)' }}>
            <span style={{ color: 'var(--text)' }}>Tienda</span>
            <span style={{ color: 'var(--accent)' }}>.</span>
            <span style={{ color: 'var(--text-dim)', fontSize: '0.45em', marginLeft: 8 }}>{modeLabel}</span>
          </h2>

          <div style={{
            position: 'relative',
            display: 'inline-flex',
            border: '1px solid var(--line)',
            background: 'rgba(20, 20, 26, 0.6)',
            padding: 4,
            fontFamily: 'var(--font-mono)', fontSize: 11,
            letterSpacing: '0.2em', textTransform: 'uppercase'
          }}>
            <div style={{
            position: 'absolute',
              top: 4, bottom: 4,
              left: mode === 'digital' ? 4 : 'calc(50%)',
              width: 'calc(50% - 4px)',
              background: 'var(--accent)',
              transition: 'left 0.32s cubic-bezier(.6,.05,.3,1)',
              boxShadow: '0 0 18px var(--accent-glow)'
            }}></div>
            {[{key:'digital',label:'digital'},{key:'physical',label:'física'}].map((m) =>
            <button key={m.key}
            onClick={(e) => {setMode(m.key);emitSparks(e.clientX, e.clientY, 14);}}
            style={{
              position: 'relative', zIndex: 1,
              appearance: 'none', background: 'transparent', border: 0,
              color: mode === m.key ? 'var(--bg-0)' : 'var(--text-dim)',
              fontWeight: mode === m.key ? 700 : 400,
              font: 'inherit', letterSpacing: 'inherit', textTransform: 'inherit',
              padding: '10px 22px', cursor: 'pointer',
              transition: 'color 0.2s'
            }}>{m.label}</button>
            )}
          </div>
        </div>

        <div style={{
          display: 'grid',
          gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))',
          gap: 16,
          flex: 1,
          alignContent: 'start'
        }}>
          {items.map((p, i) => <ProductCard key={mode + i} p={p} />)}
        </div>

        <div style={{
          marginTop: 18,
          fontFamily: 'var(--font-mono)', fontSize: 10,
          color: 'var(--text-faint)', letterSpacing: '0.22em', textTransform: 'uppercase',
          display: 'flex', justifyContent: 'space-between', flexWrap: 'wrap', gap: 8
        }}>
          <span>{items.length} items · {mode === 'digital' ? 'descarga inmediata' : 'envío mundial'}</span>
          <span>pago seguro · stripe · paypal</span>
        </div>
      </div>
    </section>);

}

// ═══════════════════════════════════════════════════════════
// 05 — LINKS
// ═══════════════════════════════════════════════════════════
const SOCIALS = [
{ name: 'YouTube', handle: '@hecstrim', url: 'youtube.com/@hecstrim', cat: 'vídeo' },
{ name: 'Instagram', handle: '@hecstrim', url: 'instagram.com/hecstrim', cat: 'visual' },
{ name: 'GitHub', handle: '/hecstrim', url: 'github.com/hecstrim', cat: 'código' },
{ name: 'TikTok', handle: '@hecstrim', url: 'tiktok.com/@hecstrim', cat: 'shorts' },
{ name: 'X / Twitter', handle: '@hecstrim', url: 'x.com/hecstrim', cat: 'texto' },
{ name: 'Spotify', handle: 'hecstrim · lab', url: 'open.spotify.com/user/hx', cat: 'audio' },
{ name: 'Substack', handle: 'hecstrim.sub', url: 'hecstrim.substack.com', cat: 'long-form' },
{ name: 'Discord', handle: 'hx.node', url: 'discord.gg/hxnode', cat: 'comunidad' }];


function LinkRow({ s, i }) {
  return (
    <a
      href={'https://' + s.url}
      target="_blank" rel="noopener noreferrer"
      onClick={(e) => {emitSparks(e.clientX, e.clientY, 14);window.__pulseFlash && window.__pulseFlash();}}
      style={{
        display: 'grid',
        gridTemplateColumns: '36px 1fr 1fr auto',
        alignItems: 'center', gap: 18,
        padding: '20px 22px',
        borderBottom: '1px solid var(--line-soft)',
        textDecoration: 'none',
        color: 'inherit',
        transition: 'background 0.22s, padding 0.22s'
      }}
      onMouseEnter={(e) => {e.currentTarget.style.background = 'var(--accent-soft)';e.currentTarget.style.paddingLeft = '32px';}}
      onMouseLeave={(e) => {e.currentTarget.style.background = 'transparent';e.currentTarget.style.paddingLeft = '22px';}}>
      
      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-faint)' }}>
        {String(i + 1).padStart(2, '0')}
      </span>
      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 14, color: 'var(--text)', letterSpacing: '0.04em' }}>
        {s.name}
      </span>
      <span style={{
        fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text-dim)',
        minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap'
      }}>{s.url}</span>
      <span style={{
        fontFamily: 'var(--font-mono)', fontSize: 10,
        letterSpacing: '0.22em', textTransform: 'uppercase',
        color: 'var(--text-dim)',
        display: 'inline-flex', alignItems: 'center', gap: 8
      }}>
        {s.cat} <span style={{ color: 'var(--accent)' }}>↗</span>
      </span>
    </a>);

}

function Links({ active }) {
  return (
    <section className="screen" data-screen-label="05 Links">
      <div className="screen-inner">
        <div className="eyebrow">
          <span className="num">// 04</span>
          <span>red.contactos</span>
          <span className="sec-tag">{SOCIALS.length} nodos</span>
        </div>

        <div style={{
          display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
          flexWrap: 'wrap', gap: 16, marginBottom: 28
        }}>
          <h2 className="h-display" style={{ fontSize: 'clamp(36px, 5vw, 72px)' }}>
            <span style={{ color: 'var(--text)' }}>enlaces</span>
            <span style={{ color: 'var(--accent)' }}>.</span>
          </h2>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-dim)', letterSpacing: '0.14em' }}>
            todas las rutas cifradas · túnel ssh listo
          </div>
        </div>

        <div className="card" style={{ flex: 1, overflowY: 'auto', minHeight: 0 }}>
          {SOCIALS.map((s, i) => <LinkRow key={s.name} s={s} i={i} />)}
        </div>

        <div style={{
          marginTop: 18,
          fontFamily: 'var(--font-mono)', fontSize: 13,
          color: 'var(--text-dim)',
          display: 'flex', justifyContent: 'space-between', flexWrap: 'wrap', gap: 8
        }}>
          <span><span style={{ color: 'var(--accent)' }}>$</span> echo "saluda → hola@hecstrim.com"</span>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase' }}>
            // continuar · el loop vuelve al inicio
          </span>
        </div>
      </div>
    </section>);

}

// Pulse keyframes injection (one-off)
if (!document.getElementById('__sec-styles')) {
  const sty = document.createElement('style');
  sty.id = '__sec-styles';
  sty.textContent = `
    @keyframes pulse {
      0%, 100% { opacity: 1; transform: scale(1); }
      50%      { opacity: 0.4; transform: scale(0.85); }
    }
  `;
  document.head.appendChild(sty);
}

Object.assign(window, {
  Hero, About, Deliverables, Shop, Links, HectorCard
});