// ghast-ds.jsx — Ghast AI design system primitives
// Mono palette · Liquid Glass · macOS chrome
// Loads after React; exports onto window for sibling babel scripts.

// ─────────────────────────────────────────────────────────────
// Tokens — light + dark
// ─────────────────────────────────────────────────────────────
const G = {
  font: '-apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Helvetica Neue", system-ui, sans-serif',
  mono: '"SF Mono", "JetBrains Mono", ui-monospace, "Menlo", monospace',
  borel: '"Borel", cursive',

  // light
  l: {
    bg: '#FAFAF9',           // canvas
    surface: '#FFFFFF',       // raised
    surface2: '#F4F4F2',      // recessed
    border: 'rgba(0,0,0,0.08)',
    border2: 'rgba(0,0,0,0.04)',
    fg: '#0A0A0A',
    fg2: 'rgba(10,10,10,0.65)',
    fg3: 'rgba(10,10,10,0.42)',
    fg4: 'rgba(10,10,10,0.22)',
    glassBg: 'rgba(255,255,255,0.55)',
    glassBorder: 'rgba(255,255,255,0.7)',
    glassInset: 'rgba(255,255,255,0.5)',
    accent: '#0A0A0A',
    accentFg: '#FAFAF9',
    danger: '#0A0A0A',
    shadow: '0 8px 32px rgba(0,0,0,0.08), 0 1px 3px rgba(0,0,0,0.06)',
    shadowLg: '0 24px 80px rgba(0,0,0,0.14), 0 2px 6px rgba(0,0,0,0.06)',
  },
  // dark
  d: {
    bg: '#0A0A0A',
    surface: '#161616',
    surface2: '#202020',
    border: 'rgba(255,255,255,0.08)',
    border2: 'rgba(255,255,255,0.04)',
    fg: '#F5F5F4',
    fg2: 'rgba(245,245,244,0.65)',
    fg3: 'rgba(245,245,244,0.42)',
    fg4: 'rgba(245,245,244,0.22)',
    glassBg: 'rgba(40,40,40,0.55)',
    glassBorder: 'rgba(255,255,255,0.12)',
    glassInset: 'rgba(255,255,255,0.06)',
    accent: '#F5F5F4',
    accentFg: '#0A0A0A',
    danger: '#F5F5F4',
    shadow: '0 8px 32px rgba(0,0,0,0.5), 0 1px 3px rgba(0,0,0,0.4)',
    shadowLg: '0 24px 80px rgba(0,0,0,0.7), 0 2px 6px rgba(0,0,0,0.5)',
  },
};

// ─────────────────────────────────────────────────────────────
// Inject global resets & font import (one-time)
// ─────────────────────────────────────────────────────────────
if (typeof document !== 'undefined' && !document.getElementById('ghast-ds-styles')) {
  // Borel for the welcome animation
  const link = document.createElement('link');
  link.rel = 'stylesheet';
  link.href = 'https://fonts.googleapis.com/css2?family=Borel&display=swap';
  document.head.appendChild(link);

  const s = document.createElement('style');
  s.id = 'ghast-ds-styles';
  s.textContent = `
    .gh * { box-sizing: border-box; }
    .gh {
      font-family: ${G.font};
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      letter-spacing: -0.01em;
    }
    .gh-mono { font-family: ${G.mono}; letter-spacing: 0; }
    .gh-borel { font-family: ${G.borel}; }
    .gh-scroll::-webkit-scrollbar { width: 8px; height: 8px; }
    .gh-scroll::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.15); border-radius: 4px; }
    .gh-scroll::-webkit-scrollbar-track { background: transparent; }
    .gh-noscroll::-webkit-scrollbar { display: none; }
    .gh-noscroll { scrollbar-width: none; }

    /* Stroke-by-stroke writing animation */
    @keyframes gh-stroke {
      to { stroke-dashoffset: 0; }
    }
    @keyframes gh-fade-in {
      from { opacity: 0; transform: translateY(8px); }
      to { opacity: 1; transform: translateY(0); }
    }
    @keyframes gh-pulse {
      0%, 100% { opacity: 0.4; }
      50% { opacity: 1; }
    }
    @keyframes gh-blink {
      0%, 49% { opacity: 1; }
      50%, 100% { opacity: 0; }
    }
    @keyframes gh-shimmer {
      0% { background-position: -200% 0; }
      100% { background-position: 200% 0; }
    }
    @keyframes gh-spin {
      to { transform: rotate(360deg); }
    }

    /* Lightweight CSS-only tooltip — wrap an element with .gh-tip and put the
       label in a child .gh-tip-bubble. No JS state, no React effect. */
    .gh-tip { position: relative; }
    .gh-tip > .gh-tip-bubble {
      position: absolute;
      bottom: calc(100% + 6px);
      left: 50%;
      transform: translateX(-50%);
      padding: 6px 10px;
      background: #0a0a0a;
      color: #fafaf9;
      border-radius: 8px;
      font-size: 11px;
      line-height: 1.3;
      white-space: nowrap;
      pointer-events: none;
      opacity: 0;
      transition: opacity .12s ease;
      z-index: 100;
      box-shadow: 0 8px 24px rgba(0,0,0,0.18);
    }
    .gh-tip > .gh-tip-bubble::after {
      content: '';
      position: absolute;
      top: 100%;
      left: 50%;
      transform: translateX(-50%);
      border: 4px solid transparent;
      border-top-color: #0a0a0a;
    }
    .gh-tip:hover > .gh-tip-bubble { opacity: 1; }
  `;
  document.head.appendChild(s);
}

// ─────────────────────────────────────────────────────────────
// Theme provider — children get { t, dark } via useTheme()
// ─────────────────────────────────────────────────────────────
const ThemeCtx = React.createContext({ t: G.l, dark: false });
const useTheme = () => React.useContext(ThemeCtx);

function Theme({ dark = false, children, style }) {
  const t = dark ? G.d : G.l;
  return (
    <ThemeCtx.Provider value={{ t, dark, G }}>
      <div className="gh" style={{ background: t.bg, color: t.fg, width: '100%', height: '100%', ...style }}>
        {children}
      </div>
    </ThemeCtx.Provider>
  );
}

// ─────────────────────────────────────────────────────────────
// Liquid Glass panel — works in light + dark
// ─────────────────────────────────────────────────────────────
function Glass({ children, radius = 16, dark, style = {}, strong = false, ...rest }) {
  const { dark: ctxDark } = useTheme();
  const isDark = dark ?? ctxDark;
  const tone = isDark
    ? { bg: strong ? 'rgba(30,30,30,0.78)' : 'rgba(40,40,40,0.55)', border: 'rgba(255,255,255,0.12)', inset: 'rgba(255,255,255,0.06)' }
    : { bg: strong ? 'rgba(255,255,255,0.78)' : 'rgba(255,255,255,0.55)', border: 'rgba(255,255,255,0.7)', inset: 'rgba(255,255,255,0.5)' };
  return (
    <div style={{ position: 'relative', borderRadius: radius, ...style }} {...rest}>
      <div style={{
        position: 'absolute', inset: 0, borderRadius: radius,
        background: tone.bg,
        backdropFilter: 'blur(40px) saturate(180%)',
        WebkitBackdropFilter: 'blur(40px) saturate(180%)',
        border: `0.5px solid ${tone.border}`,
        boxShadow: isDark
          ? '0 8px 40px rgba(0,0,0,0.4)'
          : `0 8px 40px rgba(0,0,0,0.06), inset 0 1px 0 ${tone.inset}`,
        pointerEvents: 'none',
      }} />
      <div style={{ position: 'relative', zIndex: 1, height: '100%' }}>{children}</div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Traffic lights — clickable-looking (cosmetic)
// ─────────────────────────────────────────────────────────────
function TrafficLights({ style = {} }) {
  return (
    <div style={{ display: 'flex', gap: 8, alignItems: 'center', ...style }}>
      <div style={{ width: 12, height: 12, borderRadius: '50%', background: '#ff5f57', border: '0.5px solid rgba(0,0,0,0.1)' }} />
      <div style={{ width: 12, height: 12, borderRadius: '50%', background: '#febc2e', border: '0.5px solid rgba(0,0,0,0.1)' }} />
      <div style={{ width: 12, height: 12, borderRadius: '50%', background: '#28c840', border: '0.5px solid rgba(0,0,0,0.1)' }} />
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Window chrome — full bleed with traffic lights at top-left.
// Inner content fills.
// ─────────────────────────────────────────────────────────────
function GhastWindow({ children, dark, style = {}, radius = 14 }) {
  const { t, dark: ctxDark } = useTheme();
  const isDark = dark ?? ctxDark;
  return (
    <div style={{
      width: '100%', height: '100%',
      borderRadius: radius, overflow: 'hidden',
      background: isDark ? G.d.bg : G.l.bg,
      color: isDark ? G.d.fg : G.l.fg,
      boxShadow: isDark
        ? '0 0 0 1px rgba(255,255,255,0.08), 0 24px 80px rgba(0,0,0,0.6)'
        : '0 0 0 1px rgba(0,0,0,0.08), 0 24px 80px rgba(0,0,0,0.18)',
      position: 'relative',
      fontFamily: G.font,
      ...style,
    }}>
      {children}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Ghast Logo — original mono illustration (cube body + tendrils)
// ./assets/ghast-logo.png ships with a true transparent background (corner
// alpha = 0), so the source image renders correctly on any canvas color
// without blend-mode or filter hacks. `color` and `dark` props are kept for
// API compatibility with old call sites; they no longer affect rendering.
// ─────────────────────────────────────────────────────────────
function GhastLogo({ size = 32, color, style = {}, dark }) {
  return (
    <img
      src="./assets/ghast-logo.png"
      width={size}
      height={size}
      alt="Ghast"
      draggable="false"
      style={{
        display: 'block',
        objectFit: 'contain',
        userSelect: 'none',
        flexShrink: 0,
        ...style,
      }}
    />
  );
}

// ─────────────────────────────────────────────────────────────
// Buttons & inputs
// ─────────────────────────────────────────────────────────────
function Button({ children, variant = 'primary', size = 'md', icon, full, style = {}, ...rest }) {
  const { t } = useTheme();
  const sizes = {
    sm: { h: 28, px: 12, fs: 12, gap: 6 },
    md: { h: 36, px: 16, fs: 13, gap: 8 },
    lg: { h: 44, px: 20, fs: 14, gap: 10 },
    xl: { h: 52, px: 24, fs: 15, gap: 10 },
  };
  const sz = sizes[size];
  const variants = {
    primary: { bg: t.fg, color: t.bg, border: 'transparent' },
    secondary: { bg: 'transparent', color: t.fg, border: t.border },
    ghost: { bg: 'transparent', color: t.fg, border: 'transparent' },
    glass: { bg: t.glassBg, color: t.fg, border: t.border },
    danger: { bg: 'transparent', color: '#ff5f57', border: t.border },
  };
  const v = variants[variant];
  return (
    <button
      style={{
        height: sz.h, padding: `0 ${sz.px}px`, fontSize: sz.fs,
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: sz.gap,
        background: v.bg, color: v.color,
        border: `1px solid ${v.border}`,
        borderRadius: sz.h / 2,
        fontFamily: G.font, fontWeight: 500, letterSpacing: -0.1,
        cursor: 'pointer', whiteSpace: 'nowrap',
        width: full ? '100%' : undefined,
        transition: 'all 0.15s cubic-bezier(0.32,0.72,0,1)',
        ...style,
      }}
      {...rest}
    >
      {icon}{children}
    </button>
  );
}

function Input({ label, value, placeholder, type = 'text', icon, suffix, autoFocus, style = {}, dark, ...rest }) {
  const { t } = useTheme();
  return (
    <label style={{ display: 'block', width: '100%' }}>
      {label && <div style={{ fontSize: 12, fontWeight: 500, color: t.fg2, marginBottom: 6 }}>{label}</div>}
      <div style={{
        height: 44, padding: '0 14px',
        display: 'flex', alignItems: 'center', gap: 10,
        background: t.surface,
        border: `1px solid ${t.border}`, borderRadius: 10,
        ...style,
      }}>
        {icon}
        <input
          type={type} placeholder={placeholder} defaultValue={value} autoFocus={autoFocus}
          style={{
            flex: 1, border: 'none', outline: 'none', background: 'transparent',
            fontFamily: G.font, fontSize: 14, color: t.fg,
            letterSpacing: -0.1,
          }}
          {...rest}
        />
        {suffix}
      </div>
    </label>
  );
}

// ─────────────────────────────────────────────────────────────
// Iconography — Lucide (lucide.dev) line icons.
// 24px grid · 2px stroke · round caps & joins · single currentColor stroke.
// All paths are taken from the official Lucide icon set with light per-path
// trimming where two icons share a glyph (aliases below).
// ─────────────────────────────────────────────────────────────
const ICON_ALIASES = {
  bolt: 'zap',
  warning: 'warn',
  external: 'ext',
  'external-link': 'ext',
  x: 'close',
  shell: 'terminal',
  zsh: 'terminal',
  read_file: 'docs',
  grep: 'searchCode',
  reverse: 'undo',
  // Tolerate informal kebab-case agent names that occasionally
  // get passed in by mistake — render as a generic sparkle.
  'ghast-auditor': 'sparkle',
  'ghast-fixer': 'sparkle',
  'ghast-writer': 'sparkle',
};

const ICON_PATHS = {
  // Communication / nav
  chat: <><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></>,
  search: <><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></>,
  searchCode: <><path d="M9 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V9"/><path d="M11 12 8 9l-3 3"/><path d="M11 7v5"/><circle cx="17" cy="6" r="3"/><path d="m22 11-2-2"/></>,
  plus: <><path d="M5 12h14"/><path d="M12 5v14"/></>,
  sparkle: <><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/><path d="M20 3v4"/><path d="M22 5h-4"/><path d="M4 17v2"/><path d="M5 18H3"/></>,
  zap: <><path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/></>,
  workflow: <><rect width="8" height="8" x="3" y="3" rx="2"/><path d="M7 11v4a2 2 0 0 0 2 2h4"/><rect width="8" height="8" x="13" y="13" rx="2"/></>,
  settings: <><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></>,
  skills: <><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10"/></>,
  plug: <><path d="M12 22v-5"/><path d="M9 8V2"/><path d="M15 8V2"/><path d="M18 8v5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8z"/></>,
  grid: <><rect width="7" height="7" x="3" y="3" rx="1"/><rect width="7" height="7" x="14" y="3" rx="1"/><rect width="7" height="7" x="14" y="14" rx="1"/><rect width="7" height="7" x="3" y="14" rx="1"/></>,
  history: <><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/><path d="M12 7v5l4 2"/></>,
  folder: <><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"/></>,
  code: <><path d="m16 18 6-6-6-6"/><path d="m8 6-6 6 6 6"/></>,
  terminal: <><path d="M12 19h8"/><path d="m4 17 6-6-6-6"/></>,
  file: <><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/></>,
  docs: <><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/></>,
  image: <><rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/></>,
  mic: <><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" x2="12" y1="19" y2="22"/></>,
  paperclip: <><path d="M13.234 20.252 21 12.3"/><path d="m16 6-8.414 8.586a2 2 0 0 0 0 2.828 2 2 0 0 0 2.828 0l8.414-8.586a4 4 0 0 0 0-5.656 4 4 0 0 0-5.656 0l-8.415 8.585a6 6 0 1 0 8.486 8.486"/></>,
  arrowUp: <><path d="m5 12 7-7 7 7"/><path d="M12 19V5"/></>,
  arrowRight: <><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></>,
  arrowLeft: <><path d="m12 19-7-7 7-7"/><path d="M19 12H5"/></>,
  chevronRight: <><path d="m9 18 6-6-6-6"/></>,
  chevronDown: <><path d="m6 9 6 6 6-6"/></>,
  check: <><path d="M20 6 9 17l-5-5"/></>,
  close: <><path d="M18 6 6 18"/><path d="m6 6 12 12"/></>,
  user: <><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></>,
  google: <><path d="M21.6 12.227c0-.792-.07-1.553-.202-2.282H12v4.317h5.382c-.232 1.252-.937 2.313-1.997 3.022v2.512h3.234c1.892-1.743 2.981-4.305 2.981-7.569Z" fill="currentColor" stroke="none"/><path d="M12 22c2.7 0 4.964-.895 6.619-2.422l-3.234-2.512c-.896.6-2.041.953-3.385.953-2.604 0-4.808-1.758-5.594-4.121H3.063v2.594A9.996 9.996 0 0 0 12 22Z" fill="currentColor" stroke="none"/><path d="M6.406 13.898A5.99 5.99 0 0 1 6.087 12c0-.659.114-1.298.319-1.898V7.508H3.063A9.996 9.996 0 0 0 2 12c0 1.614.386 3.14 1.063 4.492l3.343-2.594Z" fill="currentColor" stroke="none"/><path d="M12 5.977c1.471 0 2.79.504 3.83 1.498l2.871-2.872C16.96 2.987 14.696 2 12 2 8.099 2 4.736 4.236 3.063 7.508l3.343 2.594C7.192 7.735 9.396 5.977 12 5.977Z" fill="currentColor" stroke="none"/></>,
  mail: <><rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></>,
  moon: <><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/></>,
  sun: <><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/></>,
  download: <><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" x2="12" y1="15" y2="3"/></>,
  star: <><path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"/></>,
  book: <><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></>,
  bell: <><path d="M10.268 21a2 2 0 0 0 3.464 0"/><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"/></>,
  play: <><polygon points="6 3 20 12 6 21 6 3"/></>,
  pause: <><rect x="14" y="4" width="4" height="16" rx="1"/><rect x="6" y="4" width="4" height="16" rx="1"/></>,
  stop: <><rect width="18" height="18" x="3" y="3" rx="2"/></>,
  refresh: <><path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/><path d="M8 16H3v5"/></>,
  copy: <><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></>,
  edit: <><path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/><path d="m15 5 4 4"/></>,
  trash: <><path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" x2="10" y1="11" y2="17"/><line x1="14" x2="14" y1="11" y2="17"/></>,
  ext: <><path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/></>,
  eye: <><path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"/><circle cx="12" cy="12" r="3"/></>,
  layers: <><path d="M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z"/><path d="M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12"/><path d="M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17"/></>,
  git: <><line x1="6" x2="6" y1="3" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></>,
  cmd: <><path d="M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3"/></>,
  box: <><path d="M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z"/><path d="M12 22V12"/><path d="m3.3 7 7.703 4.734a2 2 0 0 0 1.994 0L20.7 7"/><path d="m7.5 4.27 9 5.15"/></>,
  cube: <><path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"/></>,
  moreH: <><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></>,
  moreV: <><circle cx="12" cy="12" r="1"/><circle cx="12" cy="5" r="1"/><circle cx="12" cy="19" r="1"/></>,
  pin: <><path d="M12 17v5"/><path d="M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z"/></>,
  archive: <><rect width="20" height="5" x="2" y="3" rx="1"/><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"/><path d="M10 12h4"/></>,
  share: <><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7"/><polyline points="16 6 12 2 8 6"/><line x1="12" x2="12" y1="2" y2="15"/></>,
  link: <><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></>,
  dot: <><circle cx="12" cy="12" r="4" fill="currentColor"/></>,
  sound: <><path d="M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z"/><path d="M16 9a5 5 0 0 1 0 6"/><path d="M19.364 18.364a9 9 0 0 0 0-12.728"/></>,
  info: <><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></>,
  warn: <><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/></>,
  keyboard: <><path d="M10 8h.01"/><path d="M12 12h.01"/><path d="M14 8h.01"/><path d="M16 12h.01"/><path d="M18 8h.01"/><path d="M6 8h.01"/><path d="M7 16h10"/><path d="M8 12h.01"/><rect width="20" height="16" x="2" y="4" rx="2"/></>,
  lock: <><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></>,
  globe: <><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></>,
  key: <><path d="m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4"/><path d="m21 2-9.6 9.6"/><circle cx="7.5" cy="15.5" r="5.5"/></>,
  monitor: <><rect width="20" height="14" x="2" y="3" rx="2"/><line x1="8" x2="16" y1="21" y2="21"/><line x1="12" x2="12" y1="17" y2="21"/></>,
  node: <><circle cx="12" cy="12" r="3"/><path d="M3 12h6"/><path d="M15 12h6"/><circle cx="3" cy="12" r="1.5" fill="currentColor"/><circle cx="21" cy="12" r="1.5" fill="currentColor"/></>,
  wallet: <><path d="M19 7V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-2"/><path d="M3 5a2 2 0 0 0 2 2h16v4h-4a2 2 0 0 0 0 4h4v4H5a2 2 0 0 1-2-2z"/></>,
  chart: <><path d="M3 3v16a2 2 0 0 0 2 2h16"/><path d="M7 16h8"/><path d="M7 11h12"/><path d="M7 6h3"/></>,
  cpu: <><rect width="16" height="16" x="4" y="4" rx="2"/><rect width="6" height="6" x="9" y="9" rx="1"/><path d="M15 2v2"/><path d="M15 20v2"/><path d="M2 15h2"/><path d="M2 9h2"/><path d="M20 15h2"/><path d="M20 9h2"/><path d="M9 2v2"/><path d="M9 20v2"/></>,
  shield: <><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/></>,
  activity: <><path d="M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.5.5 0 0 1-.96 0L9.24 3.18a.5.5 0 0 0-.96 0l-2.35 8.36A2 2 0 0 1 4 13H2"/></>,
  clock: <><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></>,
  undo: <><path d="M9 14 4 9l5-5"/><path d="M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5v0a5.5 5.5 0 0 1-5.5 5.5H11"/></>,
  'chevron-right': <><path d="m9 18 6-6-6-6"/></>,
  'chevron-down': <><path d="m6 9 6 6 6-6"/></>,
  'chevron-up': <><path d="m18 15-6-6-6 6"/></>,
  'chevron-left': <><path d="m15 18-6-6 6-6"/></>,
  'arrow-down-to-line': <><path d="M12 17V3"/><path d="m6 11 6 6 6-6"/><path d="M19 21H5"/></>,
  wrench: <><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></>,
};

const Icon = ({ name, size = 18, color = 'currentColor', style }) => {
  const resolved = ICON_ALIASES[name] || name;
  const node = ICON_PATHS[resolved];
  if (!node) {
    // Graceful empty: keeps layout stable; never crashes if a name is wrong.
    return <svg width={size} height={size} viewBox="0 0 24 24" style={style} aria-hidden="true" />;
  }
  return (
    <svg
      width={size} height={size} viewBox="0 0 24 24" fill="none"
      stroke={color} strokeWidth={2} strokeLinecap="round" strokeLinejoin="round"
      style={style}
    >
      {node}
    </svg>
  );
};

// ─────────────────────────────────────────────────────────────
// Image placeholder — striped diagonal w/ mono caption
// ─────────────────────────────────────────────────────────────
function ImgPlaceholder({ label = 'image', height = 160, style = {} }) {
  const { t } = useTheme();
  return (
    <div style={{
      height, width: '100%',
      backgroundImage: `repeating-linear-gradient(45deg, ${t.border} 0 1px, transparent 1px 8px)`,
      background: `linear-gradient(45deg, ${t.surface2}, ${t.surface}), repeating-linear-gradient(45deg, ${t.border} 0 1px, transparent 1px 10px)`,
      border: `1px dashed ${t.border}`,
      borderRadius: 10,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      fontFamily: G.mono, fontSize: 11, color: t.fg3, textTransform: 'uppercase', letterSpacing: 0.8,
      ...style,
    }}>{label}</div>
  );
}

// ─────────────────────────────────────────────────────────────
// macOS chrome row — simple inline traffic lights for screens
// ─────────────────────────────────────────────────────────────
function ChromeBar({ title, dark, right, dense = false, style = {} }) {
  const { t, dark: ctxDark } = useTheme();
  const isDark = dark ?? ctxDark;
  return (
    <div style={{
      height: dense ? 36 : 44, flexShrink: 0,
      display: 'flex', alignItems: 'center', gap: 14,
      padding: '0 14px',
      borderBottom: `0.5px solid ${t.border}`,
      background: isDark ? 'rgba(20,20,20,0.6)' : 'rgba(255,255,255,0.6)',
      backdropFilter: 'blur(20px) saturate(180%)',
      WebkitBackdropFilter: 'blur(20px) saturate(180%)',
      ...style,
    }}>
      <TrafficLights />
      {title && <div style={{ fontSize: 12, fontWeight: 500, color: t.fg2, letterSpacing: -0.1 }}>{title}</div>}
      <div style={{ flex: 1 }} />
      {right}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Tag / Badge / KBD
// ─────────────────────────────────────────────────────────────
function Tag({ children, variant = 'default', style = {} }) {
  const { t } = useTheme();
  const tones = {
    default: { bg: t.surface2, fg: t.fg2, border: t.border },
    solid: { bg: t.fg, fg: t.bg, border: 'transparent' },
    outline: { bg: 'transparent', fg: t.fg2, border: t.border },
  };
  const v = tones[variant];
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 4,
      height: 22, padding: '0 8px',
      background: v.bg, color: v.fg,
      border: `1px solid ${v.border}`, borderRadius: 11,
      fontSize: 11, fontWeight: 500, letterSpacing: -0.05, whiteSpace: 'nowrap',
      ...style,
    }}>{children}</span>
  );
}

function Kbd({ children, style = {} }) {
  const { t } = useTheme();
  return (
    <kbd style={{
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      minWidth: 18, height: 18, padding: '0 4px',
      background: t.surface, color: t.fg2,
      border: `1px solid ${t.border}`,
      borderBottom: `1.5px solid ${t.border}`,
      borderRadius: 4,
      fontFamily: G.mono, fontSize: 10, fontWeight: 500,
      ...style,
    }}>{children}</kbd>
  );
}

// ─────────────────────────────────────────────────────────────
// Avatar
// ─────────────────────────────────────────────────────────────
function Avatar({ name = 'Y', size = 28, style = {} }) {
  const { t } = useTheme();
  return (
    <div style={{
      width: size, height: size, borderRadius: size / 2,
      background: t.fg, color: t.bg,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      fontSize: size * 0.4, fontWeight: 600, letterSpacing: -0.2,
      flexShrink: 0,
      ...style,
    }}>{name?.[0]?.toUpperCase()}</div>
  );
}

// ─────────────────────────────────────────────────────────────
// Card (for grid items in stores etc.)
// ─────────────────────────────────────────────────────────────
function Card({ children, style = {}, hover = true, ...rest }) {
  const { t } = useTheme();
  return (
    <div style={{
      background: t.surface,
      border: `1px solid ${t.border}`,
      borderRadius: 14,
      padding: 16,
      transition: 'all 0.15s cubic-bezier(0.32,0.72,0,1)',
      ...style,
    }} {...rest}>{children}</div>
  );
}

// ─────────────────────────────────────────────────────────────
// Section divider
// ─────────────────────────────────────────────────────────────
function Divider({ style = {}, vertical }) {
  const { t } = useTheme();
  return (
    <div style={{
      [vertical ? 'width' : 'height']: 1,
      [vertical ? 'height' : 'width']: '100%',
      background: t.border,
      flexShrink: 0,
      ...style,
    }} />
  );
}


// Export everything to window
Object.assign(window, {
  G, Theme, useTheme, Glass, TrafficLights, GhastWindow, GhastLogo,
  Button, Input, Icon, ImgPlaceholder, ChromeBar, Tag, Kbd, Avatar, Card, Divider,
});
