// Trellum — shared primitives

// Route map. Kept in window so ChromePages.jsx (Nav/Footer) can render
// real <a href> links before App.jsx's URL routing runs.
const PAGE_PATHS = {
  home: '/',
  services: '/services',
  pfi: '/pfi',
  block: '/block',
  approach: '/approach',
  contact: '/contact',
};
const pagePath = (key) => PAGE_PATHS[key] || '/';

// onClick wrapper for in-app anchors: lets the browser handle middle-click,
// cmd/ctrl-click, and shift-click (open in new tab/window); intercepts a
// plain left click to drive the SPA via setPage.
const navClick = (setPage, key) => (e) => {
  if (e.defaultPrevented) return;
  if (e.button !== 0) return;
  if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
  e.preventDefault();
  setPage(key);
};

Object.assign(window, { PAGE_PATHS, pagePath, navClick });


const Eyebrow = ({ children, tone = 'canton', size = 11, style = {} }) => (
  <div style={{
    fontFamily: 'var(--ff-body)', fontSize: size, fontWeight: 500,
    letterSpacing: '0.12em', textTransform: 'uppercase',
    color: tone === 'paper' ? 'var(--paper)' : tone === 'stone' ? 'var(--stone)' : 'var(--canton)',
    ...style,
  }}>{children}</div>
);

const Descriptor = ({ children, style = {} }) => (
  <span style={{
    fontFamily: 'var(--ff-body)', fontSize: 9, fontWeight: 400,
    letterSpacing: '0.18em', textTransform: 'uppercase', color: 'var(--canton)',
    ...style,
  }}>{children}</span>
);

const SectionLabel = ({ children, onDark = false, style = {} }) => (
  <div style={{
    fontFamily: 'var(--ff-body)', fontSize: 10, fontWeight: 500,
    letterSpacing: '0.12em', textTransform: 'uppercase', color: 'var(--canton)',
    paddingBottom: 8, borderBottom: `1px solid ${onDark ? 'rgba(191,200,198,0.2)' : 'var(--border)'}`,
    marginBottom: 28, ...style,
  }}>{children}</div>
);

const AccentBar = ({ w = 32, style = {} }) => (
  <div style={{ width: w, height: 2, background: 'var(--canton)', ...style }} />
);

const Tag = ({ children, tone = 'canton', style = {} }) => (
  <span style={{
    fontFamily: 'var(--ff-body)', fontSize: 10, fontWeight: 500,
    letterSpacing: '0.08em', textTransform: 'uppercase',
    color: tone === 'paper' ? 'var(--paper)' : 'var(--canton)',
    border: `1px solid ${tone === 'paper' ? 'rgba(245,245,243,0.45)' : 'var(--canton)'}`,
    padding: '3px 8px', borderRadius: 2, marginRight: 6, marginBottom: 4,
    display: 'inline-block',
    ...style,
  }}>{children}</span>
);

const Button = ({ variant = 'primary', onClick, children, ariaLabel, style = {}, size = 'md' }) => {
  const sizes = {
    sm: { fontSize: 12, padding: '9px 16px' },
    md: { fontSize: 13, padding: '11px 20px' },
    lg: { fontSize: 14, padding: '13px 24px' },
  };
  const variants = {
    primary: 'btn btn-primary',
    ghostDark: 'btn btn-ghost-dark',
    ghostLight: 'btn btn-ghost-light',
  };
  return (
    <button
      type="button"
      aria-label={ariaLabel}
      onClick={onClick}
      className={variants[variant]}
      style={{ ...sizes[size], ...style }}
    >{children}</button>
  );
};

// Text link with underline animation
const TextLink = ({ onClick, children, color = 'var(--canton)', style = {} }) => (
  <span
    role="button" tabIndex={0}
    onClick={onClick}
    onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onClick?.(); } }}
    className="tr-link"
    style={{
      fontFamily: 'var(--ff-body)', fontSize: 13, fontWeight: 500,
      color, letterSpacing: '0.02em', display: 'inline-block',
      ...style,
    }}
  >{children}</span>
);

// Italic Canton span — brand signature
const Em = ({ children, ariaLabel }) => (
  <em aria-label={ariaLabel} style={{ fontStyle: 'italic', color: 'var(--canton)', fontFamily: 'var(--ff-display)' }}>{children}</em>
);

// Fade-in on mount (for hero elements)
const FadeIn = ({ delay = 0, duration = 520, y = 12, children, as = 'div', style = {}, ...rest }) => {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    el.animate(
      [{ opacity: 0, transform: `translateY(${y}px)` }, { opacity: 1, transform: 'translateY(0)' }],
      { duration, easing: 'cubic-bezier(.2,.7,.2,1)', delay, fill: 'both' }
    );
  }, []);
  const Tag = as;
  return <Tag ref={ref} style={{ opacity: 0, ...style }} {...rest}>{children}</Tag>;
};

// Observe + fade on scroll
const InView = ({ children, style = {}, as = 'div', rootMargin = '0px 0px -10% 0px', ...rest }) => {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach(en => {
        if (en.isIntersecting) { el.classList.add('in-view'); io.disconnect(); }
      });
    }, { rootMargin, threshold: 0.08 });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  const Tag = as;
  return <Tag ref={ref} className="in-view-target" style={style} {...rest}>{children}</Tag>;
};

// Ruled row used across pages
const RuledRow = ({ n, title, body, tags, right, onClick, first = false, onDark = false, cols = '60px 1fr auto' }) => (
  <div
    className={`tr-ruled${first ? ' first' : ''}${onDark ? ' tr-ruled--dark' : ''}`}
    onClick={onClick}
    onKeyDown={(e) => { if (onClick && (e.key === 'Enter' || e.key === ' ')) { e.preventDefault(); onClick(); } }}
    role={onClick ? 'button' : undefined}
    tabIndex={onClick ? 0 : undefined}
    style={{ gridTemplateColumns: cols }}
  >
    <div style={{
      fontFamily: 'var(--ff-display)', fontStyle: 'italic', fontSize: 36,
      color: 'var(--canton)', lineHeight: 1,
    }}>{n}</div>
    <div>
      <div style={{
        fontFamily: 'var(--ff-display)', fontSize: 22,
        color: onDark ? 'var(--paper)' : 'var(--slate)', lineHeight: 1.2,
        letterSpacing: '-0.005em',
      }}>{title}</div>
      {body && (
        <div style={{
          fontFamily: 'var(--ff-body)', fontWeight: 300, fontSize: 14,
          color: onDark ? 'rgba(245,245,243,0.65)' : 'var(--charcoal)',
          lineHeight: 1.65, marginTop: 6, maxWidth: 640,
        }}>{body}</div>
      )}
      {tags && tags.length > 0 && (
        <div style={{ marginTop: 14 }}>
          {tags.map((t, i) => <Tag key={i} tone={onDark ? 'paper' : 'canton'}>{t}</Tag>)}
        </div>
      )}
    </div>
    <div style={{ color: onDark ? 'rgba(245,245,243,0.55)' : 'var(--stone)', fontSize: 18, alignSelf: 'center' }}>
      {right || (onClick ? '→' : '')}
    </div>
  </div>
);

Object.assign(window, { Eyebrow, Descriptor, SectionLabel, AccentBar, Tag, Button, TextLink, Em, FadeIn, InView, RuledRow });
