// ---- Shared UI primitives -------------------------------------------
const { useState, useEffect, useRef } = React;

// Thin, elegant line icons (1.6 stroke), inherit currentColor
const ICONS = {
  feather: "M20.24 12.24a6 6 0 0 0-8.49-8.49L5 10.5V19h8.5zM16 8 2 22M17.5 15H9",
  calendar:"M8 2v4M16 2v4M3 10h18M5 4h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z",
  home:    "M3 9.5 12 3l9 6.5V20a1 1 0 0 1-1 1h-5v-6H9v6H4a1 1 0 0 1-1-1z",
  sparkle: "M12 3l1.9 5.6L19.5 10l-5.6 1.9L12 17l-1.9-5.1L4.5 10l5.6-1.4zM19 4v3M5 18v2.5M18 18v2",
  heart:   "M20.8 5.6a5.5 5.5 0 0 0-7.8 0L12 6.6l-1-1a5.5 5.5 0 1 0-7.8 7.8l1 1L12 21l7.8-7.6 1-1a5.5 5.5 0 0 0 0-7.8z",
  leaf:    "M11 20A7 7 0 0 1 4 13c0-5 5-9 16-9 0 9-4 14-9 14zM4 21c2-5 6-9 11-11",
  truck:   "M1 4h13v12H1zM14 8h4l3 3v5h-7M5.5 19a2 2 0 1 0 0-.1M17.5 19a2 2 0 1 0 0-.1",
  cart:    "M2 3h2.2l2 13h11.6l2-9H6M9 21a1 1 0 1 0 0-.1M18 21a1 1 0 1 0 0-.1",
  star:    "M12 2.5l2.9 6.1 6.6.9-4.8 4.6 1.2 6.6L12 18.6 6.1 21.3l1.2-6.6L2.5 9.5l6.6-.9z",
  check:   "M20 6 9 17l-5-5",
  chevron: "M9 18l6-6-6-6",
  chevronD:"M6 9l6 6 6-6",
  search:  "M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM21 21l-4.3-4.3",
  user:    "M20 21a8 8 0 0 0-16 0M12 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8z",
  close:   "M18 6 6 18M6 6l12 12",
  plus:    "M12 5v14M5 12h14",
  minus:   "M5 12h14",
  arrow:   "M5 12h14M13 6l6 6-6 6",
  moon:    "M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z",
  sun:     "M12 2v3M12 19v3M4.2 4.2l2.1 2.1M17.7 17.7l2.1 2.1M2 12h3M19 12h3M4.2 19.8l2.1-2.1M17.7 6.3l2.1-2.1M12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8z",
  book:    "M4 4.5A2.5 2.5 0 0 1 6.5 2H20v18H6.5A2.5 2.5 0 0 0 4 22.5zM4 19.5A2.5 2.5 0 0 1 6.5 17H20",
  bookmark:"M6 3h12a1 1 0 0 1 1 1v17l-7-4-7 4V4a1 1 0 0 1 1-1z",
  users:   "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM22 21v-2a4 4 0 0 0-3-3.87M16 3.13A4 4 0 0 1 16 11",
  ruler:   "M3 8l5-5 13 13-5 5zM8 7l2 2M11 4l3 3M5 10l3 3",
  heartline:"M19.5 5.5a4.5 4.5 0 0 0-7 .5l-.5.6-.5-.6a4.5 4.5 0 1 0-6.8 5.9L12 20l7.3-7.6a4.5 4.5 0 0 0 .2-6.9z",
  quote:   "M7 7H4a1 1 0 0 0-1 1v4a1 1 0 0 0 1 1h3v3a3 3 0 0 1-3 3M20 7h-3a1 1 0 0 0-1 1v4a1 1 0 0 0 1 1h3v3a3 3 0 0 1-3 3",
  arrowUpRight:"M7 17 17 7M8 7h9v9",
  image:   "M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2zM8.5 11a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM21 16l-4.5-4.5L7 21",
};

function Icon({ name, size = 22, stroke = 1.6, fill = false, style }) {
  const d = ICONS[name] || "";
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none"
         stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round"
         style={style} aria-hidden="true">
      <path d={d} fill={fill ? "currentColor" : "none"} stroke={fill ? "none" : "currentColor"} />
    </svg>
  );
}

// Brand logos (recolored asset variants live in /assets). brandAsset() resolves
// to a bundled blob URL (window.__resources) when present, else the file path —
// so the same code works in normal preview and in the standalone export.
function brandAsset(type, variant) {
  const id = (type === "mark" ? "logoMark_" : "logoWord_") + variant;
  return (window.__resources && window.__resources[id]) || ("assets/logo-" + type + "-" + variant + ".svg");
}
function LogoMark({ color = "brown", height = 40, style }) {
  return <img src={brandAsset("mark", color)} alt="Journella" style={{ height, display: "block", ...style }} />;
}
function LogoWord({ color = "brown", height = 26, style }) {
  return <img src={brandAsset("word", color)} alt="Journella" style={{ height, display: "block", ...style }} />;
}

function Stars({ value = 5, size = 16, color = "var(--gold-deep)" }) {
  return (
    <span style={{ display: "inline-flex", gap: 2, color }}>
      {[0,1,2,3,4].map(i => (
        <svg key={i} width={size} height={size} viewBox="0 0 24 24" aria-hidden="true">
          <path d={ICONS.star} fill={i < Math.round(value) ? color : "var(--line)"} />
        </svg>
      ))}
    </span>
  );
}

function Button({ children, variant = "primary", size = "md", onClick, type = "button", style, disabled, full }) {
  const base = {
    fontFamily: "var(--ui)", fontWeight: 600, letterSpacing: ".01em",
    border: "1px solid transparent", borderRadius: 999, cursor: disabled ? "default" : "pointer",
    display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 9,
    transition: "transform .18s var(--ease), background .2s, color .2s, border-color .2s, box-shadow .2s",
    width: full ? "100%" : "auto", opacity: disabled ? 0.5 : 1,
    whiteSpace: "nowrap",
  };
  const sizes = {
    sm: { padding: "9px 18px", fontSize: 13 },
    md: { padding: "14px 28px", fontSize: 15 },
    lg: { padding: "18px 38px", fontSize: 16 },
  };
  const variants = {
    primary:   { background: "var(--espresso)", color: "var(--cream)" },
    terracotta:{ background: "var(--terracotta)", color: "var(--cream)" },
    outline:   { background: "transparent", color: "var(--espresso)", borderColor: "var(--espresso)" },
    ghost:     { background: "var(--cream-2)", color: "var(--espresso)", borderColor: "transparent" },
  };
  return (
    <button type={type} onClick={disabled ? undefined : onClick} disabled={disabled}
      className={"j-btn j-btn-" + variant}
      style={{ ...base, ...sizes[size], ...variants[variant], ...style }}>
      {children}
    </button>
  );
}

// Marquee strip — gentle scrolling text, like the reference shop's ribbon
function Marquee({ items, speed = 38, style }) {
  const content = items.concat(items);
  return (
    <div style={{ overflow: "hidden", whiteSpace: "nowrap", ...style }}>
      <div className="j-marquee" style={{ animationDuration: speed + "s", display: "inline-flex", alignItems: "center" }}>
        {content.map((t, i) => (
          <span key={i} style={{ display: "inline-flex", alignItems: "center", gap: 18, paddingInline: 22 }}>
            <span>{t}</span>
            <svg width="9" height="9" viewBox="0 0 24 24" style={{ opacity: .6 }}><path d={ICONS.sparkle} fill="currentColor" /></svg>
          </span>
        ))}
      </div>
    </div>
  );
}

// Section heading: small kicker + serif headline
function SectionHead({ kicker, title, sub, center, light }) {
  return (
    <div style={{ textAlign: center ? "center" : "left", maxWidth: center ? 640 : "none", marginInline: center ? "auto" : 0 }}>
      {kicker && <div className="j-kicker" style={{ color: light ? "var(--cream-gold)" : "var(--terracotta)", justifyContent: center ? "center" : "flex-start" }}>
        <span className="j-kicker-line" /> {kicker}
      </div>}
      <h2 style={{ fontFamily: "var(--display)", fontWeight: 700, fontSize: "clamp(28px, 4vw, 44px)",
        lineHeight: 1.14, letterSpacing: "-.01em", margin: "14px 0 0", color: light ? "var(--cream)" : "var(--espresso)" }}>
        {title}
      </h2>
      {sub && <p style={{ marginTop: 14, fontSize: 16.5, lineHeight: 1.6, color: light ? "rgba(255,247,229,.78)" : "var(--ink-soft)" }}>{sub}</p>}
    </div>
  );
}

// Reveal-on-scroll: visible by DEFAULT (never stuck hidden); the entrance
// animation is added as an enhancement when the element enters the viewport.
function Reveal({ children, delay = 0, style }) {
  const ref = useRef(null);
  const [anim, setAnim] = useState(false);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const r = el.getBoundingClientRect();
    if (r.top < (window.innerHeight || 800) + 60 && r.bottom > -60) { setAnim(true); return; }
    const io = new IntersectionObserver((es) => {
      es.forEach(e => { if (e.isIntersecting) { setAnim(true); io.disconnect(); } });
    }, { threshold: 0.1 });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return (
    <div ref={ref} className={anim ? "j-reveal-in" : undefined}
      style={{ animationDelay: delay + "s", ...style }}>{children}</div>
  );
}

Object.assign(window, { Icon, ICONS, brandAsset, LogoMark, LogoWord, Stars, Button, Marquee, SectionHead, Reveal });
