// src/home.jsx — Home screen.
// Novel moment: "Ask Opa" — an AI command bar with suggested prompts that compose a mini-cart across stores.
// Also: hero store tiles, quick-start picks, trending, and a bodega-aware "what's open right now" rail.

// AskResultCard — cross-store results grouped by store. Each cluster renders its
// store chip (primary gets a "Best match" badge) followed by product tiles that
// each label which store they came from.
function AskResultCard({ answer, onNav, addToCart, onAddAll, onClose }) {
  if (!answer) return null;
  // Normalize legacy {store, items} shape into {clusters: [...]}.
  const clusters = answer.clusters || [{ store: answer.store, items: answer.items, primary: true }];
  const flat = clusters.flatMap(c => c.items.map(id => ({ storeId: c.store.id, productId: id })));
  const totalCount = flat.length;
  const { reason } = answer;

  return (
    <div className="fade-in" style={{
      marginTop: 20,
      background: "var(--surface)", border: "1px solid var(--line)",
      borderRadius: "var(--radius-lg)", padding: "16px 16px 18px",
      boxShadow: "var(--shadow-sm)",
    }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16, marginBottom: 4 }}>
        <div style={{ display: "inline-flex", alignItems: "center", gap: 8, fontSize: 11,
                     fontWeight: 600, color: "var(--accent)", letterSpacing: "0.08em", textTransform: "uppercase" }}>
          <Icons.Sparkle size={12} stroke={2.2} /> Opa picked · {totalCount} items
          {clusters.length > 1 && (
            <span style={{ color: "var(--ink-3)", letterSpacing: "0.02em", textTransform: "none", fontWeight: 500, fontSize: 12 }}>
              · {clusters.length} stores
            </span>
          )}
        </div>
        <div style={{ display: "inline-flex", alignItems: "center", gap: 8 }}>
          <button className="btn-reset" onClick={() => onAddAll?.(clusters)}
            style={{
              height: 32, padding: "0 14px", borderRadius: 999,
              background: "var(--accent)", color: "#fff",
              fontWeight: 600, fontSize: 12.5,
              display: "inline-flex", alignItems: "center", gap: 6,
            }}>
            <Icons.Plus size={13} stroke={2.4} />
            Add all {totalCount}
          </button>
          <button className="btn-reset" onClick={onClose}
            aria-label="Hide Opa's picks"
            title="Hide"
            style={{
              height: 28, width: 28, borderRadius: 999,
              background: "var(--surface-2)", border: "1px solid var(--line)",
              color: "var(--ink-3)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
            }}>
            <Icons.Close size={13} stroke={2} />
          </button>
        </div>
      </div>
      <p style={{ margin: "6px 0 14px", fontSize: 13.5, color: "var(--ink-2)", lineHeight: 1.5 }}>{reason}</p>

      <div className="no-scrollbar" style={{
        display: "flex", gap: 8, overflowX: "auto", overflowY: "hidden",
        margin: "0 -16px", padding: "4px 16px 8px 16px",
        scrollSnapType: "x mandatory",
        WebkitMaskImage: "linear-gradient(90deg, #000 0, #000 calc(100% - 32px), transparent 100%)",
        maskImage: "linear-gradient(90deg, #000 0, #000 calc(100% - 32px), transparent 100%)",
      }}>
        {clusters.map((cluster, ci) => {
          const products = cluster.items.map(id => PRODUCT_INDEX[id]).filter(Boolean);
          return (
            <React.Fragment key={cluster.store.id}>
              {/* Store chip — primary gets a "Best match" badge */}
              <button className="btn-reset"
                onClick={() => onNav({ screen: "store", storeId: cluster.store.id })}
                style={{
                  flexShrink: 0, width: 188, scrollSnapAlign: "start",
                  display: "flex", flexDirection: "column", gap: 0,
                  background: cluster.primary ? "var(--navy-fill)" : "var(--surface-2)",
                  color: cluster.primary ? "#fff" : "var(--ink)",
                  borderRadius: 14, overflow: "hidden", textAlign: "left",
                  border: cluster.primary ? "1px solid var(--navy)" : "1px solid var(--line)",
                  position: "relative",
                }}>
                <div style={{ position: "relative" }}>
                  <Ph label={cluster.store.hero} aspect="1/1" img={storeImage(cluster.store)} seed={cluster.store.id} radius={0} />
                  {cluster.primary && (
                    <div style={{ position: "absolute", top: 8, left: 8,
                                  display: "inline-flex", alignItems: "center", gap: 5,
                                  padding: "4px 9px", borderRadius: 999,
                                  background: "var(--accent)", color: "#fff",
                                  fontSize: 10, fontWeight: 600, letterSpacing: "0.06em", textTransform: "uppercase" }}>
                      <Icons.Sparkle size={10} stroke={2.4} /> Best match
                    </div>
                  )}
                </div>
                <div style={{ padding: "10px 12px 12px", display: "flex", flexDirection: "column", gap: 2 }}>
                  <div style={{ fontSize: 10, opacity: cluster.primary ? 0.7 : 0.55, letterSpacing: "0.08em", textTransform: "uppercase",
                                fontFamily: '"JetBrains Mono", monospace' }}>
                    {ci === 0 ? "From" : "Also from"}
                  </div>
                  <div style={{ fontSize: 13.5, fontWeight: 600, lineHeight: 1.25,
                                display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical", overflow: "hidden" }}>
                    {cluster.store.name}
                  </div>
                  <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginTop: 8 }}>
                    <span style={{ fontSize: 11, opacity: 0.75, display: "inline-flex", alignItems: "center", gap: 4 }}>
                      <Icons.Clock size={11} stroke={2} /> {cluster.store.eta}
                    </span>
                    <span aria-label="Visit store"
                      style={{ width: 28, height: 28, borderRadius: 999,
                               background: cluster.primary ? "rgba(255,255,255,0.18)" : "var(--navy-tint)",
                               color: cluster.primary ? "#fff" : "var(--navy)",
                               display: "inline-flex", alignItems: "center", justifyContent: "center" }}>
                      <Icons.ArrowRight size={13} stroke={2.2} />
                    </span>
                  </div>
                </div>
              </button>

              {/* Product tiles for this cluster */}
              {products.map(p => (
                <div key={p.id} style={{
                  flexShrink: 0, width: 172, scrollSnapAlign: "start",
                  background: "var(--surface-2)", border: "1px solid var(--line)",
                  borderRadius: 14, overflow: "hidden", display: "flex", flexDirection: "column",
                }}>
                  <button className="btn-reset" onClick={() => onNav({ screen: "product", storeId: cluster.store.id, productId: p.id })}
                    style={{ display: "block", position: "relative" }}>
                    <Ph label={p.name.split(" ")[0]} aspect="1/1" img={productImage(p)} seed={p.id} radius={0} />
                  </button>
                  <div style={{ padding: "10px 12px 10px", flex: 1, display: "flex", flexDirection: "column", gap: 2 }}>
                    <div style={{ fontSize: 10, color: "var(--ink-3)", letterSpacing: "0.04em",
                                  fontFamily: '"JetBrains Mono", monospace', textTransform: "uppercase",
                                  whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>
                      {cluster.store.name.split(" ")[0]}
                    </div>
                    <div style={{ fontSize: 12.5, fontWeight: 500, color: "var(--ink)", lineHeight: 1.25,
                                  display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical", overflow: "hidden",
                                  minHeight: 32 }}>{p.name}</div>
                    <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginTop: 6 }}>
                      <span className="num" style={{ fontSize: 13, fontWeight: 600, color: "var(--ink)" }}>{money(p.price)}</span>
                      <button className="btn-reset" aria-label={`Add ${p.name}`}
                        onClick={() => addToCart(cluster.store.id, p.id, 1)}
                        style={{ width: 30, height: 30, borderRadius: 999,
                                 background: "var(--navy-fill)", color: "#fff",
                                 display: "inline-flex", alignItems: "center", justifyContent: "center",
                                 boxShadow: "var(--shadow-sm)" }}>
                        <Icons.Plus size={16} stroke={2.2} />
                      </button>
                    </div>
                  </div>
                </div>
              ))}
            </React.Fragment>
          );
        })}
      </div>
    </div>
  );
}

function AskOpa({ onNav, onAddMany, addToCart, answer, setAnswer }) {
  const [q, setQ] = React.useState("");
  const [state, setState] = React.useState("idle"); // idle | thinking | answer
  const inputRef = React.useRef(null);

  const suggestions = [
    { label: "Hangover stuff under $20", q: "i need hangover stuff under $20 from a place nearby" },
    { label: "Something for pasta night", q: "pasta night for 4, under $40, from one store" },
    { label: "Game-day snacks + a 12-pack", q: "game-day snacks plus a 12-pack of modelo" },
    { label: "Tools to hang a picture", q: "what do i need to hang 3 frames on drywall" },
  ];

  const respond = async (query) => {
    setQ(query);
    setState("thinking");
    // Mocked response — in a real build this would route to claude.complete with a tool that returns SKU ids.
    // Simulate latency.
    await new Promise(r => setTimeout(r, 900));
    const storeOf = (id) => STORES.find(s => s.id === id);
    let picks;
    if (/hangover|tired|headache/i.test(query)) {
      picks = { clusters: [
                  { store: storeOf("kalymnos"), primary: true,
                    items: ["drk-gatorade", "deli-eggcheese", "drk-poland", "drk-ouj", "snk-peanuts", "cof-coldbrew"] },
                  { store: storeOf("liu"),
                    items: ["hh-advil", "drk-celsius"] }
                ],
                reason: "Advil + Gatorade + a Bacon-Egg-Cheese for the reset, then water, OJ, a cold brew, and shells to break. Liu's is the only late-night nearby that stocks Celsius." };
    } else if (/pasta/i.test(query)) {
      picks = { clusters: [
                  { store: storeOf("kalymnos"), primary: true,
                    items: ["pan-pasta", "pan-olive", "pan-butter", "prd-tomato", "deli-italian", "snk-oreo"] },
                  { store: storeOf("fig"),
                    items: ["bw-meiomi", "drk-topo"] }
                ],
                reason: "Rao's jar, good olive oil, Kerrygold, vine tomatoes, a backup hero, and Oreos for after. Fig & Thistle pulls the Pinot because their wall is better." };
    } else if (/game|super bowl|modelo|beer/i.test(query)) {
      picks = { clusters: [
                  { store: storeOf("kalymnos"), primary: true,
                    items: ["bw-modelo", "snk-doritos", "snk-flamin", "snk-peanuts", "snk-popchips", "drk-topo", "deli-custom"] },
                  { store: storeOf("fig"),
                    items: ["bw-whiteclaw"] }
                ],
                reason: "Modelo 12-pack, four bags that matter, sparkling water, and a build-your-own hero for halftime. White Claw plan B from Fig & Thistle." };
    } else if (/hang|picture|frame|drywall|tool|hammer/i.test(query)) {
      picks = { clusters: [
                  { store: storeOf("arbor"), primary: true,
                    items: ["hw-hammer", "hw-hooks", "hw-anchors", "hw-level", "hw-pencil"] },
                  { store: storeOf("kalymnos"),
                    items: ["hw-tape", "hh-lightbulb"] }
                ],
                reason: "Arbor carries the hammer, picture hooks, drywall anchors, level, and pencil. Kalymnos is the corner-shop grab for painter's tape and a fresh bulb." };
    } else if (/dinner/i.test(query)) {
      picks = { clusters: [
                  { store: storeOf("kalymnos"), primary: true,
                    items: ["pan-pasta", "pan-olive", "prd-tomato", "pan-butter", "bw-meiomi", "snk-oreo"] }
                ],
                reason: "Marinara, olive oil, vine tomatoes, butter, a decent Pinot, and cookies." };
    } else {
      picks = { clusters: [
                  { store: storeOf("kalymnos"), primary: true,
                    items: ["snk-popchips", "snk-oreo", "bw-meiomi", "drk-topo", "snk-peanuts", "cof-coldbrew", "drk-celsius"] }
                ],
                reason: "Movie-night default — Kalymnos carries all of it." };
    }
    setAnswer(picks);
    setState("answer");
  };

  return (
    <section style={{
      background: "var(--navy-fill)", color: "#fff",
      borderRadius: "var(--radius-xl)",
      padding: "36px 36px 32px",
      position: "relative", overflow: "hidden",
      boxShadow: "var(--shadow-md)",
    }}>
      {/* decorative — stronger warm accent in dark mode */}
      <div aria-hidden style={{
        position: "absolute", inset: 0,
        background: `
          radial-gradient(900px 420px at 85% -10%, oklch(from var(--accent) l c h / 0.32), transparent 60%),
          radial-gradient(700px 340px at 8% 120%, oklch(from var(--accent) l c h / 0.28), transparent 65%),
          radial-gradient(600px 300px at 50% 50%, oklch(from var(--navy) calc(l + 0.06) c h / 0.3), transparent 70%)
        `,
        pointerEvents: "none",
      }} />
      {/* hairline warm sheen along the top edge */}
      <div aria-hidden style={{
        position: "absolute", inset: "0 0 auto 0", height: 1,
        background: "linear-gradient(90deg, transparent, oklch(from var(--accent) l c h / 0.6), transparent)",
        pointerEvents: "none",
      }} />
      <div style={{ position: "relative", display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 24, flexWrap: "wrap" }}>
        <div style={{ maxWidth: 520 }}>
          <div style={{ display: "inline-flex", alignItems: "center", gap: 8,
                         padding: "5px 12px", borderRadius: 999,
                         background: "rgba(255,255,255,0.1)",
                         fontSize: 11, fontWeight: 500, letterSpacing: "0.06em", textTransform: "uppercase",
                         marginBottom: 16 }}>
            <Icons.Sparkle size={13} stroke={2} style={{ color: "var(--accent)" }} /> Ask Opa · new
          </div>
          <h1 className="serif" style={{ fontSize: 42, lineHeight: 1.05, margin: 0, letterSpacing: "-0.02em" }}>
            Tell us what you need.<br />
            <span style={{ fontStyle: "italic", color: "oklch(from #fff l c h / 0.7)" }}>We'll read the aisles.</span>
          </h1>
          <p style={{ marginTop: 14, fontSize: 15, color: "oklch(from #fff l c h / 0.72)", maxWidth: 460, lineHeight: 1.5 }}>
            3,500 local stores. One sentence. We'll build the cart — you just check it.
          </p>
        </div>

        <div style={{ flex: "1 1 440px", minWidth: 320 }}>
          <div style={{
            background: "rgba(255,255,255,0.07)",
            border: "1px solid rgba(255,255,255,0.14)",
            borderRadius: 16, padding: 4,
            display: "flex", alignItems: "center", gap: 4,
          }}>
            <div style={{ padding: "0 6px 0 14px", color: "var(--accent)", display: "inline-flex" }}>
              <Icons.Sparkle size={18} stroke={2} />
            </div>
            <input ref={inputRef} className="ask-opa-input"
              value={q} onChange={(e) => setQ(e.target.value)}
              onKeyDown={(e) => { if (e.key === "Enter" && q.trim()) respond(q); }}
              placeholder="a hangover kit · pasta night for 4 · supplies for the new puppy…"
              style={{
                flex: 1, height: 48,
                background: "transparent", border: 0, outline: 0,
                color: "#fff", fontSize: 15, fontFamily: "inherit",
              }} />
            <button className="btn-reset" onClick={() => q.trim() && respond(q)}
              style={{ height: 44, padding: "0 18px", borderRadius: 12,
                       background: "var(--accent)", color: "#fff", fontWeight: 600, fontSize: 14,
                       display: "inline-flex", alignItems: "center", gap: 6 }}>
              Ask
              <Icons.Chevron size={14} stroke={2.2} />
            </button>
          </div>

          <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginTop: 14 }}>
            {suggestions.map(s => (
              <button key={s.label} className="btn-reset" onClick={() => respond(s.q)}
                style={{
                  padding: "7px 13px", borderRadius: 999,
                  background: "rgba(255,255,255,0.07)", border: "1px solid rgba(255,255,255,0.16)",
                  color: "#fff", fontSize: 12.5, fontWeight: 500,
                }}>{s.label}</button>
            ))}
          </div>

          {state === "thinking" && (
            <div className="fade-in" style={{
              marginTop: 14, padding: "12px 16px",
              background: "rgba(255,255,255,0.08)", border: "1px solid rgba(255,255,255,0.14)",
              borderRadius: 12, color: "#fff",
              display: "flex", alignItems: "center", gap: 10, fontSize: 13.5,
            }}>
              <span style={{ display: "inline-flex", gap: 3 }}>
                <span style={{ width: 6, height: 6, borderRadius: 99, background: "var(--accent)", animation: "pulseDot 1.2s ease-in-out infinite" }} />
                <span style={{ width: 6, height: 6, borderRadius: 99, background: "var(--accent)", animation: "pulseDot 1.2s ease-in-out infinite .15s" }} />
                <span style={{ width: 6, height: 6, borderRadius: 99, background: "var(--accent)", animation: "pulseDot 1.2s ease-in-out infinite .3s" }} />
              </span>
              Reading aisles at nearby stores…
            </div>
          )}
        </div>
      </div>
    </section>
  );
}

function StoreCard({ store, onOpen, big }) {
  return (
    <button className="btn-reset" onClick={onOpen}
      style={{
        textAlign: "left", display: "flex", flexDirection: "column", gap: 12,
        background: "var(--surface)", border: "1px solid var(--line)",
        borderRadius: "var(--radius-lg)", padding: 12,
        transition: "transform 0.12s, box-shadow 0.12s",
        height: "100%",
      }}
      onMouseEnter={(e) => { e.currentTarget.style.transform = "translateY(-2px)"; e.currentTarget.style.boxShadow = "var(--shadow-md)"; }}
      onMouseLeave={(e) => { e.currentTarget.style.transform = "none"; e.currentTarget.style.boxShadow = "none"; }}>
      <Ph label={store.hero} aspect={big ? "16/9" : "4/3"} radius="var(--radius)" img={storeImage(store)} seed={store.id} />
      <div style={{ padding: "2px 4px 4px", display: "flex", flexDirection: "column", gap: 6, flex: 1 }}>
        {/* Title on its own line — no inline rating, so long names don't wrap to 3 lines. */}
        <div style={{ fontSize: 15, fontWeight: 600, color: "var(--ink)", lineHeight: 1.25,
                      display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical",
                      overflow: "hidden" }}>
          {store.name}
        </div>
        {/* Rating + tagline row */}
        <div style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 12.5, color: "var(--ink-3)",
                      flexWrap: "wrap", rowGap: 2 }}>
          {store.rating && <Rating value={store.rating} reviews={store.reviews} size={12} />}
          {store.rating && store.tagline && <span style={{ color: "var(--ink-4)" }}>·</span>}
          {store.tagline && (
            <span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", minWidth: 0, flex: 1 }}>
              {store.tagline}
            </span>
          )}
        </div>
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6, marginTop: 4 }}>
          <Pill tone="navy" icon={<Icons.Clock size={11} stroke={2} />}>{store.eta}</Pill>
          <Pill icon={<Icons.Pin size={11} stroke={2} />}>{store.distance}</Pill>
          {store.tags && store.tags.slice(0, 2).map(t => <Pill key={t} tone="ghost">{t}</Pill>)}
        </div>
      </div>
    </button>
  );
}

// Mocked order-history + saved lists, distinct visual shape from product grids.
// Two tabs in one strip: "Buy again" is timestamped item tiles; "Your usuals"
// shows multi-thumbnail list cards with a rebuild-cart CTA.
const BUY_AGAIN = [
  { id: "cof-coldbrew",  storeId: "kalymnos", last: "Tue · 2 days ago" },
  { id: "deli-italian",  storeId: "kalymnos", last: "Mon · 3 days ago" },
  { id: "drk-topo",      storeId: "kalymnos", last: "Fri · last week" },
  { id: "snk-oreo",      storeId: "kalymnos", last: "Thu · last week" },
  { id: "hh-advil",      storeId: "liu",       last: "Sun · 5 days ago" },
  { id: "bw-modelo",     storeId: "kalymnos", last: "Sat · last week" },
  { id: "pan-pasta",     storeId: "kalymnos", last: "Wed · last week" },
  { id: "drk-celsius",   storeId: "liu",       last: "Mon · last week" },
];
const USUALS = [
  { id: "sunday-am", label: "Sunday breakfast", subtitle: "Opa keeps this list warm.",
    items: ["deli-eggcheese", "cof-latte", "drk-ouj", "snk-popchips"], storeId: "kalymnos" },
  { id: "pantry-reup", label: "Pantry re-up", subtitle: "Every other Tuesday, like clockwork.",
    items: ["pan-pasta", "pan-olive", "pan-butter", "hh-tp", "hh-ptowel", "hh-tide"], storeId: "kalymnos" },
  { id: "wed-lunch", label: "Wednesday lunch", subtitle: "Italian combo, chips, topo.",
    items: ["deli-italian", "snk-flamin", "drk-topo"], storeId: "kalymnos" },
];

function PantryStrip({ onNav, addToCart, addMany, isMobile }) {
  const [tab, setTab] = React.useState("again");

  return (
    <section style={{ marginTop: "var(--section-gap)" }}>
      <div style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between",
                    gap: 16, flexWrap: "wrap", marginBottom: 14 }}>
        <div>
          <div className="uppercase-mono">Your pantry</div>
          <h2 className="serif" style={{ fontSize: 28, margin: "2px 0 0", letterSpacing: "-0.01em" }}>
            Pick up where you left off.
          </h2>
        </div>
        <div role="tablist" aria-label="Pantry view"
          style={{ display: "inline-flex", padding: 3, borderRadius: 999,
                   background: "var(--surface-2)", border: "1px solid var(--line)" }}>
          {[
            { id: "again",  label: `Buy again · ${BUY_AGAIN.length}` },
            { id: "usuals", label: `Your usuals · ${USUALS.length}` },
          ].map(t => (
            <button key={t.id} role="tab" aria-selected={tab === t.id}
              onClick={() => setTab(t.id)}
              className="btn-reset"
              style={{
                padding: "8px 16px", borderRadius: 999, fontSize: 12.5, fontWeight: 600,
                background: tab === t.id ? "var(--navy-fill)" : "transparent",
                color: tab === t.id ? "var(--navy-fill-ink, #fff)" : "var(--ink-2)",
              }}>
              {t.label}
            </button>
          ))}
        </div>
      </div>

      {tab === "again" && (
        <div className="no-scrollbar fade-in" style={{
          display: "flex", gap: 10, overflowX: "auto", overflowY: "hidden",
          margin: "0 -4px", padding: "2px 4px 4px", scrollSnapType: "x mandatory",
        }}>
          {BUY_AGAIN.map(b => {
            const p = PRODUCT_INDEX[b.id]; if (!p) return null;
            const store = STORES.find(s => s.id === b.storeId);
            return (
              <div key={b.id} style={{
                flexShrink: 0, width: 220, scrollSnapAlign: "start",
                background: "var(--surface)", border: "1px solid var(--line)",
                borderRadius: 14, padding: 10, display: "flex", gap: 12, alignItems: "center",
              }}>
                <button className="btn-reset"
                  onClick={() => onNav({ screen: "product", storeId: b.storeId, productId: p.id })}
                  style={{ flexShrink: 0 }}>
                  <Ph label={p.name.split(" ")[0]} aspect="1/1" img={productImage(p)} seed={p.id}
                      style={{ width: 62, height: 62, borderRadius: 10 }} />
                </button>
                <div style={{ flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: 2 }}>
                  <div style={{ fontSize: 9.5, letterSpacing: "0.05em", textTransform: "uppercase",
                                color: "var(--ink-3)", fontFamily: '"JetBrains Mono", monospace',
                                whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>
                    {b.last}
                  </div>
                  <div style={{ fontSize: 13, fontWeight: 600, color: "var(--ink)", lineHeight: 1.2,
                                overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                    {p.name}
                  </div>
                  <div style={{ fontSize: 11.5, color: "var(--ink-3)",
                                whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>
                    {store?.name} · <span className="num" style={{ color: "var(--ink-2)", fontWeight: 600 }}>{money(p.price)}</span>
                  </div>
                </div>
                <button className="btn-reset" aria-label={`Buy ${p.name} again`}
                  onClick={() => addToCart(b.storeId, p.id, 1)}
                  style={{ flexShrink: 0, width: 34, height: 34, borderRadius: 999,
                           background: "var(--navy-fill)", color: "#fff",
                           display: "inline-flex", alignItems: "center", justifyContent: "center",
                           boxShadow: "var(--shadow-sm)" }}>
                  <Icons.Plus size={15} stroke={2.4} />
                </button>
              </div>
            );
          })}
        </div>
      )}

      {tab === "usuals" && (
        <div className="fade-in" style={{
          display: "grid", gap: 12,
          gridTemplateColumns: `repeat(${isMobile ? 1 : 3}, 1fr)`,
        }}>
          {USUALS.map(u => {
            const items = u.items.map(id => PRODUCT_INDEX[id]).filter(Boolean);
            const total = items.reduce((s, p) => s + p.price, 0);
            return (
              <div key={u.id} style={{
                background: "var(--surface)", border: "1px solid var(--line)",
                borderRadius: 16, padding: 14, display: "flex", flexDirection: "column", gap: 12,
                boxShadow: "var(--shadow-sm)",
              }}>
                {/* Mini collage — 4 up */}
                <div style={{
                  display: "grid", gridTemplateColumns: "1fr 1fr", gap: 4,
                  borderRadius: 10, overflow: "hidden",
                }}>
                  {items.slice(0, 4).map((p, i) => (
                    <Ph key={p.id + i} label={p.name.split(" ")[0]} aspect="4/3"
                      img={productImage(p)} seed={p.id} radius={0}
                      style={{ minHeight: 72 }} />
                  ))}
                </div>
                <div>
                  <div style={{ fontSize: 15, fontWeight: 600, color: "var(--ink)" }}>{u.label}</div>
                  <div style={{ fontSize: 12.5, color: "var(--ink-3)", marginTop: 2 }}>{u.subtitle}</div>
                </div>
                <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginTop: "auto" }}>
                  <span style={{ fontSize: 12, color: "var(--ink-2)" }}>
                    {items.length} items · <span className="num" style={{ fontWeight: 600, color: "var(--ink)" }}>~{money(total)}</span>
                  </span>
                  <button className="btn-reset"
                    onClick={() => addMany(u.storeId, u.items)}
                    style={{
                      height: 34, padding: "0 14px", borderRadius: 999,
                      background: "var(--navy-fill)", color: "#fff",
                      fontWeight: 600, fontSize: 12.5,
                      display: "inline-flex", alignItems: "center", gap: 6,
                    }}>
                    <Icons.Plus size={13} stroke={2.4} />
                    Rebuild cart
                  </button>
                </div>
              </div>
            );
          })}
        </div>
      )}
    </section>
  );
}

// Time-aware band — surfaces a contextual "what's open late / breakfast soon / etc."
// Currently hard-mocked to late-night for the demo so it always renders the same
// moment regardless of actual clock.
function LateNightBand({ onNav }) {
  const late = STORES.filter(s => /Late-night|24hr/i.test((s.tags || []).join(" ") + " " + (s.tagline || s.hours || "")));
  const list = late.length ? late : STORES.slice(0, 2);
  return (
    <div style={{
      marginTop: 18, padding: "14px 18px",
      background: "linear-gradient(135deg, oklch(from var(--navy) calc(l + 0.08) c h / 0.18), oklch(from var(--accent) l c h / 0.14))",
      border: "1px solid oklch(from var(--navy) calc(l + 0.12) c h / 0.2)",
      borderRadius: 14,
      display: "flex", alignItems: "center", gap: 14, flexWrap: "wrap",
    }}>
      <span style={{
        width: 34, height: 34, borderRadius: 999, flexShrink: 0,
        background: "oklch(from var(--navy) calc(l + 0.1) c h / 0.28)",
        display: "grid", placeItems: "center", color: "var(--ink)",
      }}>
        <Icons.Moon size={16} stroke={1.8} />
      </span>
      <div style={{ flex: 1, minWidth: 220, fontSize: 13.5, color: "var(--ink)" }}>
        <span style={{ fontWeight: 600 }}>It's 11:34 PM.</span>{" "}
        <span style={{ color: "var(--ink-2)" }}>
          Two stores near you are still open — {list.map(s => s.name).join(" and ")} stays on until close.
        </span>
      </div>
      <div style={{ display: "inline-flex", gap: 6 }}>
        {list.slice(0, 2).map(s => (
          <button key={s.id} className="btn-reset"
            onClick={() => onNav({ screen: "store", storeId: s.id })}
            style={{
              padding: "7px 13px", borderRadius: 999,
              background: "var(--surface)", border: "1px solid var(--line)",
              fontSize: 12.5, fontWeight: 500, color: "var(--ink)",
              display: "inline-flex", alignItems: "center", gap: 6,
            }}>
            <Icons.Clock size={12} stroke={1.8} style={{ color: "var(--ok)" }} />
            {s.name.split(" ")[0]}
          </button>
        ))}
      </div>
    </div>
  );
}

function Home({ onNav, cart, addToCart, addMany }) {
  const isMobile = useMedia("(max-width: 720px)");
  const isWide = useMedia("(min-width: 1200px)");
  const nearby = STORES;
  const hero = STORES[0];
  const [answer, setAnswer] = React.useState(null);

  return (
    <div style={{ maxWidth: 1280, margin: "0 auto", padding: isMobile ? "14px 16px 100px" : "28px 28px 60px" }}>

      <PickupBanner onNav={onNav} />

      <AskOpa onNav={onNav} addToCart={addToCart} onAddMany={addMany} answer={answer} setAnswer={setAnswer} />

      {answer && <AskResultCard answer={answer} onNav={onNav} addToCart={addToCart}
        onAddAll={(clusters) => clusters.forEach(c => addMany(c.store.id, c.items))}
        onClose={() => setAnswer(null)} />}

      <LateNightBand onNav={onNav} />

      <PantryStrip onNav={onNav} addToCart={addToCart} addMany={addMany} isMobile={isMobile} />

      {/* Quick categories strip */}
      <div style={{ marginTop: "var(--section-gap)" }}>
        <SectionHeader eyebrow="Shop by" title="What are you after?" />
        <div style={{ display: "grid",
          gridTemplateColumns: isMobile ? "repeat(4, 1fr)" : "repeat(8, 1fr)", gap: "var(--grid-gap)" }}>
          {[
            { id: "deli", label: "Deli", icon: "Baguette", tint: "oklch(93% 0.06 80)" },
            { id: "coffee", label: "Coffee", icon: "Coffee", tint: "oklch(92% 0.04 60)" },
            { id: "drinks", label: "Drinks", icon: "Snow", tint: "oklch(92% 0.05 210)" },
            { id: "beer", label: "Beer & Wine", icon: "Beer", tint: "oklch(92% 0.07 100)" },
            { id: "snacks", label: "Snacks", icon: "Cookie", tint: "oklch(92% 0.06 40)" },
            { id: "produce", label: "Produce", icon: "Apple", tint: "oklch(93% 0.08 140)" },
            { id: "pantry", label: "Pantry", icon: "Box", tint: "oklch(93% 0.04 90)" },
            { id: "household", label: "Household", icon: "Pill", tint: "oklch(93% 0.03 280)" },
          ].slice(0, isMobile ? 8 : 8).map(c => {
            const Icon = Icons[c.icon];
            return (
              <button key={c.id} className="btn-reset"
                onClick={() => onNav({ screen: "store", storeId: hero.id, category: c.id })}
                style={{
                  display: "flex", flexDirection: "column", alignItems: "center", gap: 10,
                  padding: "16px 8px", borderRadius: "var(--radius)",
                  background: "var(--surface)", border: "1px solid var(--line)",
                  transition: "transform 0.12s",
                }}
                onMouseEnter={(e) => { e.currentTarget.style.transform = "translateY(-2px)"; }}
                onMouseLeave={(e) => { e.currentTarget.style.transform = "none"; }}>
                <div className="cat-tint" style={{ width: 44, height: 44, borderRadius: "50%",
                              background: c.tint, display: "grid", placeItems: "center",
                              color: "var(--navy)" }}>
                  <Icon size={20} stroke={1.6} />
                </div>
                <span style={{ fontSize: 12.5, fontWeight: 500, color: "var(--ink)" }}>{c.label}</span>
              </button>
            );
          })}
        </div>
      </div>

      {/* Stores open right now — horizontal slider on both mobile and desktop */}
      <StoresOpenSlider stores={nearby} isMobile={isMobile}
        onOpen={(s) => onNav({ screen: "store", storeId: s.id })} />

      {/* Curated bundles — bodega-style */}
      <div style={{ marginTop: "var(--section-gap)" }}>
        <SectionHeader eyebrow="Picked for you" title="Bundles from the block"
          action={<span style={{ fontSize: 12, color: "var(--ink-4)" }}>Editor-curated, one tap to cart.</span>} />
        <div style={{ display: "grid",
          gridTemplateColumns: isMobile ? "1fr" : "repeat(3, 1fr)", gap: "var(--grid-gap)" }}>
          {BUNDLES.map((b, idx) => {
            const items = b.items.map(id => PRODUCT_INDEX[id]).filter(Boolean);
            const total = items.reduce((s,p)=>s+p.price,0);
            // Each bundle gets a different visual character
            const themes = [
              { tint: "oklch(94% 0.06 80)",  ink: "oklch(35% 0.10 60)",  pat: "wave" },
              { tint: "oklch(93% 0.05 220)", ink: "oklch(35% 0.12 240)", pat: "grid" },
              { tint: "oklch(94% 0.07 130)", ink: "oklch(38% 0.10 145)", pat: "dots" },
            ];
            const th = themes[idx % themes.length];
            return (
              <div key={b.id} style={{
                background: "var(--surface)", border: "1px solid var(--line)",
                borderRadius: "var(--radius-lg)", overflow: "hidden",
                display: "flex", flexDirection: "column",
              }}>
                {/* Stylized header band */}
                <div style={{
                  position: "relative", height: 132, overflow: "hidden",
                  background: th.tint, color: th.ink,
                }}>
                  <BundleBackdrop pattern={th.pat} color={th.ink} />
                  <div style={{ position: "absolute", inset: 0, padding: "16px 18px",
                                display: "flex", flexDirection: "column", justifyContent: "space-between" }}>
                    <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                      <span className="uppercase-mono" style={{ fontSize: 10, color: th.ink, opacity: 0.75 }}>
                        Bundle · {items.length} items
                      </span>
                    </div>
                    <div className="serif" style={{ fontSize: 22, lineHeight: 1.1, letterSpacing: "-0.01em",
                                                     fontWeight: 500, textWrap: "balance" }}>
                      {b.label}
                    </div>
                  </div>
                </div>
                {/* Body */}
                <div style={{ padding: 16, display: "flex", flexDirection: "column", gap: 12, flex: 1 }}>
                  <div style={{ fontSize: 13, color: "var(--ink-3)", lineHeight: 1.45 }}>{b.desc}</div>
                  {/* Item thumbnails */}
                  <div style={{ display: "flex", gap: 6 }}>
                    {items.map(p => (
                      <Ph key={p.id} label={p.name.split(" ")[0]} aspect="1/1" radius={10}
                        img={productImage(p)} seed={p.id}
                        style={{ flex: 1, fontSize: 9 }} />
                    ))}
                  </div>
                  {/* Item names list (dense, mono) */}
                  <ul style={{ margin: 0, padding: 0, listStyle: "none",
                               display: "flex", flexDirection: "column", gap: 4 }}>
                    {items.map(p => (
                      <li key={p.id} style={{ display: "flex", alignItems: "baseline",
                                              justifyContent: "space-between", gap: 8,
                                              fontSize: 12, color: "var(--ink-3)",
                                              borderBottom: "1px dashed var(--line)", paddingBottom: 4 }}>
                        <span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{p.name}</span>
                        <span className="num" style={{ flexShrink: 0, color: "var(--ink-4)" }}>{money(p.price)}</span>
                      </li>
                    ))}
                  </ul>
                  <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between",
                                marginTop: "auto", paddingTop: 4 }}>
                    <div style={{ display: "flex", flexDirection: "column" }}>
                      <span className="num" style={{ fontSize: 18, fontWeight: 600, color: "var(--ink)" }}>{money(total)}</span>
                      <span style={{ fontSize: 11, color: "var(--ink-4)" }}>before delivery</span>
                    </div>
                    <Btn size="sm" variant="primary" icon={<Icons.Plus size={14} stroke={2} />}
                      onClick={() => addMany("kalymnos", b.items)}>Add bundle</Btn>
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      </div>

      {/* Two CTA cards — eco / community */}
      <div style={{ marginTop: "var(--section-gap)", display: "grid",
        gridTemplateColumns: isMobile ? "1fr" : "1fr 1fr", gap: "var(--grid-gap)" }}>
        <CtaCard
          tone="green"
          eyebrow="Bundle to save plastic"
          title="Group your run, halve the bags."
          body="Combine items from up to 3 nearby stores into one rider. We re-use one tote and credit you $1.50 per shared trip."
          stat={{ k: "3.2k", l: "bags saved this month" }}
          ctaLabel="How it works"
          icon="Leaf"
        />
        <CtaCard
          tone="navy"
          eyebrow="Round up at checkout"
          title="Stock the LES food pantry."
          body="Add a quarter (or any amount) to your order. Hits the LES Catholic Worker shelf the same day your groceries arrive."
          stat={{ k: "$8,420", l: "contributed this year" }}
          ctaLabel="Turn it on"
          icon="Heart"
        />
      </div>

      {/* Most shopped near you — horizontal slider, breathable */}
      <MostShoppedSlider
        products={PRODUCTS.filter(p => p.trending).slice(0, 12)}
        isMobile={isMobile}
        cart={cart}
        onOpen={(p) => onNav({ screen: "product", storeId: "kalymnos", productId: p.id })}
        addToCart={addToCart}
      />

      {/* Worth your attention — promoted long-form/video carousel */}
      <WorthYourAttention isMobile={isMobile} onNav={onNav} />

      {/* Warm end-of-page moment so the scroll doesn't cliff-dive into nothing. */}
      <HomeFarewell onNav={onNav} isMobile={isMobile} />
    </div>
  );
}

function MiniProductCard({ p, onOpen, qty, onAdd, onRemove, pattern = "morph", storeName }) {
  return (
    <div style={{
      background: "var(--surface)", border: "1px solid var(--line)",
      borderRadius: "var(--radius-lg)", padding: 10,
      position: "relative",
    }}>
      <button className="btn-reset" onClick={onOpen} style={{ display: "block", width: "100%" }}>
        <Ph label={p.name.split(" ").slice(0,2).join(" ")} aspect="1/1" radius={10} img={productImage(p)} seed={p.id} />
      </button>
      <div style={{ padding: "10px 4px 4px" }}>
        {storeName && (
          <div style={{ fontSize: 10, letterSpacing: "0.05em", textTransform: "uppercase",
                        color: "var(--ink-3)", fontFamily: '"JetBrains Mono", monospace',
                        overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap",
                        marginBottom: 3 }}>
            {storeName}
          </div>
        )}
        <div style={{ fontSize: 13, fontWeight: 500, color: "var(--ink)", lineHeight: 1.25,
                      display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical",
                      overflow: "hidden", minHeight: 32 }}>{p.name}</div>
        <div style={{ fontSize: 11, color: "var(--ink-4)", marginTop: 2 }}>{p.unit}</div>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginTop: 8 }}>
          <span className="num" style={{ fontSize: 14, fontWeight: 600, color: "var(--ink)" }}>{money(p.price)}</span>
          <AddStepper qty={qty} onAdd={onAdd} onRemove={onRemove} size="sm" pattern={pattern} />
        </div>
      </div>
    </div>
  );
}

// ─── StoresOpenSlider ─────────────────────────────────────────────────────
// Horizontal-scroll rail that works on both mobile and desktop. Desktop shows
// chevron controls; mobile relies on swipe. Card width scales per viewport.
function StoresOpenSlider({ stores, isMobile, onOpen }) {
  const scrollerRef = React.useRef(null);
  const [canLeft, setCanLeft] = React.useState(false);
  const [canRight, setCanRight] = React.useState(true);
  const cardW = isMobile ? 240 : 300;

  const update = React.useCallback(() => {
    const el = scrollerRef.current; if (!el) return;
    setCanLeft(el.scrollLeft > 4);
    setCanRight(el.scrollLeft + el.clientWidth < el.scrollWidth - 4);
  }, []);
  React.useEffect(() => {
    const el = scrollerRef.current; if (!el) return;
    update();
    el.addEventListener("scroll", update, { passive: true });
    window.addEventListener("resize", update);
    return () => {
      el.removeEventListener("scroll", update);
      window.removeEventListener("resize", update);
    };
  }, [update]);
  const step = (dir) => {
    const el = scrollerRef.current; if (!el) return;
    el.scrollBy({ left: dir * el.clientWidth * 0.8, behavior: "smooth" });
  };

  return (
    <div style={{ marginTop: "var(--section-gap)" }}>
      <SectionHeader eyebrow="Near 98 Orchard St" title="Stores open right now"
        action={
          <div style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
            {!isMobile && (
              <>
                <button className="btn-reset" onClick={() => step(-1)} disabled={!canLeft}
                  style={{ width: 32, height: 32, borderRadius: 99,
                           border: "1px solid var(--line)", background: "var(--surface)",
                           display: "grid", placeItems: "center",
                           opacity: canLeft ? 1 : 0.35, transition: "opacity 160ms" }}>
                  <Icons.ArrowLeft size={14} stroke={2} />
                </button>
                <button className="btn-reset" onClick={() => step(1)} disabled={!canRight}
                  style={{ width: 32, height: 32, borderRadius: 99,
                           border: "1px solid var(--line)", background: "var(--surface)",
                           display: "grid", placeItems: "center",
                           opacity: canRight ? 1 : 0.35, transition: "opacity 160ms" }}>
                  <Icons.ArrowRight size={14} stroke={2} />
                </button>
              </>
            )}
            <Btn variant="ghost" size="sm" iconRight={<Icons.Chevron size={14} stroke={2} />}>See all 412</Btn>
          </div>
        } />
      <div ref={scrollerRef} className="no-scrollbar" style={{
        display: "grid", gridAutoFlow: "column",
        gridAutoColumns: `${cardW}px`,
        gap: "var(--grid-gap)",
        overflowX: "auto", overflowY: "hidden",
        scrollSnapType: "x mandatory",
        paddingBottom: 4,
        marginInline: isMobile ? -16 : 0,
        paddingInline: isMobile ? 16 : 0,
      }}>
        {stores.map(s => (
          <div key={s.id} style={{ scrollSnapAlign: "start" }}>
            <StoreCard store={s} onOpen={() => onOpen(s)} />
          </div>
        ))}
      </div>
    </div>
  );
}

// ─── HomeFarewell ─────────────────────────────────────────────────────────
// Warm end-of-page moment so the home screen doesn't cliff-dive into nothing.
// Personality more than CTA — but it does surface a one-tap Ask Opa shortcut.
function HomeFarewell({ onNav, isMobile }) {
  const hour = new Date().getHours();
  const when = hour < 5 ? "late tonight"
             : hour < 11 ? "this morning"
             : hour < 15 ? "this afternoon"
             : hour < 19 ? "tonight"
             : "tonight";
  return (
    <div style={{
      marginTop: "var(--section-gap)",
      position: "relative", overflow: "hidden",
      borderRadius: "var(--radius-xl)",
      background: "linear-gradient(135deg, var(--navy-fill), oklch(from var(--navy-fill) calc(l - 0.05) c h))",
      color: "#fff",
      padding: isMobile ? "32px 24px 30px" : "44px 44px 42px",
      textAlign: "center",
    }}>
      <div aria-hidden style={{
        position: "absolute", inset: 0,
        background: `radial-gradient(600px 260px at 50% 110%, oklch(from var(--accent) l c h / 0.28), transparent 65%)`,
        pointerEvents: "none",
      }} />
      <div style={{ position: "relative" }}>
        <span style={{ display: "inline-flex", alignItems: "center", gap: 8,
                       padding: "5px 14px", borderRadius: 999,
                       background: "rgba(255,255,255,0.1)",
                       fontSize: 11.5, fontWeight: 500, letterSpacing: "0.06em",
                       textTransform: "uppercase", color: "#fff" }}>
          <Icons.Sparkle size={12} stroke={2} style={{ color: "var(--accent)" }} />
          That's everything {when}
        </span>
        <h2 className="serif" style={{
          margin: "16px auto 0", maxWidth: 640,
          fontSize: isMobile ? 28 : 36, lineHeight: 1.15,
          letterSpacing: "-0.02em",
        }}>
          Still not sure?{" "}
          <span style={{ fontStyle: "italic", color: "oklch(from #fff l c h / 0.72)" }}>
            Ask Opa — it's the whole block in one sentence.
          </span>
        </h2>
        <p style={{ margin: "12px auto 0", maxWidth: 520,
                    fontSize: 14, lineHeight: 1.6, color: "oklch(from #fff l c h / 0.72)" }}>
          3,500 local stores. One question. We'll read the aisles for you and build the cart.
        </p>
        <div style={{ marginTop: 22, display: "inline-flex", gap: 10, flexWrap: "wrap", justifyContent: "center" }}>
          <button className="btn-reset" onClick={() => { window.scrollTo({ top: 0, behavior: "smooth" }); }}
            style={{ height: 44, padding: "0 18px", borderRadius: 999,
                     background: "var(--accent)", color: "#fff", fontSize: 14, fontWeight: 600,
                     display: "inline-flex", alignItems: "center", gap: 8 }}>
            <Icons.Sparkle size={14} stroke={2.2} /> Ask Opa
          </button>
          <button className="btn-reset" onClick={() => onNav({ screen: "search" })}
            style={{ height: 44, padding: "0 18px", borderRadius: 999,
                     background: "rgba(255,255,255,0.08)",
                     border: "1px solid rgba(255,255,255,0.18)",
                     color: "#fff", fontSize: 14, fontWeight: 500,
                     display: "inline-flex", alignItems: "center", gap: 8 }}>
            <Icons.Search size={14} stroke={1.9} /> Search stores
          </button>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Home, MiniProductCard, StoresOpenSlider, HomeFarewell });

// ─── MostShoppedSlider ─────────────────────────────────────────────────────
// Horizontal scroll carousel. Desktop shows ~4.5 cards visible → inviting scroll.
// Mobile shows ~2.4 cards. Cards are larger + more breathable than the old grid.
function MostShoppedSlider({ products, isMobile, cart, onOpen, addToCart }) {
  const scrollerRef = React.useRef(null);
  const [canScrollLeft, setCanScrollLeft] = React.useState(false);
  const [canScrollRight, setCanScrollRight] = React.useState(true);

  const updateArrows = React.useCallback(() => {
    const el = scrollerRef.current;
    if (!el) return;
    setCanScrollLeft(el.scrollLeft > 4);
    setCanScrollRight(el.scrollLeft + el.clientWidth < el.scrollWidth - 4);
  }, []);

  React.useEffect(() => {
    const el = scrollerRef.current;
    if (!el) return;
    updateArrows();
    el.addEventListener("scroll", updateArrows, { passive: true });
    window.addEventListener("resize", updateArrows);
    return () => {
      el.removeEventListener("scroll", updateArrows);
      window.removeEventListener("resize", updateArrows);
    };
  }, [updateArrows]);

  const scrollBy = (dir) => {
    const el = scrollerRef.current;
    if (!el) return;
    el.scrollBy({ left: dir * (el.clientWidth * 0.8), behavior: "smooth" });
  };

  const cardWidth = isMobile ? 168 : 232;

  return (
    <div style={{ marginTop: "var(--section-gap)" }}>
      <SectionHeader eyebrow="Right now" title="Most shopped near you"
        action={
          <div style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
            {!isMobile && (
              <>
                <button className="btn-reset" onClick={() => scrollBy(-1)} disabled={!canScrollLeft}
                  style={{ width: 32, height: 32, borderRadius: 99,
                           border: "1px solid var(--line)", background: "var(--surface)",
                           display: "grid", placeItems: "center",
                           opacity: canScrollLeft ? 1 : 0.35,
                           cursor: canScrollLeft ? "pointer" : "default",
                           transition: "opacity 160ms" }}>
                  <Icons.ArrowLeft size={14} stroke={2} />
                </button>
                <button className="btn-reset" onClick={() => scrollBy(1)} disabled={!canScrollRight}
                  style={{ width: 32, height: 32, borderRadius: 99,
                           border: "1px solid var(--line)", background: "var(--surface)",
                           display: "grid", placeItems: "center",
                           opacity: canScrollRight ? 1 : 0.35,
                           cursor: canScrollRight ? "pointer" : "default",
                           transition: "opacity 160ms" }}>
                  <Icons.ArrowRight size={14} stroke={2} />
                </button>
              </>
            )}
            <Btn variant="ghost" size="sm" iconRight={<Icons.Chevron size={14} stroke={2} />}>More</Btn>
          </div>
        } />

      <div style={{ position: "relative" }}>
        <div ref={scrollerRef} className="no-scrollbar" style={{
          display: "grid", gridAutoFlow: "column",
          gridAutoColumns: `${cardWidth}px`,
          gap: 14,
          overflowX: "auto", overflowY: "hidden",
          scrollSnapType: "x mandatory",
          paddingBottom: 4,
          // Bleed so last card clearly extends past container edge on wide screens
          paddingRight: 24,
        }}>
          {products.map(p => (
            <div key={p.id} style={{ scrollSnapAlign: "start" }}>
              <MiniProductCard p={p}
                onOpen={() => onOpen(p)}
                qty={cart.items.find(i => i.productId === p.id)?.qty || 0}
                onAdd={() => addToCart("kalymnos", p.id, 1)}
                onRemove={() => addToCart("kalymnos", p.id, -1)} />
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { MostShoppedSlider });

// ─── PickupBanner ──────────────────────────────────────────────────────────
// Persistent strip on home when there's a pickup waiting. Real action.
function PickupBanner({ onNav }) {
  const [dismissed, setDismissed] = React.useState(false);
  const isMobile = useMedia("(max-width: 720px)");
  if (dismissed) return null;
  return (
    <div className="fade-in pickup-banner" style={{
      display: "flex", alignItems: "center", gap: isMobile ? 12 : 16,
      padding: isMobile ? "16px 16px 16px 14px" : "18px 20px 18px 20px",
      marginBottom: 22,
      background: "var(--pickup-bg)",
      border: "1px solid var(--pickup-border)",
      borderRadius: 14, color: "var(--ink)",
      position: "relative", overflow: "hidden",
      flexWrap: isMobile ? "wrap" : "nowrap",
    }}>
      {/* Subtle diagonal accent stripe */}
      <div aria-hidden style={{
        position: "absolute", inset: 0,
        background: "linear-gradient(100deg, transparent 70%, oklch(from var(--ok) l c h / 0.08))",
        pointerEvents: "none",
      }} />
      <div style={{ width: 44, height: 44, borderRadius: 12,
                    background: "var(--pickup-icon-bg)",
                    border: "1px solid var(--pickup-icon-border)",
                    display: "grid", placeItems: "center",
                    color: "var(--ok)", flexShrink: 0,
                    position: "relative", zIndex: 1 }}>
        <Icons.Pickup size={18} stroke={1.8} />
        <span aria-hidden style={{
          position: "absolute", top: -2, right: -2,
          width: 10, height: 10, borderRadius: 99, background: "var(--ok)",
          boxShadow: "0 0 0 3px var(--pickup-bg)",
          animation: "pulseRing 1.8s ease-in-out infinite",
        }} />
      </div>
      <div style={{ flex: 1, minWidth: 0, position: "relative", zIndex: 1 }}>
        <div style={{ display: "flex", alignItems: "baseline", gap: 10, flexWrap: "wrap", rowGap: 4 }}>
          <strong style={{ fontSize: 14, fontWeight: 600, color: "var(--ink)" }}>
            Pickup ready at Kalymnos
          </strong>
          <span style={{ fontSize: 12, color: "var(--ink-3)", fontFamily: '"JetBrains Mono", monospace',
                         letterSpacing: "0.02em", display: "inline-flex", alignItems: "center", gap: 6,
                         flexWrap: "wrap", rowGap: 2 }}>
            <span>#4821</span>
            <span style={{ color: "var(--ink-4)" }}>·</span>
            <span>3 items</span>
            <span style={{ color: "var(--ink-4)" }}>·</span>
            <span style={{ whiteSpace: "nowrap" }}>held until <span style={{ color: "var(--ok)" }}>8:30 PM</span></span>
          </span>
        </div>
        <div style={{ fontSize: 12.5, color: "var(--ink-3)", marginTop: 4, lineHeight: 1.45 }}>
          Show your name at the counter — Maria knows you're on the way.
        </div>
      </div>
      <Btn size="sm" variant="primary"
        onClick={() => onNav({ screen: "store", storeId: "kalymnos" })}
        style={{ flexShrink: 0, position: "relative", zIndex: 1 }}>
        {isMobile ? "Go" : "Get directions"}
      </Btn>
      <button className="btn-reset" onClick={() => setDismissed(true)}
        title="Dismiss"
        style={{ width: 28, height: 28, display: "grid", placeItems: "center",
                 color: "var(--ink-4)", flexShrink: 0, position: "relative", zIndex: 1 }}>
        <Icons.X size={14} stroke={2} />
      </button>
    </div>
  );
}

// ─── CtaCard ───────────────────────────────────────────────────────────────
// Full-bleed image-less promo card. Tone drives palette; stat anchors a number.
function CtaCard({ tone = "green", eyebrow, title, body, stat, ctaLabel, icon = "Leaf" }) {
  const palettes = {
    green: {
      bg: "var(--ok-tint)",
      border: "oklch(from var(--ok) l c h / 0.22)",
      ink: "var(--ink)",
      eyebrow: "var(--ok)",
      iconBg: "var(--surface)",
      iconColor: "var(--ok)",
      btn: "primary",
      pattern: "var(--ok)",
    },
    navy: {
      bg: "var(--navy-fill)",
      border: "transparent",
      ink: "#fff",
      eyebrow: "oklch(from #fff l c h / 0.7)",
      iconBg: "rgba(255,255,255,0.10)",
      iconColor: "#fff",
      btn: "inverse",
      pattern: "rgba(255,255,255,0.6)",
    },
  }[tone];
  const Icon = Icons[icon] || Icons.Leaf;
  return (
    <div style={{
      position: "relative", overflow: "hidden",
      borderRadius: "var(--radius-lg)",
      background: palettes.bg, border: `1px solid ${palettes.border}`,
      padding: 22, color: palettes.ink,
      display: "flex", flexDirection: "column", gap: 14,
      minHeight: 200,
    }}>
      {/* decorative arc */}
      <svg viewBox="0 0 200 200" aria-hidden style={{
        position: "absolute", right: -40, top: -40, width: 220, height: 220,
        opacity: tone === "navy" ? 0.12 : 0.18, color: palettes.pattern,
      }}>
        <circle cx="100" cy="100" r="80" fill="none" stroke="currentColor" strokeWidth="1" />
        <circle cx="100" cy="100" r="56" fill="none" stroke="currentColor" strokeWidth="1" />
        <circle cx="100" cy="100" r="32" fill="none" stroke="currentColor" strokeWidth="1" />
      </svg>

      <div style={{ position: "relative", display: "flex", alignItems: "center", gap: 10 }}>
        <span style={{ width: 36, height: 36, borderRadius: 10,
                       background: palettes.iconBg, color: palettes.iconColor,
                       display: "grid", placeItems: "center" }}>
          <Icon size={18} stroke={1.8} />
        </span>
        <span className="uppercase-mono" style={{ color: palettes.eyebrow, fontSize: 10.5 }}>{eyebrow}</span>
      </div>

      <div style={{ position: "relative" }}>
        <div className="serif" style={{ fontSize: 24, lineHeight: 1.15, letterSpacing: "-0.01em",
                                        textWrap: "balance" }}>{title}</div>
        <div style={{ fontSize: 13.5, marginTop: 8, lineHeight: 1.5,
                      color: tone === "navy" ? "oklch(from #fff l c h / 0.78)" : "var(--ink-3)",
                      maxWidth: 460 }}>{body}</div>
      </div>

      <div style={{ position: "relative", marginTop: "auto", display: "flex", alignItems: "flex-end",
                    justifyContent: "space-between", gap: 12, flexWrap: "wrap" }}>
        <div>
          <div className="num" style={{ fontSize: 22, fontWeight: 600, lineHeight: 1 }}>{stat.k}</div>
          <div style={{ fontSize: 11.5, color: tone === "navy" ? "oklch(from #fff l c h / 0.65)" : "var(--ink-4)",
                        marginTop: 4 }}>{stat.l}</div>
        </div>
        <Btn size="sm" variant={palettes.btn} iconRight={<Icons.Chevron size={13} stroke={2} />}>{ctaLabel}</Btn>
      </div>
    </div>
  );
}

// ─── WorthYourAttention ────────────────────────────────────────────────────
// Promoted stories / video carousel. Every card has the "Promoted" tag.
function WorthYourAttention({ isMobile, onNav }) {
  const items = [
    { id: "verde", brand: "Verde Corner Produce", kind: "Video · 0:42",
      hed: "Watch how Hudson Valley apples get from orchard to your bag in 14 hours.",
      kicker: "This week's harvest", img: { url: "https://images.unsplash.com/photo-1568702846914-96b305d2aaeb?w=800&auto=format" }, color: "oklch(48% 0.12 140)" },
    { id: "fig", brand: "Fig & Thistle Wine", kind: "Story · 3 min read",
      hed: "Three under-$22 reds the staff is fighting over right now.",
      kicker: "Buyer's notes · Nov", img: { url: "https://images.unsplash.com/photo-1547595628-c61a29f496f0?w=800&auto=format" }, color: "oklch(35% 0.09 20)" },
    { id: "kalymnos", brand: "Kalymnos Deli", kind: "Recipe",
      hed: "Maria's hangover egg-cheese: 4 ingredients, 6 minutes, $9 cart.",
      kicker: "From the deli counter", img: { url: "https://images.unsplash.com/photo-1528735602780-2552fd46c7af?w=800&auto=format" }, color: "oklch(45% 0.10 60)" },
    { id: "elmo", brand: "Elmo's Chicken & Fixins", kind: "Video · 1:08",
      hed: "We brined 200 thighs this morning. Here's why Tuesday is the night.",
      kicker: "Behind the counter", img: { url: "https://images.unsplash.com/photo-1532550907401-a500c9a57435?w=800&auto=format" }, color: "oklch(40% 0.13 30)" },
  ];
  return (
    <div style={{ marginTop: "var(--section-gap)" }}>
      <SectionHeader eyebrow="Worth your attention" title="From shops on your block"
        action={<Btn variant="ghost" size="sm" iconRight={<Icons.Chevron size={14} stroke={2} />}>All stories</Btn>} />
      <div style={{
        display: "grid",
        gridTemplateColumns: isMobile ? "85% 85% 85% 85%" : "repeat(4, 1fr)",
        gap: "var(--grid-gap)",
        overflowX: isMobile ? "auto" : "visible",
        scrollSnapType: isMobile ? "x mandatory" : "none",
        paddingBottom: isMobile ? 4 : 0,
        marginInline: isMobile ? -16 : 0,
        paddingInline: isMobile ? 16 : 0,
      }}>
        {items.map(it => (
          <button key={it.id} className="btn-reset" onClick={() => onNav({ screen: "store", storeId: it.id })}
            style={{
              textAlign: "left", display: "flex", flexDirection: "column", gap: 0,
              borderRadius: "var(--radius-lg)", overflow: "hidden",
              background: "var(--surface)", border: "1px solid var(--line)",
              scrollSnapAlign: "start",
              transition: "transform .15s, box-shadow .15s",
            }}
            onMouseEnter={(e) => { e.currentTarget.style.transform = "translateY(-2px)"; e.currentTarget.style.boxShadow = "var(--shadow-md)"; }}
            onMouseLeave={(e) => { e.currentTarget.style.transform = "none"; e.currentTarget.style.boxShadow = "none"; }}>
            <div style={{ position: "relative", aspectRatio: "4/5", overflow: "hidden", background: it.color }}>
              <img src={it.img.url} alt="" loading="lazy"
                onError={(e) => { e.currentTarget.style.display = "none"; }}
                style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" }} />
              <div style={{ position: "absolute", inset: 0,
                            background: "linear-gradient(180deg, rgba(0,0,0,0.05) 0%, rgba(0,0,0,0.15) 50%, rgba(0,0,0,0.78) 100%)" }} />
              {/* Promoted tag */}
              <div style={{ position: "absolute", top: 10, left: 10,
                            display: "inline-flex", alignItems: "center", gap: 6,
                            padding: "4px 9px 4px 8px", borderRadius: 999,
                            background: "rgba(255,255,255,0.92)", color: "var(--ink-2)",
                            fontSize: 10.5, fontWeight: 600, letterSpacing: "0.04em",
                            textTransform: "uppercase" }}>
                <span style={{ width: 5, height: 5, borderRadius: 99, background: "var(--accent)" }} />
                Promoted
              </div>
              {/* Kind chip */}
              {it.kind.startsWith("Video") && (
                <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center" }}>
                  <span style={{ width: 52, height: 52, borderRadius: 99,
                                 background: "rgba(255,255,255,0.92)", color: "#0A1F44",
                                 display: "grid", placeItems: "center",
                                 boxShadow: "0 4px 16px rgba(0,0,0,0.3)" }}>
                    <svg width="20" height="20" viewBox="0 0 24 24" aria-hidden
                         style={{ marginLeft: 3 }}>
                      <path d="M7 4v16l13-8z" fill="currentColor" />
                    </svg>
                  </span>
                </div>
              )}
              {/* Bottom text overlay */}
              <div style={{ position: "absolute", left: 0, right: 0, bottom: 0,
                            padding: "14px 14px 14px", color: "#fff" }}>
                <div style={{ fontSize: 10.5, opacity: 0.85, letterSpacing: "0.06em",
                              textTransform: "uppercase", marginBottom: 6 }}>
                  {it.kicker} · {it.kind}
                </div>
                <div className="serif" style={{ fontSize: 17, lineHeight: 1.2, textWrap: "pretty",
                                                 letterSpacing: "-0.005em" }}>{it.hed}</div>
              </div>
            </div>
            <div style={{ padding: "12px 14px", display: "flex", alignItems: "center",
                          justifyContent: "space-between", gap: 10 }}>
              <div style={{ display: "flex", alignItems: "center", gap: 9, minWidth: 0 }}>
                <span style={{ width: 22, height: 22, borderRadius: 99, background: it.color,
                               flexShrink: 0, border: "1px solid var(--line)" }} />
                <span style={{ fontSize: 12.5, fontWeight: 500, color: "var(--ink)",
                               overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{it.brand}</span>
              </div>
              <Icons.Chevron size={14} stroke={2} style={{ color: "var(--ink-4)", flexShrink: 0 }} />
            </div>
          </button>
        ))}
      </div>
    </div>
  );
}

Object.assign(window, { PickupBanner, CtaCard, WorthYourAttention });

// ─── BundleBackdrop ────────────────────────────────────────────────────────
// Decorative pattern fills for bundle headers — wave / grid / dots.
function BundleBackdrop({ pattern, color }) {
  const stroke = `oklch(from ${color} l c h / 0.18)`;
  if (pattern === "wave") {
    return (
      <svg viewBox="0 0 320 132" preserveAspectRatio="none" aria-hidden
        style={{ position: "absolute", inset: 0, width: "100%", height: "100%" }}>
        <g fill="none" stroke={stroke} strokeWidth="1.2">
          {[...Array(7)].map((_, i) => (
            <path key={i} d={`M0 ${20 + i * 14} Q 80 ${10 + i * 14}, 160 ${24 + i * 14} T 320 ${20 + i * 14}`} />
          ))}
        </g>
      </svg>
    );
  }
  if (pattern === "grid") {
    return (
      <svg viewBox="0 0 320 132" preserveAspectRatio="none" aria-hidden
        style={{ position: "absolute", inset: 0, width: "100%", height: "100%" }}>
        <defs>
          <pattern id="bgrid" width="20" height="20" patternUnits="userSpaceOnUse">
            <path d="M 20 0 L 0 0 0 20" fill="none" stroke={stroke} strokeWidth="1" />
          </pattern>
        </defs>
        <rect width="320" height="132" fill="url(#bgrid)" />
        <circle cx="260" cy="34" r="40" fill={`oklch(from ${color} l c h / 0.10)`} />
      </svg>
    );
  }
  // dots
  return (
    <svg viewBox="0 0 320 132" preserveAspectRatio="none" aria-hidden
      style={{ position: "absolute", inset: 0, width: "100%", height: "100%" }}>
      <g fill={`oklch(from ${color} l c h / 0.22)`}>
        {[...Array(7)].map((_, row) =>
          [...Array(17)].map((__, col) => (
            <circle key={`${row}-${col}`} cx={10 + col * 20} cy={10 + row * 20} r={1.6} />
          ))
        )}
      </g>
    </svg>
  );
}

window.BundleBackdrop = BundleBackdrop;
