/* AKMBD Website — Primitives
   Shared building blocks: Wordmark, Button, Eyebrow, ArrowLink, Placeholder, hooks.
   Each text/babel script shares the global lexical scope, so this (loaded first)
   declares the React hook aliases ONCE for every later file to use. */

const { useState, useEffect, useRef, useCallback, Fragment } = React;

/* ---- AKM Wordmark (recolorable) ---- */
function Wordmark({ reversed = false, size = 32, onClick }) {
  const ink = reversed ? '#fff' : 'var(--akm-charcoal)';
  const box = reversed ? '#fff' : 'var(--accent)';
  const boxText = reversed ? 'var(--accent)' : '#fff';
  return (
    <div onClick={onClick} style={{ display:'inline-flex', alignItems:'center', cursor:onClick?'pointer':'default' }}>
      <div style={{ background:box, color:boxText, display:'flex', alignItems:'center', justifyContent:'center', height:size*1.34,
        padding:`0 ${size*0.26}px 0 ${size*0.26 + size*0.5*0.14}px`, boxSizing:'border-box',
        fontFamily:'var(--font-display)', fontWeight:400, letterSpacing:'0.14em', fontSize:size*0.5, lineHeight:1 }}>AKM</div>
      <div style={{ width:1.5, height:size*0.8, margin:`0 ${size*0.26}px`, background:ink }}></div>
      <div style={{ display:'flex', flexDirection:'column', justifyContent:'center', fontFamily:'var(--font-display)',
        fontSize:size*0.295, lineHeight:1.18, letterSpacing:'0.13em', textTransform:'uppercase', color:ink, whiteSpace:'nowrap' }}>
        <span>Building</span><span>&amp;&nbsp;Design</span>
      </div>
    </div>
  );
}

/* ---- Buttons ---- */
function Button({ children, variant = 'primary', onClick, style = {}, type = 'button', disabled = false }) {
  const [h, setH] = useState(false);
  const base = {
    fontFamily:'var(--font-display)', fontWeight:500, fontSize:12.5, letterSpacing:'0.16em',
    textTransform:'uppercase', padding:'15px 30px', borderRadius:2, cursor:'pointer',
    display:'inline-flex', alignItems:'center', gap:11, border:'1px solid transparent',
    transition:'all .24s cubic-bezier(.22,1,.36,1)', ...style,
  };
  const variants = {
    primary:    { background: h ? 'var(--accent-dark)':'var(--accent)', color:'#fff', transform: h?'translateY(-1px)':'none' },
    ghost:      { background: h ? 'var(--accent)':'transparent', color: h?'#fff':'var(--accent)', borderColor:'var(--accent)' },
    ghostLight: { background: h ? '#fff':'transparent', color: h?'var(--akm-indigo-900)':'#fff', borderColor:'rgba(255,255,255,.55)' },
  };
  return (
    <button type={type} disabled={disabled} onMouseEnter={()=>setH(true)} onMouseLeave={()=>setH(false)} onClick={onClick}
      style={{ ...base, ...variants[variant], ...(disabled ? { opacity:.65, cursor:'default' } : {}) }}>{children}</button>
  );
}

/* ---- Eyebrow (tracked label with optional rule) ---- */
function Eyebrow({ children, color = 'var(--accent)', rule = true, style = {} }) {
  return (
    <span style={{ display:'inline-flex', alignItems:'center', fontFamily:'var(--font-display)', fontWeight:500,
      fontSize:12.5, letterSpacing:'0.24em', textTransform:'uppercase', color, ...style }}>
      {rule && <span style={{ width:26, height:1, background:'currentColor', marginRight:14, display:'inline-block', opacity:.85 }}></span>}
      {children}
    </span>
  );
}

/* ---- Arrow text link (underline grows from left on hover) ---- */
function ArrowLink({ children, onClick, color = 'var(--ink-1)', style = {} }) {
  const [h, setH] = useState(false);
  return (
    <button onMouseEnter={()=>setH(true)} onMouseLeave={()=>setH(false)} onClick={onClick}
      style={{ background:'none', border:'none', cursor:'pointer', padding:'6px 0', position:'relative',
        fontFamily:'var(--font-display)', fontWeight:500, fontSize:12.5, letterSpacing:'0.16em', textTransform:'uppercase',
        color: h ? 'var(--accent)' : color, display:'inline-flex', alignItems:'center', gap: h?13:9,
        transition:'all .28s cubic-bezier(.22,1,.36,1)', ...style }}>
      <span style={{ position:'relative' }}>
        {children}
        <span style={{ position:'absolute', left:0, bottom:-3, height:1, width: h?'100%':'0%',
          background:'var(--accent)', transition:'width .3s cubic-bezier(.22,1,.36,1)' }}></span>
      </span>
      <span style={{ fontSize:15 }}>&rarr;</span>
    </button>
  );
}

/* ---- Branded image placeholder (clearly-marked; blueprint paper + crop marks) ---- */
function Placeholder({ label = 'Project Image', sub, ratio, height, style = {}, dark = false, tag, bare = false }) {
  const bg = dark ? 'var(--akm-indigo-900)' : 'var(--surface-2)';
  const lineCol = dark ? 'rgba(255,255,255,0.07)' : 'rgba(32,28,112,0.06)';
  const inkCol = dark ? 'rgba(255,255,255,0.55)' : 'var(--ink-3)';
  const corner = dark ? 'rgba(255,255,255,0.4)' : 'var(--line-3)';
  const wrap = {
    position:'relative', width:'100%', background:bg, overflow:'hidden',
    backgroundImage:`linear-gradient(${lineCol} 1px, transparent 1px), linear-gradient(90deg, ${lineCol} 1px, transparent 1px)`,
    backgroundSize:'34px 34px',
    ...(ratio ? { aspectRatio: ratio } : {}),
    ...(height ? { height } : {}),
    display:'flex', alignItems:'center', justifyContent:'center', ...style,
  };
  const mark = (pos) => (
    <span aria-hidden="true" style={{ position:'absolute', width:13, height:13, ...pos,
      borderColor:corner, borderStyle:'solid', borderWidth:0 }} />
  );
  return (
    <div style={wrap} role="img" aria-label={`${label} — photography placeholder`}>
      {/* corner crop marks */}
      <span aria-hidden="true" style={{ position:'absolute', top:14, left:14, width:14, height:14, borderTop:`1px solid ${corner}`, borderLeft:`1px solid ${corner}` }} />
      <span aria-hidden="true" style={{ position:'absolute', top:14, right:14, width:14, height:14, borderTop:`1px solid ${corner}`, borderRight:`1px solid ${corner}` }} />
      <span aria-hidden="true" style={{ position:'absolute', bottom:14, left:14, width:14, height:14, borderBottom:`1px solid ${corner}`, borderLeft:`1px solid ${corner}` }} />
      <span aria-hidden="true" style={{ position:'absolute', bottom:14, right:14, width:14, height:14, borderBottom:`1px solid ${corner}`, borderRight:`1px solid ${corner}` }} />
      {tag && (
        <span style={{ position:'absolute', top:14, left:'50%', transform:'translateX(-50%)', fontFamily:'var(--font-display)',
          fontSize:10, letterSpacing:'0.2em', textTransform:'uppercase', color:inkCol, opacity:.7, whiteSpace:'nowrap' }}>{tag}</span>
      )}
      {!bare && (
      <div style={{ textAlign:'center', padding:'0 24px' }}>
        <svg width="30" height="30" viewBox="0 0 24 24" fill="none" stroke={inkCol} strokeWidth="1.3" style={{ opacity:.8, marginBottom:12 }}>
          <rect x="3" y="3" width="18" height="18" /><circle cx="8.5" cy="8.5" r="1.6" /><path d="M21 15l-5-5L5 21" />
        </svg>
        <div style={{ fontFamily:'var(--font-display)', fontSize:11.5, letterSpacing:'0.22em', textTransform:'uppercase', color:inkCol }}>{label}</div>
        {sub && <div style={{ fontFamily:'var(--font-body)', fontSize:11.5, color:inkCol, opacity:.7, marginTop:7, letterSpacing:'0.02em' }}>{sub}</div>}
      </div>
      )}
    </div>
  );
}

/* ---- Real (placeholder) project photograph — watermarked image baked on disk.
   Root is a single <div> with a cover background so the carousel hover-scale
   rule (.akm-img-clip > div { transform: scale() }) still applies. ---- */
function ProjPhoto({ img, ratio, height, style = {}, label = '', pos = 'center' }) {
  return (
    <div role="img" aria-label={`${label} — placeholder photograph`}
      style={{ position:'relative', width:'100%', overflow:'hidden', backgroundColor:'var(--surface-2)',
        backgroundImage:`url("${RES('proj-'+img, 'assets/projects/'+img+'.jpg')}")`, backgroundSize:'cover', backgroundPosition:pos,
        ...(ratio ? { aspectRatio: ratio } : {}), ...(height ? { height } : {}), ...style }} />
  );
}

/* ---- hook: has the page scrolled past threshold ---- */
function useScrolled(threshold = 70) {
  const [s, setS] = useState(false);
  useEffect(() => {
    const onScroll = () => setS(window.scrollY > threshold);
    onScroll();
    window.addEventListener('scroll', onScroll, { passive:true });
    return () => window.removeEventListener('scroll', onScroll);
  }, [threshold]);
  return s;
}

/* ---- Reveal: fade + short rise when scrolled into view.
   "shown" is React state (NOT an imperative classList toggle) so that a parent
   re-render can't wipe the class and strand content at opacity:0. Always reveals
   via a safety-net timeout even if the observer never fires. ---- */
function Reveal({ children, delay = 0, y = 18, style = {}, as = 'div' }) {
  const ref = useRef(null);
  const [shown, setShown] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { setShown(true); return; }
    const fallback = setTimeout(() => setShown(true), 1400);
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting) { setShown(true); clearTimeout(fallback); io.disconnect(); } });
    }, { threshold: 0.12, rootMargin: '0px 0px -4% 0px' });
    io.observe(el);
    return () => { clearTimeout(fallback); io.disconnect(); };
  }, []);
  const Tag = as;
  return (
    <Tag ref={ref} className={shown ? 'reveal in' : 'reveal'}
      style={{ '--rv-y': y+'px', '--rv-delay': delay+'ms', ...style }}>{children}</Tag>
  );
}

/* ---- resource resolver: returns the bundled blob URL when present
   (standalone export), else the normal relative path ---- */
function RES(id, fallback) {
  return (window.__resources && window.__resources[id]) || fallback;
}

Object.assign(window, { Wordmark, Button, Eyebrow, ArrowLink, Placeholder, ProjPhoto, useScrolled, Reveal, RES });
