// shared.jsx — primitives reused across the 3 directions.
// Photo helper uses curated Unsplash URLs (studio interiors, nail work, hands).
// No hand-drawn SVG imagery; no AI-looking gradient blobs.

// Curated, neutral-toned photos. Keys are stable across directions so the
// same image can appear in the same spot regardless of styling.
const PHOTOS = {
  studioWide:   'https://images.unsplash.com/photo-1604902396830-aca29e19b067?w=1600&q=70&auto=format&fit=crop',
  studioRoom:   'https://images.unsplash.com/photo-1632345031435-8727f6897d53?w=1200&q=70&auto=format&fit=crop',
  nailArt:      'https://images.unsplash.com/photo-1610992015732-2449b76344bc?w=1200&q=70&auto=format&fit=crop',
  polishClose:  'https://images.unsplash.com/photo-1604654894610-df63bc536371?w=900&q=70&auto=format&fit=crop',
  workstation:  'https://images.unsplash.com/photo-1607779097040-26e80aa78e66?w=1200&q=70&auto=format&fit=crop',
  technician:   'https://images.unsplash.com/photo-1620331311520-246422fd82f9?w=1200&q=70&auto=format&fit=crop',
  pinkNails:    'https://images.unsplash.com/photo-1571290274554-6a2eaa771e5f?w=1200&q=70&auto=format&fit=crop',
  hands:        'https://images.unsplash.com/photo-1632344004151-4dde8c5b9a2c?w=1200&q=70&auto=format&fit=crop',
  studioGreen:  'https://images.unsplash.com/photo-1633681926022-84c23e8cb2d6?w=1200&q=70&auto=format&fit=crop',
  studioWarm:   'https://images.unsplash.com/photo-1522337094846-8a818192de1f?w=1200&q=70&auto=format&fit=crop',
  artistAtWork: 'https://images.unsplash.com/photo-1632344004151-4dde8c5b9a2c?w=1200&q=70&auto=format&fit=crop',
  interior2:    'https://images.unsplash.com/photo-1633681926022-84c23e8cb2d6?w=1200&q=70&auto=format&fit=crop',

  // Additional shots for studio profile pages
  studioDetail1: 'https://images.unsplash.com/photo-1610992015734-77f1c5f8da5b?w=1200&q=70&auto=format&fit=crop',
  studioDetail2: 'https://images.unsplash.com/photo-1604654894610-df63bc536371?w=1200&q=70&auto=format&fit=crop',
  studioDetail3: 'https://images.unsplash.com/photo-1633681926664-65c83cabb077?w=1200&q=70&auto=format&fit=crop',
  studioDetail4: 'https://images.unsplash.com/photo-1604948501466-4e9c339b9c24?w=1200&q=70&auto=format&fit=crop',
  artist1:       'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=400&q=80&auto=format&fit=crop',
  artist2:       'https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=400&q=80&auto=format&fit=crop',
  artist3:       'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=400&q=80&auto=format&fit=crop',
  artist4:       'https://images.unsplash.com/photo-1531123897727-8f129e1688ce?w=400&q=80&auto=format&fit=crop',
  owner:         'https://images.unsplash.com/photo-1580489944761-15a19d654956?w=400&q=80&auto=format&fit=crop',
};

/** Real photo block. Pass a key from PHOTOS as `src` or any direct url. */
function Photo({ src, alt = '', radius = 0, style, children, mute = false }) {
  const url = PHOTOS[src] || src;
  return (
    <div style={{
      position: 'relative',
      overflow: 'hidden',
      borderRadius: radius,
      background: '#0a0a0a',
      width: '100%', height: '100%',
      ...style,
    }}>
      <img
        src={url}
        alt={alt}
        loading="lazy"
        style={{
          width: '100%', height: '100%', objectFit: 'cover',
          display: 'block',
          filter: mute ? 'saturate(0.85) contrast(1.02)' : 'none',
        }}
      />
      {children}
    </div>
  );
}

/** Tiny arrow used in CTAs. */
function ArrowR({ size = 14, stroke = 1.5 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" style={{ display: 'inline-block', verticalAlign: '-2px' }}>
      <path d="M3 8h10" />
      <path d="M9 4l4 4l-4 4" />
    </svg>
  );
}

/** Single dot indicator. */
function Dot({ size = 6, color = 'currentColor', pulse = false }) {
  return (
    <span style={{
      display: 'inline-block', width: size, height: size, borderRadius: '50%',
      background: color, animation: pulse ? 'pulseDot 1.8s ease-in-out infinite' : 'none',
      verticalAlign: 'middle',
    }} />
  );
}

/** Inline check mark. */
function Check({ size = 14, stroke = 1.6 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" style={{ display: 'inline-block' }}>
      <polyline points="3 8 7 12 13 4" />
    </svg>
  );
}

/** Speech bubble icon for messaging UI accents. */
function ChatIcon({ size = 14, stroke = 1.5 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round">
      <path d="M2 4a2 2 0 0 1 2 2v5a2 2 0 0 1 2 2H8l3 2.5V13h3a2 2 0 0 0 2 2V4a2 2 0 0 0 2 2H4a2 2 0 0 0 2 2z" transform="translate(-2,-3)" />
    </svg>
  );
}

/** Scroll-driven reveal. Returns [ref, isInView]. Uses bounding-rect checks +
 *  scroll/resize listeners so it works in sandboxed iframes where
 *  IntersectionObserver can stay silent. */
function useReveal({ once = true, threshold = 0.1 } = {}) {
  const ref = React.useRef(null);
  const [inView, setInView] = React.useState(false);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let done = false;

    const check = () => {
      if (done) return;
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight || document.documentElement.clientHeight;
      // Element is "in view" if its top has crossed into the bottom 90% of the
      // viewport AND any part of it is still on screen. This handles both
      // tall hero blocks and short inline items (logos, badges).
      const visibleBand = r.top < vh * (1 - threshold) && r.bottom > 0;
      if (visibleBand) {
        setInView(true);
        if (once) {
          done = true;
          window.removeEventListener('scroll', check);
          window.removeEventListener('resize', check);
        }
      } else if (!once) {
        setInView(false);
      }
    };

    // Initial check after layout settles (rAF defers one frame so refs are sized).
    requestAnimationFrame(check);

    window.addEventListener('scroll', check, { passive: true });
    window.addEventListener('resize', check, { passive: true });

    return () => {
      window.removeEventListener('scroll', check);
      window.removeEventListener('resize', check);
    };
  }, [once, threshold]);
  return [ref, inView];
}

/** Wrap children in a scroll-revealing block. delay in ms. */
function Reveal({ children, delay = 0, y = 16, duration = 800, style }) {
  const [ref, inView] = useReveal();
  return (
    <div ref={ref} style={{
      opacity: inView ? 1 : 0,
      transform: inView ? 'none' : `translateY(${y}px)`,
      transition: `opacity ${duration}ms cubic-bezier(.2,.7,.2,1) ${delay}ms, transform ${duration}ms cubic-bezier(.2,.7,.2,1) ${delay}ms`,
      willChange: 'opacity, transform',
      ...style,
    }}>{children}</div>
  );
}

/** Tracks how far the user has scrolled within a section. Returns [ref, progress 0..1].
 *  progress is 0 when the section's top hits the viewport top, 1 when its bottom
 *  meets the viewport bottom. Designed for sticky-scroll narrative sections. */
function useScrollProgress() {
  const ref = React.useRef(null);
  const [progress, setProgress] = React.useState(0);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let rafId = 0;
    const update = () => {
      rafId = 0;
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight || document.documentElement.clientHeight;
      const total = r.height - vh;
      const p = total > 0 ? Math.max(0, Math.min(1, -r.top / total)) : 0;
      setProgress(p);
    };
    const schedule = () => {
      if (!rafId) rafId = requestAnimationFrame(update);
    };
    update();
    window.addEventListener('scroll', schedule, { passive: true });
    window.addEventListener('resize', schedule, { passive: true });
    return () => {
      if (rafId) cancelAnimationFrame(rafId);
      window.removeEventListener('scroll', schedule);
      window.removeEventListener('resize', schedule);
    };
  }, []);
  return [ref, progress];
}

// Inject pulse keyframes once.
if (typeof document !== 'undefined' && !document.getElementById('shared-kf')) {
  const s = document.createElement('style');
  s.id = 'shared-kf';
  s.textContent = `
    @keyframes pulseDot { 0%,100%{opacity:1;transform:scale(1)} 50%{opacity:.45;transform:scale(.7)} }
    @keyframes marqA { from{transform:translateX(0)} to{transform:translateX(-50%)} }
  `;
  document.head.appendChild(s);
}

Object.assign(window, { Photo, PHOTOS, ArrowR, Dot, Check, ChatIcon, Reveal, useReveal, useScrollProgress });
