/* components.jsx - shared data, theme hooks and small UI primitives */

const THEMES = [
  {
    id: "blue",
    name: "Blue / Original",
    short: "Blue",
    sub: "Cyan -> Blue -> Violet",
    note: "The core Devis Lab signal: cool, digital, optimistic.",
    status: "core",
    asset: "blue",
    c1: "#00D4CB",
    c2: "#2563EB",
    c3: "#7C3AED",
    logoCyan: "#00D4CB",
    logoAccent: "#2563EB",
    logoEnd: "#7C3AED",
    logoSparkle: "#BFFFF8",
    logoSparkleStrong: "#0EA5E9",
    pixelBase1: "#00D4CB",
    pixelBase2: "#2563EB",
    pixelBase3: "#7C3AED",
    pixelSignal: "#00F0C8",
    soft: "rgba(37,99,235,0.09)",
    ring: "rgba(0,212,203,0.28)",
  },
  {
    id: "magenta",
    name: "Magenta",
    short: "Magenta",
    sub: "Pink -> Magenta -> Berry",
    note: "Creative, bright and maker-friendly for playful experiments.",
    status: "experiment",
    asset: "magenta",
    c1: "#F472B6",
    c2: "#EC4899",
    c3: "#BE185D",
    logoCyan: "#F472B6",
    logoAccent: "#EC4899",
    logoEnd: "#BE185D",
    logoSparkle: "#FFD6EC",
    logoSparkleStrong: "#EC4899",
    pixelBase1: "#FF6FBF",
    pixelBase2: "#EC4899",
    pixelBase3: "#8B5CF6",
    pixelSignal: "#00F0C8",
    soft: "rgba(236,72,153,0.09)",
    ring: "rgba(244,114,182,0.28)",
  },
  {
    id: "green",
    name: "Green / Teal",
    short: "Green",
    sub: "Mint -> Teal -> Emerald",
    note: "Fresh, focused and useful for productivity or automation tools.",
    status: "support",
    asset: "green",
    c1: "#34D399",
    c2: "#10B981",
    c3: "#059669",
    logoCyan: "#34D399",
    logoAccent: "#10B981",
    logoEnd: "#059669",
    logoSparkle: "#D9FFE9",
    logoSparkleStrong: "#10B981",
    pixelBase1: "#7CFFD4",
    pixelBase2: "#22D3A6",
    pixelBase3: "#14B8A6",
    pixelSignal: "#8AFFE0",
    soft: "rgba(16,185,129,0.09)",
    ring: "rgba(52,211,153,0.28)",
  },
  {
    id: "sunset",
    name: "Sunset",
    short: "Sunset",
    sub: "Amber -> Orange -> Red",
    note: "Warm, punchy and good for launches, side quests and demos.",
    status: "experiment",
    asset: "sunset",
    c1: "#F59E0B",
    c2: "#F97316",
    c3: "#EF4444",
    logoCyan: "#F59E0B",
    logoAccent: "#F97316",
    logoEnd: "#EF4444",
    logoSparkle: "#FFE7B8",
    logoSparkleStrong: "#F97316",
    pixelBase1: "#FFB02E",
    pixelBase2: "#FF7A1A",
    pixelBase3: "#F43F5E",
    pixelSignal: "#00F0C8",
    soft: "rgba(249,115,22,0.10)",
    ring: "rgba(245,158,11,0.28)",
  },
  {
    id: "violet",
    name: "Violet",
    short: "Violet",
    sub: "Lavender -> Violet -> Deep",
    note: "Studio-like, AI-friendly and slightly more serious.",
    status: "support",
    asset: "violet",
    c1: "#A78BFA",
    c2: "#7C3AED",
    c3: "#5B21B6",
    logoCyan: "#A78BFA",
    logoAccent: "#7C3AED",
    logoEnd: "#5B21B6",
    logoSparkle: "#EEE4FF",
    logoSparkleStrong: "#7C3AED",
    pixelBase1: "#B99CFF",
    pixelBase2: "#7C3AED",
    pixelBase3: "#2563EB",
    pixelSignal: "#00F0C8",
    soft: "rgba(124,58,237,0.10)",
    ring: "rgba(167,139,250,0.30)",
  },
];

const THEME_ALIASES = {
  brand: "blue",
  forest: "green",
};

function getTheme(themeId) {
  const normalized = THEME_ALIASES[themeId] || themeId;
  return THEMES.find((x) => x.id === normalized) || THEMES[0];
}

const BRAND_FIXED = [
  { name: "Ink", hex: "#0D132B", note: "Primary text / dark surfaces" },
  { name: "Blue", hex: "#2563EB", note: "Brand accent / primary action" },
  { name: "Violet", hex: "#7C3AED", note: "Brand accent / depth" },
  { name: "Cyan", hex: "#00D4CB", note: "Brand accent / highlight" },
  { name: "Mist", hex: "#F1F3F6", note: "Light surface / neutral" },
];

const IDENTITY_MODES = {
  original: {
    label: "Primary Mark",
    claim: "Built to ship.",
    headline: "Clear signal.\nPlayful systems.\nBuilt to ship.",
    eyebrow: "Primary signal",
    description:
      "The official Devis Lab mark for product pages, banners and public identity.",
    bannerLine: "official signal for product pages",
    mode: "Core lab",
  },
  pixel: {
    label: "Pixel Mode",
    claim: "Lab experiments.",
    headline: "Tiny pixels.\nBig signal.\nLab experiments.",
    eyebrow: "Pixel mode",
    description:
      "A playful mode for quick experiments, fan pages and AI lab moments.",
    bannerLine: "playful pixels for lab moments",
    mode: "Experiment",
  },
  geometric: {
    label: "Studio Mark",
    claim: "Same signal.",
    headline: "Sharper geometry.\nStudio polish.\nSame signal.",
    eyebrow: "Studio mode",
    description:
      "A calmer geometric mode for premium studio contexts and cleaner layouts.",
    bannerLine: "clean geometry for studio polish",
    mode: "Support",
  },
  monochrome: {
    label: "Utility Mono",
    claim: "Maximum clarity.",
    headline: "Tiny surfaces.\nOne color.\nMaximum clarity.",
    eyebrow: "Utility mode",
    description:
      "A contrast-safe utility mark for favicons, masks, docs and tiny badges.",
    bannerLine: "one-color clarity for tiny surfaces",
    mode: "Utility",
  },
};

function getIdentityMode(direction) {
  return IDENTITY_MODES[direction] || IDENTITY_MODES.original;
}

function applyThemeVariables(themeId) {
  const t = getTheme(themeId);
  document.documentElement.dataset.accent = t.id;
  const r = document.documentElement.style;
  r.setProperty("--accent-1", t.c1);
  r.setProperty("--accent-2", t.c2);
  r.setProperty("--accent-3", t.c3);
  r.setProperty("--logo-cyan", t.logoCyan);
  r.setProperty("--logo-accent", t.logoAccent);
  r.setProperty("--logo-end", t.logoEnd);
  r.setProperty("--logo-sparkle", t.logoSparkle);
  r.setProperty("--logo-sparkle-strong", t.logoSparkleStrong);
  r.setProperty("--wordmark-dot", t.logoSparkleStrong || t.logoAccent || t.c2);
  r.setProperty("--wordmark-lab-start", t.logoCyan);
  r.setProperty("--wordmark-lab-mid", t.logoAccent);
  r.setProperty("--wordmark-lab-end", t.logoEnd);
  r.setProperty("--pixel-theme-tint", t.logoSparkleStrong || t.logoAccent || t.c2);
  r.setProperty("--pixel-base-1", t.pixelBase1 || t.logoCyan);
  r.setProperty("--pixel-base-2", t.pixelBase2 || t.logoAccent);
  r.setProperty("--pixel-base-3", t.pixelBase3 || t.logoEnd);
  r.setProperty("--pixel-signal", t.pixelSignal || "#00F0C8");
  r.setProperty("--pixel-signal-soft", `color-mix(in oklab, ${t.pixelSignal || "#00F0C8"}, transparent 74%)`);
  r.setProperty("--signal-dot", t.logoSparkleStrong || t.logoAccent || t.c2);
  r.setProperty("--signal-core", t.logoSparkleStrong || t.logoAccent || t.c2);
  r.setProperty("--signal-core-glow", `color-mix(in oklab, ${t.logoSparkleStrong || t.logoAccent || t.c2}, transparent 70%)`);
  r.setProperty("--accent-soft", t.soft);
  r.setProperty("--accent-ring", t.ring);
  r.setProperty("--glow-1", `color-mix(in oklab, ${t.c1}, transparent 70%)`);
  r.setProperty("--glow-2", `color-mix(in oklab, ${t.c2}, transparent 68%)`);
  r.setProperty("--glow-3", `color-mix(in oklab, ${t.c3}, transparent 66%)`);
  r.setProperty("--brand-grad", `linear-gradient(120deg, ${t.c1}, ${t.c2} 50%, ${t.c3})`);
  r.setProperty("--github-banner-file", `"github-banner-${t.asset}.svg"`);
  return t;
}

function applyModeVariables(mode) {
  document.documentElement.dataset.mode = mode;
}

function useApplyTheme(themeId) {
  React.useEffect(() => {
    applyThemeVariables(themeId);
  }, [themeId]);
}

function useApplyMode(mode) {
  React.useEffect(() => {
    applyModeVariables(mode);
  }, [mode]);
}

function faviconVariantForDirection(direction = "original") {
  if (typeof normalizeLogoVariant === "function") return normalizeLogoVariant(direction);
  return { original: "primary", refined: "primary", geometric: "studio", monochrome: "utility" }[direction] || direction || "primary";
}

function buildDevisFaviconSvg({ themeId = "blue", direction = "original", mode = "dark" } = {}) {
  const theme = getTheme(themeId);
  const variant = faviconVariantForDirection(direction);
  const dark = mode !== "light";
  const bg = dark ? "#070A1A" : "#EEF3F8";
  const panel = dark ? "#0D132B" : "#FFFFFF";
  const border = dark ? "rgba(255,255,255,.16)" : "rgba(13,19,43,.14)";
  const mono = dark ? "#F8FAFC" : "#0D132B";
  const paint = variant === "utility" ? mono : "url(#mark)";
  const sparkle = variant === "utility" ? mono : theme.logoSparkleStrong;
  const cap = variant === "pixel" ? "square" : "round";
  const join = variant === "pixel" ? "miter" : "round";
  const strokeWidth = variant === "pixel" ? 5.4 : 6.2;
  const pixelCore = `
      <rect x="31" y="26" width="6" height="6" rx="1" fill="${sparkle}" />
      <rect x="31" y="34" width="6" height="6" rx="1" fill="${sparkle}" />
      <rect x="23" y="30" width="6" height="6" rx="1" fill="${sparkle}" />
      <rect x="31" y="30" width="6" height="6" rx="1" fill="${sparkle}" />
      <rect x="39" y="30" width="6" height="6" rx="1" fill="${sparkle}" />`;
  const coreSvg = variant === "pixel"
    ? pixelCore
    : `<path d="M34 23L37 30L44 33L37 36L34 43L31 36L24 33L31 30Z" fill="${sparkle}" />`;
  const extraPixels = variant === "pixel"
    ? `
      <rect x="13" y="18" width="5" height="5" rx="1.1" fill="${theme.logoCyan}" />
      <rect x="18" y="13" width="5" height="5" rx="1.1" fill="${theme.logoCyan}" opacity=".86" />
      <rect x="46" y="30" width="5" height="8" rx="1.1" fill="${theme.logoEnd}" opacity=".92" />
      <rect x="34" y="47" width="8" height="5" rx="1.1" fill="${theme.logoAccent}" opacity=".92" />`
    : `
      <rect x="12" y="13" width="5" height="5" rx="${variant === "studio" ? 1.8 : 1.3}" fill="${paint}" opacity=".9" />`;

  return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
    <defs>
      <linearGradient id="mark" x1="10" y1="10" x2="56" y2="56" gradientUnits="userSpaceOnUse">
        <stop offset="0%" stop-color="${theme.logoCyan}" />
        <stop offset="55%" stop-color="${theme.logoAccent}" />
        <stop offset="100%" stop-color="${theme.logoEnd}" />
      </linearGradient>
      <radialGradient id="glow" cx="28%" cy="20%" r="78%">
        <stop offset="0%" stop-color="${variant === "utility" ? mono : theme.logoCyan}" stop-opacity="${dark ? ".34" : ".28"}" />
        <stop offset="100%" stop-color="${variant === "utility" ? mono : theme.logoEnd}" stop-opacity="0" />
      </radialGradient>
    </defs>
    <rect width="64" height="64" rx="15" fill="${bg}" />
    <rect x="4" y="4" width="56" height="56" rx="13" fill="${panel}" stroke="${border}" />
    <rect x="4" y="4" width="56" height="56" rx="13" fill="url(#glow)" />
    ${extraPixels}
    <path d="M22 10H36C48 10 56 18 56 30C56 40 50 45 42 46V55H55" stroke="${paint}" stroke-width="${strokeWidth}" stroke-linecap="${cap}" stroke-linejoin="${join}" fill="none" />
    <path d="M22 20V43H35" stroke="${paint}" stroke-width="${strokeWidth}" stroke-linecap="${cap}" stroke-linejoin="${join}" fill="none" />
    ${coreSvg}
  </svg>`;
}

function useApplyFavicon(themeId, direction, mode) {
  React.useEffect(() => {
    const svg = buildDevisFaviconSvg({ themeId, direction, mode });
    const href = `data:image/svg+xml,${encodeURIComponent(svg)}`;
    const link = document.querySelector('link[data-devis-icon="favicon"]') || document.querySelector('link[rel="icon"]') || document.createElement("link");
    link.setAttribute("rel", "icon");
    link.setAttribute("type", "image/svg+xml");
    link.setAttribute("href", href);
    link.setAttribute("data-devis-icon", "favicon");
    if (!link.parentNode) document.head.appendChild(link);

    const apple = document.querySelector('link[data-devis-icon="apple"]') || document.createElement("link");
    apple.setAttribute("rel", "apple-touch-icon");
    apple.setAttribute("href", href);
    apple.setAttribute("data-devis-icon", "apple");
    if (!apple.parentNode) document.head.appendChild(apple);
  }, [themeId, direction, mode]);
}

const SOUND_STORAGE_KEY = "devisSoundEnabled";
const INTERACTION_SOUND_PRESETS = {
  primary: { type: "sine", freqs: [440, 660], duration: .12, gain: .035 },
  pixel: { type: "square", freqs: [880, 1320], duration: .07, gain: .022 },
  studio: { type: "triangle", freqs: [523.25, 784], duration: .14, gain: .03 },
  utility: { type: "triangle", freqs: [220], duration: .06, gain: .026 },
  accent: { type: "sine", freqs: [660], duration: .075, gain: .024 },
  mood: { type: "sine", freqs: [520], duration: .045, gain: .018 },
  dark: { type: "triangle", freqs: [196], duration: .075, gain: .024 },
  light: { type: "sine", freqs: [740], duration: .07, gain: .022 },
};

const interactionAudioState = {
  ctx: null,
  enabled: false,
};

function initInteractionAudio() {
  if (typeof window === "undefined") return null;
  const AudioCtor = window.AudioContext || window.webkitAudioContext;
  if (!AudioCtor) return null;
  if (!interactionAudioState.ctx) {
    interactionAudioState.ctx = new AudioCtor();
  }
  if (interactionAudioState.ctx.state === "suspended") {
    interactionAudioState.ctx.resume?.();
  }
  return interactionAudioState.ctx;
}

function setSoundEnabled(enabled) {
  interactionAudioState.enabled = !!enabled;
  try {
    window.localStorage?.setItem(SOUND_STORAGE_KEY, enabled ? "1" : "0");
  } catch (err) {}
  if (enabled) initInteractionAudio();
}

function getStoredSoundEnabled() {
  try {
    return window.localStorage?.getItem(SOUND_STORAGE_KEY) === "1";
  } catch (err) {
    return false;
  }
}

function playInteractionPreset(name) {
  if (!interactionAudioState.enabled) return;
  const ctx = initInteractionAudio();
  const preset = INTERACTION_SOUND_PRESETS[name] || INTERACTION_SOUND_PRESETS.mood;
  if (!ctx) return;

  const now = ctx.currentTime;
  const master = ctx.createGain();
  master.gain.setValueAtTime(0, now);
  master.gain.linearRampToValueAtTime(preset.gain, now + .006);
  master.gain.exponentialRampToValueAtTime(.0008, now + preset.duration);
  master.connect(ctx.destination);

  preset.freqs.forEach((freq, index) => {
    const osc = ctx.createOscillator();
    const oscGain = ctx.createGain();
    osc.type = preset.type;
    osc.frequency.setValueAtTime(freq, now + index * .018);
    osc.frequency.exponentialRampToValueAtTime(freq * (index ? 1.015 : 1.04), now + preset.duration);
    oscGain.gain.setValueAtTime(index ? .68 : 1, now);
    osc.connect(oscGain);
    oscGain.connect(master);
    osc.start(now + index * .018);
    osc.stop(now + preset.duration + .018);
  });
}

function playLogoModeSound(mode) {
  playInteractionPreset(faviconVariantForDirection(mode));
}

function playAccentSound() {
  playInteractionPreset("accent");
}

function playSurfaceSound(surface) {
  playInteractionPreset(surface === "light" ? "light" : "dark");
}

function playMoodSound() {
  playInteractionPreset("mood");
}

function useInteractionSoundToggle() {
  const [enabled, setEnabled] = React.useState(false);
  React.useEffect(() => {
    const stored = getStoredSoundEnabled();
    interactionAudioState.enabled = stored;
    setEnabled(stored);
  }, []);

  const toggle = React.useCallback(() => {
    setEnabled((current) => {
      const next = !current;
      setSoundEnabled(next);
      if (next) playInteractionPreset("light");
      return next;
    });
  }, []);

  return [enabled, toggle];
}

function useScrollCompact(threshold = 36) {
  const [compact, setCompact] = React.useState(false);
  React.useEffect(() => {
    let current = false;
    const update = () => {
      const next = window.scrollY > threshold;
      if (next !== current) {
        current = next;
        setCompact(next);
      }
    };
    update();
    window.addEventListener("scroll", update, { passive: true });
    return () => window.removeEventListener("scroll", update);
  }, [threshold]);
  return compact;
}

function SoundToggleButton({ enabled, onToggle, compact = false }) {
  return (
    <button
      type="button"
      className={"sound-toggle" + (enabled ? " on" : "") + (compact ? " compact" : "")}
      aria-label={enabled ? "Turn interface sound off" : "Turn interface sound on"}
      aria-pressed={enabled}
      onClick={onToggle}
    >
      <span className="sound-toggle__icon" aria-hidden="true">
        <svg viewBox="0 0 18 18" focusable="false">
          <path className="sound-toggle__speaker" d="M3.5 7.1H6L9.2 4.4V13.6L6 10.9H3.5Z" />
          <path className="sound-toggle__wave" d="M11.2 6.2C12.1 6.9 12.6 7.9 12.6 9C12.6 10.1 12.1 11.1 11.2 11.8" />
          {enabled && <path className="sound-toggle__wave sound-toggle__wave--outer" d="M13.1 4.7C14.3 5.8 15 7.3 15 9C15 10.7 14.3 12.2 13.1 13.3" />}
        </svg>
      </span>
      <span>Sound</span>
      <b>{enabled ? "On" : "Off"}</b>
    </button>
  );
}

function ActiveThemeSignal({ theme, mode, className = "" }) {
  return (
    <span className={"active-theme-signal " + className} aria-label={`Active theme ${theme.short} ${mode}`}>
      <i aria-hidden="true" />
      {theme.short} / {mode}
    </span>
  );
}

const IconGithub = ({ size = 18, color = "currentColor" }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill={color} aria-hidden="true">
    <path d="M12 .5C5.6.5.5 5.6.5 12c0 5.1 3.3 9.5 7.9 11 .6.1.8-.3.8-.6v-2c-3.2.7-3.9-1.5-3.9-1.5-.5-1.4-1.3-1.7-1.3-1.7-1-.7.1-.7.1-.7 1.2.1 1.8 1.2 1.8 1.2 1 1.8 2.8 1.3 3.5 1 .1-.8.4-1.3.7-1.6-2.6-.3-5.3-1.3-5.3-5.8 0-1.3.5-2.3 1.2-3.1-.1-.3-.5-1.5.1-3.2 0 0 1-.3 3.3 1.2 1-.3 2-.4 3-.4s2 .1 3 .4c2.3-1.6 3.3-1.2 3.3-1.2.7 1.7.2 2.9.1 3.2.8.8 1.2 1.9 1.2 3.1 0 4.5-2.7 5.4-5.3 5.7.4.4.8 1.1.8 2.2v3.3c0 .3.2.7.8.6 4.6-1.5 7.9-5.9 7.9-11C23.5 5.6 18.4.5 12 .5z" />
  </svg>
);

const IconX = ({ size = 18, color = "currentColor" }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill={color} aria-hidden="true">
    <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
  </svg>
);

const IconDiscord = ({ size = 18, color = "currentColor" }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill={color} aria-hidden="true">
    <path d="M19.27 5.33C17.94 4.71 16.5 4.26 15 4a.09.09 0 00-.07.03c-.18.33-.39.76-.53 1.09a16.09 16.09 0 00-4.8 0c-.14-.34-.35-.76-.54-1.09-.01-.02-.04-.03-.07-.03-1.5.26-2.93.71-4.27 1.33-.01 0-.02.01-.03.02-2.72 4.07-3.47 8.03-3.1 11.95 0 .02.01.04.03.05 1.8 1.32 3.53 2.12 5.24 2.65.03.01.06 0 .07-.02.4-.55.76-1.13 1.07-1.74.02-.04 0-.08-.04-.09-.57-.22-1.11-.48-1.64-.78-.04-.02-.04-.08-.01-.11.11-.08.22-.17.33-.25.02-.02.05-.02.07-.01 3.44 1.57 7.15 1.57 10.55 0 .02-.01.05-.01.07.01.11.09.22.17.33.26.04.03.04.09-.01.11-.52.31-1.07.56-1.64.78-.04.01-.05.06-.04.09.32.61.68 1.19 1.07 1.74.03.01.06.02.09.01 1.72-.53 3.45-1.33 5.25-2.65.02-.01.03-.03.03-.05.44-4.53-.73-8.46-3.1-11.95-.01-.01-.02-.02-.04-.02zM8.52 14.91c-1.03 0-1.89-.95-1.89-2.12s.84-2.12 1.89-2.12c1.06 0 1.9.96 1.89 2.12 0 1.17-.84 2.12-1.89 2.12zm6.97 0c-1.03 0-1.89-.95-1.89-2.12s.84-2.12 1.89-2.12c1.06 0 1.9.96 1.89 2.12 0 1.17-.83 2.12-1.89 2.12z" />
  </svg>
);

const Sparkle = ({ size = 14, color = "currentColor" }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill={color} aria-hidden="true">
    <path d="M12 2 14 9l7 2-7 2-2 7-2-7-7-2 7-2z" />
  </svg>
);

const IconBulb = ({ size = 20, color = "currentColor" }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.6" aria-hidden="true">
    <path d="M9 18h6M10 21h4M12 3a6 6 0 00-3.5 10.9c.5.4.8.9.9 1.5l.1.6h5l.1-.6c.1-.6.4-1.1.9-1.5A6 6 0 0012 3z" />
  </svg>
);

const IconBeaker = ({ size = 20, color = "currentColor" }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.6" aria-hidden="true">
    <path d="M9 3h6M10 3v6L5 19a2 2 0 002 3h10a2 2 0 002-3l-5-10V3" />
    <path d="M7.5 14h9" opacity=".5" />
  </svg>
);

const IconCube = ({ size = 20, color = "currentColor" }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.6" aria-hidden="true">
    <path d="M12 2.5l9 5v9l-9 5-9-5v-9z" />
    <path d="M3 7.5l9 5 9-5M12 12.5v9" opacity=".55" />
  </svg>
);

const IconCopy = ({ size = 13, color = "currentColor" }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.8" aria-hidden="true">
    <rect x="8" y="8" width="13" height="13" rx="2" />
    <path d="M16 8V5a2 2 0 00-2-2H5a2 2 0 00-2 2v9a2 2 0 002 2h3" />
  </svg>
);

/* ───────── Motion primitives — stable slots with layered transitions ───────── */

function usePrefersReducedMotion() {
  const [reduce, setReduce] = React.useState(false);
  React.useEffect(() => {
    if (typeof window === "undefined" || !window.matchMedia) return;
    const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
    const update = () => setReduce(mq.matches);
    update();
    mq.addEventListener?.("change", update);
    return () => mq.removeEventListener?.("change", update);
  }, []);
  return reduce;
}

const TEXT_SLOT_DURATION = 260;

function AnimatedTextSlot({ tokenKey, value, children, className = "", variant = "default", as = "span" }) {
  const content = children !== undefined ? children : value;
  const compareKey = tokenKey !== undefined ? tokenKey : value;
  const reduce = usePrefersReducedMotion();
  const [layers, setLayers] = React.useState(() => [{ key: 0, content, compareKey }]);
  const prev = React.useRef(compareKey);
  const seq = React.useRef(0);

  React.useEffect(() => {
    if (prev.current === compareKey) {
      // Refresh content of current layer if children changed for same key.
      setLayers((current) => current.map((l, i) => i === current.length - 1 ? { ...l, content } : l));
      return;
    }
    prev.current = compareKey;
    seq.current += 1;
    const nextKey = seq.current;
    setLayers((current) => [...current, { key: nextKey, content, compareKey }]);
    const dur = reduce ? 120 : TEXT_SLOT_DURATION;
    const id = window.setTimeout(() => {
      setLayers((current) => current.filter((l) => l.key === nextKey));
    }, dur);
    return () => window.clearTimeout(id);
  }, [compareKey, content, reduce]);

  const Tag = as;
  return (
    <Tag className={`animated-text-slot animated-text-slot-${variant} ${className}`.trim()} data-reduce={reduce ? "1" : "0"}>
      {layers.map((l, idx) => {
        const isLast = idx === layers.length - 1;
        const animClass = layers.length === 1
          ? ""
          : isLast
            ? "animated-text-slot__item--enter"
            : "animated-text-slot__item--exit";
        return (
          <span key={l.key} className={`animated-text-slot__item ${animClass}`.trim()} aria-hidden={!isLast}>{l.content}</span>
        );
      })}
    </Tag>
  );
}

const DEFAULT_LOGO_STATE = { variant: "primary", accent: "blue", surface: "dark" };
const LOGO_SWITCH_DURATION = 260;
const LOGO_ACCENT_DURATION = 360;

function normalizeLogoVariantForState(value) {
  if (typeof normalizeLogoVariant === "function") return normalizeLogoVariant(value);
  const map = { original: "primary", refined: "primary", geometric: "studio", monochrome: "utility" };
  return map[value] || value || "primary";
}

function normalizeLogoAccent(value) {
  const normalized = THEME_ALIASES[value] || value || DEFAULT_LOGO_STATE.accent;
  return THEMES.some((theme) => theme.id === normalized) ? normalized : DEFAULT_LOGO_STATE.accent;
}

function normalizeLogoSurface(value) {
  if (value === "light" || value === "dark") return value;
  if (typeof document !== "undefined") {
    const mode = document.documentElement?.dataset?.mode;
    if (mode === "light" || mode === "dark") return mode;
  }
  return DEFAULT_LOGO_STATE.surface;
}

function createLogoState({ direction, themeId, accent, surface, variant } = {}) {
  const paintOnlyVariants = ["color", "mono", "mono-current", "mono-light", "mono-white", "mono-dark"];
  const logoVariant = variant && !paintOnlyVariants.includes(variant) ? variant : direction;
  return {
    variant: normalizeLogoVariantForState(logoVariant || DEFAULT_LOGO_STATE.variant),
    accent: normalizeLogoAccent(accent || themeId || DEFAULT_LOGO_STATE.accent),
    surface: normalizeLogoSurface(surface || DEFAULT_LOGO_STATE.surface),
  };
}

function transitionLogo(fromState, toState) {
  const from = { ...DEFAULT_LOGO_STATE, ...(fromState || {}) };
  const to = { ...DEFAULT_LOGO_STATE, ...(toState || {}) };
  const variantChanged = from.variant !== to.variant;
  const accentChanged = from.accent !== to.accent;
  const surfaceChanged = from.surface !== to.surface;
  let kind = "idle";
  let duration = 0;

  if (variantChanged) {
    if (from.variant === "primary" && to.variant === "pixel") {
      kind = "primary-to-pixel";
      duration = LOGO_SWITCH_DURATION;
    } else if (from.variant === "pixel" && to.variant === "primary") {
      kind = "pixel-to-primary";
      duration = LOGO_SWITCH_DURATION;
    } else if (to.variant === "utility") {
      kind = "to-utility";
      duration = LOGO_SWITCH_DURATION;
    } else if (from.variant === "utility") {
      kind = "from-utility";
      duration = LOGO_SWITCH_DURATION;
    } else if (
      (from.variant === "primary" && to.variant === "studio") ||
      (from.variant === "studio" && to.variant === "primary")
    ) {
      kind = from.variant === "primary" ? "primary-to-studio" : "studio-to-primary";
      duration = LOGO_SWITCH_DURATION;
    } else {
      kind = "variant-refine";
      duration = LOGO_SWITCH_DURATION;
    }
  } else if (accentChanged) {
    kind = "accent-shift";
    duration = LOGO_ACCENT_DURATION;
  } else if (surfaceChanged) {
    kind = "surface-shift";
    duration = 300;
  }

  return {
    fromState: from,
    toState: to,
    from,
    to,
    kind,
    duration,
    isVariantChange: variantChanged,
    isAccentChange: accentChanged,
    isSurfaceChange: surfaceChanged,
  };
}

function AnimatedLogoSwitch({
  direction = "original",
  variant = "color",
  size,
  className = "",
  sizeVar = "260px",
  surface = "auto",
  themeId = "blue",
  accent = null,
  pulseToken = null,
  context = "preview",
  displayMode = "expressive",
  signalCore = "default",
}) {
  const reduce = usePrefersReducedMotion();
  const resolvedAccent = accent || themeId || (THEMES.some((theme) => theme.id === pulseToken) ? pulseToken : "blue");
  const nextState = React.useMemo(
    () => createLogoState({ direction, variant, themeId: resolvedAccent, surface }),
    [direction, variant, resolvedAccent, surface],
  );
  const [logoState, setLogoState] = React.useState(nextState);
  const prevState = React.useRef(nextState);
  const [activeTransition, setActiveTransition] = React.useState(() => transitionLogo(nextState, nextState));
  const [transitioning, setTransitioning] = React.useState(false);
  const [motionKey, setMotionKey] = React.useState(0);

  React.useEffect(() => {
    const tx = transitionLogo(prevState.current, nextState);
    if (tx.kind === "idle") {
      setLogoState(nextState);
      return;
    }

    const duration = reduce ? 120 : tx.duration || LOGO_SWITCH_DURATION;
    const refinedTransition = { ...tx, duration };
    prevState.current = nextState;
    setLogoState(nextState);
    setActiveTransition(refinedTransition);
    setTransitioning(!reduce);
    setMotionKey((key) => key + 1);
    if (typeof window !== "undefined") window.__lastLogoTransition = refinedTransition;

    const id = window.setTimeout(() => setTransitioning(false), duration);
    return () => window.clearTimeout(id);
  }, [nextState.variant, nextState.accent, nextState.surface, reduce]);

  const style = {};
  if (sizeVar) style["--logo-transition-size"] = sizeVar;
  style["--logo-transition-duration"] = `${activeTransition.duration || LOGO_SWITCH_DURATION}ms`;

  const resolveLogo = (id) => {
    const def = (typeof LOGO_DIRECTIONS !== "undefined" ? LOGO_DIRECTIONS : []).find((d) => d.id === id);
    return def?.Component || (typeof LogoOriginalClean !== "undefined" ? LogoOriginalClean : () => null);
  };
  const Logo = resolveLogo(direction);
  const logoPaint = direction === "monochrome"
    ? (logoState.surface === "light" ? "mono-dark" : "mono-white")
    : variant;
  const coreMode = direction === "pixel"
    ? "pixel"
    : direction === "monochrome"
      ? "mono"
      : signalCore;

  return (
    <div
      className={`logo-transition original-logo-transition ${transitioning ? "is-transitioning" : ""} ${className}`.trim()}
      data-surface={logoState.surface}
      data-reduce={reduce ? "1" : "0"}
      data-variant={logoState.variant}
      data-accent={logoState.accent}
      data-transition-kind={activeTransition.kind}
      style={style}
    >
      <div key={motionKey} className="logo-transition__stable-logo" data-direction={direction}>
        <Logo
          size={size ?? 220}
          variant={logoPaint}
          mode={logoState.variant}
          surface={logoState.surface}
          context={context}
          displayMode={displayMode}
          signalCore={coreMode}
        />
      </div>
    </div>
  );
}

Object.assign(window, {
  THEMES,
  THEME_ALIASES,
  BRAND_FIXED,
  IDENTITY_MODES,
  getTheme,
  getIdentityMode,
  applyThemeVariables,
  applyModeVariables,
  useApplyTheme,
  useApplyMode,
  buildDevisFaviconSvg,
  useApplyFavicon,
  initInteractionAudio,
  playLogoModeSound,
  playAccentSound,
  playSurfaceSound,
  playMoodSound,
  setSoundEnabled,
  useInteractionSoundToggle,
  useScrollCompact,
  SoundToggleButton,
  ActiveThemeSignal,
  IconGithub,
  IconX,
  IconDiscord,
  Sparkle,
  IconBulb,
  IconBeaker,
  IconCube,
  IconCopy,
  AnimatedTextSlot,
  AnimatedLogoSwitch,
  transitionLogo,
  usePrefersReducedMotion,
});
