/* Primitives & shared marks for the heARTist UI kit */
const { useState } = React;

/* ---- Hand-lettered wordmark (SVG file) ---- */
function Logo({ height = 30, invert = false }) {
  return (
    <img src="assets/naomi-logo.svg" alt="@naomiygal"
      style={{ height, display:'block', filter: invert ? 'invert(1)' : 'none' }} />
  );
}

/* ---- Signature (same hand-lettered mark, used in body copy as her sign-off) ---- */
function Signature({ height = 56, invert = false, tilt = -3, style = {} }) {
  return (
    <img src="assets/naomi-logo.svg" alt="Naomi Gal"
      style={{ height, display:'block',
        filter: invert ? 'invert(1)' : 'none',
        transform: `rotate(${tilt}deg)`, transformOrigin: 'left center', ...style }} />
  );
}

/* ---- Yellow ribbon mark (simple drawn loop, not emoji) ---- */
function Ribbon({ size = 18, color = 'var(--ribbon)' }) {
  return (
    <svg width={size} height={size*1.3} viewBox="0 0 20 26" fill="none" aria-hidden="true"
      style={{ display:'block' }}>
      <path d="M10 13 L4 24 M10 13 L16 24" stroke={color} strokeWidth="3.2" strokeLinecap="round"/>
      <path d="M10 14 C4 10 4 3 8 2 C11 1.2 12 5 10 8 C8 11 5 12 10 14 C15 12 12 11 10 8 C8 5 9 1.2 12 2 C16 3 16 10 10 14 Z"
        stroke={color} strokeWidth="2.4" strokeLinejoin="round" fill="none"/>
    </svg>
  );
}

function Button({ children, kind = 'ink', onClick, type, style }) {
  const [press, setPress] = useState(false);
  const [hover, setHover] = useState(false);
  const base = {
    fontFamily:'var(--font-sans)', fontWeight:700, fontSize:15, lineHeight:1,
    border:'1.5px solid transparent', borderRadius:'var(--radius-sm)', padding:'13px 24px',
    cursor:'pointer', letterSpacing:'.01em', position:'relative', overflow:'hidden',
    transition:'transform .18s cubic-bezier(.34,1.56,.64,1), box-shadow .22s ease, background .18s ease, filter .18s ease',
    display:'inline-flex', alignItems:'center', gap:9, willChange:'transform',
  };
  const kinds = {
    ink:    { background:'var(--ink)', color:'var(--paper)' },
    yellow: { background:'var(--ribbon)', color:'var(--ink)' },
    red:    { background:'var(--marker-red)', color:'#fff' },
    ghost:  { background:'transparent', color:'var(--ink)', borderColor:'var(--ink)' },
    quiet:  { background:'transparent', color:'var(--graphite)', padding:'13px 6px' },
  };
  const lift = {
    ink:    '0 10px 22px rgba(20,17,15,.22)',
    yellow: '0 10px 22px rgba(200,146,10,.30)',
    red:    '0 10px 24px rgba(200,54,43,.30)',
    ghost:  '0 8px 18px rgba(20,17,15,.12)',
    quiet:  'none',
  };
  const hovered = hover && kind!=='quiet'
    ? { transform:'translateY(-2px)', boxShadow:lift[kind], filter:'brightness(1.04)' } : {};
  const pressed = press
    ? { transform:'translateY(1px) scale(.98)', boxShadow:'inset 0 2px 5px rgba(20,17,15,.22)', filter:'none' } : {};
  return (
    <button type={type} onClick={onClick}
      onMouseEnter={()=>setHover(true)}
      onMouseDown={()=>setPress(true)} onMouseUp={()=>setPress(false)}
      onMouseLeave={()=>{ setPress(false); setHover(false); }}
      style={{ ...base, ...kinds[kind], ...hovered, ...pressed, ...style }}>
      {children}
    </button>
  );
}

/* ---- Minimalist line icons — one thin marker stroke, rounded caps.
   Inherit color via currentColor; sized in px. ---- */
function CloseIcon({ size = 18, strokeWidth = 1.6 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor"
      strokeWidth={strokeWidth} strokeLinecap="round" aria-hidden="true" style={{ display:'block' }}>
      <path d="M6 6 L18 18 M18 6 L6 18"/>
    </svg>
  );
}
function Chevron({ size = 22, dir = 'left', strokeWidth = 1.7 }) {
  const d = {
    left:  'M15 5 L8 12 L15 19',
    right: 'M9 5 L16 12 L9 19',
    down:  'M5 9 L12 16 L19 9',
    up:    'M5 15 L12 8 L19 15',
  }[dir] || 'M15 5 L8 12 L15 19';
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor"
      strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" style={{ display:'block' }}>
      <path d={d}/>
    </svg>
  );
}

/* Tag — a small solid label pill. Replaces the old tracked-uppercase eyebrow:
   sentence case, filled (not outlined), reads modern and substantial. */
function Eyebrow({ children, color }) {
  const red = color === 'var(--marker-red)';
  return <span style={{ display:'inline-flex', alignItems:'center', alignSelf:'flex-start', width:'fit-content',
    fontFamily:'var(--font-sans)', fontWeight:700, fontSize:12.5, lineHeight:1,
    padding:'6px 12px', borderRadius:7,
    background: red ? 'var(--marker-red)' : 'var(--ink)', color: red ? '#fff' : 'var(--paper)' }}>{children}</span>;
}

/* status → look */
const STATUS = {
  held:     { label:'Still held', dot:'var(--ribbon)',     text:'var(--ink)' },
  returned: { label:'Home',       dot:'var(--hope)',       text:'var(--hope)' },
  memory:   { label:'ז״ל',        dot:'var(--memory)',     text:'var(--memory)' },
};

function StatusTag({ status }) {
  const s = STATUS[status];
  return (
    <span style={{ display:'inline-flex', alignItems:'center', gap:7, background:'var(--paper-2)',
      borderRadius:999, padding:'5px 12px',
      fontSize:12, fontWeight:700, color:s.text, fontFamily:'var(--font-sans)' }}>
      <span style={{ width:8, height:8, borderRadius:'50%', background:s.dot }} />
      {s.label}
    </span>
  );
}

/* ---- Portrait placeholder: a marker portrait slot ----
   Honest stand-in for Naomi's real drawing. Paper ground, faint
   line figure, top-right status tag + bottom color strip (unified
   across statuses — only the color changes). */
function Portrait({ person, size = 'md' }) {
  const s = STATUS[person.status];
  const tagText = person.tag || s.label;
  return (
    <div style={{ position:'relative', width:'100%', aspectRatio: size==='tall' ? '3/4' : '1/1',
      background:'var(--paper-2)', display:'flex', alignItems:'center', justifyContent:'center',
      overflow:'hidden' }}>
      <svg viewBox="0 0 24 24" fill="none" stroke="var(--ink)" strokeWidth="1.1"
        strokeLinecap="round" strokeLinejoin="round" style={{ width:'46%', height:'46%' }}>
        <circle cx="12" cy="9" r="3.4"/><path d="M5 20.5c0-3.9 3.1-7 7-7s7 3.1 7 7"/>
      </svg>
      <span style={{ position:'absolute', top:8, right:9, fontSize:10.5, fontWeight:700,
        letterSpacing:0, padding:'3px 8px', borderRadius:'var(--radius-xs)',
        background: s.dot, color: person.status==='held' ? 'var(--ink)' : '#fff' }}>
        {tagText}
      </span>
      <div style={{ position:'absolute', left:0, right:0, bottom:0, height:5, background: s.dot }}/>
    </div>
  );
}

Object.assign(window, { Logo, Signature, Ribbon, Button, Eyebrow, StatusTag, Portrait, STATUS, Reveal, ScribbleUnderline, CloseIcon, Chevron, HeroBackdrop });

/* --- HeroBackdrop: the same faded, slowly-cycling marker imagery used in the
   home hero. Drop it as the first child of a position:relative / overflow:hidden
   section, and lift the section's content above it with z-index. Reuses the
   .ng-hero-bg animation + veil from the global stylesheet. --- */
function HeroBackdrop({ veilClass = 'ng-hero-veil' }) {
  return (
    <div className="ng-hero-bg" aria-hidden="true">
      <img src="assets/hero-1.jpg" alt="" decoding="async"/>
      <img src="assets/hero-2.jpg" alt="" decoding="async"/>
      <img src="assets/hero-3.jpg" alt="" decoding="async"/>
      <img src="assets/hero-4.jpg" alt="" decoding="async"/>
      <img src="assets/hero-5.jpg" alt="" decoding="async"/>
      <div className="ng-hero-sketch"></div>
      <div className={veilClass}></div>
    </div>
  );
}

/* --- Reveal: fades + lifts content in as it scrolls into view. Uses the
   `delay` prop (previously inert) to stagger groups. Falls back to fully
   visible when reduced-motion is on or IntersectionObserver is unavailable. */
function Reveal({ children, delay = 0, as: As = 'div', style = {}, className }) {
  const ref = React.useRef(null);
  const [shown, setShown] = React.useState(false);
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) { setShown(true); return; }
    if (!('IntersectionObserver' in window)) { setShown(true); return; }
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting) { setShown(true); io.disconnect(); } });
    }, { rootMargin: '0px 0px -8% 0px', threshold: 0.08 });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return (
    <As ref={ref} className={className} style={{
      ...style,
      opacity: shown ? 1 : 0,
      transform: shown ? 'none' : 'translateY(16px)',
      transition: 'opacity .6s ease, transform .6s cubic-bezier(.22,.61,.36,1)',
      transitionDelay: (delay/1000) + 's',
      willChange: 'opacity, transform',
    }}>{children}</As>
  );
}

/* --- ScribbleUnderline: animated marker line under a word.
   Stretches to fill its container (the word it underlines) on every screen size. --- */
function ScribbleUnderline({ width = '100%', height = 18, color = 'var(--marker-red)', delay = 200 }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const p = ref.current; if (!p) return;
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { p.style.strokeDashoffset = 0; return; }
    const len = p.getTotalLength(); p.style.strokeDasharray = len; p.style.strokeDashoffset = len;
    const t = setTimeout(() => { p.style.transition = 'stroke-dashoffset 1.1s cubic-bezier(.4,.7,.2,1)'; p.style.strokeDashoffset = 0; }, delay);
    return () => clearTimeout(t);
  }, [delay]);
  return (
    <svg width={width} height={height} viewBox="0 0 220 18" preserveAspectRatio="none"
      fill="none" style={{ display:'block', width, marginTop:-4 }}>
      <path ref={ref} d="M6 11 C 45 5, 95 15, 135 9 S 198 13, 214 8"
        stroke={color} strokeWidth="6" strokeLinecap="round" fill="none"
        vectorEffect="non-scaling-stroke"/>
    </svg>
  );
}
