// ui.jsx — shared building blocks. Theme comes through context.
const ASFThemeCtx = React.createContext(null);
const useTheme = () => React.useContext(ASFThemeCtx);

// ── Icons: simple geometric line set (stroke = currentColor) ──
const ICON_PATHS = {
  home: 'M3 11.5 12 4l9 7.5M5.5 10v9.5h13V10',
  book: 'M5 4.5h9a3 3 0 0 1 3 3V20a2.5 2.5 0 0 0-2.5-2.5H5zM5 4.5V20',
  spark: 'M12 3v4M12 17v4M3 12h4M17 12h4M12 12l5-5M12 12l-5 5M12 12l5 5M12 12l-5-5',
  cal: 'M4 6.5h16V20H4zM4 9.5h16M8 3.5v4M16 3.5v4',
  plus: 'M12 5v14M5 12h14',
  right: 'M9 5l7 7-7 7',
  left: 'M15 5l-7 7 7 7',
  x: 'M6 6l12 12M18 6 6 18',
  check: 'M5 12.5 10 17l9-10',
  volume: 'M4 10v4h3l4 4V6l-4 4zM15 9.5a4 4 0 0 1 0 5M17.5 7a7 7 0 0 1 0 10',
  play: 'M7 5l12 7-12 7z',
  clock: 'M12 12V7M12 12l3.5 2M12 21a9 9 0 1 1 0-18 9 9 0 0 1 0 18z',
  pin: 'M12 21s7-6.3 7-11a7 7 0 1 0-14 0c0 4.7 7 11 7 11zM12 12.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5z',
  user: 'M12 12.5a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM4.5 20c.8-3.8 3.8-5.5 7.5-5.5s6.7 1.7 7.5 5.5',
  flame: 'M12 3c.5 3-2.5 4-2.5 7A2.5 2.5 0 0 0 12 12.5 2.5 2.5 0 0 0 14.5 10c0-.8-.3-1.4-.6-2 2 1 3.6 3 3.6 5.5a5.5 5.5 0 1 1-11 0C6.5 9 11 8 12 3z',
  refresh: 'M19 12a7 7 0 1 1-2-4.9M19 4v3.5h-3.5',
  eye: 'M2.5 12S6 5.5 12 5.5 21.5 12 21.5 12 18 18.5 12 18.5 2.5 12 2.5 12zM12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z',
  edit: 'M14 5.5l4.5 4.5M4 20l1-4L16.5 4.5a2 2 0 0 1 3 3L8 19z',
  quote: 'M9 7H5.5A1.5 1.5 0 0 0 4 8.5V12h5V7H6.5M19 7h-3.5A1.5 1.5 0 0 0 14 8.5V12h5V7h-2.5M4 12c0 3-1 4-1 4M14 12c0 3-1 4-1 4',
  star: 'M12 3.5l2.6 5.3 5.9.9-4.2 4.1 1 5.8L12 17l-5.3 2.6 1-5.8-4.2-4.1 5.9-.9z',
  arrowR: 'M5 12h14M13 6l6 6-6 6',
  sun: 'M12 7.5a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9zM12 2v2.5M12 19.5V22M4 12H1.5M22.5 12H20M5 5l1.8 1.8M17.2 17.2 19 19M19 5l-1.8 1.8M6.8 17.2 5 19',
  layers: 'M12 3.5 21 8l-9 4.5L3 8zM3 12l9 4.5L21 12M3 16l9 4.5L21 16',
};
function Icon({ name, size = 22, stroke = 2, fill = false, style }) {
  const p = ICON_PATHS[name] || '';
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={fill ? 'currentColor' : 'none'}
      stroke={fill ? 'none' : 'currentColor'} strokeWidth={stroke}
      strokeLinecap="round" strokeLinejoin="round" style={style} aria-hidden="true">
      <path d={p} />
    </svg>
  );
}

// ── Book cover: striped placeholder with a hashed hue, monospace label ──
function BookCover({ seed = '', label, src, kind = 'JY', w = 96, h = 132, dim = false }) {
  const c = useTheme();
  let hsum = 0; for (let i = 0; i < seed.length; i++) hsum = (hsum * 31 + seed.charCodeAt(i)) % 360;
  const stripe = c.dark ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.05)';
  const useClayCover = !!c.cover;
  if (src) return (
    <div style={{
      width: w, height: h, borderRadius: Math.min(10, Math.max(7, w * 0.12)), position: 'relative', overflow: 'hidden',
      flexShrink: 0, opacity: dim ? 0.5 : 1, background: c.surfaceAlt,
      boxShadow: c.dark ? '0 8px 16px rgba(0,0,0,0.35), inset 0 0 0 1px rgba(255,255,255,0.08)' : '0 6px 16px rgba(44,32,23,0.16), inset 0 0 0 1px rgba(0,0,0,0.05)',
    }}>
      <img src={src} alt={label || 'Book cover'} style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
    </div>
  );
  return (
    <div style={{
      width: w, height: h, borderRadius: useClayCover ? Math.min(14, Math.max(10, w * 0.24)) : 10, position: 'relative', overflow: 'hidden',
      flexShrink: 0, opacity: dim ? 0.5 : 1,
      background: useClayCover ? c.cover : `repeating-linear-gradient(135deg, ${c.surfaceAlt}, ${c.surfaceAlt} 7px, ${stripe} 7px, ${stripe} 14px)`,
      boxShadow: c.coverShadow || (c.dark ? 'inset 0 0 0 1px rgba(255,255,255,0.08)' : '0 4px 14px rgba(44,32,23,0.12), inset 0 0 0 1px rgba(0,0,0,0.04)'),
      display: 'flex', flexDirection: 'column', justifyContent: 'flex-end',
    }}>
      <div style={{ position: 'absolute', top: 10, left: 10, width: 26, height: 4, borderRadius: 2, background: useClayCover ? 'rgba(255,255,255,0.72)' : c.accent, opacity: 0.85 }} />
      <div style={{
        margin: 8, padding: '6px 8px', borderRadius: 7, background: useClayCover ? 'rgba(255,255,255,0.18)' : c.surface,
        fontFamily: c.headingStack || 'ui-monospace, "SF Mono", Menlo, monospace', fontSize: 9.5,
        letterSpacing: '0.03em', color: useClayCover ? (c.dark ? c.accent : c.accentInk) : c.textMuted, lineHeight: 1.35,
        textShadow: useClayCover && !c.dark ? '0 1px 1px rgba(0,0,0,0.16)' : 'none',
      }}>{label}</div>
    </div>
  );
}

// ── Progress ring ──
function Ring({ value = 0, size = 40, stroke = 4, children }) {
  const c = useTheme();
  const r = (size - stroke) / 2, circ = 2 * Math.PI * r;
  return (
    <div style={{ width: size, height: size, position: 'relative', flexShrink: 0 }}>
      <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={c.border} strokeWidth={stroke} />
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={c.accent} strokeWidth={stroke}
          strokeDasharray={circ} strokeDashoffset={circ * (1 - value)} strokeLinecap="round"
          style={{ transition: 'stroke-dashoffset .5s cubic-bezier(.4,0,.2,1)' }} />
      </svg>
      <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>{children}</div>
    </div>
  );
}

// ── Chip / pill ──
function Chip({ children, active, onClick, style }) {
  const c = useTheme();
  return (
    <button onClick={onClick} style={{
      border: 'none', cursor: 'pointer', whiteSpace: 'nowrap',
      padding: '7px 14px', borderRadius: 999, fontSize: 13.5, fontWeight: 600,
      fontFamily: 'inherit', letterSpacing: '0.01em',
      background: active ? c.accent : c.surface,
      color: active ? c.accentInk : c.textMuted,
      boxShadow: active ? 'none' : `inset 0 0 0 1px ${c.border}`,
      transition: 'all .18s', ...style,
    }}>{children}</button>
  );
}

// ── Round icon button ──
function IconBtn({ name, onClick, size = 40, accent = false, style }) {
  const c = useTheme();
  return (
    <button onClick={onClick} style={{
      width: size, height: size, borderRadius: 999, border: 'none', cursor: 'pointer',
      display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
      background: accent ? c.accent : c.surface, color: accent ? c.accentInk : c.text,
      boxShadow: accent ? 'none' : `inset 0 0 0 1px ${c.border}`, ...style,
    }}><Icon name={name} size={size * 0.5} /></button>
  );
}

// ── Bottom sheet ──
function Sheet({ open, onClose, children, title }) {
  const c = useTheme();
  if (!open) return null;
  return (
    <div onClick={onClose} style={{
      position: 'absolute', inset: 0, zIndex: 200, display: 'flex', alignItems: 'flex-end',
      background: 'rgba(0,0,0,0.4)', animation: 'asf-fade .2s ease',
    }}>
      <div onClick={(e) => e.stopPropagation()} style={{
        width: '100%', maxHeight: '88%', overflow: 'auto', background: c.surface,
        borderRadius: '26px 26px 0 0', padding: '10px 0 30px',
        boxShadow: '0 -10px 40px rgba(0,0,0,0.25)', animation: 'asf-up .28s cubic-bezier(.2,.7,.2,1)',
      }}>
        <div style={{ width: 38, height: 5, borderRadius: 3, background: c.border, margin: '8px auto 6px' }} />
        {title && <div style={{ padding: '4px 22px 10px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
          <span style={{ fontFamily: c.headingStack, fontSize: 21, fontWeight: 600, color: c.text }}>{title}</span>
          <IconBtn name="x" size={34} onClick={onClose} />
        </div>}
        <div style={{ padding: '0 22px' }}>{children}</div>
      </div>
    </div>
  );
}

Object.assign(window, { ASFThemeCtx, useTheme, Icon, BookCover, Ring, Chip, IconBtn, Sheet });
