// Shared tiny components — Button, Eyebrow, Stat, StatCard, ServiceCard, MathCallout
// Uses CSS vars from colors_and_type.css. All copy is bracketed placeholder.

const { Link } = ReactRouterDOM;

function Button({ as='button', variant='primary', to, href, children, onClick, style, icon }) {
  const base = {
    fontFamily: 'var(--font-body)', fontSize: 16, fontWeight: 500,
    padding: '16px 28px', borderRadius: 8, border: 0, cursor: 'pointer',
    display: 'inline-flex', alignItems: 'center', gap: 8,
    transition: 'background 200ms var(--ease-out), color 200ms var(--ease-out), border-color 200ms',
    textDecoration: 'none', lineHeight: 1.2, letterSpacing: '-0.005em',
  };
  const variants = {
    primary: { background: 'var(--bg-forest)', color: 'var(--text-cream)' },
    primaryHover: { background: '#24301F' },
    secondary: { background: 'transparent', color: 'var(--text-charcoal)', border: '1px solid var(--text-charcoal)' },
    secondaryHover: { background: 'var(--bg-bone)' },
    cream: { background: 'var(--bg-cream)', color: 'var(--bg-forest)' },
    creamHover: { background: '#fff' },
    onForest: { background: 'transparent', color: '#fff', border: '1px solid rgba(255,255,255,0.7)' },
    onForestHover: { background: 'rgba(255,255,255,0.08)' },
    link: { background: 'none', color: 'var(--text-charcoal)', padding: '4px 0',
            borderBottom: '1px solid var(--accent-clay)', borderRadius: 0 },
    linkHover: { color: 'var(--accent-olive)' },
  };
  const [hover, setHover] = React.useState(false);
  const s = { ...base, ...variants[variant], ...(hover && variants[variant+'Hover'] || {}), ...style };
  const props = { style: s, onClick, onMouseEnter: () => setHover(true), onMouseLeave: () => setHover(false) };
  const inner = <>{children}{icon && <i data-lucide={icon} style={{width:16,height:16}}></i>}</>;
  if (to) return <Link to={to} {...props}>{inner}</Link>;
  if (href) return <a href={href} {...props}>{inner}</a>;
  return <button {...props}>{inner}</button>;
}

function Eyebrow({ children, color, style }) {
  return <span style={{
    fontFamily: 'var(--font-body)', fontSize: 12, letterSpacing: '0.12em',
    textTransform: 'uppercase', fontWeight: 500,
    color: color || 'var(--accent-clay)', ...style
  }}>{children}</span>;
}

function Stat({ number, label, divider }) {
  return (
    <div style={{ display:'flex', alignItems:'center', gap:24, flex:1 }}>
      <div>
        <div style={{ fontFamily:'var(--font-display)', fontSize:40, fontWeight:500, letterSpacing:'-0.02em', lineHeight:1, color:'var(--text-charcoal)' }}>
          [{number}]
        </div>
        <div style={{ fontFamily:'var(--font-body)', fontSize:14, color:'var(--text-muted)', marginTop:6, letterSpacing:'0.02em' }}>
          [{label}]
        </div>
      </div>
      {divider && <div style={{ width:1, height:44, background:'var(--border-hair)', marginLeft:'auto' }} />}
    </div>
  );
}

function StatCard({ number, label }) {
  return (
    <div style={{ background:'var(--accent-clay-soft)', borderRadius:16, padding:24, flex:'1 1 180px', minWidth:170 }}>
      <div style={{ fontFamily:'var(--font-display)', fontSize:44, fontWeight:500, lineHeight:1, letterSpacing:'-0.02em', color:'var(--text-charcoal)' }}>[{number}]</div>
      <div style={{ fontFamily:'var(--font-body)', fontSize:14, lineHeight:1.4, color:'var(--text-charcoal)', opacity:0.8, marginTop:10 }}>[{label}]</div>
    </div>
  );
}

function ServiceCard({ slug, name, desc, img }) {
  const [hover, setHover] = React.useState(false);
  return (
    <Link to={`/services/${slug}`}
      onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      style={{
        position:'relative', aspectRatio:'4/5', borderRadius:16, overflow:'hidden',
        display:'flex', flexDirection:'column', justifyContent:'flex-end',
        padding:22, textDecoration:'none', color:'#fff', flex:'1 1 0',
        transition: 'transform 300ms var(--ease-out), box-shadow 300ms',
        transform: hover ? 'translateY(-4px)' : 'translateY(0)',
        boxShadow: hover ? 'var(--shadow-lift)' : 'none',
    }}>
      <div style={{ position:'absolute', inset:0,
        backgroundImage:`linear-gradient(to top, rgba(0,0,0,0.65), rgba(0,0,0,0.1) 65%), url(${img})`,
        backgroundSize:'cover', backgroundPosition:'center',
        transition: 'transform 400ms var(--ease-out)',
        transform: hover ? 'scale(1.03)' : 'scale(1)'
      }} />
      <div style={{
        position:'absolute', top:14, right:14, width:36, height:36, borderRadius:'50%',
        border:'1px solid rgba(255,255,255,0.7)', display:'flex', alignItems:'center', justifyContent:'center',
        background: hover ? 'var(--bg-cream)' : 'transparent',
        color: hover ? 'var(--text-charcoal)' : '#fff',
        transition: 'background 300ms, color 300ms',
      }}><i data-lucide="arrow-up-right" style={{width:16, height:16}}></i></div>
      <div style={{ position:'relative', zIndex:1 }}>
        <div style={{ fontFamily:'var(--font-display)', fontSize:28, fontWeight:500, lineHeight:1.15, letterSpacing:'-0.015em' }}>[{name}]</div>
        <div style={{ fontFamily:'var(--font-body)', fontSize:14, color:'rgba(255,255,255,0.82)', marginTop:6 }}>[{desc}]</div>
      </div>
    </Link>
  );
}

function MathCallout() {
  return (
    <div style={{ maxWidth:800, margin:'0 auto', background:'var(--accent-clay-soft)',
      borderRadius:20, padding:'56px 48px' }}>
      <Eyebrow color="#7a5a2f">The math</Eyebrow>
      <div style={{ marginTop:18, fontFamily:'var(--font-body)', fontSize:18, lineHeight:1.6, color:'var(--text-charcoal)' }}>
        <p style={{margin:'0 0 1em'}}>[Body copy with arithmetic, ~80 words. Two paragraphs. First paragraph walks through the expensive manual baseline in concrete dollar terms.]</p>
        <p style={{margin:0}}>[Second paragraph shows the automated alternative, also in dollars, and lands on a plainspoken conclusion. "The math is not close." kind of tone.]</p>
      </div>
    </div>
  );
}

function SectionHeader({ eyebrow, headline, align='left', color='charcoal' }) {
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:16,
      textAlign: align, alignItems: align==='center'?'center':'flex-start' }}>
      <Eyebrow>{eyebrow}</Eyebrow>
      <h2 style={{
        fontFamily:'var(--font-display)', fontWeight:400, letterSpacing:'-0.02em',
        fontSize: 'clamp(36px, 5vw, 56px)', lineHeight: 1.1,
        color: color==='cream' ? 'var(--text-cream)' : 'var(--text-charcoal)',
        margin: 0, maxWidth: 900,
      }}>[{headline}]</h2>
    </div>
  );
}

// ── Scroll-in reveal + number count-up ──────────────────────────

function useInView(options = {}) {
  const ref = React.useRef(null);
  const [inView, setInView] = React.useState(false);
  React.useEffect(() => {
    if (!ref.current || inView) return;
    const io = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) { setInView(true); io.disconnect(); }
    }, { threshold: 0.18, rootMargin: '0px 0px -40px 0px', ...options });
    io.observe(ref.current);
    return () => io.disconnect();
  }, [inView]);
  return [ref, inView];
}

function Reveal({ children, delay = 0, y = 24, as: Tag = 'div', style, ...rest }) {
  const [ref, inView] = useInView();
  return (
    <Tag ref={ref} style={{
      opacity: inView ? 1 : 0,
      transform: inView ? 'translateY(0)' : `translateY(${y}px)`,
      transition: `opacity 750ms var(--ease-out) ${delay}ms, transform 750ms var(--ease-out) ${delay}ms`,
      willChange: 'opacity, transform',
      ...style,
    }} {...rest}>{children}</Tag>
  );
}

// Parse a stat string into leading non-digits, first numeric run, trailing text.
// Handles "21×", "80%", "60+ hrs", "5–7×", "10–30%", "33%".
function parseStat(str) {
  const s = String(str);
  const m = s.match(/(\d+)/);
  if (!m) return { pre: '', num: 0, post: s };
  // For ranges like "5–7" or "10–30", animate to the SECOND number.
  const rangeMatch = s.match(/(\d+)\s*[–-]\s*(\d+)/);
  if (rangeMatch) {
    const idx = s.indexOf(rangeMatch[0]);
    return {
      pre: s.slice(0, idx) + rangeMatch[1] + '–',
      num: parseInt(rangeMatch[2], 10),
      post: s.slice(idx + rangeMatch[0].length),
    };
  }
  return {
    pre: s.slice(0, m.index),
    num: parseInt(m[1], 10),
    post: s.slice(m.index + m[1].length),
  };
}

function CountUp({ value, duration = 1400, style, className }) {
  const { pre, num, post } = React.useMemo(() => parseStat(value), [value]);
  const [ref, inView] = useInView();
  const [n, setN] = React.useState(0);
  React.useEffect(() => {
    if (!inView) return;
    let raf, start;
    const ease = t => 1 - Math.pow(1 - t, 3); // easeOutCubic
    const tick = (ts) => {
      if (!start) start = ts;
      const p = Math.min(1, (ts - start) / duration);
      setN(Math.round(ease(p) * num));
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [inView, num, duration]);
  return <span ref={ref} style={style} className={className}>{pre}{n}{post}</span>;
}

Object.assign(window, { Button, Eyebrow, Stat, StatCard, ServiceCard, MathCallout, SectionHeader, Reveal, CountUp, useInView });
