// Shared UI primitives for KindleStartup Hub
const { useState, useEffect, useRef, useMemo, useCallback, createContext, useContext } = React;

// ----- Icons (Lucide-style hand-rolled, only what we use) -----
const Icon = ({ d, size = 18, stroke = 1.75, fill = "none", style, ...rest }) => (
  <svg viewBox="0 0 24 24" width={size} height={size} fill={fill} stroke="currentColor"
       strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0, ...style }} {...rest}>
    {typeof d === 'string' ? <path d={d} /> : d}
  </svg>
);

const Icons = {
  home: <><path d="M3 11l9-8 9 8"/><path d="M5 10v10a1 1 0 0 0 1 1h4v-6h4v6h4a1 1 0 0 0 1-1V10"/></>,
  shop: <><path d="M3 7h18l-1.5 11a2 2 0 0 1-2 1.7H6.5a2 2 0 0 1-2-1.7L3 7z"/><path d="M8 7V5a4 4 0 0 1 8 0v2"/></>,
  bag: <><path d="M6 7h12l-1 12a2 2 0 0 1-2 1.8H9a2 2 0 0 1-2-1.8L6 7z"/><path d="M9 7V5a3 3 0 0 1 6 0v2"/></>,
  user: <><circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0"/></>,
  bell: <><path d="M6 8a6 6 0 1 1 12 0c0 7 3 7 3 9H3c0-2 3-2 3-9z"/><path d="M10 21a2 2 0 0 0 4 0"/></>,
  search: <><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></>,
  arrowRight: "M5 12h14M13 5l7 7-7 7",
  arrowLeft: "M19 12H5M11 19l-7-7 7-7",
  chevronRight: "m9 6 6 6-6 6",
  chevronDown: "m6 9 6 6 6-6",
  chevronUp: "m18 15-6-6-6 6",
  check: "M5 12l4.5 4.5L20 6",
  plus: "M12 5v14M5 12h14",
  x: "M6 6l12 12M18 6 6 18",
  star: <path d="M12 3l2.7 5.5 6 .9-4.4 4.2 1 6L12 16.8l-5.4 2.8 1-6L3.3 9.4l6-.9L12 3z"/>,
  download: <><path d="M12 4v12"/><path d="m6 12 6 6 6-6"/><path d="M5 20h14"/></>,
  external: <><path d="M14 4h6v6"/><path d="M20 4l-9 9"/><path d="M19 13v6a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h6"/></>,
  settings: <><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1.1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"/></>,
  logout: <><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><path d="m16 17 5-5-5-5"/><path d="M21 12H9"/></>,
  book: <><path d="M4 4.5A2.5 2.5 0 0 1 6.5 2H20v16H6.5A2.5 2.5 0 0 0 4 20.5z"/><path d="M4 20.5A2.5 2.5 0 0 1 6.5 18H20v4H6.5A2.5 2.5 0 0 1 4 20.5z"/></>,
  search2: <><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></>,
  sparkle: <path d="M12 3v4M12 17v4M3 12h4M17 12h4M5.6 5.6l2.8 2.8M15.6 15.6l2.8 2.8M5.6 18.4l2.8-2.8M15.6 8.4l2.8-2.8"/>,
  feather: <><path d="M20 4c-3 0-6 1.5-9 4.5L4 16v4h4l7.5-7.5C18 10 19 7 20 4z"/><path d="M16 8L4 20"/></>,
  layout: <><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18M9 21V9"/></>,
  filter: <path d="M4 5h16l-6 8v6l-4-2v-4z"/>,
  grid: <><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></>,
  list: <><path d="M8 6h13M8 12h13M8 18h13"/><circle cx="4" cy="6" r="1"/><circle cx="4" cy="12" r="1"/><circle cx="4" cy="18" r="1"/></>,
  cart: <><circle cx="9" cy="20" r="1.5"/><circle cx="18" cy="20" r="1.5"/><path d="M3 4h2l2.5 12.5a1 1 0 0 0 1 .8h9.5a1 1 0 0 0 1-.8L21 8H6"/></>,
  qr: <><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><path d="M14 14h3v3M20 14v7M14 20h3"/></>,
  card: <><rect x="3" y="6" width="18" height="13" rx="2"/><path d="M3 10h18M7 15h3"/></>,
  shield: <path d="M12 3l8 3v6c0 5-4 8-8 9-4-1-8-4-8-9V6l8-3z"/>,
  lock: <><rect x="5" y="11" width="14" height="9" rx="2"/><path d="M8 11V8a4 4 0 0 1 8 0v3"/></>,
  mail: <><rect x="3" y="5" width="18" height="14" rx="2"/><path d="m3 7 9 6 9-6"/></>,
  google: <><path d="M21.6 12.2c0-.7-.1-1.4-.2-2H12v3.9h5.4a4.6 4.6 0 0 1-2 3v2.4h3.3c1.9-1.8 3-4.4 3-7.3z" fill="#4285F4" stroke="none"/><path d="M12 22c2.7 0 5-.9 6.7-2.5l-3.3-2.4c-.9.6-2 1-3.4 1A5.9 5.9 0 0 1 6.5 14H3.1v2.5A10 10 0 0 0 12 22z" fill="#34A853" stroke="none"/><path d="M6.5 14a5.9 5.9 0 0 1 0-3.9V7.6H3.1a10 10 0 0 0 0 9z" fill="#FBBC05" stroke="none"/><path d="M12 6.1c1.5 0 2.8.5 3.9 1.5l2.9-2.9C17 3 14.7 2 12 2A10 10 0 0 0 3.1 7.5L6.5 10c.8-2.4 3-3.9 5.5-3.9z" fill="#EA4335" stroke="none"/></>,
  arrowUp: "m12 19-7-7h4V5h6v7h4z",
  arrowDownRight: <><path d="M7 7l10 10"/><path d="M17 8v9h-9"/></>,
  trendUp: <><path d="m3 17 6-6 4 4 8-8"/><path d="M14 7h7v7"/></>,
  trendDown: <><path d="m3 7 6 6 4-4 8 8"/><path d="M14 17h7v-7"/></>,
  more: <><circle cx="5" cy="12" r="1.3"/><circle cx="12" cy="12" r="1.3"/><circle cx="19" cy="12" r="1.3"/></>,
  play: <path d="M7 4v16l13-8z"/>,
  clock: <><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></>,
  package: <><path d="M21 16V8l-9-5-9 5v8l9 5z"/><path d="m3 8 9 5 9-5"/><path d="M12 13v10"/></>,
  copy: <><rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></>,
  globe: <><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18"/></>,
  help: <><circle cx="12" cy="12" r="9"/><path d="M9.5 9a2.5 2.5 0 0 1 5 0c0 1.5-2.5 2-2.5 4"/><circle cx="12" cy="17" r="0.5" fill="currentColor"/></>,
  users: <><circle cx="9" cy="8" r="3.5"/><path d="M2 21a7 7 0 0 1 14 0"/><circle cx="17" cy="9" r="2.5"/><path d="M16 21a5 5 0 0 1 6-3"/></>,
  chart: <><path d="M3 3v18h18"/><path d="m7 14 3-3 3 3 5-6"/></>,
  tag: <><path d="M3 3h7l11 11-7 7L3 10z"/><circle cx="7" cy="7" r="1.5"/></>,
  refund: <><path d="M3 12a9 9 0 1 0 3-6.7"/><path d="M3 4v5h5"/></>,
  receipt: <><path d="M5 3v18l3-2 3 2 3-2 3 2 3-2V3z"/><path d="M9 8h6M9 12h6M9 16h4"/></>,
  message: <path d="M21 12a8 8 0 0 1-11.5 7.2L4 21l1.8-5.5A8 8 0 1 1 21 12z"/>,
  bookmark: <path d="M6 3h12v18l-6-4-6 4z"/>,
  award: <><circle cx="12" cy="9" r="6"/><path d="m9 14-2 7 5-3 5 3-2-7"/></>,
  community: <><circle cx="12" cy="8" r="3"/><circle cx="6" cy="13" r="2.5"/><circle cx="18" cy="13" r="2.5"/><path d="M2 21a4 4 0 0 1 8 0M14 21a4 4 0 0 1 8 0M8 21a4 4 0 0 1 8 0"/></>,
  trash: <><path d="M4 7h16M9 7V4h6v3M6 7l1 13a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-13"/></>,
  edit: <><path d="M14 4l6 6L8 22H2v-6z"/></>,
  eye: <><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z"/><circle cx="12" cy="12" r="3"/></>,
  inbox: <><path d="M3 13h5l1 3h6l1-3h5"/><path d="M3 13l3-9h12l3 9v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></>,
  thai: <path d="M4 4h16v16H4z" />, // placeholder unused
};

const I = ({ name, size = 18, ...rest }) => <Icon d={Icons[name]} size={size} {...rest} />;

// ----- Buttons -----
const Button = ({ variant = 'primary', size = 'md', icon, iconRight, children, style, full, onClick, ...rest }) => {
  const sizes = {
    sm: { padding: '6px 12px', fontSize: 13, height: 32, gap: 6 },
    md: { padding: '9px 16px', fontSize: 14, height: 40, gap: 8 },
    lg: { padding: '12px 22px', fontSize: 15, height: 48, gap: 10 },
    xl: { padding: '16px 28px', fontSize: 16, height: 56, gap: 10 },
  };
  const variants = {
    primary: { background: 'var(--ink)', color: 'var(--bg)', border: '1px solid var(--ink)' },
    accent:  { background: 'var(--accent)', color: '#fff', border: '1px solid var(--accent)' },
    secondary: { background: 'var(--surface)', color: 'var(--ink)', border: '1px solid var(--line-2)' },
    ghost: { background: 'transparent', color: 'var(--ink)', border: '1px solid transparent' },
    soft: { background: 'var(--bg-2)', color: 'var(--ink)', border: '1px solid transparent' },
    danger: { background: 'var(--danger)', color: '#fff', border: '1px solid var(--danger)' },
  };
  return (
    <button
      onClick={onClick}
      style={{
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        borderRadius: 'var(--r-pill)',
        cursor: 'pointer',
        fontWeight: 500,
        letterSpacing: '0.01em',
        transition: 'transform .08s ease, opacity .15s ease, background .15s ease, border-color .15s ease',
        width: full ? '100%' : 'auto',
        whiteSpace: 'nowrap',
        ...sizes[size],
        ...variants[variant],
        ...style,
      }}
      onMouseDown={e => e.currentTarget.style.transform = 'scale(0.98)'}
      onMouseUp={e => e.currentTarget.style.transform = ''}
      onMouseLeave={e => e.currentTarget.style.transform = ''}
      {...rest}
    >
      {icon && <I name={icon} size={size === 'sm' ? 14 : size === 'lg' || size === 'xl' ? 18 : 16} />}
      {children}
      {iconRight && <I name={iconRight} size={size === 'sm' ? 14 : size === 'lg' || size === 'xl' ? 18 : 16} />}
    </button>
  );
};

// ----- Card -----
const Card = ({ children, style, hover, onClick, padding = 20, ...rest }) => (
  <div
    onClick={onClick}
    style={{
      background: 'var(--surface)',
      border: '1px solid var(--line)',
      borderRadius: 'var(--r-lg)',
      padding,
      boxShadow: 'var(--sh-1)',
      transition: 'box-shadow .2s ease, border-color .2s ease, transform .2s ease',
      cursor: onClick || hover ? 'pointer' : 'default',
      ...style,
    }}
    onMouseEnter={hover || onClick ? e => { e.currentTarget.style.boxShadow = 'var(--sh-3)'; e.currentTarget.style.borderColor = 'var(--line-2)'; } : undefined}
    onMouseLeave={hover || onClick ? e => { e.currentTarget.style.boxShadow = 'var(--sh-1)'; e.currentTarget.style.borderColor = 'var(--line)'; } : undefined}
    {...rest}
  >
    {children}
  </div>
);

// ----- Badge -----
const Badge = ({ tone = 'neutral', children, size = 'md', icon, style }) => {
  const tones = {
    neutral: { bg: 'var(--bg-2)', fg: 'var(--ink-2)' },
    primary: { bg: 'rgba(139,111,71,0.12)', fg: 'var(--primary-ink)' },
    accent: { bg: 'var(--accent-soft)', fg: '#A14E32' },
    success: { bg: 'var(--success-soft)', fg: '#3F6B2C' },
    warn: { bg: 'var(--warn-soft)', fg: '#7B5916' },
    danger: { bg: 'var(--danger-soft)', fg: '#7E342B' },
    outline: { bg: 'transparent', fg: 'var(--ink-2)', border: '1px solid var(--line-2)' },
    dark: { bg: 'var(--ink)', fg: 'var(--bg)' },
  };
  const t = tones[tone];
  const sz = size === 'sm' ? { padding: '2px 8px', fontSize: 11.5 } : { padding: '4px 10px', fontSize: 12.5 };
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 4,
      background: t.bg, color: t.fg, borderRadius: 999,
      fontWeight: 500, lineHeight: 1.4,
      border: t.border || '1px solid transparent',
      ...sz, ...style,
    }}>
      {icon && <I name={icon} size={11} />}
      {children}
    </span>
  );
};

// ----- Avatar -----
const Avatar = ({ name = '', size = 32, src, style }) => {
  const initials = (name || '?').trim().split(' ').slice(0, 2).map(s => s[0]).join('').toUpperCase();
  // generate stable bg
  let h = 0; for (const c of name) h = (h * 31 + c.charCodeAt(0)) >>> 0;
  const hue = h % 360;
  return (
    <div style={{
      width: size, height: size, borderRadius: '50%',
      background: src ? `center/cover no-repeat url(${src}), hsl(${hue} 35% 80%)` : `hsl(${hue} 35% 78%)`,
      color: `hsl(${hue} 40% 28%)`,
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      fontWeight: 600, fontSize: size * 0.4, flexShrink: 0,
      border: '1px solid rgba(0,0,0,0.05)',
      ...style,
    }}>
      {!src && initials}
    </div>
  );
};

// ----- Input -----
const Input = ({ label, hint, error, icon, full = true, style, inputStyle, ...rest }) => (
  <label style={{ display: full ? 'block' : 'inline-block', width: full ? '100%' : 'auto', ...style }}>
    {label && <div style={{ fontSize: 13, fontWeight: 500, color: 'var(--ink-2)', marginBottom: 6 }}>{label}</div>}
    <div style={{ position: 'relative' }}>
      {icon && (
        <div style={{ position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)', color: 'var(--ink-3)' }}>
          <I name={icon} size={16} />
        </div>
      )}
      <input
        style={{
          width: '100%', height: 42,
          padding: icon ? '0 14px 0 38px' : '0 14px',
          background: 'var(--surface)',
          border: `1px solid ${error ? 'var(--danger)' : 'var(--line-2)'}`,
          borderRadius: 'var(--r-md)',
          outline: 'none',
          fontSize: 14,
          transition: 'border-color .15s ease, box-shadow .15s ease',
          ...inputStyle,
        }}
        onFocus={e => { if (!error) { e.target.style.borderColor = 'var(--ink-2)'; e.target.style.boxShadow = '0 0 0 3px rgba(40,30,15,0.06)'; } }}
        onBlur={e => { if (!error) { e.target.style.borderColor = 'var(--line-2)'; e.target.style.boxShadow = 'none'; } }}
        {...rest}
      />
    </div>
    {(hint || error) && (
      <div style={{ fontSize: 12, marginTop: 6, color: error ? 'var(--danger)' : 'var(--ink-3)' }}>{error || hint}</div>
    )}
  </label>
);

// ----- Logo / Wordmark -----
const Logo = ({ size = 22, color = 'var(--ink)' }) => (
  <div style={{ display: 'inline-flex', alignItems: 'center', gap: 8, color }}>
    <svg width={size} height={size} viewBox="0 0 32 32" fill="none">
      <rect x="3" y="3" width="26" height="26" rx="7" fill="var(--primary)"/>
      <path d="M11 9v14M11 16l8-7M11 16l8 7" stroke="#FAF7F2" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
    <span style={{ fontWeight: 600, fontSize: size * 0.78, letterSpacing: '-0.01em' }}>KindleStartup</span>
  </div>
);

// ----- Product Logo Tile (for the 4 systems) -----
// Each system has a distinctive emblem: bespoke SVG mark with layered depth,
// gradient mesh, ornament, and a subtle inner stroke + corner highlight.
const SystemGlyph = ({ system, size = 44, rounded = 12 }) => {
  const presets = {
    Academy: {
      // forest / scholarly — stacked pages with bookmark
      bg1: '#4F5F40', bg2: '#2E3826', accent: '#D4E0A8', ink: '#F4F1E4',
      mark: (s) => (
        <g>
          {/* stack of pages */}
          <rect x={s*0.22} y={s*0.30} width={s*0.50} height={s*0.42} rx={s*0.04} fill="rgba(255,255,255,0.10)" />
          <rect x={s*0.26} y={s*0.26} width={s*0.50} height={s*0.42} rx={s*0.04} fill="rgba(255,255,255,0.18)" />
          <rect x={s*0.30} y={s*0.22} width={s*0.50} height={s*0.42} rx={s*0.04} fill="#F4F1E4" />
          {/* lines on top page */}
          <rect x={s*0.36} y={s*0.32} width={s*0.30} height={s*0.025} rx={s*0.012} fill="#4F5F40" />
          <rect x={s*0.36} y={s*0.40} width={s*0.36} height={s*0.025} rx={s*0.012} fill="#4F5F40" opacity="0.7" />
          <rect x={s*0.36} y={s*0.48} width={s*0.22} height={s*0.025} rx={s*0.012} fill="#4F5F40" opacity="0.5" />
          {/* bookmark */}
          <path d={`M ${s*0.62} ${s*0.22} L ${s*0.74} ${s*0.22} L ${s*0.74} ${s*0.40} L ${s*0.68} ${s*0.36} L ${s*0.62} ${s*0.40} Z`} fill="#D4E0A8" />
        </g>
      ),
    },
    SEO: {
      // amber / search — magnifier with rays
      bg1: '#9A5A35', bg2: '#5C2E15', accent: '#FFD9A3', ink: '#FFF1DD',
      mark: (s) => (
        <g>
          {/* sparkle rays */}
          <g stroke="#FFD9A3" strokeWidth={s*0.025} strokeLinecap="round" opacity="0.7">
            <line x1={s*0.20} y1={s*0.30} x2={s*0.28} y2={s*0.34} />
            <line x1={s*0.78} y1={s*0.28} x2={s*0.72} y2={s*0.34} />
            <line x1={s*0.18} y1={s*0.50} x2={s*0.26} y2={s*0.50} />
          </g>
          {/* lens ring */}
          <circle cx={s*0.46} cy={s*0.46} r={s*0.20} fill="none" stroke="#FFF1DD" strokeWidth={s*0.06} />
          <circle cx={s*0.46} cy={s*0.46} r={s*0.13} fill="rgba(255,217,163,0.35)" />
          {/* highlight */}
          <ellipse cx={s*0.40} cy={s*0.40} rx={s*0.06} ry={s*0.04} fill="#FFF1DD" opacity="0.7" />
          {/* handle */}
          <rect x={s*0.60} y={s*0.60} width={s*0.22} height={s*0.08} rx={s*0.04} fill="#FFD9A3" transform={`rotate(45 ${s*0.60} ${s*0.60})`} />
        </g>
      ),
    },
    Lumo: {
      // gold / spark — radiant sun-burst sparkle
      bg1: '#B58A3A', bg2: '#6E4E15', accent: '#FFE89A', ink: '#FFF8DC',
      mark: (s) => (
        <g>
          {/* halo */}
          <circle cx={s*0.50} cy={s*0.50} r={s*0.32} fill="none" stroke="#FFE89A" strokeWidth={s*0.012} opacity="0.5" strokeDasharray={`${s*0.04} ${s*0.04}`} />
          {/* 4-point star */}
          <path d={`M ${s*0.50} ${s*0.18} L ${s*0.56} ${s*0.44} L ${s*0.82} ${s*0.50} L ${s*0.56} ${s*0.56} L ${s*0.50} ${s*0.82} L ${s*0.44} ${s*0.56} L ${s*0.18} ${s*0.50} L ${s*0.44} ${s*0.44} Z`} fill="#FFF8DC" />
          {/* small ornament star */}
          <path d={`M ${s*0.74} ${s*0.26} L ${s*0.76} ${s*0.32} L ${s*0.82} ${s*0.34} L ${s*0.76} ${s*0.36} L ${s*0.74} ${s*0.42} L ${s*0.72} ${s*0.36} L ${s*0.66} ${s*0.34} L ${s*0.72} ${s*0.32} Z`} fill="#FFE89A" opacity="0.85" />
          {/* center dot */}
          <circle cx={s*0.50} cy={s*0.50} r={s*0.06} fill="#B58A3A" />
        </g>
      ),
    },
    Muze: {
      // plum / muse — feather quill with ink drop
      bg1: '#6B4E80', bg2: '#3A2A4E', accent: '#E0C8F0', ink: '#F4E8FF',
      mark: (s) => (
        <g>
          {/* ink dot */}
          <circle cx={s*0.26} cy={s*0.74} r={s*0.06} fill="#E0C8F0" />
          {/* quill body — diagonal teardrop */}
          <path d={`
            M ${s*0.30} ${s*0.70}
            Q ${s*0.40} ${s*0.50} ${s*0.62} ${s*0.30}
            Q ${s*0.78} ${s*0.18} ${s*0.82} ${s*0.22}
            Q ${s*0.80} ${s*0.42} ${s*0.62} ${s*0.58}
            Q ${s*0.46} ${s*0.70} ${s*0.30} ${s*0.70}
            Z
          `} fill="#F4E8FF" />
          {/* feather barbs (highlight) */}
          <path d={`M ${s*0.40} ${s*0.62} Q ${s*0.50} ${s*0.50} ${s*0.66} ${s*0.40}`} stroke="#6B4E80" strokeWidth={s*0.02} fill="none" opacity="0.5" />
          <path d={`M ${s*0.46} ${s*0.66} Q ${s*0.56} ${s*0.54} ${s*0.72} ${s*0.42}`} stroke="#6B4E80" strokeWidth={s*0.02} fill="none" opacity="0.4" />
          {/* sparkle */}
          <path d={`M ${s*0.22} ${s*0.30} L ${s*0.24} ${s*0.36} L ${s*0.30} ${s*0.38} L ${s*0.24} ${s*0.40} L ${s*0.22} ${s*0.46} L ${s*0.20} ${s*0.40} L ${s*0.14} ${s*0.38} L ${s*0.20} ${s*0.36} Z`} fill="#E0C8F0" opacity="0.85" />
        </g>
      ),
    },
  };
  const p = presets[system] || presets.Academy;
  const id = `glyph-${system}`;
  return (
    <svg
      width={size} height={size}
      viewBox={`0 0 ${size} ${size}`}
      style={{ flexShrink: 0, display: 'inline-block', filter: size >= 28 ? 'drop-shadow(0 2px 6px rgba(40,30,20,0.18))' : 'none' }}
      aria-label={system}
    >
      <defs>
        {/* radial mesh: warmer top-left, deeper bottom-right */}
        <radialGradient id={`${id}-bg`} cx="30%" cy="25%" r="95%">
          <stop offset="0%" stopColor={p.bg1} />
          <stop offset="100%" stopColor={p.bg2} />
        </radialGradient>
        {/* subtle noise/sheen overlay */}
        <linearGradient id={`${id}-sheen`} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#fff" stopOpacity="0.18" />
          <stop offset="50%" stopColor="#fff" stopOpacity="0" />
          <stop offset="100%" stopColor="#000" stopOpacity="0.10" />
        </linearGradient>
        <clipPath id={`${id}-clip`}>
          <rect width={size} height={size} rx={rounded} ry={rounded} />
        </clipPath>
      </defs>
      {/* base */}
      <rect width={size} height={size} rx={rounded} ry={rounded} fill={`url(#${id}-bg)`} />
      {/* big soft accent blob top-right for depth */}
      <g clipPath={`url(#${id}-clip)`}>
        <circle cx={size * 0.95} cy={size * 0.05} r={size * 0.55} fill={p.accent} opacity="0.18" />
        {/* the mark */}
        {p.mark(size)}
      </g>
      {/* sheen */}
      <rect width={size} height={size} rx={rounded} ry={rounded} fill={`url(#${id}-sheen)`} />
      {/* inner stroke */}
      <rect x="0.5" y="0.5" width={size - 1} height={size - 1} rx={rounded} ry={rounded} fill="none" stroke="rgba(255,255,255,0.14)" strokeWidth="1" />
    </svg>
  );
};

// ----- Placeholder image block -----
const Placeholder = ({ ratio = '4/3', label, tone = 1, style, children, rounded = 'var(--r-md)' }) => {
  const tones = [
    { bg: 'linear-gradient(135deg, #ECE5D8, #DFD6C4)', fg: '#8A7F73' },
    { bg: 'linear-gradient(135deg, #E3DBC8, #CFC2A6)', fg: '#7A6F5F' },
    { bg: 'linear-gradient(135deg, #EFE2D5, #E2CFB8)', fg: '#7E624A' },
    { bg: 'linear-gradient(135deg, #DDE2D3, #C4CDB1)', fg: '#5E6A4A' },
    { bg: 'linear-gradient(135deg, #E8DDD3, #D0BFAE)', fg: '#7B5E48' },
  ];
  const t = tones[tone % tones.length];
  return (
    <div style={{
      aspectRatio: ratio, width: '100%',
      background: t.bg, color: t.fg,
      borderRadius: rounded, overflow: 'hidden',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      fontSize: 13, fontWeight: 500, position: 'relative',
      ...style,
    }}>
      {children || (label && <span style={{ opacity: 0.7 }}>{label}</span>)}
    </div>
  );
};

// ----- Section heading -----
const SectionHeading = ({ eyebrow, title, action, style }) => (
  <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 16, marginBottom: 16, ...style }}>
    <div>
      {eyebrow && <div style={{ fontSize: 12, fontWeight: 500, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 6 }}>{eyebrow}</div>}
      {title && <h3 className="display" style={{ margin: 0, fontSize: 22, fontWeight: 600, letterSpacing: '-0.01em' }}>{title}</h3>}
    </div>
    {action}
  </div>
);

// ----- Tabs -----
const Tabs = ({ items, value, onChange, style }) => (
  <div style={{ display: 'flex', gap: 4, borderBottom: '1px solid var(--line)', ...style }}>
    {items.map(it => (
      <button key={it.value} onClick={() => onChange(it.value)} style={{
        background: 'transparent', border: 'none', padding: '10px 14px',
        cursor: 'pointer', fontSize: 14, fontWeight: 500,
        color: value === it.value ? 'var(--ink)' : 'var(--ink-3)',
        borderBottom: `2px solid ${value === it.value ? 'var(--ink)' : 'transparent'}`,
        marginBottom: -1, transition: 'color .15s, border-color .15s',
      }}>{it.label}</button>
    ))}
  </div>
);

// ----- Toast (very lightweight) -----
const ToastCtx = createContext(null);
function ToastProvider({ children }) {
  const [items, setItems] = useState([]);
  const push = useCallback((msg, opts = {}) => {
    const id = Math.random();
    setItems(s => [...s, { id, msg, ...opts }]);
    setTimeout(() => setItems(s => s.filter(i => i.id !== id)), opts.duration || 2500);
  }, []);
  return (
    <ToastCtx.Provider value={push}>
      {children}
      <div style={{ position: 'fixed', bottom: 24, right: 24, zIndex: 9999, display: 'flex', flexDirection: 'column', gap: 8 }}>
        {items.map(it => (
          <div key={it.id} className="fade-up" style={{
            background: 'var(--ink)', color: 'var(--bg)',
            padding: '10px 16px', borderRadius: 999, fontSize: 13, fontWeight: 500,
            boxShadow: 'var(--sh-pop)',
          }}>{it.msg}</div>
        ))}
      </div>
    </ToastCtx.Provider>
  );
}
const useToast = () => useContext(ToastCtx);

// expose to other babel scripts
Object.assign(window, {
  Icon, I, Icons,
  Button, Card, Badge, Avatar, Input, Logo,
  SystemGlyph, Placeholder, SectionHeading, Tabs,
  ToastProvider, useToast,
});
