// primitives.jsx — Positeam shared visual primitives
// Blueprint hairlines, drafting marks, eyebrow labels, buttons, fields.
// All exported to window at the bottom for cross-file use.

const { useState, useEffect, useRef } = React;

/* ---- GRAIN: fixed texture over everything ---- */
function GrainOverlay({ intensity = 0.05 }) {
  return <div className="ps-grain" style={{ opacity: intensity }} aria-hidden="true" />;
}

/* ---- BLUEPRINT GRID: faint ruled paper, optional ---- */
function BlueprintGrid({ opacity = 1, gap = 88 }) {
  const css = {
    position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 0,
    opacity,
    backgroundImage:
      `linear-gradient(var(--line) 1px, transparent 1px),
       linear-gradient(90deg, var(--line) 1px, transparent 1px)`,
    backgroundSize: `${gap}px ${gap}px`,
    maskImage: 'radial-gradient(ellipse 90% 80% at 50% 40%, #000 30%, transparent 100%)',
    WebkitMaskImage: 'radial-gradient(ellipse 90% 80% at 50% 40%, #000 30%, transparent 100%)',
  };
  return <div style={css} aria-hidden="true" />;
}

/* ---- EYEBROW: the signature tracked uppercase annotation ---- */
function Eyebrow({ children, gold, style }) {
  return (
    <span className="ps-label" style={{ color: gold ? 'var(--accent)' : 'var(--fg-3)',
      display: 'inline-flex', alignItems: 'center', gap: 10, whiteSpace: 'nowrap', ...style }}>
      {gold && <span style={{ width: 18, height: 1, background: 'var(--line-gold)' }} />}
      {children}
    </span>
  );
}

/* ---- RULE: a hairline divider ---- */
function Rule({ gold, vertical, length = '100%', style }) {
  const base = gold ? 'var(--line-gold)' : 'var(--line-strong)';
  return vertical
    ? <span style={{ width: 1, height: length, background: base, display: 'inline-block', ...style }} />
    : <span style={{ height: 1, width: length, background: base, display: 'block', ...style }} />;
}

/* ---- CORNER MARKS: drafting registration crops around a frame ---- */
function CornerMarks({ size = 14, color = 'var(--line-gold)', inset = 0 }) {
  const arm = { position: 'absolute', background: color };
  const h = (extra) => ({ ...arm, width: size, height: 1, ...extra });
  const v = (extra) => ({ ...arm, width: 1, height: size, ...extra });
  const o = inset;
  return (
    <React.Fragment>
      <span style={h({ top: o, left: o })} /><span style={v({ top: o, left: o })} />
      <span style={h({ top: o, right: o })} /><span style={v({ top: o, right: o })} />
      <span style={h({ bottom: o, left: o })} /><span style={v({ bottom: o, left: o })} />
      <span style={h({ bottom: o, right: o })} /><span style={v({ bottom: o, right: o })} />
    </React.Fragment>
  );
}

/* ---- TICK COORD: blueprint coordinate annotation, e.g. "N 47.4979° · E 19.0402°" ---- */
function Tick({ children, style }) {
  return <span className="ps-tick" style={style}>{children}</span>;
}

/* ---- BUTTON: ghost (default) / solid gold / minimal link ---- */
function Button({ children, variant = 'ghost', onClick, href, style, className }) {
  const [hov, setHov] = useState(false);
  const base = {
    fontFamily: 'var(--font-sans)', fontWeight: 500, fontSize: 13,
    letterSpacing: '0.22em', textTransform: 'uppercase',
    padding: variant === 'link' ? '4px 0' : '16px 30px',
    border: '1px solid transparent', borderRadius: 0, cursor: 'pointer',
    transition: 'all var(--dur-fast) var(--ease)', textDecoration: 'none',
    display: 'inline-flex', alignItems: 'center', gap: 12, lineHeight: 1, whiteSpace: 'nowrap',
  };
  const variants = {
    ghost: {
      background: 'transparent', color: hov ? 'var(--ink-900)' : 'var(--fg)',
      borderColor: hov ? 'var(--accent)' : 'var(--line-strong)',
      backgroundColor: hov ? 'var(--accent)' : 'transparent',
    },
    solid: {
      background: hov ? 'var(--accent-hi)' : 'var(--accent)', color: 'var(--ink-900)',
      borderColor: 'transparent',
    },
    link: {
      background: 'transparent', color: hov ? 'var(--accent-hi)' : 'var(--accent)',
      borderBottom: '1px solid', borderColor: hov ? 'var(--accent-hi)' : 'var(--line-gold)',
    },
  };
  const El = href ? 'a' : 'button';
  const external = href && /^https?:\/\//.test(href);
  return (
    <El href={href} onClick={onClick} className={className} onMouseEnter={() => setHov(true)} onMouseLeave={() => setHov(false)}
      target={external ? '_blank' : undefined} rel={external ? 'noopener noreferrer' : undefined}
      style={{ ...base, ...variants[variant], ...style }}>
      {children}
      {variant !== 'link' && variant === 'ghost' && <span style={{ fontSize: 11, opacity: 0.7 }}>→</span>}
    </El>
  );
}

/* ---- FIELD: blueprint underline input ---- */
function Field({ label, placeholder, value, onChange, type = 'text', as = 'input' }) {
  const [foc, setFoc] = useState(false);
  const El = as;
  return (
    <label style={{ display: 'block' }}>
      <span className="ps-label" style={{ display: 'block', marginBottom: 10,
        color: foc ? 'var(--accent)' : 'var(--fg-3)' }}>{label}</span>
      <El type={as === 'input' ? type : undefined} placeholder={placeholder} value={value}
        onChange={onChange ? (e) => onChange(e.target.value) : undefined}
        onFocus={() => setFoc(true)} onBlur={() => setFoc(false)}
        rows={as === 'textarea' ? 3 : undefined}
        style={{
          width: '100%', background: 'transparent', border: 'none',
          borderBottom: `1px solid ${foc ? 'var(--accent)' : 'var(--line-strong)'}`,
          padding: '10px 0', color: 'var(--fg-bright)', fontFamily: 'var(--font-sans)',
          fontSize: 16, outline: 'none', transition: 'border-color var(--dur-fast) var(--ease)',
          resize: 'none',
        }} />
    </label>
  );
}

/* ---- REVEAL: slow fade-up on scroll into view ---- */
function Reveal({ children, delay = 0, y = 24, style, motion }) {
  const ref = useRef(null);
  const [vis, setVis] = useState(false);
  const m = motion != null ? motion : (typeof window !== 'undefined' && window.__psMotion != null ? window.__psMotion : 1);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    if (reduce || m === 0) { setVis(true); return; }
    let done = false;
    const check = () => {
      if (done) return;
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight || document.documentElement.clientHeight || 800;
      if (r.top < vh * 0.92 && r.bottom > 0) { done = true; setVis(true); cleanup(); }
    };
    const cleanup = () => {
      window.removeEventListener('scroll', check, true);
      window.removeEventListener('resize', check);
      clearTimeout(t);
    };
    window.addEventListener('scroll', check, true);
    window.addEventListener('resize', check);
    const t = setTimeout(() => { done = true; setVis(true); }, 2200);
    check(); // initial (covers above-the-fold)
    return cleanup;
  }, []);
  return (
    <div ref={ref} style={{
      opacity: vis ? 1 : 0,
      transform: vis ? 'none' : `translateY(${y * m}px)`,
      transition: `opacity ${1100 * m}ms var(--ease-out) ${delay * m}ms, transform ${1100 * m}ms var(--ease-out) ${delay * m}ms`,
      ...style,
    }}>{children}</div>
  );
}

/* ---- SECTION INDEX: blueprint section numbering "01 — TÍTULUS" ---- */
function SectionIndex({ n, children }) {
  return (
    <div style={{ display: 'flex', alignItems: 'baseline', gap: 16, marginBottom: 28 }}>
      <span style={{ fontFamily: 'var(--font-sans)', fontWeight: 300, fontSize: 13,
        color: 'var(--accent)', letterSpacing: '0.1em' }}>{n}</span>
      <Rule style={{ flex: 1, alignSelf: 'center' }} />
      <Eyebrow>{children}</Eyebrow>
    </div>
  );
}

/* ---- SECTION SPINE: blueprint joint threading sections (continuity + density) ---- */
function SectionSpine({ label, height = 64, node = true }) {
  return (
    <div aria-hidden="true" style={{
      position: 'absolute', top: 0, left: '50%', transform: 'translateX(-50%)',
      display: 'flex', flexDirection: 'column', alignItems: 'center', zIndex: 1, pointerEvents: 'none',
    }}>
      <span style={{ width: 1, height, backgroundImage: 'linear-gradient(var(--line-strong) 50%, transparent 0)',
        backgroundSize: '1px 7px', opacity: 0.7 }} />
      {node ? <span style={{ width: 6, height: 6, transform: 'rotate(45deg)', border: '1px solid var(--line-gold)',
        background: 'var(--bg)', marginTop: -3 }} /> : null}
      {label ? <span className="ps-tick" style={{ marginTop: 12, color: 'var(--fg-faint)' }}>{label}</span> : null}
    </div>
  );
}

/* ---- SIDE RAIL: faint coordinate annotations down a section edge (blueprint density) ---- */
function SideRail({ side = 'left', marks }) {
  const items = marks || ['+00', '+01', '+02', '+03'];
  return (
    <div aria-hidden="true" style={{
      position: 'absolute', top: 0, bottom: 0, [side]: 'calc(var(--gutter) * 0.34)',
      display: 'flex', flexDirection: 'column', justifyContent: 'space-evenly', alignItems: 'center',
      zIndex: 1, pointerEvents: 'none',
    }}>
      {items.map((m, i) => (
        <div key={i} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6 }}>
          <span style={{ width: 5, height: 1, background: 'var(--line-gold)' }} />
          <span className="ps-tick" style={{ writingMode: 'vertical-rl', color: 'var(--fg-faint)', letterSpacing: '0.2em' }}>{m}</span>
        </div>
      ))}
    </div>
  );
}

/* ---- LOOP MARK: a jel vonalas, önrajzolódó interpretációja (∞ + kereszt) ---- */
function LoopMark({ size = 88, stroke = 'var(--accent)' }) {
  const [drawn, setDrawn] = useState(false);
  useEffect(() => {
    const reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    if (reduce) { setDrawn(true); return; }
    const t = setTimeout(() => setDrawn(true), 140);
    return () => clearTimeout(t);
  }, []);
  const seg = (delay) => ({
    pathLength: 1, strokeDasharray: 1, strokeDashoffset: drawn ? 0 : 1,
    transition: `stroke-dashoffset 1700ms var(--ease-out) ${delay}ms`,
  });
  return (
    <svg width={size} height={size} viewBox="0 0 100 100" fill="none" aria-hidden="true"
      style={{ display: 'block', overflow: 'visible' }}>
      <circle cx="63" cy="37" r="19" stroke={stroke} strokeWidth="2.4" strokeLinecap="round"
        vectorEffect="non-scaling-stroke" style={seg(0)} />
      <circle cx="37" cy="63" r="19" stroke={stroke} strokeWidth="2.4" strokeLinecap="round"
        vectorEffect="non-scaling-stroke" style={seg(320)} />
      <line x1="50" y1="37" x2="50" y2="63" stroke={stroke} strokeWidth="2.4" strokeLinecap="round"
        vectorEffect="non-scaling-stroke" style={seg(920)} />
      <line x1="37" y1="50" x2="63" y2="50" stroke={stroke} strokeWidth="2.4" strokeLinecap="round"
        vectorEffect="non-scaling-stroke" style={seg(1120)} />
    </svg>
  );
}

/* ---- CROSS MARK: a jel keresztje — minden döntési pont jele ---- */
function CrossMark({ size = 28, color = 'var(--line-gold)', thickness = 1 }) {
  return (
    <span aria-hidden="true" style={{ position: 'relative', display: 'inline-block', width: size, height: size }}>
      <span style={{ position: 'absolute', left: '50%', top: 0, width: thickness, height: '100%',
        background: color, transform: 'translateX(-50%)' }} />
      <span style={{ position: 'absolute', top: '50%', left: 0, height: thickness, width: '100%',
        background: color, transform: 'translateY(-50%)' }} />
      <span style={{ position: 'absolute', left: '50%', top: '50%', width: 4, height: 4, borderRadius: '50%',
        background: 'var(--accent)', transform: 'translate(-50%,-50%)' }} />
    </span>
  );
}

Object.assign(window, {
  GrainOverlay, BlueprintGrid, Eyebrow, Rule, CornerMarks, Tick,
  Button, Field, Reveal, SectionIndex, SectionSpine, SideRail, LoopMark, CrossMark,
});
