/* Geek n Wine — Editorial single-page Home */
const { useState, useEffect, useRef } = React;

const CLOSE_SECS = 11 * 3600 + 42 * 60 + 8;

const DROP = {
  sku: "GW-014", kicker: "Drop 014 · Tuscan Reserve",
  name: "The Tuesday Six", price: 89, claimed: 217, total: 500,
};

const WINES = [
  { code: "GW-014-01", name: "Chianti Classico", region: "Tuscany", grape: "Sangiovese", body: "Medium red", abv: "13.5%", pair: "tomato anything",
    note: "Bright cherry with a little tea-leaf edge — the kind of red that makes a Tuesday feel like a plan. No decanting, no fuss; pour it and go." },
  { code: "GW-014-02", name: "Bolgheri Vermentino", region: "Tuscan coast", grape: "Vermentino", body: "Crisp white", abv: "12.5%", pair: "anything off the grill",
    note: "Saline and citrus-skin, a sea-breeze white that disappears faster than you'd like. This is the patio bottle — serve it cold and don't overthink it." },
  { code: "GW-014-03", name: "Barbera d'Asti", region: "Piedmont", grape: "Barbera", body: "Juicy red", abv: "13%", pair: "pizza night",
    note: "All bramble fruit and zippy acidity, low on tannin — the people-pleaser of the box. Give it fifteen minutes in the fridge and it sings." },
  { code: "GW-014-04", name: "Langhe Nebbiolo", region: "Piedmont", grape: "Nebbiolo", body: "Structured red", abv: "14%", pair: "mushroom risotto",
    note: "Rose, tar and dried cherry — baby-Barolo energy at a fraction of the ask. The one wine here worth a ten-minute wait in the glass." },
  { code: "GW-014-05", name: "Montepulciano d'Abruzzo", region: "Abruzzo", grape: "Montepulciano", body: "Plush red", abv: "13.5%", pair: "a slow ragù",
    note: "Dark plum, soft and a touch smoky — the cozy one. This is the bottle you reach for when it starts raining and you cancel your plans." },
  { code: "GW-014-06", name: "Moscato d'Asti", region: "Piedmont", grape: "Moscato", body: "Off-dry sparkling", abv: "5.5%", pair: "fruit & cheese",
    note: "Lightly fizzy, peach and orange-blossom, barely sweet. The closer — pour it with dessert, or just because the night isn't over yet." },
];

const TAGLINES = [
  "You didn't pick the wine. That's the point.",
  "One of them might change your evening.",
  "Open it like you mean it.",
];

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "type": "Modern",
  "reserveReadout": "Boxes left",
  "oddsN": 11,
  "tagline": "You didn't pick the wine. That's the point.",
  "lineupOpen": true,
  "heroGlow": true
}/*EDITMODE-END*/;

/* ---------------- Nav ---------------- */
function Nav({ cart, onCart, theme, onToggleTheme }) {
  const { str } = useCountdown(CLOSE_SECS);
  const left = DROP.total - DROP.claimed;
  return (
    <React.Fragment>
      <div className="ticker">
        <LiveDot /> DROP 014 · TUSCAN RESERVE — LIVE · CLOSES IN <strong>{str}</strong> · {left} BOXES LEFT
      </div>
      <nav className="nav">
        <div className="ed-wrap nav-in">
          <a href="#top" style={{ display: "flex" }}>
            <span className="wm-light"><Wordmark width={186} /></span>
            <span className="wm-dark"><Wordmark width={186} paper /></span>
          </a>
          <div className="nav-links">
            <a href="#lineup">The lineup</a>
            <a href="#surprise">The surprise</a>
            <a href="#how">How it works</a>
            <button className="theme-btn" onClick={onToggleTheme} title={theme === "light" ? "Switch to dark" : "Switch to light"} aria-label="Toggle theme">
              <i data-lucide={theme === "light" ? "moon" : "sun"} style={{ width: 16, height: 16 }}></i>
            </button>
            <button className="cart" onClick={onCart}>
              <i data-lucide="package" style={{ width: 16, height: 16 }}></i>
              Cellar · {cart}
            </button>
          </div>
        </div>
      </nav>
    </React.Fragment>
  );
}

/* ---------------- Hero ---------------- */
function Hero({ t, onClaim }) {
  const { h, m, s } = useCountdown(CLOSE_SECS);
  return (
    <header className="ed-wrap hero-ed">
      <span className="pill pill-live"><LiveDot /> Live now · Drop 014</span>
      <h1>Six bottles.<br />Seventy&#8209;two hours.</h1>
      <p className="tagline">{t.tagline}</p>
      <TimerBar h={h} m={m} s={s} center />
      <div className="boxstage">
        {t.heroGlow && <div className="glow"></div>}
        <WineCrate size={384} sku={DROP.sku} hint hintText={`1 in ${t.oddsN} hides a Reserve`} sealed />
      </div>
      <ReserveBar claimed={DROP.claimed} total={DROP.total} readout={t.reserveReadout} />
      <div className="cta-row">
        <button className="btn btn-volt btn-lg" onClick={() => onClaim(DROP)}>
          <i data-lucide="sparkles" style={{ width: 18, height: 18 }}></i>Claim a box · ${DROP.price}
        </button>
        <a href="#lineup" className="btn btn-ghost btn-lg" style={{ textDecoration: "none" }}>
          See the lineup <i data-lucide="arrow-down" style={{ width: 16, height: 16 }}></i>
        </a>
      </div>
      <p className="note" style={{ marginTop: 14 }}>2 per person · ships Monday · 21+</p>
    </header>
  );
}

/* ---------------- Surprise band ---------------- */
function SurpriseBand({ t }) {
  return (
    <section id="surprise" className="ed-wrap section2">
      <div className="surprise-band">
        <div>
          <span className="kicker volt">The hook · why it's worth it</span>
          <h2>One in every {t.oddsN - 1}&ndash;{t.oddsN + 1} boxes hides a <em>Reserve</em>.</h2>
          <p>
            Most boxes are a brilliant, fairly-priced six. But a hidden fraction of every drop
            tucks in a high-end bottle worth far more than the box price — a 2016 Brunello,
            a back-vintage Barolo. You don't know if you got one until you open it.
          </p>
          <div style={{ display: "flex", gap: 10, flexWrap: "wrap" }}>
            <span className="pill pill-hidden"><VoltDrop size={13} />Volt means a surprise is live</span>
            <span className="pill pill-low"><GoldStar size={13} />Gold means you got one</span>
          </div>
        </div>
        <div className="odds-wrap">
          <div className="odds-head">
            <span className="kicker">The odds · per drop</span>
            <span className="pill pill-hidden">≈ 1 in {t.oddsN}</span>
          </div>
          <OddsGrid n={t.oddsN} />
          <p className="note" style={{ marginTop: 14, textAlign: "center" }}>One glowing box ≈ the hidden Reserve. The rest are still a great night.</p>
        </div>
      </div>
    </section>
  );
}

/* ---------------- How it works ---------------- */
function HowItWorks() {
  return (
    <section id="how" className="ed-wrap section2" style={{ paddingTop: 0 }}>
      <div className="sec-head">
        <div>
          <span className="kicker volt">How the drop works</span>
          <h2 style={{ maxWidth: "16ch" }}>You don't pick the wine.<br />That's the whole point.</h2>
        </div>
      </div>
      <div className="steps3">
        <Step n="01 — DROP" title="Limited time, limited count">A box drops on a 72-hour timer, capped at 500. When the counter hits zero it's gone — the reserve bar up top is that countdown, draining live.</Step>
        <Step n="02 — SURPRISE" title="A Reserve might be inside">Roughly one box in eleven hides a high-end bottle worth multiples of the price. The volt drop means those odds are live right now.</Step>
        <Step n="03 — UNBOX" title="Open it to find out">Your box ships sealed. Crack it open — most are a flawless six, a lucky few pull gold. Either way, you drank well above your spend.</Step>
      </div>
    </section>
  );
}

/* ---------------- Lineup accordion ---------------- */
function Lineup({ t }) {
  const [openIdx, setOpenIdx] = useState(t.lineupOpen ? 0 : -1);
  useEffect(() => { setOpenIdx(t.lineupOpen ? 0 : -1); }, [t.lineupOpen]);
  return (
    <section id="lineup" className="ed-wrap section2" style={{ paddingTop: 0 }}>
      <div className="divline" style={{ marginBottom: 44 }}></div>
      <div className="sec-head">
        <div>
          <span className="kicker">What's in the box · Drop 014</span>
          <h2>The Tuesday Six</h2>
          <p className="sub">Six bottles picked to play together across a week. Tap any to read it.</p>
        </div>
        <span className="pill pill-neutral" style={{ alignSelf: "center" }}>6 bottles · all revealed</span>
      </div>
      <div className="acc2">
        {WINES.map((w, i) => (
          <WineRow key={w.code} wine={w} idx={i} open={openIdx === i}
            onToggle={() => setOpenIdx(openIdx === i ? -1 : i)} />
        ))}
      </div>
      <p className="note" style={{ marginTop: 16 }}>
        Plus — in roughly 1 box of {t.oddsN} — a sealed Reserve you won't see on this list until you open it.
      </p>
    </section>
  );
}

/* ---------------- Provenance ---------------- */
function Provenance() {
  return (
    <section className="ed-wrap section2" style={{ paddingTop: 0 }}>
      <div className="divline" style={{ marginBottom: 44 }}></div>
      <div className="prov">
        <div>
          <span className="kicker">Why trust the box</span>
          <h2>We taste 400 wines so you taste six.</h2>
          <p>No algorithm, no filler. A small team tastes blind through hundreds of bottles each season and only the ones worth your Tuesday make the box. The surprise is the fun part — the baseline is just good wine.</p>
        </div>
        <div className="statgrid">
          <div className="stat"><b>400+</b><span>wines tasted blind per season</span></div>
          <div className="stat"><b>6</b><span>that make it into the box</span></div>
          <div className="stat"><b>500</b><span>boxes per drop, then it's gone</span></div>
          <div className="stat"><b className="stat-volt">1:11</b><span>boxes hide a high-end Reserve</span></div>
        </div>
      </div>
    </section>
  );
}

/* ---------------- Claim drawer ---------------- */
function ClaimDrawer({ open, drop, onClose, onConfirm, oddsN }) {
  const [qty, setQty] = useState(1);
  const [email, setEmail] = useState("");
  useEffect(() => { if (open) { setQty(1); setEmail(""); } }, [open]);
  if (!drop) return null;
  return (
    <div className={"scrim" + (open ? " open" : "")} onClick={onClose}>
      <div className="drawer" onClick={(e) => e.stopPropagation()}>
        <div style={{ padding: "24px 26px" }}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 22 }}>
            <p className="kicker" style={{ margin: 0 }}>Claim your box</p>
            <button onClick={onClose} style={{ background: "none", border: 0, color: "var(--fg-2)", cursor: "pointer" }}><i data-lucide="x" style={{ width: 20, height: 20 }}></i></button>
          </div>
          <div style={{ display: "flex", gap: 16, background: "var(--ink-700)", border: "1px solid var(--border)", borderRadius: 14, padding: 14, marginBottom: 24 }}>
            <div style={{ width: 92, flex: "none" }}><BoxVisual size={92} sku={drop.sku} hint={false} sealed /></div>
            <div>
              <p className="kicker" style={{ margin: "2px 0 6px" }}>{drop.kicker}</p>
              <h3 style={{ fontSize: 18, fontWeight: 700, margin: "0 0 8px" }}>{drop.name}</h3>
              <span className="pill pill-hidden" style={{ fontSize: 10 }}><VoltDrop size={11} />1 in {oddsN} odds live</span>
            </div>
          </div>
          <label className="kicker" style={{ display: "block", marginBottom: 10 }}>Quantity · max 2</label>
          <div className="stepper" style={{ marginBottom: 24 }}>
            <button onClick={() => setQty((q) => Math.max(1, q - 1))}>–</button>
            <span className="q">{qty}</span>
            <button onClick={() => setQty((q) => Math.min(2, q + 1))}>+</button>
          </div>
          <label className="kicker" style={{ display: "block", marginBottom: 10 }}>Email for your drop receipt</label>
          <input className="fld" placeholder="you@table.com" value={email} onChange={(e) => setEmail(e.target.value)} style={{ marginBottom: 26 }} />
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 18 }}>
            <span className="note">{qty} box{qty > 1 ? "es" : ""} × ${drop.price}</span>
            <b style={{ fontSize: 26, fontWeight: 700 }}>${drop.price * qty}</b>
          </div>
          <button className="btn btn-volt btn-lg" style={{ width: "100%", justifyContent: "center" }} onClick={() => onConfirm(qty)}>
            <i data-lucide="lock" style={{ width: 17, height: 17 }}></i>Claim {qty} box{qty > 1 ? "es" : ""}
          </button>
          <p className="note" style={{ textAlign: "center", marginTop: 14 }}>Sealed on claim · ships Monday · 21+</p>
        </div>
      </div>
    </div>
  );
}

/* ---------------- Unbox reveal (signature moment) ---------------- */
function UnboxModal({ open, onClose, reserve, oddsN }) {
  const [stage, setStage] = useState("sealed");
  useEffect(() => { if (open) setStage("sealed"); }, [open]);
  const lift = () => { setStage("opening"); setTimeout(() => setStage("revealed"), 900); };
  return (
    <div className={"scrim" + (open ? " open" : "")} onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <div style={{ padding: "30px 30px 26px", textAlign: "center", position: "relative" }}>
          <button onClick={onClose} style={{ position: "absolute", top: 18, right: 18, background: "none", border: 0, color: "var(--fg-2)", cursor: "pointer" }}><i data-lucide="x" style={{ width: 20, height: 20 }}></i></button>
          {stage !== "revealed" && (
            <React.Fragment>
              <p className="kicker volt" style={{ marginBottom: 22 }}>Box 3 of 500 · GW-014</p>
              <div style={{ position: "relative", width: 220, margin: "0 auto 26px", transition: "transform .9s var(--ease-out)", transform: stage === "opening" ? "translateY(8px) scale(1.03)" : "none" }}>
                <div style={{ position: "absolute", inset: -30, background: "radial-gradient(circle, var(--volt-glow), transparent 70%)", opacity: stage === "opening" ? 1 : 0, transition: "opacity .9s" }}></div>
                <div style={{ position: "relative" }}><WineCrate size={220} sku="GW-014" hint={false} sealed /></div>
              </div>
              <h2 style={{ fontSize: 26, fontWeight: 700, letterSpacing: "-.02em", margin: "0 0 8px" }}>Open it like you mean it.</h2>
              <p className="note" style={{ marginBottom: 24 }}>Most boxes are a brilliant six. A lucky few pull gold.</p>
              <button className="btn btn-volt btn-lg" onClick={lift} disabled={stage === "opening"}>
                <i data-lucide="sparkles" style={{ width: 17, height: 17 }}></i>{stage === "opening" ? "Opening…" : "Lift the lid"}
              </button>
            </React.Fragment>
          )}
          {stage === "revealed" && reserve && (
            <div style={{ animation: "fadeUp .5s var(--ease-out)" }}>
              <span style={{ display: "inline-block", marginBottom: 14 }}><GoldStar size={46} /></span>
              <p className="kicker" style={{ color: "var(--gold-500)", marginBottom: 10 }}>Reserve hit · 1 in {oddsN}</p>
              <h2 style={{ fontSize: 30, fontWeight: 700, letterSpacing: "-.02em", margin: "0 0 10px" }}>You pulled a Reserve.</h2>
              <p style={{ color: "var(--fg-2)", fontSize: 15, lineHeight: 1.6, margin: "0 auto 22px", maxWidth: "34ch" }}>
                Tucked under the six: a <strong style={{ color: "var(--gold-300)" }}>2016 Brunello di Montalcino</strong>, normally $140 a bottle. It's yours.
              </p>
              <div className="pill pill-low" style={{ marginBottom: 24 }}>Box value · $310 for $89</div>
              <div><button className="btn btn-primary" onClick={onClose}>Add to my cellar</button></div>
            </div>
          )}
          {stage === "revealed" && !reserve && (
            <div style={{ animation: "fadeUp .5s var(--ease-out)" }}>
              <p className="kicker volt" style={{ marginBottom: 10 }}>The six, revealed</p>
              <h2 style={{ fontSize: 28, fontWeight: 700, letterSpacing: "-.02em", margin: "0 0 14px" }}>A brilliant Tuesday six.</h2>
              <div style={{ textAlign: "left", margin: "0 auto 22px", maxWidth: 320 }}>
                {WINES.map((w, i) => (
                  <div key={i} className="mono" style={{ fontSize: 13, color: "var(--fg-2)", padding: "8px 0", borderBottom: "1px solid var(--ink-700)" }}>{String(i + 1).padStart(2, "0")} · {w.name}</div>
                ))}
              </div>
              <button className="btn btn-primary" onClick={onClose}>Add to my cellar</button>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

/* ---------------- App ---------------- */
function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [drawer, setDrawer] = useState({ open: false, drop: null });
  const [cart, setCart] = useState(0);
  const [unbox, setUnbox] = useState(false);
  const [hasBox, setHasBox] = useState(false);
  const [showBar, setShowBar] = useState(false);
  const [theme, setTheme] = useState(() => localStorage.getItem("gw-theme") || "dark");
  const firstRef = useRef(true);

  useEffect(() => { if (window.lucide) lucide.createIcons(); });
  useEffect(() => {
    document.documentElement.dataset.theme = theme;
    localStorage.setItem("gw-theme", theme);
  }, [theme]);
  useEffect(() => {
    const onScroll = () => setShowBar(window.scrollY > window.innerHeight * 0.85);
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  const claim = (drop) => setDrawer({ open: true, drop });
  const confirm = (qty) => { setCart((c) => c + qty); setDrawer({ open: false, drop: null }); setHasBox(true); };
  const reserve = firstRef.current ? true : Math.random() < 0.4;

  return (
    <div className="type-root" data-type={(t.type || "Editorial").toLowerCase()}>
      <Nav cart={cart} onCart={() => hasBox && setUnbox(true)} theme={theme} onToggleTheme={() => setTheme((v) => (v === "light" ? "dark" : "light"))} />
      <Hero t={t} onClaim={claim} />
      <SurpriseBand t={t} />
      <HowItWorks />
      <Lineup t={t} />
      <Provenance />
      <Footer />

      {/* sticky claim / unbox bar */}
      <div className={"claimbar" + (showBar ? " show" : "")}>
        <div className="ed-wrap claimbar-in">
          <div className="l">
            <div style={{ width: 42, flex: "none" }}><BoxVisual size={42} sku={DROP.sku} hint={false} sealed /></div>
            {hasBox
              ? <span><b>You've got a sealed box.</b><span className="meta-hide"> — open it now to see what you pulled.</span></span>
              : <span><b>{DROP.name}</b> · ${DROP.price}<span className="meta-hide"> / box of 6 · {DROP.total - DROP.claimed} left</span></span>}
          </div>
          {hasBox
            ? <button className="btn btn-volt" onClick={() => setUnbox(true)}><i data-lucide="sparkles" style={{ width: 16, height: 16 }}></i>Unbox now</button>
            : <button className="btn btn-volt" onClick={() => claim(DROP)}><i data-lucide="sparkles" style={{ width: 16, height: 16 }}></i>Claim a box</button>}
        </div>
      </div>

      <ClaimDrawer open={drawer.open} drop={drawer.drop} oddsN={t.oddsN} onClose={() => setDrawer({ open: false, drop: null })} onConfirm={confirm} />
      <UnboxModal open={unbox} reserve={reserve} oddsN={t.oddsN} onClose={() => { firstRef.current = false; setUnbox(false); }} />

      <TweaksPanel>
        <TweakSection label="The drop" />
        <TweakRadio label="Reserve readout" value={t.reserveReadout} options={["Boxes left", "Percent", "Both"]} onChange={(v) => setTweak("reserveReadout", v)} />
        <TweakSlider label="Surprise odds (1 in N)" value={t.oddsN} min={10} max={12} step={1} onChange={(v) => setTweak("oddsN", v)} />
        <TweakSection label="Type & layout" />
        <TweakRadio label="Typeface" value={t.type} options={["Editorial", "Modern", "Classic"]} onChange={(v) => setTweak("type", v)} />
        <TweakSelect label="Hero tagline" value={t.tagline} options={TAGLINES} onChange={(v) => setTweak("tagline", v)} />
        <TweakToggle label="First wine open" value={t.lineupOpen} onChange={(v) => setTweak("lineupOpen", v)} />
        <TweakToggle label="Hero volt glow" value={t.heroGlow} onChange={(v) => setTweak("heroGlow", v)} />
      </TweaksPanel>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
