// @ds-adherence-ignore -- animation kit: brand tokens declared as raw values for the engine
/* ============================================================================
   AINA — Shared Animation Kit
   Brand primitives + reusable motion components for all lesson-video styles.
   Loaded as a Babel script; exports everything to window so each style's
   inline scene script can use them (Babel scripts don't share scope).
   Depends on: animations.jsx (Stage/Sprite/useTime/Easing/interpolate).
   ========================================================================== */

const AINA = {
  navy900: "#0D1B2A", navy800: "#10233A", navy700: "#0F2637",
  teal800: "#0E4D4A", teal700: "#1C6B65", teal600: "#1AA79D", teal500: "#249487",
  gold500: "#C9A96E", gold600: "#B88E4C", gold700: "#D4AF37",
  mist50: "#F9F8F4", mist100: "#F5EFE6", stone100: "#E7DFD2", cool100: "#E6ECEF",
  ivory: "#F5F5F8",
  ink900: "#142033", ink700: "#3E4E63", ink500: "#6E7B8B",
  lavender: "#6F77FB",
  onDark: "#F7F6F2", onDarkMute: "rgba(247,246,242,0.72)",
  line: "rgba(20,32,51,0.08)", lineStrong: "rgba(20,32,51,0.14)", lineDark: "rgba(247,246,242,0.12)",
  fontDisplay: '"Playfair Display", Georgia, serif',
  fontUI: '"Inter", system-ui, sans-serif',
  fontMono: '"JetBrains Mono", ui-monospace, monospace',
};

// Tag → accent color map (annotations across all styles)
function tagColor(tag) {
  const t = (tag || "").toUpperCase();
  if (["NEVER", "RISK", "MANUAL"].includes(t)) return AINA.gold600;
  if (["AI-READY", "AI-ASSIST", "TASK", "STRUCTURE", "RULE", "REPETITION"].includes(t)) return AINA.teal500;
  if (["ROLE", "CONTEXT", "OUTPUT", "EXAMPLE", "TECHNICAL"].includes(t)) return AINA.navy900;
  return AINA.ink700;
}

const { useTime, useTimeline, useSprite, Easing, interpolate, animate, clamp } = window;

// ── Typewriter helper: returns the substring of `text` revealed at progress p ──
function typed(text, p) {
  const n = Math.round(clamp(p, 0, 1) * text.length);
  return text.slice(0, n);
}

// ── Brand wings mark ──────────────────────────────────────────────────────
function BrandMark({ size = 48, style = {} }) {
  return (
    <img src="assets/mark.svg" alt="AINA"
      style={{ width: size, height: "auto", display: "block", ...style }} />
  );
}

// ── Animated signature wave-line overlay (gold + teal thin curves) ─────────
// Slowly sweeps. Sits in a corner third. tone: 'gold' | 'teal' | 'both'
function WaveBG({ tone = "both", dark = false, opacity = 1, anchor = "right" }) {
  const time = useTime();
  const sweep = Math.sin(time * 0.35) * 14;
  const sweep2 = Math.cos(time * 0.28) * 10;
  const gold = dark ? "rgba(212,175,55,0.5)" : "rgba(201,169,110,0.55)";
  const teal = dark ? "rgba(36,148,135,0.45)" : "rgba(36,148,135,0.42)";
  const flip = anchor === "left";
  return (
    <svg viewBox="0 0 1200 800" preserveAspectRatio="none"
      style={{ position: "absolute", inset: 0, width: "100%", height: "100%",
        opacity, pointerEvents: "none", transform: flip ? "scaleX(-1)" : "none" }}>
      {(tone === "gold" || tone === "both") && [0, 1, 2, 3].map((i) => (
        <path key={"g" + i}
          d={`M ${760 + i * 22} -40 C ${560 + sweep + i * 18} 240, ${980 - sweep + i * 14} 420, ${720 + i * 20} 860`}
          fill="none" stroke={gold} strokeWidth="1" opacity={0.85 - i * 0.14} />
      ))}
      {(tone === "teal" || tone === "both") && [0, 1, 2].map((i) => (
        <path key={"t" + i}
          d={`M ${860 + i * 26} -40 C ${680 - sweep2 + i * 16} 300, ${1080 + sweep2 - i * 12} 520, ${820 + i * 22} 860`}
          fill="none" stroke={teal} strokeWidth="1" opacity={0.7 - i * 0.16} />
      ))}
    </svg>
  );
}

// ── Quiet dot-grid texture ─────────────────────────────────────────────────
function DotGrid({ dark = false, opacity = 1 }) {
  const c = dark ? "rgba(247,246,242,0.10)" : "rgba(20,32,51,0.12)";
  return (
    <div style={{ position: "absolute", inset: 0, opacity, pointerEvents: "none",
      backgroundImage: `radial-gradient(${c} 1px, transparent 1px)`,
      backgroundSize: "26px 26px" }} />
  );
}

// ── Kicker (wide-tracked eyebrow) ──────────────────────────────────────────
function Kicker({ children, color = AINA.teal700, size = 13, style = {} }) {
  return (
    <div style={{ fontFamily: AINA.fontUI, fontSize: size, fontWeight: 600,
      textTransform: "uppercase", letterSpacing: "0.16em", color, ...style }}>
      {children}
    </div>
  );
}

// ── Chip / pill ─────────────────────────────────────────────────────────────
function Chip({ children, tone = "teal", dark = false, style = {} }) {
  const tones = {
    teal: { bg: "rgba(36,148,135,0.14)", fg: AINA.teal700 },
    gold: { bg: "rgba(201,169,110,0.20)", fg: AINA.gold600 },
    navy: { bg: "rgba(13,27,42,0.08)", fg: AINA.navy900 },
    lavender: { bg: "rgba(111,119,251,0.14)", fg: "#5A63E8" },
  };
  const c = tones[tone] || tones.teal;
  return (
    <span style={{ display: "inline-flex", alignItems: "center", gap: 6,
      padding: "6px 13px", borderRadius: 999, fontFamily: AINA.fontUI,
      fontSize: 13, fontWeight: 600, letterSpacing: "0.03em",
      background: dark ? "rgba(247,246,242,0.10)" : c.bg,
      color: dark ? AINA.onDark : c.fg, ...style }}>
      {children}
    </span>
  );
}

// ── Gold hairline divider ──────────────────────────────────────────────────
function GoldRule({ width = 72, color = AINA.gold500, style = {} }) {
  return (
    <div style={{ height: 1, width,
      background: `linear-gradient(90deg, transparent, ${color}, transparent)`, ...style }} />
  );
}

// ── Animated audio waveform (NotebookLM) ───────────────────────────────────
// bars driven by time; `active` brightens; `seed` varies the shape.
function Waveform({ bars = 48, color = AINA.teal500, width = 520, height = 64, active = true, seed = 0 }) {
  const time = useTime();
  const arr = Array.from({ length: bars });
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 3, width, height }}>
      {arr.map((_, i) => {
        const phase = i * 0.45 + seed * 3;
        const env = 0.35 + 0.65 * Math.abs(Math.sin(i / bars * Math.PI)); // center-weighted
        const h = (0.18 + 0.82 * Math.pow(Math.abs(Math.sin(time * 6 + phase) * Math.cos(time * 2.2 + phase * 0.5)), 1.2)) * env;
        return (
          <div key={i} style={{ flex: 1, height: `${(active ? h : 0.12) * 100}%`,
            minHeight: 2, borderRadius: 3, background: color,
            opacity: active ? 0.55 + 0.45 * h : 0.25,
            transition: "opacity 80ms linear" }} />
        );
      })}
    </div>
  );
}

// ── Timeline progress bar (sits at top/bottom of frame) ────────────────────
function ProgressBar({ color = AINA.gold500, track = "rgba(20,32,51,0.10)", height = 4, top = true }) {
  const { time, duration } = useTimeline();
  const p = clamp(time / duration, 0, 1);
  return (
    <div style={{ position: "absolute", left: 0, right: 0, [top ? "top" : "bottom"]: 0,
      height, background: track, zIndex: 30 }}>
      <div style={{ height: "100%", width: `${p * 100}%`, background: color }} />
    </div>
  );
}

// ── Caption band (lower-third subtitle, NotebookLM/social) ─────────────────
// pass the lesson.captions array + current time; renders the active line.
function CaptionTrack({ captions, dark = true, maxWidth = 900, bottom = 64, fontSize = 30 }) {
  const time = useTime();
  let active = captions[0];
  for (const c of captions) if (time >= c.t) active = c;
  // fade between lines
  const since = time - active.t;
  const op = clamp(since / 0.28, 0, 1);
  return (
    <div style={{ position: "absolute", left: "50%", bottom, transform: "translateX(-50%)",
      width: maxWidth, textAlign: "center", opacity: op }}>
      <div style={{ fontFamily: AINA.fontUI, fontSize, fontWeight: 500, lineHeight: 1.35,
        color: dark ? AINA.onDark : AINA.ink900, textWrap: "balance",
        textShadow: dark ? "0 2px 24px rgba(0,0,0,0.5)" : "none" }}>
        {active.text}
      </div>
    </div>
  );
}

// ── Reveal wrapper: fades + rises children in over [delay, delay+dur] ──────
// Use inside a Sprite — reads local time via useSprite.
function Rise({ delay = 0, dur = 0.5, dy = 18, children, ease = Easing.easeOutCubic }) {
  const { localTime } = useSprite();
  const t = ease(clamp((localTime - delay) / dur, 0, 1));
  return (
    <div style={{ opacity: t, transform: `translateY(${(1 - t) * dy}px)`, willChange: "transform, opacity" }}>
      {children}
    </div>
  );
}

// ── Count-up number (scorecards) ───────────────────────────────────────────
function CountUp({ to = 100, dur = 1, delay = 0, suffix = "", style = {} }) {
  const { localTime } = useSprite();
  const t = Easing.easeOutCubic(clamp((localTime - delay) / dur, 0, 1));
  return <span style={style}>{Math.round(to * t)}{suffix}</span>;
}

Object.assign(window, {
  AINA, tagColor, typed,
  BrandMark, WaveBG, DotGrid, Kicker, Chip, GoldRule,
  Waveform, ProgressBar, CaptionTrack, Rise, CountUp,
});
