/* ui.jsx — 共享基元：字标 / 按钮 / 揭示动画 / 弹层 / 二维码 / 图标 */

/* ---------- 图片取址 ----------
   所有可替换的站点图片统一从这里取：
   1) 后台配置（QD.site.images[key]）优先
   2) 没有配置就用内置默认（QD.siteImages[key].v）
   这样运营在后台换图，前端所有引用点同时生效。
*/
function img(key, fallback) {
  const conf = (window.QD && QD.site && QD.site.images) || {};
  const v = conf[key];
  if (v) return v;
  const def = window.QD && QD.siteImages && QD.siteImages[key];
  return (def && def.v) || fallback || '';
}
window.__img = img;

/* ---------- 字标重绘：开口圆环（意识）+ 下落金点（下沉） ---------- */
function Logo({ size = 38, stacked = false, inv = false }) {
  return (
    <span className="logo" style={{ alignItems: stacked ? 'flex-start' : 'center' }}>
      {/* 官方标识：透明底 PNG，可从后台替换（site.logoMark） */}
      <img className="logo-mark" src={img('logoMark')}
        alt="" style={{ '--logo-h': size + 'px' }} aria-hidden="true" />
      <span className="logo-txt">
        <span className="logo-cn" style={inv ? { color: 'var(--on-dark)' } : null}>量子催眠中国</span>
        <span className="logo-en" style={inv ? { color: 'rgba(238,244,243,.42)' } : null}>QUANTUM HEALING HYPNOSIS · CHINA</span>
      </span>
    </span>
  );
}

/* ---------- 按钮 ---------- */
function Btn({ as = 'button', kind = 'primary', size, children, arw, block, ...rest }) {
  const cls = ['btn', 'btn-' + kind, size ? 'btn-' + size : '', block ? 'btn-block' : ''].filter(Boolean).join(' ');
  const Tag = as;
  return (
    <Tag className={cls} {...rest}>
      {children}
      {arw && <span className="arw" aria-hidden="true">→</span>}
    </Tag>
  );
}

function Eyebrow({ children, tone, plain }) {
  return <div className={'eyebrow' + (tone ? ' ' + tone : '') + (plain ? ' plain' : '')}>{children}</div>;
}

/* ---------- 滚动揭示：每个元素自带 observer，路由切换后仍可靠 ---------- */
function Reveal({ children, delay = 0, style, ...rest }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    if (!('IntersectionObserver' in window)) { el.classList.add('in'); return; }
    const io = new IntersectionObserver((es) => {
      es.forEach((e) => {
        if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); }
      });
    }, { threshold: 0.05, rootMargin: '0px 0px -6% 0px' });
    io.observe(el);
    /* 兜底：若因布局原因始终不触发，2s 后强制显示 */
    const fb = setTimeout(() => el.classList.add('in'), 2000);
    return () => { clearTimeout(fb); io.disconnect(); };
  }, []);
  return (
    <div ref={ref} className="reveal" style={{ transitionDelay: delay + 'ms', ...style }} {...rest}>
      {children}
    </div>
  );
}
function useReveal() { /* 保留 API：现在由 Reveal 自管理 */ }

/* ---------- 图标（极简线条） ---------- */
const Ico = {
  clock: (p) => <svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><circle cx="12" cy="12" r="9" /><path d="M12 7.5V12l3 2" strokeLinecap="round" /></svg>,
  book: (p) => <svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M4 4.5h6a2.5 2.5 0 012.5 2.5v13A2 2 0 0010.5 18H4z" strokeLinejoin="round" /><path d="M20 4.5h-4A2.5 2.5 0 0013.5 7v13A2 2 0 0115.5 18H20z" strokeLinejoin="round" /></svg>,
  wechat: (p) => <svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M15.5 10.2c0-3-2.8-5.4-6.2-5.4S3 7.2 3 10.2c0 1.7.9 3.2 2.4 4.2l-.6 2 2.2-1.1c.7.2 1.5.3 2.3.3" strokeLinecap="round" strokeLinejoin="round" /><path d="M21 14.6c0-2.4-2.2-4.3-5-4.3s-5 1.9-5 4.3 2.2 4.3 5 4.3c.6 0 1.2-.1 1.8-.2l1.8.9-.5-1.6c1.2-.8 1.9-2 1.9-3.4z" strokeLinecap="round" strokeLinejoin="round" /></svg>,
  play: (p) => <svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><circle cx="12" cy="12" r="9" /><path d="M10 8.5l6 3.5-6 3.5z" fill="currentColor" stroke="none" /></svg>,
  pin: (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M12 21s7-6.1 7-11a7 7 0 10-14 0c0 4.9 7 11 7 11z" strokeLinejoin="round" /><circle cx="12" cy="10" r="2.4" /></svg>,
  check: (p) => <svg viewBox="0 0 24 24" width="26" height="26" fill="none" stroke="currentColor" strokeWidth="1.7" {...p}><path d="M4.5 12.5l5 5L20 7" strokeLinecap="round" strokeLinejoin="round" /></svg>,
  close: (p) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="1.6" {...p}><path d="M5.5 5.5l13 13M18.5 5.5l-13 13" strokeLinecap="round" /></svg>,
  arrow: (p) => <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><path d="M4 12h15M13 6l6 6-6 6" strokeLinecap="round" strokeLinejoin="round" /></svg>,
  menu: (p) => <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="1.5" {...p}><path d="M4 8h16M4 16h16" strokeLinecap="round" /></svg>,
  star: (p) => <svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M12 4l2.4 5.2 5.6.7-4.1 3.9 1 5.6-4.9-2.7-4.9 2.7 1-5.6L4 9.9l5.6-.7z" strokeLinejoin="round" /></svg>,
  sync: (p) => <svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" strokeWidth="1.4" {...p}><path d="M20 12a8 8 0 01-13.7 5.6M4 12a8 8 0 0113.7-5.6" strokeLinecap="round" /><path d="M17 3v4h-4M7 21v-4h4" strokeLinecap="round" strokeLinejoin="round" /></svg>,
};

/* ---------- 弹层 ---------- */
function Modal({ onClose, children, max = 460 }) {
  React.useEffect(() => {
    const h = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', h);
    document.body.style.overflow = 'hidden';
    return () => { window.removeEventListener('keydown', h); document.body.style.overflow = ''; };
  }, [onClose]);
  return (
    <div className="scrim" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="modal" style={{ maxWidth: max }} role="dialog" aria-modal="true">{children}</div>
    </div>
  );
}

/* ---------- 公众号二维码 ----------
   原来这里是"确定性矩阵"生成的假码，现在直接显示上传的真实订阅号二维码。
   图片地址来自站点配置（后台可替换）：site.qrSubscribe
   仅当配置了动态码（site.qrDynamic）时才改用后台下发的图片。
*/
function QrCanvas({ size = 172, alt = '量子催眠中国 订阅号二维码' }) {
  const src = img('qrSubscribe');
  return (
    <img src={src} alt={alt} loading="lazy"
      style={{ width: '100%', height: '100%', objectFit: 'contain', display: 'block', background: '#fff' }} />
  );
}

/* ---------- 分节标题 ---------- */
function SecHead({ eyebrow, title, sub, right, tone }) {
  return (
    <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 32, flexWrap: 'wrap', marginBottom: 'clamp(28px,3.4vw,52px)' }}>
      <div style={{ maxWidth: 720 }}>
        {eyebrow && <Eyebrow tone={tone}>{eyebrow}</Eyebrow>}
        <h2 className="d2" style={{ marginTop: 18 }}>{title}</h2>
        {sub && <p className="lede" style={{ marginTop: 18, maxWidth: '58ch' }}>{sub}</p>}
      </div>
      {right}
    </div>
  );
}

Object.assign(window, { Logo, Btn, Eyebrow, Reveal, useReveal, Ico, Modal, QrCanvas, SecHead, img });
