// ─────────────────────────────────────────────────────────────
// Leaf-specific motion primitives. These exist only so the
// viral-leaves screens can feel like something is happening to
// every leaf at every moment, even when the data is static in the
// brainstorm board.
// ─────────────────────────────────────────────────────────────


// ── 1 · Spark sparkline — 16 vertical bars + a moving leading dot.
// Conveys velocity at a glance. Bars are heights from a stable seed
// (so re-renders don't redraw); the leading dot pulses at the cadence
// the data is "growing".
function VelocitySpark({ seed = 'x', velocity = 12, color = '#D4960C',
                          height = 20, width = 72 }) {
  const bars = React.useMemo(() => {
    let x = 0;
    for (let i = 0; i < seed.length; i++) x = (x * 31 + seed.charCodeAt(i)) | 0;
    const out = [];
    for (let i = 0; i < 16; i++) {
      x = (x * 1103515245 + 12345) & 0x7fffffff;
      const base = 0.35 + (x % 65) / 100;
      // upward-trending tail → multiply later bars
      const trend = 1 + (i / 16) * Math.min(1.0, velocity / 30);
      out.push(Math.min(1, base * trend));
    }
    return out;
  }, [seed, velocity]);

  // Cadence — faster pulse for faster velocity
  const dur = Math.max(0.9, 2.6 - velocity / 30);

  return (
    <span style={{
      display: 'inline-flex', alignItems: 'flex-end', gap: 1.5,
      height, width, position: 'relative', overflow: 'visible',
    }}>
      {bars.map((b, i) => (
        <span data-fl-anim key={i} style={{
          width: 2, height: `${Math.max(1, b * height)}px`,
          background: i >= bars.length - 3 ? color : 'rgba(168,197,160,0.40)',
          borderRadius: 1,
          transformOrigin: 'bottom',
          animation: i >= bars.length - 3
            ? `flSparkPulse ${dur}s var(--ease-organic) ${i * 60}ms infinite`
            : 'none',
        }}/>
      ))}
      {/* Leading edge dot */}
      <span data-fl-anim style={{
        position: 'absolute', right: 0, top: 0,
        width: 5, height: 5, borderRadius: '50%', background: color,
        boxShadow: `0 0 8px ${color}`,
        animation: `flSparkDot ${dur}s var(--ease-organic) infinite`,
      }}/>
    </span>
  );
}


// ── 2 · Drifting leaves overlay — small angled rectangles drift up
// across the card background. Used on velocity-feed cards. Subtle
// enough to feel ambient, not theatrical.
function LeafDriftOverlay({ seed = 'x', count = 4, accent = '#A8C5A0',
                             borderRadius = 14 }) {
  const items = React.useMemo(() => {
    let x = 0;
    for (let i = 0; i < seed.length; i++) x = (x * 31 + seed.charCodeAt(i)) | 0;
    const list = [];
    for (let i = 0; i < count; i++) {
      x = (x * 1664525 + 1013904223) & 0x7fffffff;
      list.push({
        left:  (x % 92) + 4,                     // 4–96 %
        dx:    (((x >> 4) % 60) - 30),           // ±30 px sway
        rot:   (((x >> 7) % 80) - 40),           // ±40°
        delay: ((x >> 11) % 1000) / 100,         // 0–10s
        dur:   8 + (((x >> 14) % 12)),           // 8–20s
        size:  3 + (((x >> 17) % 3)),            // 3–5 px
        hue:   (x & 1) ? accent : '#5E8048',
      });
    }
    return list;
  }, [seed, count, accent]);
  return (
    <span aria-hidden="true" style={{
      position: 'absolute', inset: 0, borderRadius, overflow: 'hidden',
      pointerEvents: 'none', zIndex: 0,
    }}>
      {items.map((it, i) => (
        <span data-fl-anim key={i} style={{
          position: 'absolute', left: `${it.left}%`, bottom: 0,
          width: it.size, height: Math.round(it.size * 1.6),
          background: it.hue, opacity: 0,
          borderRadius: '40% 60% 40% 60% / 60% 30% 70% 40%',
          '--leaf-dx': `${it.dx}px`,
          '--leaf-rot': `${it.rot}deg`,
          animation: `flLeafDrift ${it.dur}s linear ${it.delay}s infinite`,
        }}/>
      ))}
    </span>
  );
}


// ── 3 · Live leaf ticker — a small marquee that cycles through
// "fern-12 caught +3 sunlight in Philosophy" lines. Lives above the
// feed and gives the user a constant micro-FOMO without being loud.
const TICKER_EVENTS = [
  { handle: 'fern-12',  delta: 3, where: 'Philosophy', when: 'just now' },
  { handle: 'marina_k', delta: 2, where: 'BART Riders', when: '12s' },
  { handle: 'oakling',  delta: 5, where: 'Slow Reading', when: '34s' },
  { handle: 'samh',     delta: 1, where: 'Philosophy', when: '1m' },
  { handle: 'leaf-902', delta: 4, where: 'SF', when: '2m' },
  { handle: 'tulip-aa', delta: 2, where: 'Indie Film', when: '2m' },
];

function LiveLeafTicker() {
  const [i, setI] = React.useState(0);
  React.useEffect(() => {
    const id = setInterval(() => setI(v => (v + 1) % TICKER_EVENTS.length), 3200);
    return () => clearInterval(id);
  }, []);
  const ev = TICKER_EVENTS[i];
  return (
    <div style={{
      position: 'relative', overflow: 'hidden',
      height: 36, padding: '0 12px',
      display: 'flex', alignItems: 'center', gap: 10,
      background: 'rgba(212,150,12,0.06)',
      border: '0.5px solid rgba(212,150,12,0.22)',
      borderRadius: 10,
    }}>
      <span style={{ position: 'relative', display: 'inline-flex', flexShrink: 0 }}>
        <FLIcons.Sun size={13} color="#D4960C"/>
        <span data-fl-anim style={{
          position: 'absolute', inset: -3, borderRadius: '50%',
          border: '1px solid #D4960C', opacity: 0.5,
          animation: 'flCanopyRipple 2.4s var(--ease-organic) infinite',
        }}/>
      </span>
      <span style={{ font: '500 10px var(--font-sans)', color: '#F4DCA0',
                     letterSpacing: '0.12em', textTransform: 'uppercase',
                     flexShrink: 0 }}>Live</span>
      <span style={{ flex: 1, minWidth: 0, height: '100%',
                      position: 'relative', overflow: 'hidden' }}>
        <span data-fl-anim key={i} style={{
          position: 'absolute', inset: 0,
          display: 'flex', alignItems: 'center', gap: 6,
          font: '400 12.5px var(--font-sans)', color: '#C9D2BB',
          animation: 'flTickerSlide 3.2s var(--ease-organic) both',
          whiteSpace: 'nowrap',
        }}>
          <span style={{ font: '500 12px var(--font-mono)', color: '#F2EDE4' }}>{ev.handle}</span>
          <span style={{ color: '#586552' }}>caught</span>
          <span style={{ color: '#F4DCA0', fontFamily: 'var(--font-mono)' }}>+{ev.delta}</span>
          <FLIcons.Sun size={10} color="#D4960C"/>
          <span style={{ color: '#586552' }}>in</span>
          <span style={{ font: '500 12px var(--font-mono)', color: '#A8C5A0' }}>{ev.where}</span>
        </span>
      </span>
      <span style={{ font: '400 11px var(--font-mono)', color: '#586552',
                      flexShrink: 0 }}>{ev.when}</span>
    </div>
  );
}


// ── 4 · Self-incrementing sunlight count.
// Every X seconds it ticks up by 1; the digit briefly grows and
// changes from canopy → sunlight color. The user is meant to *see*
// the count moving while they read.
function LiveSunlightCount({ baseline = 100, intervalMs = 4200, style = {} }) {
  const [c, setC] = React.useState(baseline);
  const [tickKey, setTickKey] = React.useState(0);
  React.useEffect(() => {
    const id = setInterval(() => {
      setC(prev => prev + (Math.random() < 0.7 ? 1 : 0));
      setTickKey(k => k + 1);
    }, intervalMs);
    return () => clearInterval(id);
  }, [intervalMs]);
  return (
    <span data-fl-anim key={tickKey} style={{
      display: 'inline-block',
      '--tick-from': '#F2EDE4',
      '--tick-to':   '#F4DCA0',
      animation: 'flCountTick 700ms var(--ease-organic) both',
      ...style,
    }}>{c}</span>
  );
}


// ── 5 · "Pull sunlight" — the brand-native upvote, with a real
// sunburst on tap. Spokes radiate out and fade; the count flies up.
function PullSunlight({ count = 0, onPulled }) {
  const [c, setC] = React.useState(count);
  const [pulled, setPulled] = React.useState(false);
  const [burstKey, setBurstKey] = React.useState(0);
  const pull = (e) => {
    e.stopPropagation();
    if (pulled) {
      setC(c - 1); setPulled(false);
      return;
    }
    setC(c + 1); setPulled(true); setBurstKey(k => k + 1);
    onPulled?.();
  };
  return (
    <button onClick={pull} style={{
      background: 'transparent', border: 'none', cursor: 'pointer',
      padding: 0, display: 'inline-flex', alignItems: 'center', gap: 6,
      font: '500 12px var(--font-mono)',
      color: pulled ? '#F4DCA0' : '#8A9678',
      transition: 'color 140ms var(--ease-organic)',
      position: 'relative',
    }}>
      <span style={{ position: 'relative', display: 'inline-flex',
                      width: 18, height: 18, alignItems: 'center', justifyContent: 'center' }}>
        <FLIcons.Sun size={15} color={pulled ? '#D4960C' : '#586552'}/>
        {burstKey > 0 && (
          <Sunburst key={burstKey}/>
        )}
        {pulled && (
          <span data-fl-anim style={{
            position: 'absolute', inset: -6, borderRadius: '50%',
            border: '1.5px solid #D4960C',
            animation: 'flCanopyRipple 700ms var(--ease-organic) forwards',
            pointerEvents: 'none',
          }}/>
        )}
      </span>
      <CountUp value={c}/>
    </button>
  );
}

// 8 sun-spokes radiating outward when you pull sunlight.
function Sunburst() {
  const spokes = Array.from({ length: 8 });
  return (
    <span aria-hidden="true" style={{
      position: 'absolute', inset: 0, pointerEvents: 'none',
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
    }}>
      <span data-fl-anim style={{
        position: 'relative', width: 18, height: 18,
        animation: 'flSunburst 700ms var(--ease-organic) forwards',
      }}>
        {spokes.map((_, i) => (
          <span key={i} style={{
            position: 'absolute', left: '50%', top: '50%',
            width: 2, height: 10, marginLeft: -1, marginTop: -16,
            background: '#D4960C', borderRadius: 1, opacity: 0.9,
            transformOrigin: '50% 16px',
            transform: `rotate(${i * 45}deg)`,
          }}/>
        ))}
      </span>
    </span>
  );
}


// ── 6 · Position-change indicator for compact rows.
// "↑3" climbing, "↓1" sliding, "▴" new. Subtle color, no shout.
function PositionDelta({ delta = 0, isNew = false }) {
  if (isNew) {
    return (
      <span data-fl-anim style={{
        display: 'inline-flex', alignItems: 'center', gap: 3,
        padding: '1px 5px', borderRadius: 999,
        background: 'rgba(212,150,12,0.10)',
        border: '0.5px solid rgba(212,150,12,0.30)',
        color: '#F4DCA0', font: '500 9.5px var(--font-mono)',
        letterSpacing: '0.04em', textTransform: 'uppercase',
        animation: 'flBeadGrow 360ms var(--ease-organic) both',
      }}>
        <span style={{ width: 4, height: 4, borderRadius: '50%', background: '#D4960C' }}/>
        new
      </span>
    );
  }
  if (delta === 0) {
    return <span style={{
      width: 9, height: 1, background: '#445239', display: 'inline-block',
      verticalAlign: 'middle', opacity: 0.6,
    }}/>;
  }
  const up = delta > 0;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 1,
      font: '500 10px var(--font-mono)',
      color: up ? '#A8C5A0' : '#A39B89',
    }}>
      <svg width="8" height="8" viewBox="0 0 8 8" style={{
        transform: up ? 'rotate(0deg)' : 'rotate(180deg)',
      }}>
        <path d="M4 1 L7 6 L1 6 Z" fill={up ? '#A8C5A0' : '#A39B89'}/>
      </svg>
      {Math.abs(delta)}
    </span>
  );
}


// ── 7 · A "growing" spur — an animated SVG curve that draws itself
// from the root tease down to the branch card. The dashes flow along
// the curve like sap.
function GrowingSpur({ height = 26 }) {
  return (
    <svg width="100%" height={height} viewBox={`0 0 200 ${height}`}
         preserveAspectRatio="none" style={{ display: 'block' }}>
      <path d={`M 6 0 Q 6 ${height * 0.6} 22 ${height * 0.85}`}
            stroke="#4F8E51" strokeOpacity="0.45"
            strokeWidth="1.2" fill="none" strokeLinecap="round"/>
      <path data-fl-anim d={`M 6 0 Q 6 ${height * 0.6} 22 ${height * 0.85}`}
            stroke="#D4960C" strokeOpacity="0.9"
            strokeWidth="1.2" fill="none" strokeLinecap="round"
            strokeDasharray="3 21"
            style={{ animation: 'flDashFlow 3.2s linear infinite' }}/>
    </svg>
  );
}


// ── 8 · Galaxy shooting-stars overlay. Periodic streaks across the
// view to suggest "a leaf just bloomed across the canopy".
function ShootingStars({ count = 3 }) {
  const seeds = React.useMemo(() => {
    return Array.from({ length: count }).map((_, i) => ({
      top: 10 + (i * 23) % 70,
      left: 5 + (i * 41) % 50,
      delay: i * 2.7,
      dur: 3.5 + (i % 2),
    }));
  }, [count]);
  return (
    <>
      {seeds.map((s, i) => (
        <span data-fl-anim key={i} style={{
          position: 'absolute', top: `${s.top}%`, left: `${s.left}%`,
          width: 36, height: 1,
          background: 'linear-gradient(90deg, transparent, #F4DCA0 60%, #D4960C)',
          borderRadius: 1, pointerEvents: 'none',
          boxShadow: '0 0 6px rgba(212,150,12,0.6)',
          animation: `flShootingStar ${s.dur}s var(--ease-organic) ${s.delay}s infinite`,
          transform: 'translate(-30px, 30px) scale(0)',
        }}/>
      ))}
    </>
  );
}


Object.assign(window, {
  VelocitySpark, LeafDriftOverlay, LiveLeafTicker,
  LiveSunlightCount, PullSunlight, PositionDelta,
  GrowingSpur, ShootingStars,
});
