// vsl-shared.jsx — Horus Hub VSL · base brand system, backgrounds, kinetic type
// Loaded after animations.jsx. Exports building blocks to window.

const HORUS = {
  bg:          '#0a0a0f',
  bgSoft:      '#0e0e18',
  card:        'hsl(240 10% 7%)',
  purple:      'hsl(263 70% 50%)',
  purpleLight: 'hsl(263 70% 66%)',
  purpleDeep:  'hsl(263 70% 32%)',
  blue:        'hsl(217 91% 60%)',
  blueLight:   'hsl(217 91% 74%)',
  cyan:        'hsl(188 94% 48%)',
  green:       'hsl(142 70% 45%)',
  white:       '#f5f6fa',
  dim:         'rgba(245,246,250,0.62)',
  faint:       'rgba(245,246,250,0.32)',
  line:        'rgba(255,255,255,0.10)',
  display:     "'Space Grotesk', system-ui, sans-serif",
  sans:        "'Inter', system-ui, sans-serif",
};
const GRAD = `linear-gradient(100deg, ${HORUS.purple} 0%, ${HORUS.blue} 100%)`;
const GRAD_PB = `linear-gradient(120deg, ${HORUS.purpleLight} 0%, ${HORUS.blueLight} 100%)`;

const { Easing: E, clamp: cl, interpolate: itp, useSprite: uSpr } = window;

// ── Full-bleed scene shell ──────────────────────────────────────────────────
function Scene({ children, bg = HORUS.bg }) {
  return (
    <div style={{ position: 'absolute', inset: 0, overflow: 'hidden', background: bg }}>
      {children}
    </div>
  );
}

// ── Phase backgrounds ─────────────────────────────────────────────────────────
// variant: 'warm' (KI), 'cool' (SHO problem), 'data' (SHO context), 'void' (TEN open),
//          'brand' (TEN/KETSU, uses bg-wide.png texture)
function PhaseBg({ variant = 'brand', t = 0, drift = 0.5 }) {
  // slow ken-burns drift value
  const k = (Math.sin(t * 0.08) + 1) / 2; // 0..1 slow
  const common = { position: 'absolute', inset: 0, pointerEvents: 'none' };

  if (variant === 'warm') {
    return (
      <React.Fragment>
        <div style={{ ...common, background: HORUS.bg }} />
        <div style={{
          ...common,
          background: `radial-gradient(60% 70% at ${64 + k * 4}% ${72 - k * 3}%, hsl(34 80% 52% / 0.22) 0%, hsl(28 70% 30% / 0.10) 32%, transparent 62%)`,
        }} />
        <div style={{ ...common, background: `radial-gradient(80% 90% at 50% 120%, hsl(263 60% 22% / 0.30) 0%, transparent 60%)` }} />
      </React.Fragment>
    );
  }
  if (variant === 'cool') {
    return (
      <React.Fragment>
        <div style={{ ...common, background: HORUS.bg }} />
        <div style={{
          ...common,
          background: `radial-gradient(70% 80% at ${30 + k * 6}% 18%, hsl(217 60% 40% / 0.16) 0%, transparent 55%)`,
        }} />
        <div style={{ ...common, background: `radial-gradient(70% 80% at 84% 96%, hsl(263 60% 38% / 0.14) 0%, transparent 55%)` }} />
      </React.Fragment>
    );
  }
  if (variant === 'void') {
    return <div style={{ ...common, background: '#050507' }} />;
  }
  if (variant === 'data') {
    return (
      <React.Fragment>
        <div style={{ ...common, background: HORUS.bgSoft }} />
        <div style={{ ...common, background: `radial-gradient(90% 90% at 50% 40%, hsl(240 30% 12% / 0.6) 0%, ${HORUS.bg} 70%)` }} />
        <GridLines opacity={0.5} />
      </React.Fragment>
    );
  }
  // brand — authentic tech texture, slowly drifting
  return (
    <React.Fragment>
      <div style={{ ...common, background: HORUS.bg }} />
      <img src="assets/bg-wide.png" alt="" style={{
        ...common,
        width: '112%', height: '112%', left: '-6%', top: '-6%',
        objectFit: 'cover',
        opacity: 0.5,
        transform: `scale(${1 + k * 0.05}) translate(${(k - 0.5) * 18}px, ${(k - 0.5) * -10}px)`,
        transformOrigin: 'center',
        filter: 'saturate(1.15)',
      }} />
      <div style={{ ...common, background: `radial-gradient(80% 80% at 50% 50%, transparent 30%, ${HORUS.bg} 92%)` }} />
    </React.Fragment>
  );
}

// faint engineering grid
function GridLines({ opacity = 1 }) {
  return (
    <div style={{
      position: 'absolute', inset: 0, pointerEvents: 'none', opacity,
      backgroundImage: `linear-gradient(${HORUS.line} 1px, transparent 1px), linear-gradient(90deg, ${HORUS.line} 1px, transparent 1px)`,
      backgroundSize: '88px 88px',
      maskImage: 'radial-gradient(70% 70% at 50% 50%, #000 30%, transparent 80%)',
      WebkitMaskImage: 'radial-gradient(70% 70% at 50% 50%, #000 30%, transparent 80%)',
    }} />
  );
}

// ── Global atmosphere: grain + vignette (placed once, above scenes) ──────────
function Atmosphere() {
  return (
    <React.Fragment>
      <div style={{
        position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 60,
        boxShadow: 'inset 0 0 240px 60px rgba(0,0,0,0.66)',
      }} />
      <div style={{
        position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 61, opacity: 0.045,
        backgroundImage: 'url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\' width=\'120\' height=\'120\'><filter id=\'n\'><feTurbulence type=\'fractalNoise\' baseFrequency=\'0.9\' numOctaves=\'2\'/></filter><rect width=\'120\' height=\'120\' filter=\'url(%23n)\'/></svg>")',
        mixBlendMode: 'overlay',
      }} />
    </React.Fragment>
  );
}

// ── Kinetic typography ───────────────────────────────────────────────────────
// envelope for a phrase living in [at, until] (local seconds within its Sprite)
function envelope(localTime, at, until, fadeIn = 0.55, fadeOut = 0.5) {
  if (localTime < at) return { o: 0, ty: 26, done: false };
  if (localTime < at + fadeIn) {
    const t = E.easeOutCubic(cl((localTime - at) / fadeIn, 0, 1));
    return { o: t, ty: (1 - t) * 26, done: false };
  }
  const fadeStart = until - fadeOut;
  if (localTime < fadeStart) return { o: 1, ty: 0, done: false };
  if (localTime < until) {
    const t = E.easeInCubic(cl((localTime - fadeStart) / fadeOut, 0, 1));
    return { o: 1 - t, ty: -t * 22, done: false };
  }
  return { o: 0, ty: -22, done: true };
}

// A single narration line, centred. children may include <HL> spans.
function Line({ at, until, children, cx = 960, cy = 540, size = 66, weight = 600,
  color = HORUS.white, font = HORUS.display, maxWidth = 1180, align = 'center',
  letterSpacing = '-0.02em', lh = 1.16, shadow = true }) {
  const { localTime } = uSpr();
  const { o, ty } = envelope(localTime, at, until);
  if (o <= 0.001) return null;
  return (
    <div style={{
      position: 'absolute', left: cx, top: cy,
      transform: `translate(-50%, calc(-50% + ${ty}px))`,
      width: maxWidth, textAlign: align,
      fontFamily: font, fontSize: size, fontWeight: weight, color,
      letterSpacing, lineHeight: lh, opacity: o,
      textWrap: 'balance', willChange: 'transform, opacity',
      textShadow: shadow ? '0 2px 30px rgba(0,0,0,0.55)' : 'none',
    }}>
      {children}
    </div>
  );
}

// gradient-highlighted run of words
function HL({ children, grad = GRAD }) {
  return (
    <span style={{
      background: grad, WebkitBackgroundClip: 'text', backgroundClip: 'text',
      WebkitTextFillColor: 'transparent', fontWeight: 700,
    }}>{children}</span>
  );
}

// small eyebrow / kicker label
function Kicker({ at, until, children, cx = 960, cy = 400, color = HORUS.purpleLight }) {
  const { localTime } = uSpr();
  const { o, ty } = envelope(localTime, at, until, 0.5, 0.4);
  if (o <= 0.001) return null;
  return (
    <div style={{
      position: 'absolute', left: cx, top: cy,
      transform: `translate(-50%, calc(-50% + ${ty}px))`,
      opacity: o, fontFamily: HORUS.display, fontSize: 22, fontWeight: 600,
      letterSpacing: '0.34em', textTransform: 'uppercase', color,
      whiteSpace: 'nowrap',
    }}>{children}</div>
  );
}

// thin progress / phase indicator (bottom)
function PhaseTag({ label, idx }) {
  return (
    <div style={{
      position: 'absolute', left: 64, bottom: 54, display: 'flex', alignItems: 'center', gap: 14,
      fontFamily: HORUS.display, zIndex: 40,
    }}>
      <div style={{ display: 'flex', gap: 7 }}>
        {[0,1,2,3].map(i => (
          <div key={i} style={{
            width: i === idx ? 30 : 9, height: 4, borderRadius: 3,
            background: i === idx ? GRAD : 'rgba(255,255,255,0.18)',
            transition: 'width .4s',
          }} />
        ))}
      </div>
      <span style={{ fontSize: 14, letterSpacing: '0.32em', textTransform: 'uppercase', color: HORUS.faint }}>{label}</span>
    </div>
  );
}

Object.assign(window, {
  HORUS, GRAD, GRAD_PB,
  Scene, PhaseBg, GridLines, Atmosphere,
  envelope, Line, HL, Kicker, PhaseTag,
});
