// ============================================================
// Tribeca Lisboa — UI primitives (faithful to reference UI kit)
// icons · logo · tags · card label · status badge · buttons
// ============================================================
const { useState } = React;

// Standalone-export resolver: returns the inlined blob URL when present
// (window.__resources keyed by path), otherwise the original path.
window.R = (p) => (window.__resources && window.__resources[p]) || p;

const CAT = {
  film:      { bg: 'var(--film-bg)',      hl: 'var(--film-hl)',      label: 'Film' },
  podcasts:  { bg: 'var(--podcasts-bg)',  hl: 'var(--podcasts-hl)',  label: 'Podcasts' },
  talks:     { bg: 'var(--talks-bg)',     hl: 'var(--talks-hl)',     label: 'Talks' },
  vibes:     { bg: 'var(--vibes-bg)',     hl: 'var(--vibes-hl)',     label: 'Vibes' },
  nightlive: { bg: 'var(--nightlive-bg)', hl: 'var(--nightlive-hl)', label: 'Night Live' },
  immersive: { bg: 'var(--immersive-bg)', hl: 'var(--immersive-hl)', label: 'Immersive' },
  awards:    { bg: 'var(--awards-bg)',    hl: 'var(--awards-hl)',    label: 'Awards' },
  industry:  { bg: 'var(--industry-bg)',  hl: 'var(--industry-hl)',  label: 'Industry' },
};

const ASSET = 'ds/assets';

// ---- Icons (1px line, 16px, currentColor) -----------------
function IconArrow({ size = 16 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none" style={{ display: 'block' }}>
      <path d="M4 12 L12 4 M5.5 4 H12 V10.5" stroke="currentColor" strokeWidth="1.4" />
    </svg>
  );
}
function IconPin({ size = 16 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none" style={{ display: 'block' }}>
      <path d="M8 1.5c-2.5 0-4.5 2-4.5 4.5 0 3.2 4.5 8 4.5 8s4.5-4.8 4.5-8c0-2.5-2-4.5-4.5-4.5z" stroke="currentColor" strokeWidth="1.2" />
      <circle cx="8" cy="6" r="1.6" stroke="currentColor" strokeWidth="1.2" />
    </svg>
  );
}
function IconInstagram({ size = 24 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" style={{ display: 'block' }}>
      <rect x="3" y="3" width="18" height="18" rx="5" stroke="currentColor" strokeWidth="1.6" />
      <circle cx="12" cy="12" r="4" stroke="currentColor" strokeWidth="1.6" />
      <circle cx="17.2" cy="6.8" r="1.1" fill="currentColor" />
    </svg>
  );
}
function Hamburger({ color = '#fff' }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 5, width: 26 }}>
      {[0, 1, 2].map(i => <span key={i} style={{ height: 2.5, background: color, display: 'block' }} />)}
    </div>
  );
}

// ---- Logo (extracted Figma wordmark) ----------------------
function Logo({ variant = 'white', width = 96 }) {
  const src = variant === 'white' ? `${ASSET}/logo-tribeca-white.svg` : `${ASSET}/logo-tribeca-black.svg`;
  return <img src={R(src)} alt="Tribeca Festival Lisboa" style={{ width, height: 'auto', display: 'block' }} />;
}

// ---- Tag (category pill) -----------------------------------
function Tag({ cat, children, solid }) {
  const c = CAT[cat] || CAT.film;
  return (
    <span className="t-tag" style={{
      display: 'inline-block', borderRadius: 'var(--radius-pill)',
      padding: '5px 11px', background: c.bg, color: solid ? '#fff' : c.hl,
    }}>{children || c.label}</span>
  );
}

// ---- Card label (square block with category wordmark mark) -
function CardLabel({ cat }) {
  const c = CAT[cat] || CAT.industry;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', background: c.bg,
      padding: '8px', height: 32, boxSizing: 'border-box',
    }}>
      <img src={R(`${ASSET}/mark-${cat}-hl.svg`)} alt={c.label} style={{ height: 16, width: 'auto', display: 'block' }} />
    </span>
  );
}

// ---- Status badge (LIVE / SOON) ----------------------------
function StatusBadge({ kind }) {
  const live = kind === 'LIVE';
  return (
    <span style={{
      borderRadius: 'var(--radius-xs)', padding: '4px 9px',
      background: live ? 'var(--pink)' : 'var(--purple)', color: '#fff',
      fontFamily: 'var(--font-text)', fontWeight: 700, fontSize: 12, letterSpacing: '.03em',
    }}>{kind}</span>
  );
}

// ---- Buttons -----------------------------------------------
function PrimaryButton({ children, onClick, full = true }) {
  const [h, setH] = useState(false);
  return (
    <button onClick={onClick} onMouseEnter={() => setH(true)} onMouseLeave={() => setH(false)}
      style={{
        width: full ? '100%' : 'auto', height: 40, border: 'none', cursor: 'pointer',
        fontFamily: 'var(--font-text)', fontWeight: 700, fontSize: 14, letterSpacing: '.02em',
        background: h ? 'var(--pink)' : '#fff', color: h ? '#fff' : '#000',
        transition: 'background .15s, color .15s', textTransform: 'uppercase',
      }}>{children}</button>
  );
}
function SecondaryButton({ children, onClick, dark = false }) {
  const [h, setH] = useState(false);
  const base = dark ? '#fff' : '#000';
  const onbg = dark ? '#000' : '#fff';
  return (
    <button onClick={onClick} onMouseEnter={() => setH(true)} onMouseLeave={() => setH(false)}
      style={{
        width: '100%', height: 38, cursor: 'pointer', border: `1px solid ${base}`,
        fontFamily: 'var(--font-text)', fontWeight: 700, fontSize: 14, letterSpacing: '.02em',
        textTransform: 'uppercase', transition: 'background .15s, color .15s',
        background: h ? base : 'transparent', color: h ? onbg : base,
      }}>{children}</button>
  );
}
function TertiaryButton({ children, onClick, color = '#000' }) {
  const [h, setH] = useState(false);
  return (
    <button onClick={onClick} onMouseEnter={() => setH(true)} onMouseLeave={() => setH(false)}
      style={{
        background: 'none', border: 'none', padding: 0, cursor: 'pointer', display: 'inline-flex',
        flexDirection: 'column', gap: 4, color, alignItems: 'flex-start',
      }}>
      <span style={{
        display: 'flex', alignItems: 'center', gap: h ? 14 : 8, transition: 'gap .15s', whiteSpace: 'nowrap',
        fontFamily: 'var(--font-text)', fontWeight: 700, fontSize: 14,
      }}>{children} <IconArrow /></span>
      <span style={{ height: 2, width: '100%', background: color, display: 'block' }} />
    </button>
  );
}
function ButtonLink({ children, onClick, color = '#fff' }) {
  return (
    <button onClick={onClick} style={{
      background: 'none', border: 'none', padding: 0, cursor: 'pointer', color, whiteSpace: 'nowrap',
      fontFamily: 'var(--font-text)', fontWeight: 700, fontSize: 12,
    }}>{children}</button>
  );
}

// ---- Reveal: subtle scroll-triggered fade + rise ------------
// Observes against the nearest scroll container (the iOS frame's
// content area). Honors prefers-reduced-motion. `delay` (ms) lets
// sibling reveals cascade for a layered, cinematic rhythm.
const PREFERS_REDUCED = typeof window !== 'undefined'
  && window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

function Reveal({ children, delay = 0, y = 24, dur = 820, style, as = 'div', className }) {
  const ref = React.useRef(null);
  const [inView, setInView] = React.useState(PREFERS_REDUCED);
  React.useEffect(() => {
    if (PREFERS_REDUCED) return;
    const el = ref.current;
    if (!el) return;
    // nearest scrollable ancestor = scroll context
    let root = el.parentElement;
    while (root && root !== document.body) {
      const oy = getComputedStyle(root).overflowY;
      if (oy === 'auto' || oy === 'scroll') break;
      root = root.parentElement;
    }
    const scroller = (root && root !== document.body) ? root : null;
    const target = scroller || window;
    let alive = true, raf;
    const inViewNow = () => {
      const er = el.getBoundingClientRect();
      const sr = scroller ? scroller.getBoundingClientRect() : { top: 0 };
      const vh = scroller ? scroller.clientHeight : (window.innerHeight || document.documentElement.clientHeight);
      const relTop = er.top - sr.top;          // element top within the scroll viewport
      return relTop < vh - 24 && (er.bottom - sr.top) > 0;
    };
    const reveal = () => {
      if (!alive) return;
      alive = false;
      cancelAnimationFrame(raf);
      target.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
      setInView(true);
    };
    const onScroll = () => { if (alive && inViewNow()) reveal(); };
    // rAF poll (covers programmatic scroll when painted) + scroll/resize
    // listeners (covers real + dispatched scroll) + deferred settle checks.
    const tick = () => { if (!alive) return; if (inViewNow()) { reveal(); return; } raf = requestAnimationFrame(tick); };
    target.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    tick();
    const t1 = setTimeout(onScroll, 250);
    const t2 = setTimeout(onScroll, 700);
    return () => {
      alive = false;
      cancelAnimationFrame(raf);
      clearTimeout(t1); clearTimeout(t2);
      target.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
    };
  }, []);
  const Comp = as;
  return (
    <Comp ref={ref} className={className} style={{
      ...style,
      opacity: inView ? 1 : 0,
      transform: inView ? 'none' : `translateY(${y}px)`,
      transition: `opacity ${dur}ms cubic-bezier(.16,1,.3,1) ${delay}ms, transform ${dur}ms cubic-bezier(.16,1,.3,1) ${delay}ms`,
      willChange: 'opacity, transform',
    }}>{children}</Comp>
  );
}

Object.assign(window, {
  CAT, ASSET, IconArrow, IconPin, IconInstagram, Hamburger, Logo, Tag, CardLabel, StatusBadge,
  PrimaryButton, SecondaryButton, TertiaryButton, ButtonLink, Reveal, PREFERS_REDUCED,
});
