// svg-nature.jsx
// Nature SVG components for The Living Mark
// React available globally via CDN (React 18). Requires Babel for JSX.
// No imports needed.

// ---------------------------------------------------------------------------
// Design tokens (CSS custom properties defined on the host page)
// --void:       #08080d
// --parchment:  #eae4da
// --gold:       #c9a84c
// --gold-glow:  rgba(201, 168, 76, 0.25)
// --ember:      #8b4513
// --honey:      #d4a017
// --bone:       #f5f0e8
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// Shared: Reduced-motion detection hook
// ---------------------------------------------------------------------------

function useNaturePrefersReducedMotion() {
  const [reduced, setReduced] = React.useState(() => {
    if (typeof window === 'undefined') return false;
    return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  });

  React.useEffect(() => {
    const mq = window.matchMedia('(prefers-reduced-motion: reduce)');
    const handler = (e) => setReduced(e.matches);
    mq.addEventListener('change', handler);
    return () => mq.removeEventListener('change', handler);
  }, []);

  return reduced;
}

// ---------------------------------------------------------------------------
// Shared: Linear interpolation
// ---------------------------------------------------------------------------

function lerp(a, b, t) {
  return a + (b - a) * Math.max(0, Math.min(1, t));
}

// Remap progress from [inLow, inHigh] → [0, 1], clamped.
function remap(value, inLow, inHigh) {
  if (inHigh === inLow) return value >= inHigh ? 1 : 0;
  return Math.max(0, Math.min(1, (value - inLow) / (inHigh - inLow)));
}

// Hex color → [r, g, b] 0-255
function hexToRgb(hex) {
  const v = parseInt(hex.replace('#', ''), 16);
  return [(v >> 16) & 255, (v >> 8) & 255, v & 255];
}

// Interpolate two hex colors and return an `rgb(...)` string.
function lerpColor(hexA, hexB, t) {
  const [ar, ag, ab] = hexToRgb(hexA);
  const [br, bg, bb] = hexToRgb(hexB);
  return `rgb(${Math.round(lerp(ar, br, t))},${Math.round(lerp(ag, bg, t))},${Math.round(lerp(ab, bb, t))})`;
}

// ---------------------------------------------------------------------------
// Component 1: FourPhaseBackground
// ---------------------------------------------------------------------------
/**
 * Scroll-driven full-viewport background that moves through four phases
 * representing the lotus / four-phase current: mud → water → surface → bloom.
 *
 * Props:
 *   progress  {number} 0–1   Scroll progress within the lotus section.
 *   children  {ReactNode}    Content rendered on top of the background.
 */
function FourPhaseBackground({ progress = 0, children, minHeight = '100vh' }) {
  const reduced = useNaturePrefersReducedMotion();
  const p = reduced ? 1.0 : Math.max(0, Math.min(1, progress));

  // ---- Phase colours ----
  // void base: #08080d
  // mud tint:  blend ember (#8b4513) at up to 10% into void
  // water tint: blend deep blue (#0a0a1a) into void
  // bloom:     lighten slightly toward #0f0f14

  let bgColor;
  let grainOpacity;
  let radialLightness;  // 0 = flat, 1 = subtle centre brightening
  let surfaceLineOpacity;
  let warmth; // 0 = cool/neutral, 1 = warm (bloom)

  if (p < 0.25) {
    // --- Mud phase ---
    const t = remap(p, 0, 0.25);
    bgColor = lerpColor('#08080d', '#130d0a', t);   // void → warm dark
    grainOpacity = lerp(0.18, 0.32, t);
    radialLightness = 0;
    surfaceLineOpacity = 0;
    warmth = 0;
  } else if (p < 0.5) {
    // --- Water phase ---
    const t = remap(p, 0.25, 0.5);
    bgColor = lerpColor('#130d0a', '#09090f', t);   // warm dark → blue-dark
    grainOpacity = lerp(0.32, 0.12, t);
    radialLightness = lerp(0, 0.6, t);
    surfaceLineOpacity = 0;
    warmth = 0;
  } else if (p < 0.65) {
    // --- Surface phase ---
    const t = remap(p, 0.5, 0.65);
    bgColor = lerpColor('#09090f', '#08080d', t);   // blue-dark → void base
    grainOpacity = lerp(0.12, 0.06, t);
    radialLightness = lerp(0.6, 0.3, t);
    // Surface line peaks at ~0.6, starts fading after
    const lineT = p < 0.6
      ? remap(p, 0.5, 0.6)           // fade in
      : 1 - remap(p, 0.6, 0.65);     // fade out
    surfaceLineOpacity = lerp(0, 0.42, lineT);
    warmth = lerp(0, 0.4, t);
  } else {
    // --- Bloom phase ---
    const t = remap(p, 0.65, 1.0);
    bgColor = lerpColor('#08080d', '#0f0f14', t);   // void → just-barely-lighter
    grainOpacity = lerp(0.06, 0.04, t);
    radialLightness = lerp(0.3, 0.15, t);
    surfaceLineOpacity = 0;
    warmth = lerp(0.4, 1.0, t);
  }

  // Radial gradient for water / surface depth feel
  const innerGlow = `rgba(${Math.round(lerp(8, 22, radialLightness))},${Math.round(lerp(8, 18, radialLightness))},${Math.round(lerp(13, 28, radialLightness))}, 1)`;
  const bgGradient = radialLightness > 0.05
    ? `radial-gradient(ellipse 80% 60% at 50% 50%, ${innerGlow} 0%, ${bgColor} 70%)`
    : bgColor;

  // Warm honey overlay in bloom phase
  const bloomOverlay = warmth > 0
    ? `rgba(201, 168, 76, ${(warmth * 0.03).toFixed(3)})`
    : 'transparent';

  const containerStyle = {
    position: 'relative',
    width: '100%',
    minHeight,
    background: bgGradient,
    transition: reduced ? 'none' : 'background 0.1s ease',
    overflow: 'hidden',
  };

  // Grain overlay — a pseudo-element would be cleaner but inline is safe here
  const grainStyle = {
    position: 'absolute',
    inset: 0,
    opacity: grainOpacity,
    backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='1'/%3E%3C/svg%3E")`,
    backgroundRepeat: 'repeat',
    backgroundSize: '200px 200px',
    mixBlendMode: 'overlay',
    pointerEvents: 'none',
    zIndex: 1,
    transition: reduced ? 'none' : 'opacity 0.3s ease',
  };

  // Bloom warm overlay
  const warmOverlayStyle = {
    position: 'absolute',
    inset: 0,
    background: `radial-gradient(ellipse 70% 50% at 50% 40%, ${bloomOverlay} 0%, transparent 70%)`,
    pointerEvents: 'none',
    zIndex: 2,
    transition: reduced ? 'none' : 'background 0.2s ease',
  };

  // Surface line — full-width, vertically centred
  const surfaceLineStyle = {
    position: 'absolute',
    left: 0,
    right: 0,
    top: '50%',
    height: '1px',
    background: `linear-gradient(90deg, transparent 0%, #c9a84c 20%, #c9a84c 80%, transparent 100%)`,
    opacity: surfaceLineOpacity,
    transform: 'translateY(-50%)',
    pointerEvents: 'none',
    zIndex: 3,
    transition: reduced ? 'none' : 'opacity 0.15s ease',
  };

  // Content sits above all overlays
  const contentStyle = {
    position: 'relative',
    zIndex: 10,
  };

  return (
    <div style={containerStyle} aria-live="off">
      <div style={grainStyle} aria-hidden="true" />
      <div style={warmOverlayStyle} aria-hidden="true" />
      <div style={surfaceLineStyle} aria-hidden="true" />
      <div style={contentStyle}>
        {children}
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Component 2: LotusSVG
// ---------------------------------------------------------------------------
/**
 * A top-down lotus that opens petal by petal, driven by scroll progress.
 *
 * Props:
 *   progress  {number} 0–1   Controls how open the lotus is.
 *   className {string}
 */
function LotusSVG({ progress = 0, className = '' }) {
  const reduced = useNaturePrefersReducedMotion();
  const p = reduced ? 1.0 : Math.max(0, Math.min(1, progress));

  // Build a teardrop petal path — elongated, botanically suggestive.
  // The petal starts at (0,0), tapers to a tip at (0, -length).
  // Width is at its widest around 35% up from the base.
  function petalPath(length, width) {
    const w = width / 2;
    // Two cubic bezier curves meeting at the tip, with the widest point
    // at about 35% of the length from the base.
    return [
      `M 0,0`,
      `C ${w},${-length * 0.15} ${w * 1.1},${-length * 0.45} 0,${-length}`,
      `C ${-w * 1.1},${-length * 0.45} ${-w},${-length * 0.15} 0,0`,
      `Z`,
    ].join(' ');
  }

  // Returns a [0.3, 1.0] open amount for a given layer's progress window.
  function layerOpenAmount(progress, layerStart, layerEnd) {
    if (progress <= layerStart) return 0.3;
    if (progress >= layerEnd) return 1.0;
    return 0.3 + 0.7 * ((progress - layerStart) / (layerEnd - layerStart));
  }

  // Layer definitions: [angle offsets, petal length, petal width, progress window]
  const layers = [
    {
      // Layer 1 — inner, 4 petals at cardinal directions
      angles: [0, 90, 180, 270],
      length: 35,
      width: 14,
      start: 0.3,
      end: 0.6,
      fillOpacityBase: 0.40,
      strokeOpacityBase: 0.60,
    },
    {
      // Layer 2 — middle, 6 petals
      angles: [30, 90, 150, 210, 270, 330],
      length: 50,
      width: 16,
      start: 0.45,
      end: 0.75,
      fillOpacityBase: 0.30,
      strokeOpacityBase: 0.50,
    },
    {
      // Layer 3 — outer, 8 petals
      angles: [22.5, 67.5, 112.5, 157.5, 202.5, 247.5, 292.5, 337.5],
      length: 65,
      width: 18,
      start: 0.6,
      end: 0.9,
      fillOpacityBase: 0.20,
      strokeOpacityBase: 0.40,
    },
  ];

  return (
    <svg
      className={className}
      viewBox="-80 -80 160 160"
      width="100%"
      height="100%"
      aria-label="A lotus flower opening from above"
      role="img"
      style={{ display: 'block' }}
    >
      {layers.map((layer, layerIdx) => {
        const openAmount = layerOpenAmount(p, layer.start, layer.end);
        // As petals open toward 1.0, push opacity slightly upward — more vivid when bloomed.
        const vivid = (openAmount - 0.3) / 0.7; // 0 when furled, 1 when fully open
        const fillOpacity = layer.fillOpacityBase + vivid * 0.12;
        const strokeOpacity = layer.strokeOpacityBase + vivid * 0.15;
        const path = petalPath(layer.length, layer.width);

        return (
          <g key={layerIdx}>
            {layer.angles.map((angleDeg, petalIdx) => {
              // Each petal: rotate to its radial position, then scale open/closed.
              // The petal path points upward (tip at negative y), so rotation
              // places it in the correct radial direction.
              const transform = `rotate(${angleDeg}) scale(${openAmount.toFixed(4)})`;

              return (
                <path
                  key={petalIdx}
                  d={path}
                  transform={transform}
                  fill="#c9a84c"
                  fillOpacity={fillOpacity.toFixed(3)}
                  stroke="#c9a84c"
                  strokeOpacity={strokeOpacity.toFixed(3)}
                  strokeWidth="0.8"
                  style={{
                    transformOrigin: '0 0',
                    transformBox: 'fill-box',
                  }}
                />
              );
            })}
          </g>
        );
      })}

      {/* Seed / centre — always visible, the origin point */}
      <circle
        cx="0"
        cy="0"
        r="5"
        fill="#d4a017"
        fillOpacity="0.9"
        stroke="#c9a84c"
        strokeOpacity="0.5"
        strokeWidth="0.8"
      />
      {/* Inner seed dot */}
      <circle
        cx="0"
        cy="0"
        r="2"
        fill="#d4a017"
        fillOpacity="1"
      />
    </svg>
  );
}

// ---------------------------------------------------------------------------
// Component 3: WaggleDanceBee
// ---------------------------------------------------------------------------
/**
 * A small animated bee tracing a figure-eight waggle dance path.
 *
 * Props:
 *   className  {string}
 *   active     {boolean}  Whether the bee is animating. Default: true.
 */
function WaggleDanceBee({ className = '', active = true }) {
  const reduced = useNaturePrefersReducedMotion();
  const shouldAnimate = active && !reduced;

  // Use a stable unique ID so injected keyframes don't collide.
  const uid = React.useId ? React.useId() : 'bee';
  // Strip React's colon-based IDs to valid CSS identifiers.
  const safeId = uid.replace(/:/g, '_').replace(/[^a-zA-Z0-9_-]/g, '');

  // Figure-eight (lemniscate) path, centred at origin.
  // Two lobes, each a pair of cubic Bezier curves that meet at the origin.
  // The "waggle run" is the straight crossing through the centre.
  //
  // Left lobe: origin → (-40, 0) and back, curving through top/bottom.
  // Right lobe: origin → (40, 0) and back, curving through bottom/top.
  // The complete path starts and ends at (0, 0) for seamless looping.
  const figurePath =
    'M 0,0 ' +
    'C -6,-22 -40,-22 -40,0 ' +   // left lobe upper arc
    'C -40,22 -6,22 0,0 ' +        // left lobe lower arc (back to centre)
    'C 6,22 40,22 40,0 ' +         // right lobe lower arc
    'C 40,-22 6,-22 0,0 ' +        // right lobe upper arc (back to centre)
    'Z';

  // Wing flutter keyframes — fast, subtle
  const wingsAnimName = `${safeId}_wings`;
  // Waggle vibration keyframes — tiny side jitter at the centre crossing
  const waggleAnimName = `${safeId}_waggle`;
  // Path travel keyframes
  const travelAnimName = `${safeId}_travel`;

  // We animate the bee body group along the path by interpolating x/y across
  // CSS keyframes (offset-path has decent support; we use it with a fallback
  // comment). The transform keyframes below trace 12 points along the lemniscate.
  //
  // Parametric lemniscate of Bernoulli: a=40
  //   x(t) = 40 * cos(t) / (1 + sin²(t))
  //   y(t) = 40 * sin(t)*cos(t) / (1 + sin²(t))
  // We sample at 12 even angles t ∈ [0, 2π).
  function lemniscate(t, a = 40) {
    const s2 = Math.sin(t) ** 2;
    return {
      x: a * Math.cos(t) / (1 + s2),
      y: a * Math.sin(t) * Math.cos(t) / (1 + s2),
    };
  }

  // Build CSS keyframe string from 13 evenly-spaced samples (including wrap).
  const keyframeStops = Array.from({ length: 13 }, (_, i) => {
    const t = (i / 12) * 2 * Math.PI;
    const { x, y } = lemniscate(t);
    // Heading direction: tangent angle for bee rotation
    const dt = 0.05;
    const next = lemniscate(t + dt);
    const angle = Math.atan2(next.y - y, next.x - x) * (180 / Math.PI);
    const pct = Math.round((i / 12) * 100);
    return `${pct}% { transform: translate(${x.toFixed(2)}px, ${y.toFixed(2)}px) rotate(${angle.toFixed(1)}deg); }`;
  });

  // Near-centre samples for waggle run detection: roughly pct 0%, 50%, 100%.
  // We'll keep waggle separate and simpler: a tiny translateX jitter on the bee body.

  const cssKeyframes = `
    @keyframes ${travelAnimName} {
      ${keyframeStops.join('\n      ')}
    }
    @keyframes ${wingsAnimName} {
      0%, 100% { transform: scaleY(1.0); }
      50%       { transform: scaleY(0.65); }
    }
    @keyframes ${waggleAnimName} {
      0%, 100% { transform: translateX(0px); }
      25%      { transform: translateX(0.8px); }
      75%      { transform: translateX(-0.8px); }
    }
  `;

  // Bee geometry — tiny but precise. Body on its side (x axis = forward direction).
  // At the starting position the bee faces right (+x), matching the tangent at t=0.
  const bodyStyle = shouldAnimate
    ? {
        animation: `${travelAnimName} 7s linear infinite`,
        transformOrigin: '0 0',
      }
    : { transform: 'translate(0px, 0px) rotate(0deg)' }; // static at centre

  const wingStyle = (side) => ({
    transformOrigin: '0 0',
    transformBox: 'fill-box',
    animation: shouldAnimate
      ? `${wingsAnimName} 0.18s ease-in-out infinite alternate`
      : 'none',
    animationDelay: side === 'top' ? '0s' : '0.09s',
  });

  // SVG viewBox: the lemniscate spans x ∈ [-40, 40], y ∈ [-~14, ~14].
  // We add margin for the bee body width.
  return (
    <svg
      className={className}
      viewBox="-55 -35 110 70"
      width="100%"
      height="100%"
      aria-label="A bee tracing a figure-eight waggle dance"
      role="img"
      style={{ display: 'block' }}
    >
      <style>{cssKeyframes}</style>

      {/* The bee — a group that travels along the path */}
      <g style={bodyStyle}>
        {/* Wing top — angled slightly back from forward direction */}
        <ellipse
          cx="-1"
          cy="-5"
          rx="5"
          ry="3"
          fill="none"
          stroke="#c9a84c"
          strokeOpacity="0.55"
          strokeWidth="0.7"
          transform="rotate(-20, -1, -5)"
          style={wingStyle('top')}
        />
        {/* Wing bottom */}
        <ellipse
          cx="-1"
          cy="5"
          rx="5"
          ry="3"
          fill="none"
          stroke="#c9a84c"
          strokeOpacity="0.55"
          strokeWidth="0.7"
          transform="rotate(20, -1, 5)"
          style={wingStyle('bottom')}
        />
        {/* Body — elongated ellipse, facing right (+x direction) */}
        <ellipse
          cx="0"
          cy="0"
          rx="6"
          ry="3.5"
          fill="#c9a84c"
          fillOpacity="0.85"
          stroke="#d4a017"
          strokeOpacity="0.4"
          strokeWidth="0.5"
        />
        {/* Abdomen stripe — a single dark band */}
        <ellipse
          cx="1.5"
          cy="0"
          rx="2"
          ry="3.4"
          fill="#08080d"
          fillOpacity="0.28"
        />
        {/* Head — small circle at the front (+x end of body) */}
        <circle
          cx="7"
          cy="0"
          r="2.5"
          fill="#d4a017"
          fillOpacity="0.9"
          stroke="#c9a84c"
          strokeOpacity="0.3"
          strokeWidth="0.4"
        />
      </g>
    </svg>
  );
}
