'use client';

import { motion, useReducedMotion } from 'framer-motion';
import type { ReactNode } from 'react';

/**
 * Fades a block up as it scrolls into view.
 *
 * The site already did this by hand with framer-motion in a few dozen places,
 * but unevenly — the homepage had nineteen, most other pages had one. This puts
 * one motion behind one wrapper, so a section gains a reveal by being wrapped
 * rather than by growing four props.
 *
 * 56px over 0.75s on an expo-out curve. The original 24px/0.55s was firing
 * correctly but was too small to notice — the movement finished before the eye
 * registered anything had moved. The longer travel and the sharp deceleration are
 * what make it read as an arrival rather than a flicker.
 *
 * Deliberately NOT `once`: the reveal replays every time a block comes into
 * view, scrolling up as well as down, so the page keeps moving rather than
 * going inert after one pass. framer-motion animates back to `initial` on exit,
 * which is what makes the return trip work.
 *
 * `margin` holds the trigger until the block is properly on screen. Without it
 * the animation fires the instant one pixel crosses the bottom edge and is over
 * before the reader sees it — which is exactly how this looked at first.
 */
export function Reveal({
  children,
  delay = 0,
  className,
}: {
  children: ReactNode;
  delay?: number;
  className?: string;
}) {
  const reduce = useReducedMotion();

  // Someone who has asked for reduced motion still gets the content, just
  // without the travel — never a blank space where a section should be.
  if (reduce) return <div className={className}>{children}</div>;

  return (
    <motion.div
      className={className}
      initial={{ opacity: 0, y: 56 }}
      whileInView={{ opacity: 1, y: 0 }}
      viewport={{ margin: '-80px' }}
      transition={{ duration: 0.75, delay, ease: [0.16, 1, 0.3, 1] }}
    >
      {children}
    </motion.div>
  );
}
