// Sections — moody premium tiki-bar feel
const { useState: useStateS } = React;

// ========== STORY ==========
const Story = () => (
  <section id="story" className="section" style={{ position: "relative", background: "var(--cream)", color: "var(--ink)" }}>
    <div className="wrap pr-story__grid" style={{ display: "grid", gap: 80, gridTemplateColumns: "1fr 1fr", alignItems: "center" }}>
      <div>
        <div className="tag" style={{ marginBottom: 18, color: "var(--accent)" }}>★ Drink and be heard</div>
        <h2 className="display" style={{ fontSize: "clamp(56px, 8vw, 120px)", marginBottom: 28, color: "var(--ink)" }}>
          A small bar.<br/>
          <span style={{ color: "var(--accent)" }}>Big voice.</span>
        </h2>
        <div style={{ display: "grid", gap: 18, fontSize: 17, lineHeight: 1.65, color: "var(--ink)", maxWidth: 540 }}>
          <p>Tucked inside Honokowai Marketplace just north of Lahaina and Ka'anapali, Pineapple Robot is the late-night sibling of <strong>Pizza Paradiso</strong> — the gourmet pizzeria right next door.</p>
          <p>By day, a tiki cocktail bar with happy hour from noon to five. By night, the lights dim, the mic comes out, and the karaoke runs from nine until 1:30 in the morning. Seven days a week.</p>
          <p style={{ fontWeight: 600, fontSize: 22, borderLeft: "4px solid var(--accent)", paddingLeft: 18, marginTop: 8 }}>
            Locals, visitors, off-shift bartenders, off-key tenors — everyone's welcome.
          </p>
        </div>
        <div className="pr-story__stats" style={{ display: "flex", gap: 32, marginTop: 36, flexWrap: "wrap" }}>
          <Stat n="12–5" label="Happy hour" />
          <Stat n="$5" label="Mai Tai, daily" />
          <Stat n="1:30am" label="Karaoke nightly" />
        </div>
      </div>
      <div className="pr-story__tiles" style={{ position: "relative", display: "grid", gap: 16, gridTemplateColumns: "1fr 1fr" }}>
        <PhotoTile color="var(--accent-2)" photo="assets/maitai.jpg" caption="Happy Hour Mai Tais" tall />
        <div style={{ display: "grid", gap: 16 }}>
          <PhotoTile color="var(--accent)" photo="assets/karaoke.jpg" caption="Karaoke nightly" />
          <PhotoTile color="var(--jungle)" photo="assets/pizza.jpg" caption="Slices next door" />
        </div>
      </div>
    </div>
  </section>
);

const Stat = ({ n, label }) => (
  <div className="pr-stat" style={{ display: "grid", gap: 4 }}>
    <div className="display pr-stat__n" style={{ fontSize: 56, color: "var(--accent)", lineHeight: 1 }}>{n}</div>
    <div className="tag pr-stat__label" style={{ color: "var(--ink)", opacity: 0.7 }}>{label}</div>
  </div>
);

const PhotoTile = ({ color, emoji, photo, caption, tall }) => (
  <div style={{
    background: color,
    borderRadius: "var(--radius-md)",
    aspectRatio: tall ? "3/5" : "1/1",
    position: "relative", overflow: "hidden",
    display: "grid", placeItems: "center",
    border: "var(--outline)",
    boxShadow: "6px 6px 0 var(--ink)",
  }}>
    <div style={{ position: "absolute", inset: 0, background: "repeating-linear-gradient(135deg, rgba(255,255,255,0.10) 0 14px, transparent 14px 28px)" }} />
    {photo ? (
      <img
        src={photo}
        alt={caption}
        style={{
          position: "absolute", inset: 18,
          width: "calc(100% - 36px)", height: "calc(100% - 36px)",
          objectFit: "cover",
          border: "2px solid var(--ink)",
          borderRadius: "calc(var(--radius-md) - 10px)",
          boxShadow: "0 10px 24px -8px rgba(0,0,0,0.35)",
        }}
      />
    ) : (
      <div style={{ fontSize: tall ? 110 : 80, filter: "drop-shadow(0 8px 18px rgba(0,0,0,0.25))" }}>{emoji}</div>
    )}
    <div className="pr-phototile__caption" style={{
      position: "absolute", left: 14, bottom: 14,
      fontFamily: "var(--sans)", fontSize: 12, letterSpacing: ".05em",
      fontWeight: 700, textTransform: "uppercase", color: "var(--ink)",
      background: "var(--cream)", padding: "6px 12px", borderRadius: 999,
      border: "2px solid var(--ink)",
      zIndex: 1,
    }}>{caption}</div>
  </div>
);

// ========== COCKTAILS ==========
// "Meet the Bots" — house signature cocktails, all $15
// `desc` is the ingredient list, not a written blurb: that is what Marqii
// publishes for a drink, so a stand-in tile reads exactly like the live one it
// gets replaced by. Keep these strings in sync with BASE_COCKTAILS in
// api/_cocktails.js so the bot never describes a drink differently from its tile.
const COCKTAILS = [
  { name: "Moscow Mule",     price: "15", color: "var(--accent-2)",
    desc: "Ocean Vodka, ginger beer, lime", tag: "Vodka" },
  { name: "Lahaina Sunset",  price: "15", color: "var(--coral)",
    desc: "bourbon, Aperol, pineapple juice, lime, simple syrup", tag: "Bourbon" },
  { name: "Lazy Tree Hugger", price: "15", color: "var(--jungle)",
    desc: "passion-fruit-infused rum, pineapple, Campari, lime, simple syrup", tag: "Rum" },
  { name: "Piñarita",        price: "15", color: "var(--gold-deep)",
    desc: "tequila reposado, pineapple juice, coconut cream, mac-nut sugar cane, fresh lime", tag: "Tequila" },
  { name: "Jarrito Loco",    price: "15", color: "var(--magenta, #C13B58)",
    desc: "spicy tamarind vodka, orange juice, sugar-cane falernum, hibiscus tea, chamoy & Tajín rim", tag: "Vodka" },
  { name: "Spam Mail",       price: "15", color: "var(--teal)",
    desc: "vodka, Choya yuzu, lime, sugar-cane syrup", tag: "Vodka" },
  { name: "Tech Mex",        price: "15", color: "var(--accent)",
    desc: "blanco tequila, ginger, pineapple, honey, tiki bitters, allspice bitters", tag: "Tequila" },
  { name: "Peach con Fuego", price: "15", color: "var(--coral)",
    desc: "mezcal, peach, lime, falernum", tag: "Mezcal" },
  { name: "R2Cheeeehoooo",   price: "15", color: "var(--accent-2)",
    desc: "gin, Don Q passion fruit, lime, sugar cane, falernum", tag: "Gin" },
  { name: "Blue Fishbowl",   price: "15", color: "var(--teal)",
    desc: "coconut rum, white rum, white tequila, blue curaçao, pineapple juice, lime, lemon-lime soda", tag: "Shareable" },
];

// ---- Live Marqii merge (via /api/drinks) ----
// The cocktails render from COCKTAILS above (hand-tuned color/tag/blurb), but
// name / price / ingredients come live from Marqii when available. Marqii item
// names carry small typos + accents, so match on a loose normalized key.
const COCKTAIL_TILE_COLORS = ["var(--coral)", "var(--teal)", "var(--accent-2)", "var(--jungle)", "var(--gold-deep)"];
const normDrink = (s) => (s || "")
  .toLowerCase()
  .normalize("NFD").replace(/[̀-ͯ]/g, "")  // strip accents (ñ→n)
  .replace(/[^a-z0-9]/g, "")
  .replace(/(.)\1+/g, "$1");                          // collapse repeats (cheeeh→ceh)

// Local placeholder photo per drink. Used only until a real photo is uploaded
// to Marqii — a live Marqii image always wins (see mergeCocktails + CocktailCard).
// Keyed by display name; looked up via the same normalized key as the merge.
const COCKTAIL_PHOTOS = {
  "Moscow Mule":      "assets/drinks/moscow-mule.jpg",
  "Lahaina Sunset":   "assets/drinks/lahaina-sunset.jpg",
  "Lazy Tree Hugger": "assets/drinks/lazy-tree-hugger.jpg",
  "Piñarita":         "assets/drinks/pinarita.jpg",
  "Jarrito Loco":     "assets/drinks/jarrito-loco.jpg",
  "Spam Mail":        "assets/drinks/spam-mail.jpg",
  "Tech Mex":         "assets/drinks/tech-mex.jpg",
  "Peach con Fuego":  "assets/drinks/peach-con-fuego.jpg",
  "R2Cheeeehoooo":    "assets/drinks/r2chee.jpg",
  "Blue Fishbowl":    "assets/drinks/blue-fishbowl.jpg",
  "Lava Flow":        "assets/drinks/lava-flow.jpg",
};
const PLACEHOLDER_BY_KEY = {};
Object.keys(COCKTAIL_PHOTOS).forEach((n) => { PLACEHOLDER_BY_KEY[normDrink(n)] = COCKTAIL_PHOTOS[n]; });
const placeholderFor = (name) => PLACEHOLDER_BY_KEY[normDrink(name)] || "";

// Spirit label derived from the ingredient list — only used for brand-new
// cocktails that have no hand-tuned entry above. Word-boundaries so "ginger"
// doesn't read as "gin".
const SPIRIT_TAGS = [["mezcal","Mezcal"],["tequila","Tequila"],["bourbon","Bourbon"],["whiskey","Whiskey"],["whisky","Whiskey"],["rum","Rum"],["gin","Gin"],["vodka","Vodka"]];
const deriveTag = (ingredients) => {
  const t = (ingredients || "").toLowerCase();
  for (const [k, label] of SPIRIT_TAGS) if (new RegExp(`\\b${k}\\b`).test(t)) return label;
  return "Signature";
};
// Merge a live Marqii drinks array into the COCKTAILS design table.
// COCKTAILS decides WHICH cocktails show; Marqii only enriches them. The widget
// often publishes a partial list (at one point just Moscow Mule), so a drink
// missing from the feed must never drop off the site — it just goes un-enriched.
const mergeCocktails = (drinks) => {
  const live = {};
  (drinks || []).forEach((dr) => { if (dr && dr.name) live[normDrink(dr.name)] = dr; });

  const merged = COCKTAILS.map((base) => {
    const dr = live[normDrink(base.name)];
    if (!dr) return base;
    // Once a drink is published in Marqii, Marqii is the source of truth for
    // everything the guest reads: name, price, ingredients and photo. The
    // stand-in copy/photo below is only for drinks the bar hasn't entered yet,
    // so it must not survive the merge.
    const liveDesc = (dr.ingredients || "").trim();
    return {
      ...base,
      name: dr.name,
      price: dr.price || base.price,
      desc: liveDesc || base.desc,
      image: dr.image || "",   // no Marqii photo yet → card falls back to the local placeholder
    };
  });

  // Anything Marqii lists that has no hand-tuned entry is a genuinely new
  // cocktail — synthesize a tile for it and append after the designed ones.
  const known = new Set(COCKTAILS.map((c) => normDrink(c.name)));
  (drinks || []).forEach((dr, i) => {
    if (!dr || !dr.name) return;
    const key = normDrink(dr.name);
    if (known.has(key)) return;
    known.add(key);
    merged.push({
      name: dr.name,
      price: dr.price || "15",
      color: COCKTAIL_TILE_COLORS[i % COCKTAIL_TILE_COLORS.length],
      desc: dr.ingredients,
      tag: deriveTag(dr.ingredients),
      image: dr.image || "",
    });
  });

  return merged;
};

// Menu-style capitalization, applied at render time only. Both our stand-in
// copy and Marqii's live text are written in running-text case ("bourbon,
// Aperol, pineapple juice"), which reads like a chopped-off sentence on a tile.
// The stored strings stay lowercase so the bot can quote them mid-sentence —
// only the tile capitalizes each comma-separated ingredient.
const capitalizeIngredients = (s) => (s || "")
  .split(",")
  .map((part) => part.replace(/\S/, (ch) => ch.toUpperCase()))
  .join(",");

// Featured cocktail tile — reused for the desktop featured card and the mobile swipe carousel.
const CocktailCard = ({ c }) => (
  <div className="pr-cocktail-card" style={{
    position: "relative",
    background: c.color,
    color: "var(--ink)",
    borderRadius: "var(--radius-lg)",
    aspectRatio: "4/5",
    padding: 40,
    display: "flex", flexDirection: "column", justifyContent: "space-between",
    overflow: "hidden",
    border: "3px solid var(--ink)",
    boxShadow: "10px 10px 0 var(--ink)",
  }}>
    <div style={{ position: "absolute", inset: 0, background: "repeating-linear-gradient(45deg, rgba(255,255,255,0.10) 0 18px, transparent 18px 36px)" }} />
    <div style={{ position: "relative", display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
      <span style={{ fontFamily: "var(--sans)", fontWeight: 700, fontSize: 12, letterSpacing: ".05em", textTransform: "uppercase", background: "var(--cream)", padding: "6px 14px", borderRadius: 999, border: "2px solid var(--ink)" }}>{c.tag}</span>
      <span className="display" style={{ fontSize: 44 }}>${c.price}</span>
    </div>
    <div className="pr-cocktail-card__media" style={{ position: "relative", flex: 1, minHeight: 0, margin: "20px 0", display: "flex" }}>
      <img
        src={c.image || placeholderFor(c.name) || "assets/maitai.jpg"}
        alt={c.name}
        onError={(e) => {
          // Marqii photo failed → try the local placeholder, then the default.
          const ph = placeholderFor(c.name);
          const next = ph && !e.currentTarget.src.endsWith(ph) ? ph : "assets/maitai.jpg";
          if (!e.currentTarget.src.endsWith(next)) e.currentTarget.src = next;
        }}
        style={{
          width: "100%", height: "100%",
          objectFit: "cover",
          objectPosition: "center 40%",
          border: "3px solid var(--ink)",
          borderRadius: "18px",
          boxShadow: "0 16px 32px -10px rgba(0,0,0,0.35)",
          display: "block",
        }}
      />
    </div>
    <div style={{ position: "relative" }}>
      <h3 className="display" style={{ fontSize: 56, lineHeight: 0.95 }}>{c.name}</h3>
      <p style={{ marginTop: 12, fontSize: 16, lineHeight: 1.5, maxWidth: 380, fontWeight: 500 }}>{capitalizeIngredients(c.desc)}</p>
    </div>
  </div>
);

// Mobile-only infinite carousel built on a transform-based track. We translate
// the track ourselves instead of using native overflow scrolling, so the loop
// "teleport" can never fight the browser's momentum — no flicker on fast swipes.
const CocktailCarousel = ({ list = COCKTAILS }) => {
  const viewportRef = React.useRef(null);
  const trackRef = React.useRef(null);

  React.useEffect(() => {
    const viewport = viewportRef.current;
    const track = trackRef.current;
    if (!viewport || !track) return;

    let step = 0, w = 0, base = 0, pos = 0, raf = 0;

    // Fold any position back into the middle copy's window. Content repeats every
    // `w`, so the equivalent position is visually identical — this is the seamless
    // loop, and because we apply it to a transform there's no native scroll to jar.
    const wrap = (p) => {
      if (w <= 0) return p;
      const lo = -2 * w;
      return lo + ((((p - lo) % w) + w) % w);
    };
    const render = () => { track.style.transform = `translate3d(${wrap(pos)}px,0,0)`; };

    const measure = () => {
      const cards = track.querySelectorAll(".pr-cocktail-card");
      if (cards.length < list.length + 1) return;
      step = cards[1].offsetLeft - cards[0].offsetLeft;
      w = step * list.length;
      base = (viewport.clientWidth - cards[0].offsetWidth) / 2; // centers the active tile
      if (!pos) pos = base - list.length * step;                // start on the middle copy
      pos = wrap(pos);
      render();
    };

    // ---- drag + flick-to-snap ----
    // mode: "idle" → nothing; "pending" → touch down, axis not yet decided;
    // "drag" → locked to a horizontal swipe. We never capture the pointer, so a
    // vertical gesture stays with the browser and the page scrolls normally.
    let mode = "idle", startX = 0, startY = 0, startPos = 0, lastX = 0, lastT = 0, vel = 0;

    const animateTo = (target) => {
      if (raf) cancelAnimationFrame(raf);
      const tick = () => {
        pos += (target - pos) * 0.18;            // exponential ease toward the snap point
        if (Math.abs(target - pos) < 0.5) { pos = wrap(target); render(); raf = 0; return; }
        render();
        raf = requestAnimationFrame(tick);
      };
      raf = requestAnimationFrame(tick);
    };

    const onDown = (e) => {
      if (raf) { cancelAnimationFrame(raf); raf = 0; }
      mode = "pending";
      pos = wrap(pos);
      startX = lastX = e.clientX; startY = e.clientY; startPos = pos;
      lastT = e.timeStamp; vel = 0;
    };
    const onMove = (e) => {
      if (mode === "idle") return;
      if (mode === "pending") {
        const dx = e.clientX - startX, dy = e.clientY - startY;
        if (Math.abs(dx) < 6 && Math.abs(dy) < 6) return;   // wait until the intent is clear
        if (Math.abs(dy) >= Math.abs(dx)) { mode = "idle"; return; } // vertical → let the page scroll
        mode = "drag";                                      // horizontal → it's ours
      }
      const dt = e.timeStamp - lastT;
      if (dt > 0) vel = (e.clientX - lastX) / dt;  // px per ms
      lastX = e.clientX; lastT = e.timeStamp;
      pos = startPos + (e.clientX - startX);
      render();
      if (e.cancelable) e.preventDefault();
    };
    const onUp = () => {
      if (mode !== "drag") { mode = "idle"; return; }
      mode = "idle";
      const projected = pos + vel * 160;           // glide a little past the release point
      const k = Math.round((base - projected) / step);
      animateTo(base - k * step);                  // snap to the nearest centered tile
    };

    measure();
    const settle = setTimeout(measure, 300);       // re-measure once layout/images settle
    const onResize = () => measure();

    track.addEventListener("pointerdown", onDown);
    window.addEventListener("pointermove", onMove);
    window.addEventListener("pointerup", onUp);
    window.addEventListener("pointercancel", onUp);
    window.addEventListener("resize", onResize);
    return () => {
      clearTimeout(settle);
      if (raf) cancelAnimationFrame(raf);
      track.removeEventListener("pointerdown", onDown);
      window.removeEventListener("pointermove", onMove);
      window.removeEventListener("pointerup", onUp);
      window.removeEventListener("pointercancel", onUp);
      window.removeEventListener("resize", onResize);
    };
  }, [list]);

  const loop = [...list, ...list, ...list];
  // Color the tiles by position (not by drink) so no two neighbors ever match.
  // 5 colors evenly divide the 10-drink list, so the loop stays seamless.
  const TILE_COLORS = ["var(--coral)", "var(--teal)", "var(--accent-2)", "var(--jungle)", "var(--gold-deep)"];
  return (
    <div className="pr-cocktails__mobile">
      <div className="pr-cocktails__viewport" ref={viewportRef}>
        <div className="pr-cocktails__track" ref={trackRef}>
          {loop.map((d, i) => (
            <CocktailCard key={i} c={{ ...d, color: TILE_COLORS[i % TILE_COLORS.length] }} />
          ))}
        </div>
      </div>
      <div className="pr-cocktails__hint">← swipe for the good stuff →</div>
    </div>
  );
};

const Cocktails = () => {
  // Live cocktails from Marqii (via /api/drinks), merged over the COCKTAILS
  // design table; starts from it so the section never flashes empty.
  const [list, setList] = useStateS(COCKTAILS);
  const [active, setActive] = useStateS(0);

  React.useEffect(() => {
    let alive = true;
    fetch("/api/drinks")
      .then((r) => r.json())
      .then((d) => {
        if (alive && d && Array.isArray(d.drinks) && d.drinks.length) setList(mergeCocktails(d.drinks));
      })
      .catch(() => {});
    return () => { alive = false; };
  }, []);

  const c = list[active] || list[0];
  return (
    <section id="cocktails" className="section" style={{ background: "var(--espresso)", color: "var(--cream)", borderTop: "3px solid var(--ink)" }}>
      <div className="wrap">
        <div style={{ display: "grid", gap: 12, marginBottom: 60 }}>
          <div className="tag" style={{ color: "var(--accent-2)" }}>02 — From the bar</div>
          <h2 className="display" style={{ fontSize: "clamp(56px, 8vw, 120px)", color: "var(--cream)" }}>
            Meet the <span style={{ color: "var(--accent-2)" }}>bots.</span>
          </h2>
          <p style={{ maxWidth: 560, color: "var(--fg-soft)", fontSize: 17, lineHeight: 1.55 }}>
            Ten house signature cocktails, all $15. Happy hour 12–5pm — home of the $5 Mai Tai. Late night from 9pm: $12 cocktails &amp; $10 shots.
          </p>
        </div>

        {/* Desktop: clickable list + featured tile */}
        <div className="pr-cocktails__grid pr-cocktails__desktop" style={{ display: "grid", gridTemplateColumns: "1fr 1.1fr", gap: 60, alignItems: "center" }}>
          {/* List */}
          <div style={{ display: "grid" }}>
            {list.map((d, i) => (
              <button key={d.name} onClick={() => setActive(i)} style={{
                display: "grid", gridTemplateColumns: "auto 1fr auto", gap: 18, alignItems: "baseline",
                padding: "22px 4px",
                borderTop: i === 0 ? "2px solid rgba(244,233,216,0.2)" : "none",
                borderBottom: "2px solid rgba(244,233,216,0.2)",
                textAlign: "left",
                color: active === i ? "var(--accent-2)" : "var(--cream)",
                transition: "color .15s, padding-left .15s",
                paddingLeft: active === i ? 14 : 4,
              }}>
                <span className="tag" style={{ color: active === i ? "var(--accent-2)" : "var(--fg-soft)" }}>{String(i+1).padStart(2,"0")}</span>
                <span>
                  <div className="display" style={{ fontSize: 32, lineHeight: 1 }}>{d.name}</div>
                  <div style={{ fontFamily: "var(--sans)", fontWeight: 600, fontSize: 12, opacity: 0.7, letterSpacing: ".05em", textTransform: "uppercase", marginTop: 6 }}>
                    {d.tag}
                  </div>
                </span>
                <span className="display" style={{ fontSize: 32 }}>${d.price}</span>
              </button>
            ))}
          </div>
          <CocktailCard c={c} />
        </div>

        {/* Mobile: infinite swipe carousel of the same tiles */}
        <CocktailCarousel list={list} />
      </div>
    </section>
  );
};

// ========== KARAOKE ==========
const SONGS = [
  { num: "001", title: "Don't Stop Believin'", who: "everyone, eventually" },
  { num: "047", title: "Sweet Caroline", who: "the bachelorette party" },
  { num: "108", title: "Dancing Queen", who: "table 4" },
  { num: "212", title: "Bohemian Rhapsody", who: "the brave" },
  { num: "303", title: "Wonderwall", who: "the guy with the guitar" },
  { num: "451", title: "I Will Survive", who: "after the breakup" },
  { num: "509", title: "Mr. Brightside", who: "millennials" },
  { num: "808", title: "Aloha 'Oe", who: "the regulars" },
];

const Karaoke = () => {
  const [queue, setQueue] = useStateS(["Don't Stop Believin'", "Sweet Caroline"]);
  const [now, setNow] = useStateS(0);
  const add = t => !queue.includes(t) && setQueue(q => [...q, t]);
  const skip = () => setNow(n => (n + 1) % Math.max(queue.length, 1));

  return (
    <section id="karaoke" className="section grain" style={{ background: "var(--bg)", color: "var(--cream)", position: "relative", overflow: "hidden" }}>
      <div className="wrap" style={{ position: "relative", zIndex: 1, display: "grid", gap: 60, gridTemplateColumns: "1fr 1.1fr", alignItems: "start" }}>
        <div>
          <div className="tag" style={{ color: "var(--accent-2)" }}>03 — The mic is yours</div>
          <h2 className="display" style={{ fontSize: "clamp(56px, 9vw, 130px)", marginTop: 16, color: "var(--cream)" }}>
            Pick a<br/>song.<br/>
            <span style={{ color: "var(--accent-2)" }}>Be the show.</span>
          </h2>
          <p style={{ marginTop: 24, fontSize: 17, lineHeight: 1.6, maxWidth: 460, color: "var(--fg-soft)" }}>
            Thousands of songs. A loaded crowd. Throw one on the queue and we'll call you up.
          </p>

          {/* Now playing screen */}
          <div style={{
            marginTop: 36,
            background: "var(--ink)",
            border: "3px solid var(--ink)",
            borderRadius: "var(--radius-md)",
            padding: "26px 28px",
            fontFamily: "var(--sans)",
            position: "relative",
            boxShadow: "8px 8px 0 var(--accent-2)",
          }}>
            <div style={{ display: "flex", justifyContent: "space-between", fontSize: 11, fontWeight: 700, letterSpacing: ".2em", marginBottom: 10, color: "var(--cream)", opacity: 0.7 }}>
              <span>▶ NOW PLAYING</span>
              <span className="glow" style={{ color: "var(--accent)" }}>● LIVE</span>
            </div>
            <div className="display" style={{ fontSize: 36, color: "var(--accent-2)", lineHeight: 1, marginTop: 4 }}>
              {queue[now] || "—"}
            </div>
            <div style={{ marginTop: 14, fontSize: 13, fontWeight: 600, color: "var(--accent)", letterSpacing: ".06em" }}>
              UP NEXT: {queue[(now + 1) % queue.length] || "your song?"}
            </div>
            <button onClick={skip} style={{
              marginTop: 18,
              padding: "10px 18px", borderRadius: 999,
              background: "var(--accent-2)", color: "var(--ink)",
              fontFamily: "var(--sans)", fontWeight: 700, fontSize: 12, letterSpacing: ".06em",
              border: "2px solid var(--cream)",
            }}>SKIP →</button>
          </div>
        </div>

        {/* Song book */}
        <div style={{ background: "var(--cream)", color: "var(--ink)", border: "3px solid var(--ink)", borderRadius: "var(--radius-md)", padding: 28, boxShadow: "10px 10px 0 var(--ink)" }}>
          <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 18, fontFamily: "var(--sans)", fontSize: 12, fontWeight: 700, letterSpacing: ".06em", textTransform: "uppercase" }}>
            <span style={{ color: "var(--accent)" }}>Song book · Vol. 47</span>
            <span style={{ opacity: 0.6 }}>{queue.length} in queue</span>
          </div>
          <div>
            {SONGS.map(s => {
              const queued = queue.includes(s.title);
              return (
                <button key={s.num} onClick={() => add(s.title)} style={{
                  display: "grid", gridTemplateColumns: "auto 1fr auto", gap: 16,
                  padding: "16px 4px",
                  borderTop: "2px solid rgba(45,27,20,0.15)",
                  alignItems: "baseline", textAlign: "left", width: "100%",
                  transition: "padding-left .12s, background .12s",
                  color: "var(--ink)",
                }} onMouseEnter={e => { e.currentTarget.style.paddingLeft = "12px"; e.currentTarget.style.background = "rgba(232,181,71,0.18)"; }}
                   onMouseLeave={e => { e.currentTarget.style.paddingLeft = "4px"; e.currentTarget.style.background = "transparent"; }}>
                  <span style={{ fontFamily: "var(--sans)", fontWeight: 700, fontSize: 12, opacity: 0.5 }}>{s.num}</span>
                  <span>
                    <div className="display" style={{ fontSize: 24 }}>{s.title}</div>
                    <div style={{ fontSize: 12, opacity: 0.6, fontFamily: "var(--sans)", letterSpacing: ".02em", marginTop: 2 }}>↳ {s.who}</div>
                  </span>
                  <span style={{
                    fontFamily: "var(--sans)", fontWeight: 700, fontSize: 11, letterSpacing: ".06em", textTransform: "uppercase",
                    color: queued ? "var(--accent)" : "var(--ink)", opacity: queued ? 1 : 0.55,
                  }}>
                    {queued ? "✓ Queued" : "+ Add"}
                  </span>
                </button>
              );
            })}
          </div>
          <div style={{ marginTop: 18, fontSize: 11, fontFamily: "var(--sans)", fontWeight: 600, opacity: 0.55, textAlign: "center", letterSpacing: ".08em" }}>
            DEMO ONLY — REQUEST YOUR REAL SONG FROM THE BARTENDER
          </div>
        </div>
      </div>
    </section>
  );
};

// ========== PIZZA ==========
const PIZZA_ORDER_URL = "https://pizzaparadiso.toast.site/order";
// Cards cycle through the brand palette — the Marqii feed has no per-item color.
const PIZZA_COLORS = ["var(--coral)", "var(--yellow)", "var(--jungle)", "var(--teal)", "var(--gold-deep)", "var(--coral-deep)"];
// Shown instantly and used if the live Marqii feed is unavailable.
const FALLBACK_PIZZAS = [
  { name: "Margherita",   description: "olive oil, candied garlic, tomato, basil pesto, mozzarella, balsamic glaze", image: "assets/pizza-margherita.jpg" },
  { name: "Maui Wowie",   description: "herb-tomato, mozzarella-provolone, ham, real pineapple",                    image: "assets/pizza-hawaiian.jpg" },
  { name: "Greek Pizza",  description: "kalamata olives, red onion, gyro meat, feta, tomato, tzatziki, fresh mint", image: "assets/pizza-greek.jpg" },
  { name: "Meat Supreme", description: "pepperoni, mozzarella-provolone, ground beef, bacon, sausage",             image: "assets/pizza-meat.jpg" },
];

const Pizza = () => {
  // Live menu from Marqii (via /api/menu); starts from fallback so it never flashes empty.
  const [pizzas, setPizzas] = useStateS(FALLBACK_PIZZAS);

  React.useEffect(() => {
    let alive = true;
    fetch("/api/menu")
      .then(r => r.json())
      .then(d => { if (alive && d && Array.isArray(d.pizzas) && d.pizzas.length) setPizzas(d.pizzas); })
      .catch(() => {});
    return () => { alive = false; };
  }, []);

  return (
    <section id="pizza" className="section" style={{ background: "var(--cream)", color: "var(--ink)" }}>
      <div className="wrap">
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", flexWrap: "wrap", gap: 24, marginBottom: 60 }}>
          <div>
            <div className="tag" style={{ color: "var(--accent)" }}>03 — From the kitchen</div>
            <h2 className="display" style={{ fontSize: "clamp(56px, 8vw, 120px)", marginTop: 16, color: "var(--ink)" }}>
              And then there's<br/>
              <span style={{ color: "var(--accent)" }}>the food.</span>
            </h2>
            <p style={{ marginTop: 18, fontSize: 17, lineHeight: 1.6, maxWidth: 580, color: "var(--ink)" }}>
              Pineapple Robot is connected to <strong>Pizza Paradiso</strong> next door — gourmet thin-crust pizza, fresh kabobs, and Mediterranean comfort food.
            </p>
          </div>
          <a href={PIZZA_ORDER_URL} target="_blank" rel="noopener noreferrer" className="btn">Order online ↗</a>
        </div>

        <div className="pr-pizza__grid">
          {pizzas.slice(0, 10).map((p, i) => (
            <a
              key={`${p.name}-${i}`}
              href={PIZZA_ORDER_URL}
              target="_blank"
              rel="noopener noreferrer"
              style={{
                display: "flex", flexDirection: "column", color: "var(--ink)", textDecoration: "none",
                background: "var(--cream)", border: "3px solid var(--ink)", borderRadius: "var(--radius-md)",
                overflow: "hidden", boxShadow: "6px 6px 0 var(--ink)",
                transition: "transform .18s ease, box-shadow .18s ease",
              }}
              onMouseEnter={e => { e.currentTarget.style.transform = "translate(-3px, -3px)"; e.currentTarget.style.boxShadow = "9px 9px 0 var(--ink)"; }}
              onMouseLeave={e => { e.currentTarget.style.transform = "none"; e.currentTarget.style.boxShadow = "6px 6px 0 var(--ink)"; }}
            >
              <div style={{
                aspectRatio: "1/1", flexShrink: 0, background: PIZZA_COLORS[i % PIZZA_COLORS.length],
                position: "relative", overflow: "hidden",
                display: "grid", placeItems: "center",
                borderBottom: "3px solid var(--ink)",
              }}>
                {p.image ? (
                  <img
                    src={p.image}
                    alt={p.name}
                    loading="lazy"
                    style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", display: "block" }}
                    onError={e => { e.currentTarget.style.display = "none"; }}
                  />
                ) : null}
              </div>
              <div className="pr-pizza__body" style={{ padding: 22, flex: 1, display: "flex", flexDirection: "column" }}>
                <span className="display pr-pizza__name" style={{ fontSize: 26, color: "var(--ink)", display: "block" }}>{p.name}</span>
                <div style={{ marginTop: "auto", paddingTop: 14, fontFamily: "var(--sans)", fontWeight: 700, fontSize: 12, letterSpacing: ".05em", textTransform: "uppercase", color: "var(--accent)" }}>
                  Order online ↗
                </div>
              </div>
            </a>
          ))}
        </div>
        <div style={{ marginTop: 40, textAlign: "center", display: "grid", gap: 16, justifyItems: "center" }}>
          <div style={{ fontFamily: "var(--sans)", fontWeight: 600, fontSize: 13, letterSpacing: ".03em", color: "var(--ink)", opacity: 0.7 }}>
            12″ &amp; 14″ pies · build-your-own from $23.25 · gluten-free crust available · tap a pizza to order
          </div>
          <a href="https://pizzaparadiso.com/pizza-paradiso/pizza-menu/" target="_blank" rel="noopener noreferrer" className="btn btn--ghost">See the full menu →</a>
        </div>
      </div>
    </section>
  );
};

// ========== PRIVATE EVENTS ==========
const PRIVATE = [
  { title: "Reserve the lounge",          sub: "The whole tiki lounge, just your crew. Private karaoke, all night." },
  { title: "Birthdays & bachelorettes",   sub: "Bring the singers. We bring the mics, the mai tais, and the confetti energy." },
  { title: "Catering by Pizza Paradiso",  sub: "Wood-fired pizza, fresh kabobs & Mediterranean spreads from next door." },
];

// ========== CONTACT ==========
// Its own brown section between "Book the bar" and the sister-brands marquee.
const ContactForm = () => {
  const [sent, setSent] = useStateS(false);
  return (
    <section id="contact" className="section" style={{ background: "var(--espresso)", color: "var(--cream)", borderTop: "3px solid var(--ink)", borderBottom: "3px solid var(--ink)" }}>
      <div className="wrap">
        <div style={{ display: "grid", gap: 12, marginBottom: 44 }}>
          <div className="tag" style={{ color: "var(--accent-2)" }}>05 — Contact us</div>
          <h2 className="display" style={{ fontSize: "clamp(56px, 8vw, 120px)", color: "var(--cream)" }}>
            Drop us a <span style={{ color: "var(--accent-2)" }}>line.</span>
          </h2>
        </div>
        <div style={{ maxWidth: 620 }}>
          {sent ? (
            <div style={{ padding: "40px 0", textAlign: "center" }}>
              <div style={{ fontSize: 64 }}>🍍</div>
              <div className="display" style={{ fontSize: 44, marginTop: 12, color: "var(--accent-2)" }}>Mahalo!</div>
              <p style={{ fontFamily: "var(--sans)", fontWeight: 600, fontSize: 13, marginTop: 10, opacity: 0.7, letterSpacing: ".05em" }}>WE'LL GET BACK TO YOU FAST.</p>
            </div>
          ) : (
            <form onSubmit={e => { e.preventDefault(); setSent(true); }} style={{ display: "grid", gap: 20 }}>
              <div className="field">
                <label>Name</label>
                <input required placeholder="Your name" />
              </div>
              <div className="field">
                <label>Email</label>
                <input required type="email" placeholder="you@aloha.com" />
              </div>
              <div className="field">
                <label>About</label>
                <select>
                  <option>General hello</option>
                  <option>Private event</option>
                  <option>Catering</option>
                </select>
              </div>
              <div className="field">
                <label>Message</label>
                <textarea rows={3} placeholder="Tell us what you're thinking…" />
              </div>
              <button className="btn pr-cta-solo" type="submit" style={{ marginTop: 6, justifySelf: "start" }}>Send it →</button>
            </form>
          )}
        </div>
      </div>
    </section>
  );
};

const Events = () => (
  <section id="events" className="section" style={{ background: "var(--bg)", color: "var(--cream)", borderTop: "3px solid var(--ink)", borderBottom: "3px solid var(--ink)" }}>
    <div className="wrap">
      <div className="pr-private__grid" style={{ display: "grid", gap: 60, gridTemplateColumns: "1fr 1fr", alignItems: "center" }}>
        <div>
          <div className="tag" style={{ color: "var(--accent-2)" }}>04 — Book the bar</div>
          <h2 className="display" style={{ fontSize: "clamp(56px, 8vw, 120px)", marginTop: 16, color: "var(--cream)" }}>
            Your night,<br/>
            <span style={{ color: "var(--accent-2)" }}>your stage.</span>
          </h2>
          <p style={{ marginTop: 24, fontSize: 17, lineHeight: 1.6, maxWidth: 480, color: "var(--fg-soft)" }}>
            Planning a birthday, bachelorette, or team party? Take over Pineapple Robot for a private karaoke party — your playlist, our mics, tiki cocktails all night, and pizza straight from Pizza Paradiso next door.
          </p>
          <div className="pr-cta-solo" style={{ marginTop: 36, display: "flex", gap: 14, flexWrap: "wrap" }}>
            <a href="#contact" className="btn">Book a private event →</a>
          </div>
        </div>
        <div className="pr-private__list" style={{ display: "grid", gap: 0, border: "3px solid var(--ink)", borderRadius: "var(--radius-md)", overflow: "hidden", background: "var(--cream)" }}>
          {PRIVATE.map((p, i) => (
            <div key={p.title} className="pr-private__cell" style={{
              padding: 28,
              color: "var(--ink)",
              borderBottom: i < PRIVATE.length - 1 ? "2px solid var(--ink)" : "none",
              display: "grid", gap: 8,
              transition: "background .18s",
            }}
            onMouseEnter={e => e.currentTarget.style.background = "var(--accent-2)"}
            onMouseLeave={e => e.currentTarget.style.background = "transparent"}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
                <span className="display" style={{ fontSize: 26, lineHeight: 1.05, color: "var(--ink)" }}>{p.title}</span>
                <span className="tag" style={{ color: "var(--accent)", opacity: 0.8 }}>0{i+1}</span>
              </div>
              <div style={{ fontFamily: "var(--sans)", fontWeight: 600, fontSize: 13, letterSpacing: ".02em", color: "var(--ink)", opacity: 0.7 }}>{p.sub}</div>
            </div>
          ))}
        </div>
      </div>
    </div>
  </section>
);

// ========== PRESS ==========
const Press = () => (
  <section className="section" style={{ background: "var(--bg-2)", color: "var(--ink)", paddingTop: 0, paddingBottom: 0 }}>
    {/* sister brands — edge to edge */}
    <div style={{ padding: "28px 0", borderTop: "3px solid var(--ink)", borderBottom: "3px solid var(--ink)", overflow: "hidden", background: "var(--bg)" }}>
      <div style={{ textAlign: "center", marginBottom: 14 }}>
        <span className="tag" style={{ color: "var(--accent-2)" }}>Our sister brands on Maui</span>
      </div>
      <div className="marquee marquee--fast" style={{ fontFamily: "var(--display)", fontSize: 36, color: "var(--cream)" }}>
        {Array.from({ length: 4 }).map((_, i) => (
          <div key={i} style={{ display: "flex", gap: 40, paddingRight: 40, alignItems: "center" }}>
            <span>Pizza Paradiso</span><Diamond2 />
            <span style={{ color: "var(--accent-2)" }}>Mala Ocean Tavern</span><Diamond2 />
            <span>Down the Hatch</span><Diamond2 />
            <span style={{ color: "var(--accent-2)" }}>Coco Deck</span><Diamond2 />
            <span>Breakwall Shave Ice</span><Diamond2 />
          </div>
        ))}
      </div>
    </div>
  </section>
);

const Diamond2 = () => (
  <svg width="10" height="10" viewBox="0 0 14 14"><path d="M7 1 L13 7 L7 13 L1 7 Z" fill="currentColor" opacity="0.5" /></svg>
);

// ========== VISIT ==========
// One address, one link — the address line and the Directions button both
// point here.
const MAPS_ADDRESS = "3350 Lower Honoapiilani Road #208, Lahaina, HI 96761";
const MAPS_URL = "https://maps.google.com/?q=3350+Lower+Honoapiilani+Road+%23208,+Lahaina,+HI+96761";

// Google Maps Embed API key. Paste the key between the quotes to switch the map
// over — everything else is already wired.
//
// This key is PUBLIC by design: the Embed API is a client-side iframe, so the
// key ships in the page and there is no way to hide it. Security comes from
// restricting it in Google Cloud (Credentials → Application restrictions →
// Websites) to these referrers, NOT from keeping it secret:
//     https://pineapple-robot.vercel.app/*
//     http://localhost:3000/*
// Also restrict it under "API restrictions" to the Maps Embed API alone. The
// Embed API is free with no usage cap, so a referrer-locked key costs nothing
// even if someone copies it.
//
// While this is empty the map falls back to the keyless embed below, which
// renders and looks correct but can't be panned or zoomed by touch — that
// limitation is Google's, not ours, and the key is the only fix.
const MAPS_EMBED_KEY = "AIzaSyDjGlvfdDaLqlEe9yAJnyoScM8SA-5F2TM";

const MAP_SRC = MAPS_EMBED_KEY
  ? `https://www.google.com/maps/embed/v1/place?key=${MAPS_EMBED_KEY}&q=${encodeURIComponent(MAPS_ADDRESS)}&zoom=15`
  : "https://maps.google.com/maps?q=3350%20Lower%20Honoapiilani%20Road%20%23208%2C%20Lahaina%2C%20HI%2096761&z=15&output=embed";

const Visit = () => {
  return (
    <section id="visit" className="section" style={{ background: "var(--ink)", color: "var(--cream)" }}>
      <div className="wrap pr-visit__grid">
        {/* Visit us — details + directions */}
        <div>
          <div className="tag" style={{ color: "var(--accent-2)" }}>06 — Visit us</div>
          {/* Cap is 96px so the headline sits beside the map instead of
              towering over it. Only the max changes — below 960px the 10vw
              term is still what wins, so every mobile width renders exactly as
              it did before. */}
          <h2 className="display" style={{ fontSize: "clamp(64px, 10vw, 96px)", marginTop: 16, color: "var(--cream)" }}>
            Drink. Sing.<br/>
            <span style={{ color: "var(--accent-2)" }}>Be heard.</span>
          </h2>
          <div style={{ marginTop: 36, display: "grid", gap: 22, maxWidth: 640 }}>
            <Info
              label="Address"
              value="3350 Lower Honoapiilani Road #208, Lahaina, HI 96761"
              link={MAPS_URL}
              plain
            />
            <Info label="Call" value="(808) 667-2929" link="tel:+18086672929" big />
            <Info label="Hours" value={<>Open daily 11am – 1:30am · Late nights 9pm – 1:30am · Happy hour 12 – 5pm</>} />
            <Info label="Karaoke" value="Nightly · 9pm – 1:30am" />
          </div>
          <div className="pr-visit__cta" style={{ marginTop: 36, display: "flex", gap: 14, flexWrap: "wrap" }} id="order">
            <a href="https://pizzaparadiso.toast.site/order" target="_blank" rel="noopener noreferrer" className="btn pr-visit__order">Order online ↗</a>
            <a
              href={MAPS_URL}
              target="_blank" rel="noopener noreferrer"
              className="btn btn--ghost"
            >
              Directions ↗
            </a>
          </div>
        </div>

        {/* Map — beside the copy on desktop, under the Directions button on
            mobile. Both layouts live in .pr-visit__grid / .pr-visit__map. */}
        <div className="pr-visit__map">
          <div style={{ position: "relative", border: "3px solid var(--accent-2)", borderRadius: "var(--radius-lg)", overflow: "hidden", boxShadow: "10px 10px 0 var(--accent)", lineHeight: 0 }}>
            <iframe
              title="Pineapple Robot on Google Maps"
              src={MAP_SRC}
              width="100%"
              height="420"
              style={{ border: 0, display: "block", filter: "grayscale(0.1)" }}
              loading="lazy"
              // The Embed API checks the Referer header against the key's
              // allowed referrers, so the origin has to be sent.
              referrerPolicy="strict-origin-when-cross-origin"
              allowFullScreen
            />
            {/* Our own chip, sitting on top of the map. Google's in-frame
                "Open in Maps" control tries to deep-link the Maps app and
                silently does nothing on a lot of phones — we can't fix or
                restyle it (it lives in a cross-origin iframe), so this is the
                one that's guaranteed to work. Plain anchor, real href. */}
            <a
              href={MAPS_URL}
              target="_blank" rel="noopener noreferrer"
              className="btn pr-map__chip"
            >
              Open in Google Maps ↗
            </a>
          </div>
        </div>
      </div>
    </section>
  );
};

const Info = ({ label, value, link, big, plain }) => {
  const isExternal = typeof link === "string" && /^https?:/.test(link);
  return (
    <div style={{ display: "grid", gap: 6 }}>
      <span className="tag" style={{ color: "var(--accent-2)", opacity: 0.9 }}>{label}</span>
      {link ? (
        plain ? (
          <a
            href={link}
            target={isExternal ? "_blank" : undefined}
            rel={isExternal ? "noopener noreferrer" : undefined}
            className="pr-info__link"
            style={{ fontSize: 17, lineHeight: 1.5, color: "var(--accent-2)" }}
          >
            {value}
          </a>
        ) : (
          <a
            href={link}
            target={isExternal ? "_blank" : undefined}
            rel={isExternal ? "noopener noreferrer" : undefined}
            className="display pr-info__link"
            style={{ fontSize: big ? 56 : 22, color: "var(--accent-2)" }}
          >
            {value}
          </a>
        )
      ) : (
        <span style={{ fontSize: 17, lineHeight: 1.5, color: "var(--cream)" }}>{value}</span>
      )}
    </div>
  );
};

const MobileBottomBar = () => (
  <div className="pr-bottombar" role="navigation" aria-label="Order online">
    <a href="https://www.order.store/store/pizza-paradiso/EkcG-5cMVvGXKejiQ7Q8Xg" target="_blank" rel="noopener noreferrer" className="pr-bottombar__btn pr-bottombar__btn--call">
      Delivery ↗
    </a>
    <a href="https://pizzaparadiso.toast.site/order" target="_blank" rel="noopener noreferrer" className="pr-bottombar__btn pr-bottombar__btn--order">
      Takeout ↗
    </a>
  </div>
);

const Footer = () => (
  <footer style={{ background: "var(--ink)", color: "var(--cream)", padding: "32px 0", borderTop: "3px solid var(--accent)" }}>
    <div className="wrap" style={{ display: "flex", justifyContent: "space-between", flexWrap: "wrap", gap: 16, alignItems: "center" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
        <img src="assets/brand-logo-transparent.png" alt="Pineapple Robot" style={{ height: 56, filter: "brightness(0) invert(1)" }} />
      </div>
      <div style={{ fontFamily: "var(--sans)", fontWeight: 600, fontSize: 12, opacity: 0.6, letterSpacing: ".05em" }}>
        © 2026 PINEAPPLE ROBOT · PIZZA PARADISO · HONOKOWAI, MAUI
      </div>
      <div style={{ display: "flex", gap: 10 }}>
        <a href="https://instagram.com/pineapplerobotbar" target="_blank" rel="noopener noreferrer" className="tag" style={{ padding: "8px 16px", border: "2px solid var(--accent-2)", borderRadius: 999, color: "var(--accent-2)" }}>IG ↗</a>
        <a href="https://facebook.com/profile.php?id=61578838160666" target="_blank" rel="noopener noreferrer" className="tag" style={{ padding: "8px 16px", border: "2px solid var(--accent-2)", borderRadius: 999, color: "var(--accent-2)" }}>FB ↗</a>
      </div>
    </div>
  </footer>
);

window.Story = Story;
window.Cocktails = Cocktails;
window.Karaoke = Karaoke;
window.Pizza = Pizza;
window.Events = Events;
window.ContactForm = ContactForm;
window.Press = Press;
window.Visit = Visit;
window.Footer = Footer;
window.MobileBottomBar = MobileBottomBar;
