// brand.jsx — shared tokens, placeholders, and small brand primitives
// Exported to window for use across the other babel scripts.

const BRAND = {
  forest:    "#1B3A2D",
  forestL:   "#2A5241",
  forestD:   "#142A21",
  greenMed:  "#4A7C2F",
  mint:      "#2ECC71",
  softGreen: "#73AD92",
  sage:      "#E8F5EE",
  sageD:     "#D4EADD",
  cream:     "#F9F6F0",
  creamD:    "#EFE9DC",
  gold:      "#C8A855",
  goldD:     "#A8893E",
  dark:      "#1A1A1A",
  ink:       "#2B2B28",
  body:      "#5A5A52",
};

const serif = "'Playfair Display', Georgia, serif";
const sans  = "'Inter', system-ui, sans-serif";
const mono  = "'Spline Sans Mono','SF Mono',ui-monospace,monospace";

// ── Striped photo placeholder ───────────────────────────────
// A subtly-striped block with a monospace caption telling the user
// what real asset belongs there.
function Ph({ label = "image", tone = "sage", radius = 0, style = {}, dark = false, children }) {
  const tones = {
    sage:   { bg: BRAND.sage,   stripe: "rgba(27,58,45,.05)",  text: "rgba(27,58,45,.55)", bd: "rgba(27,58,45,.12)" },
    cream:  { bg: BRAND.creamD, stripe: "rgba(27,58,45,.045)", text: "rgba(27,58,45,.5)",  bd: "rgba(27,58,45,.1)" },
    forest: { bg: BRAND.forestL,stripe: "rgba(255,255,255,.05)",text:"rgba(255,255,255,.65)",bd:"rgba(255,255,255,.14)" },
    gold:   { bg: "#E7D9B6",    stripe: "rgba(120,90,20,.06)", text: "rgba(120,90,20,.6)",  bd: "rgba(120,90,20,.18)" },
    dark:   { bg: BRAND.forestD,stripe: "rgba(46,204,113,.06)",text:"rgba(255,255,255,.6)", bd:"rgba(46,204,113,.18)" },
  };
  const t = tones[tone] || tones.sage;
  return (
    <div style={{
      position: "relative", borderRadius: radius, overflow: "hidden",
      background: t.bg,
      backgroundImage: `repeating-linear-gradient(135deg, ${t.stripe} 0, ${t.stripe} 1px, transparent 1px, transparent 9px)`,
      border: `1px solid ${t.bd}`,
      display: "flex", alignItems: "center", justifyContent: "center",
      ...style,
    }}>
      {children}
      <span style={{
        fontFamily: mono, fontSize: 10.5, letterSpacing: ".08em",
        textTransform: "uppercase", color: t.text,
        padding: "5px 9px", borderRadius: 999,
        background: dark ? "rgba(0,0,0,.18)" : "rgba(255,255,255,.5)",
        border: `1px solid ${t.bd}`, backdropFilter: "blur(2px)",
        whiteSpace: "nowrap",
      }}>[ {label} ]</span>
    </div>
  );
}

// ── Real-photo slot with graceful fallback ──────────────────
// Renders a real <img> (cover-cropped) when `src` is set; otherwise
// falls back to the striped Ph placeholder. Drop-in for Ph call sites.
// All real photos render through this single component so scaling is uniform
// across the site. `fit` defaults to "cover" and `position` to centre — every
// caller gets identical behaviour unless they override.
function PImg({ src, label = "image", tone = "sage", radius = 0, dark = false, style = {}, position = "50% 50%", fit = "cover" }) {
  const [ok, setOk] = React.useState(true);
  if (!src || !ok) return <Ph label={label} tone={tone} radius={radius} dark={dark} style={style} />;
  return (
    <img
      src={src}
      alt={label}
      loading="lazy"
      onError={() => setOk(false)}
      style={{ display: "block", width: "100%", height: "100%", objectFit: fit, objectPosition: position, borderRadius: radius, ...style }}
    />
  );
}

// ── Real brand logo, circle-cropped (white-bg square) ───────
function LogoMark({ size = 40, ring = BRAND.gold }) {
  return (
    <div style={{
      width: size, height: size, borderRadius: "50%", overflow: "hidden",
      flexShrink: 0, background: "#fff",
      boxShadow: `0 0 0 1.5px ${ring}, 0 1px 3px rgba(0,0,0,.15)`,
    }}>
      <img src="/logo-nav.png" alt="Millet Meals Plan"
        style={{ width: "100%", height: "100%", objectFit: "contain", display: "block" }} />
    </div>
  );
}

// ── Wordmark ─────────────────────────────────────────────────
function Wordmark({ color = "#fff", sub = BRAND.mint, size = 21 }) {
  return (
    <span style={{ display: "inline-flex", flexDirection: "column", lineHeight: 1 }}>
      <span style={{ fontFamily: serif, fontWeight: 700, fontSize: size, color, letterSpacing: "-.01em" }}>
        Millets<span style={{ color: sub }}>Fit</span>
      </span>
    </span>
  );
}

// little label (gold eyebrow)
function Eyebrow({ children, color = BRAND.gold, style = {} }) {
  return (
    <span style={{
      fontFamily: sans, fontSize: 11.5, fontWeight: 700, letterSpacing: ".22em",
      textTransform: "uppercase", color, ...style,
    }}>{children}</span>
  );
}

// ── tiny cart store (localStorage + cross-tab + same-tab events) ──
// Cart shape: [{ slug, duration, qty }]
const CART_KEY = "milletsfit.cart.v1";
const CART_EVT = "milletsfit:cart-updated";

const CartAPI = {
  read() {
    try { const x = JSON.parse(localStorage.getItem(CART_KEY) || "[]"); return Array.isArray(x) ? x : []; }
    catch { return []; }
  },
  write(items) {
    try { localStorage.setItem(CART_KEY, JSON.stringify(items)); } catch {}
    try { window.dispatchEvent(new CustomEvent(CART_EVT, { detail: items })); } catch {}
  },
  count() { return CartAPI.read().reduce((s, i) => s + (i.qty || 1), 0); },
  add(slug, duration = 10, qty = 1) {
    const items = CartAPI.read();
    const k = items.findIndex((i) => i.slug === slug && i.duration === duration);
    if (k >= 0) items[k] = { ...items[k], qty: (items[k].qty || 1) + qty };
    else items.push({ slug, duration, qty });
    CartAPI.write(items);
  },
  setQty(slug, duration, qty) {
    const items = CartAPI.read().map((i) => i.slug === slug && i.duration === duration ? { ...i, qty } : i).filter((i) => (i.qty || 0) > 0);
    CartAPI.write(items);
  },
  setDuration(slug, oldD, newD) {
    if (oldD === newD) return;
    let items = CartAPI.read();
    const fromIdx = items.findIndex((i) => i.slug === slug && i.duration === oldD);
    if (fromIdx < 0) return;
    const fromQty = items[fromIdx].qty || 1;
    items = items.filter((_, k) => k !== fromIdx);
    const toIdx = items.findIndex((i) => i.slug === slug && i.duration === newD);
    if (toIdx >= 0) items[toIdx] = { ...items[toIdx], qty: (items[toIdx].qty || 1) + fromQty };
    else items.push({ slug, duration: newD, qty: fromQty });
    CartAPI.write(items);
  },
  remove(slug, duration) {
    CartAPI.write(CartAPI.read().filter((i) => !(i.slug === slug && i.duration === duration)));
  },
  clear() { CartAPI.write([]); },
};

Object.assign(window, { BRAND, serif, sans, mono, Ph, PImg, LogoMark, Wordmark, Eyebrow, CartAPI, CART_EVT });
