/* ============================================================
   logo.jsx — the Slyck mark.
   Story: "?" (uncertainty) → hook magnetises & shakes → the
   stablecoin is pulled in along mint flux lines → snaps into the
   hook's cradle and collapses into a clean dot → locked ("slyck").

   A question mark minus its dot IS a hook, so the stroke never
   morphs — it rotates 180° while the coin flies home.
   pose(t) is pure → every frame reproducible.
   ============================================================ */

const HOOK_PATH = "M32 36 C32 18 68 18 66 38 C65 50 50 50 50 64";
const CRADLE = { x: 50, y: 33 };   // where the coin nests in the flipped hook
const REF = 12.5;                  // reference radius for the detailed coin
const LOOP = 4.8;                  // seconds per full story loop

function pose(t) {
  // ---------- rotation: 0 (?) → 180 (hook) ----------
  let rot;
  if (t < 1.5) rot = 0;
  else if (t < 2.15) rot = 180 * Ease.inOutCubic((t - 1.5) / 0.65);
  else rot = 180 + 4 * Math.sin((t - 2.15) * 14) * Math.exp(-(t - 2.15) * 5); // settle

  // magnetic shake right before / during the pull
  if (t >= 0.95 && t < 1.5) {
    const p = (t - 0.95) / 0.55;
    rot += Math.sin(t * 72) * 6 * Math.sin(p * Math.PI);
  }

  // ---------- magnet intensity (drives flux lines) ----------
  let magnet = 0;
  if (t >= 0.9 && t < 1.5) magnet = Ease.outCubic((t - 0.9) / 0.6);
  else if (t >= 1.5 && t < 2.1) magnet = 1;
  else if (t >= 2.1 && t < 2.55) magnet = 1 - Ease.outCubic((t - 2.1) / 0.45);

  // ---------- coin travel: dot → (charged, held low) → snap → settle ----------
  const DOTY = 86, HOLDY = 83, CR = CRADLE.y;
  let cx = 50, cy = DOTY;
  if (t < 0.9) {
    cy = DOTY + Math.sin(t * 4) * 0.5;                  // calm float (uncertainty)
  } else if (t < 1.5) {
    const p = (t - 0.9) / 0.6;                          // magnetised: vibrate, barely lift
    cy = lerp(DOTY, HOLDY, Ease.outCubic(p)) + Math.sin(t * 44) * 1.1 * p;
    cx = 50 + Math.sin(t * 50) * 2.2 * p;
  } else if (t < 2.15) {
    const p = (t - 1.5) / 0.65;
    cx = 50;
    cy = lerp(HOLDY, CR, Ease.outBack(p, 1.7));         // overshoot snap
  } else {
    cy = CR - Math.sin((t - 2.15) * 16) * 1.1 * Math.exp(-(t - 2.15) * 6);
  }

  // ---------- detail + radius: detailed coin → plain dot at lock ----------
  let detail = 1, cr = REF;
  if (t >= 2.06 && t < 2.5) {
    const p = (t - 2.06) / 0.44;
    detail = 1 - Ease.outCubic(p);
    cr = lerp(REF, 9.5, Ease.outCubic(p));
  } else if (t >= 2.5) { detail = 0; cr = 9.5; }

  // ---------- mint lock pulse ----------
  let pulse = 0;
  if (t >= 2.08 && t < 2.8) pulse = Math.sin(((t - 2.08) / 0.72) * Math.PI);

  // ---------- motion streak during the flight ----------
  let streak = 0;
  if (t >= 1.5 && t < 2.12) streak = Math.sin(((t - 1.5) / 0.62) * Math.PI);

  // ---------- magnet source = hook tip, rotated ----------
  const rad = rot * Math.PI / 180;
  const sx = 50 - 14 * Math.sin(rad);
  const sy = 50 + 14 * Math.cos(rad);

  return { rot, cx, cy, cr, detail, magnet, pulse, streak, sx, sy };
}

/* the USDC-style coin; `detail` cross-fades the $ + ring down to a plain dot */
function CoinIcon({ cx, cy, r, detail, color = "#2E6BFF" }) {
  const s = r / REF;
  return (
    <g transform={`translate(${cx.toFixed(2)} ${cy.toFixed(2)})`}>
      <circle r={r.toFixed(2)} fill={color} />
      <circle cx={(-r * 0.3).toFixed(2)} cy={(-r * 0.34).toFixed(2)} r={(r * 0.24).toFixed(2)}
              fill="#fff" opacity={0.38 * (1 - detail * 0.5)} />
      {detail > 0.02 && (
        <g transform={`scale(${s.toFixed(3)})`} opacity={detail.toFixed(3)}>
          <path d="M-3 -8.6 A 9 9 0 0 0 -3 8.6" fill="none" stroke="#fff"
                strokeWidth="1.7" strokeLinecap="round" />
          <path d="M3 -8.6 A 9 9 0 0 1 3 8.6" fill="none" stroke="#fff"
                strokeWidth="1.7" strokeLinecap="round" />
          <text x="0" y="0.6" textAnchor="middle" dominantBaseline="central"
                fontFamily="'Clash Display', sans-serif" fontWeight="600" fontSize="13"
                fill="#fff">$</text>
        </g>
      )}
    </g>
  );
}

/* mint magnetic field: a fan of flux lines from the charged hook tip to the
   coin, plus a glow ring on the tip — reads unmistakably as "magnetised" */
function FluxLines({ sx, sy, cx, cy, m }) {
  if (m < 0.03) return null;
  const mx = (sx + cx) / 2, my = (sy + cy) / 2;
  const arc = (bow) =>
    `M ${cx.toFixed(1)} ${cy.toFixed(1)} Q ${(mx + bow).toFixed(1)} ${my.toFixed(1)} ${sx.toFixed(1)} ${sy.toFixed(1)}`;
  return (
    <g opacity={m.toFixed(3)} stroke="#5EEAD4" fill="none" strokeLinecap="round">
      {[-15, -8, 8, 15].map((b, i) => (
        <path key={i} d={arc(b)} strokeWidth={i === 1 || i === 2 ? 2.4 : 1.8}
              opacity={i === 1 || i === 2 ? 0.9 : 0.6} />
      ))}
      <path d={arc(0)} strokeWidth="2" strokeDasharray="0.5 4.5" opacity="0.8" />
      {/* charged hook tip */}
      <circle cx={sx.toFixed(1)} cy={sy.toFixed(1)} r={(4 + 3 * m).toFixed(1)}
              strokeWidth="1.6" opacity="0.55" />
    </g>
  );
}

function SlyckMark({ t, size = 96, hook = "#0B1733", coin = "#2E6BFF" }) {
  const p = pose(t);
  return (
    <svg viewBox="0 0 100 100" width={size} height={size} className="slyck-mark" aria-label="Slyck">
      {p.pulse > 0.01 && (
        <circle cx={CRADLE.x} cy={CRADLE.y} r={lerp(11, 30, p.pulse)} fill="none"
                stroke="#5EEAD4" strokeWidth={lerp(7, 0.4, p.pulse)} opacity={(1 - p.pulse) * 0.85} />
      )}
      <g transform={`rotate(${p.rot.toFixed(2)} 50 50)`}>
        <path d={HOOK_PATH} fill="none" stroke={hook} strokeWidth="14"
              strokeLinecap="round" strokeLinejoin="round" />
      </g>
      <FluxLines sx={p.sx} sy={p.sy} cx={p.cx} cy={p.cy} m={p.magnet} />
      {p.streak > 0.02 && (
        <g opacity={(p.streak * 0.75).toFixed(3)} stroke={coin} strokeLinecap="round">
          <line x1={p.cx - 3} y1={p.cy + p.cr + 3} x2={p.cx - 3} y2={p.cy + p.cr + 10} strokeWidth="2.4" />
          <line x1={p.cx + 3} y1={p.cy + p.cr + 2} x2={p.cx + 3} y2={p.cy + p.cr + 8} strokeWidth="2" />
        </g>
      )}
      <CoinIcon cx={p.cx} cy={p.cy} r={p.cr} detail={p.detail} color={coin} />
    </svg>
  );
}

/* looping, self-playing instance */
function AnimatedMark({ size = 96, hook, coin, register }) {
  const [t, setT] = React.useState(LOOP);
  const tref = React.useRef(LOOP);
  React.useEffect(() => {
    const reduced = window.matchMedia &&
      window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduced) { setT(LOOP); return; }
    let raf, last = null;
    const loop = (ts) => {
      if (last == null) last = ts;
      tref.current += Math.min((ts - last) / 1000, 1 / 30); last = ts;
      if (tref.current > LOOP + 1.4) tref.current = 0;     // hold locked, then loop
      setT(tref.current);
      raf = requestAnimationFrame(loop);
    };
    if (register) register(() => { tref.current = 0; });
    raf = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(raf);
  }, []);
  return <SlyckMark t={t} size={size} hook={hook} coin={coin} />;
}

/* nav mark — plays the story once on mount, holds locked, replays on hover */
function NavMark({ size = 30, hook, coin }) {
  const [t, setT] = React.useState(0);
  const tref = React.useRef(0);
  const playing = React.useRef(true);
  const END = 2.95; // action is complete + settled by here
  React.useEffect(() => {
    const reduced = window.matchMedia &&
      window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduced) { setT(LOOP); return; }
    let raf, last = null;
    const loop = (ts) => {
      if (last == null) last = ts;
      const dt = Math.min((ts - last) / 1000, 1 / 30); last = ts;
      if (playing.current) {
        tref.current += dt;
        if (tref.current >= END) { tref.current = END; playing.current = false; }
        setT(tref.current);
      }
      raf = requestAnimationFrame(loop);
    };
    raf = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(raf);
  }, []);
  const replay = () => { tref.current = 0; playing.current = true; };
  return (
    <span className="nav-mark" onMouseEnter={replay}
          style={{ display: "inline-flex", lineHeight: 0 }}>
      <SlyckMark t={t} size={size} hook={hook} coin={coin} />
    </span>
  );
}

Object.assign(window, { SlyckMark, AnimatedMark, NavMark, CoinIcon, pose, LOGO_LOOP: LOOP });
