// obsidian-sections.jsx — additional sections + ticket flow + modal shell
// for the full Obsidian landing prototype. Reuses obsidianStyles from
// direction-obsidian.jsx.

// ─────────────────────────────────────────────────────────────────────
// MODAL SHELL — common to ticket + sponsor flows on the full prototype
// ─────────────────────────────────────────────────────────────────────
function ObsidianModal({ open, onClose, children }) {
  const { mobile, tablet } = useMobile();
  React.useEffect(() => {
    if (!open) return;
    const onKey = (e) => {if (e.key === 'Escape') onClose();};
    document.addEventListener('keydown', onKey);
    document.body.style.overflow = 'hidden';
    return () => {
      document.removeEventListener('keydown', onKey);
      document.body.style.overflow = '';
    };
  }, [open, onClose]);

  if (!open) return null;
  const s = obsidianStyles;

  return (
    <div
      onClick={onClose}
      style={{
        position: 'fixed', inset: 0, zIndex: 1000,
        background: 'rgba(5,5,4,0.84)',
        backdropFilter: 'blur(12px)', WebkitBackdropFilter: 'blur(12px)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        padding: mobile ? 8 : 32, animation: 'fadeIn 0.25s ease-out'
      }}>

      <style>{`@keyframes fadeIn{from{opacity:0}to{opacity:1}}@keyframes slideUp{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}`}</style>
      <div
        onClick={(e) => e.stopPropagation()}
        style={{
          width: '100%', maxWidth: mobile ? '100%' : 1280, height: mobile ? '95vh' : '88vh', maxHeight: mobile ? 'none' : 880,
          background: s.bg, border: `1px solid ${s.gold}40`,
          position: 'relative', overflow: 'hidden',
          boxShadow: '0 40px 120px rgba(0,0,0,0.6), 0 0 0 1px rgba(201,162,76,0.08)',
          animation: 'slideUp 0.32s cubic-bezier(0.16,1,0.3,1)'
        }}>

        <button onClick={onClose} aria-label="Close" style={{
          position: 'absolute', top: 20, right: 20, zIndex: 10,
          background: 'transparent', color: s.cream, border: `1px solid ${s.graySoft}`,
          width: 36, height: 36, cursor: 'pointer', fontFamily: s.sans, fontSize: 16,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          transition: 'all 0.2s'
        }}
        onMouseEnter={(e) => {e.currentTarget.style.borderColor = s.gold;e.currentTarget.style.color = s.gold;}}
        onMouseLeave={(e) => {e.currentTarget.style.borderColor = s.graySoft;e.currentTarget.style.color = s.cream;}}>
          ×</button>
        {children}
      </div>
    </div>);

}

// ─────────────────────────────────────────────────────────────────────
// OBSIDIAN TICKET FLOW
// ─────────────────────────────────────────────────────────────────────
function ObsidianTicketFlow({ onClose }) {
  const s = obsidianStyles;
  const f = useTicketFlow();
  const { mobile, tablet } = useMobile();
  const px = mobile ? 24 : 56;

  const StepDot = ({ n, label }) =>
  <div style={{ display: 'flex', alignItems: 'center', gap: mobile ? 6 : 10 }}>
      <div style={{
      width: 24, height: 24, borderRadius: '50%',
      border: `1px solid ${f.step >= n ? s.gold : s.graySoft}`,
      background: f.step > n ? s.gold : 'transparent',
      color: f.step > n ? s.bg : f.step === n ? s.gold : s.gray,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      fontFamily: s.mono, fontSize: 10, fontWeight: 500
    }}>{f.step > n ? '✓' : n}</div>
      {!mobile && <span style={{
      fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase',
      color: f.step >= n ? s.cream : s.gray
    }}>{label}</span>}
    </div>;


  const Btn = ({ children, primary, onClick, disabled }) =>
  <button onClick={onClick} disabled={disabled} style={{
    background: primary ? s.gold : 'transparent',
    color: primary ? s.bg : s.gold,
    border: primary ? 'none' : `1px solid ${s.gold}`,
    padding: mobile ? '12px 20px' : '14px 32px', fontSize: 11, letterSpacing: '0.2em', textTransform: 'uppercase',
    fontWeight: 500, cursor: disabled ? 'not-allowed' : 'pointer', fontFamily: s.sans,
    opacity: disabled ? 0.3 : 1, transition: 'all 0.2s'
  }}>{children}</button>;


  return (
    <div style={{
      width: '100%', height: '100%', background: s.bg, color: s.cream, fontFamily: s.sans,
      padding: mobile ? '32px 24px 24px' : '44px 56px 36px', display: 'flex', flexDirection: 'column', gap: mobile ? 16 : 24, position: 'relative', overflow: 'hidden'
    }}>
      <div style={{ position: 'absolute', right: -120, top: -80, opacity: 0.04, color: s.gold }}>
        <CrownGlyph size={520} stroke={0.6} />
      </div>

      {/* header */}
      <div style={{ display: 'flex', alignItems: mobile ? 'center' : 'flex-start', justifyContent: 'space-between', position: 'relative', zIndex: 2, flexDirection: mobile ? 'column' : 'row', gap: mobile ? 16 : 0 }}>
        <div>
          <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.22em', color: s.gold, marginBottom: 8 }}>RESERVATIONS · OCTOBER 17 · 2026</div>
          <div style={{ fontFamily: s.serif, fontSize: mobile ? 28 : 44, fontWeight: 300, lineHeight: 1 }}>
            Reserve <span style={{ fontStyle: 'italic', color: s.gold }}>your seat.</span>
          </div>
        </div>
        <div style={{ display: 'flex', gap: mobile ? 12 : 28, alignItems: 'center', paddingTop: mobile ? 0 : 12, paddingRight: mobile ? 0 : 44 }}>
          <StepDot n={1} label="Seat" />
          <div style={{ width: mobile ? 12 : 20, height: 1, background: s.graySoft }} />
          <StepDot n={2} label="Quantity" />
          <div style={{ width: mobile ? 12 : 20, height: 1, background: s.graySoft }} />
          <StepDot n={3} label="Checkout" />
        </div>
      </div>

      {/* steps */}
      <div style={{ flex: 1, position: 'relative', zIndex: 2, minHeight: 0, overflowY: mobile ? 'auto' : 'visible' }}>

        {f.step === 1 &&
        <div style={{ display: 'flex', flexDirection: 'column', gap: 16, height: '100%' }}>
            {/* Early bird toggle */}
            <div style={{
            display: 'flex', alignItems: mobile ? 'flex-start' : 'center', justifyContent: 'space-between',
            padding: mobile ? '12px 14px' : '14px 20px', background: s.bgSoft, border: `1px solid ${f.earlyBird ? s.gold : s.graySoft}`,
            flexDirection: mobile ? 'column' : 'row', gap: mobile ? 12 : 0
          }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
                <div style={{
                width: 8, height: 8, borderRadius: '50%',
                background: f.earlyBird ? s.gold : s.gray,
                boxShadow: f.earlyBird ? `0 0 12px ${s.gold}99` : 'none'
              }} />
                <div>
                  <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.22em', color: f.earlyBird ? s.gold : s.gray }}>
                    {f.earlyBird ? '◇ EARLY BIRD ACTIVE · LIMITED TIME' : 'REGULAR PRICING'}
                  </div>
                  <div style={{ fontSize: 12, color: s.cream, opacity: 0.7, marginTop: 2 }}>
                    {f.earlyBird ? 'Early bird pricing automatically applied — reserve before doors release.' : 'Early bird window closed.'}
                  </div>
                </div>
              </div>
              <button onClick={() => f.setEarlyBird((v) => !v)} style={{
              background: 'transparent', color: f.earlyBird ? s.gold : s.gray,
              border: `1px solid ${f.earlyBird ? s.gold : s.graySoft}`, padding: '8px 14px',
              fontFamily: s.mono, fontSize: 10, letterSpacing: '0.18em', textTransform: 'uppercase',
              cursor: 'pointer'
            }}>{f.earlyBird ? 'Toggle off' : 'Toggle on'}</button>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: mobile ? '1fr' : 'repeat(4, 1fr)', gap: 14, flex: 1, minHeight: 0 }}>
            {TICKET_TYPES.map((t, i) => {
              const sel = f.ticketId === t.id;
              const displayPrice = f.earlyBird ? t.earlyPrice : t.price;
              return (
                <button key={t.id} onClick={() => f.setTicketId(t.id)} style={{
                  background: sel ? `linear-gradient(180deg, ${s.gold}18, ${s.gold}04)` : s.bgSoft,
                  border: `1px solid ${sel ? s.gold : s.graySoft}`,
                  padding: '24px 24px', textAlign: 'left', cursor: 'pointer',
                  fontFamily: s.sans, color: s.cream, display: 'flex', flexDirection: 'column',
                  transition: 'all 0.25s', position: 'relative', overflow: 'hidden'
                }}>
                  {sel && <div style={{ position: 'absolute', top: 14, right: 14, color: s.gold, fontFamily: s.mono, fontSize: 11 }}>●</div>}
                  <div style={{ fontFamily: s.mono, fontSize: 9.5, letterSpacing: '0.22em', color: sel ? s.gold : s.gray, marginBottom: 12 }}>
                    TIER {String(i + 1).padStart(2, '0')} · {t.badge.toUpperCase()}
                  </div>
                  <div style={{ fontFamily: s.serif, fontSize: 24, fontWeight: 400, fontStyle: 'italic', color: sel ? s.gold : s.cream, lineHeight: 1.1, marginBottom: 6 }}>
                    {t.name}
                  </div>
                  <div style={{ fontSize: 11.5, color: s.cream, opacity: 0.6, marginBottom: 14, lineHeight: 1.55 }}>{t.desc}</div>

                  {/* price block */}
                  <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, marginBottom: 4 }}>
                    <div style={{ fontFamily: s.serif, fontStyle: 'italic', fontSize: 36, color: s.cream }}>
                      ${displayPrice}
                    </div>
                    {f.earlyBird &&
                    <div style={{ fontFamily: s.serif, fontSize: 18, color: s.gray, textDecoration: 'line-through' }}>
                        ${t.price}
                      </div>
                    }
                  </div>
                  <div style={{ fontFamily: s.mono, fontSize: 9.5, letterSpacing: '0.18em', textTransform: 'uppercase', color: f.earlyBird ? s.gold : s.gray, marginBottom: 14 }}>
                    {f.earlyBird ? `◇ EARLY BIRD · SAVE $${t.price - t.earlyPrice}` : 'PER TICKET'}
                  </div>
                  <div style={{ height: 1, background: sel ? `${s.gold}44` : s.graySoft, marginBottom: 14 }} />
                  <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 6, flex: 1, minHeight: 0 }}>
                    {t.perks.map((p, j) =>
                    <li key={j} style={{ fontSize: 11, lineHeight: 1.45, color: s.cream, opacity: 0.78, display: 'flex', gap: 8 }}>
                        <span style={{ color: s.gold, opacity: 0.85, flexShrink: 0 }}>—</span><span>{p}</span>
                      </li>
                    )}
                  </ul>
                </button>);
            })}
            </div>
          </div>
        }

        {f.step === 2 &&
        <div style={{ display: 'grid', gridTemplateColumns: mobile ? '1fr' : '1fr 1fr', gap: 32, height: '100%' }}>
            <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center', gap: 24 }}>
              <div>
                <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.22em', color: s.gold, marginBottom: 8 }}>HOW MANY?</div>
                <div style={{ fontFamily: s.serif, fontSize: mobile ? 26 : 32, fontWeight: 300 }}>
                  How many <span style={{ fontStyle: 'italic', color: s.gold }}>tickets?</span>
                </div>
                <p style={{ fontSize: 13, color: s.cream, opacity: 0.65, marginTop: 12, maxWidth: 380, lineHeight: 1.7 }}>
                  Bringing a group of 4+? Reach out and we'll arrange complimentary side-by-side seating and a welcome touch on arrival.
                </p>
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 24 }}>
                <button onClick={() => f.setQty((q) => Math.max(1, q - 1))}
              style={{ width: 64, height: 64, background: 'transparent', border: `1px solid ${s.gold}`, color: s.gold, fontSize: 22, cursor: 'pointer', fontFamily: s.serif }}>−</button>
                <div style={{ fontFamily: s.serif, fontSize: mobile ? 64 : 96, fontWeight: 300, color: s.cream, minWidth: 80, textAlign: 'center', lineHeight: 1 }}>
                  {f.qty}
                </div>
                <button onClick={() => f.setQty((q) => Math.min(12, q + 1))}
              style={{ width: 64, height: 64, background: 'transparent', border: `1px solid ${s.gold}`, color: s.gold, fontSize: 22, cursor: 'pointer', fontFamily: s.serif }}>+</button>
              </div>
            </div>
            {/* summary card */}
            <div style={{ background: s.bgSoft, border: `1px solid ${s.graySoft}`, padding: mobile ? 24 : 32, display: 'flex', flexDirection: 'column' }}>
              <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.22em', color: s.gold, marginBottom: 12 }}>YOUR RESERVATION</div>
              <div style={{ fontFamily: s.serif, fontSize: mobile ? 22 : 28, fontWeight: 400, lineHeight: 1.1 }}>{f.ticket.name}</div>
              <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.2em', color: s.gold, marginTop: 6 }}>{f.ticket.badge.toUpperCase()}</div>
              <div style={{ height: 1, background: s.graySoft, margin: '20px 0' }} />
              <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13, marginBottom: 10 }}>
                <span style={{ color: s.cream, opacity: 0.75 }}>
                  ${f.unitPrice} × {f.effectiveQty} {f.earlyBird ? <span style={{ color: s.gold, marginLeft: 6 }}>· early bird</span> : null}
                </span>
                <span>{money(f.subtotal)}</span>
              </div>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13, marginBottom: 10 }}>
                <span style={{ color: s.cream, opacity: 0.55 }}>Service fees</span>
                <span style={{ color: s.cream, opacity: 0.8 }}>{money(f.fees)}</span>
              </div>
              <div style={{ flex: 1 }} />
              <div style={{ height: 1, background: s.graySoft, margin: '12px 0' }} />
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
                <span style={{ fontSize: 11, letterSpacing: '0.2em', textTransform: 'uppercase', color: s.gold }}>Total</span>
                <span style={{ fontFamily: s.serif, fontSize: mobile ? 28 : 38, color: s.gold, fontStyle: 'italic' }}>{money(f.total)}</span>
              </div>
              <div style={{ fontSize: 10, color: s.gray, marginTop: 10, letterSpacing: '0.06em' }}>
                {f.ticket.id === 'vip' ? 'The ultimate experience · reserved seating · VIP gift bag.' :
              f.ticket.id === 'gold' ? 'Includes everything · refreshments → after-party · attendee gift bag.' :
              f.ticket.id === 'silver' ? 'Cultural moments · runway · panel · performances · after party.' :
              'After-party access · DJ set · live performances · cash bar.'}
              </div>
            </div>
          </div>
        }

        {f.step === 3 &&
        <div style={{ display: 'grid', gridTemplateColumns: mobile ? '1fr' : '1fr 1fr', gap: 32, height: '100%' }}>
            <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
              <div style={{ fontFamily: s.serif, fontSize: mobile ? 28 : 40, fontWeight: 300, lineHeight: 1.1, marginBottom: 16 }}>
                Complete your <span style={{ fontStyle: 'italic', color: s.gold }}>reservation.</span>
              </div>
              <p style={{ fontSize: 14, color: s.cream, opacity: 0.7, lineHeight: 1.7, marginBottom: 28, maxWidth: 420 }}>
                A secure checkout window will open to complete your purchase via Ticket Tailor. Payment is processed securely via Stripe.
              </p>
              <button onClick={() => {
                const w = 520, h = 720;
                const left = (screen.width - w) / 2, top = (screen.height - h) / 2;
                const checkoutUrl = TT_CHECKOUT + '?type=' + f.ticket.ttId + '&quantity=' + f.effectiveQty;
                window.open(checkoutUrl, 'ElevateNoirCheckout', `width=${w},height=${h},left=${left},top=${top},menubar=no,toolbar=no,location=yes,status=no,scrollbars=yes`);
              }} style={{
                display: 'inline-flex', alignItems: 'center', gap: 10,
                background: s.gold, color: s.bg, border: 'none',
                padding: '16px 32px', fontSize: 12, letterSpacing: '0.18em', textTransform: 'uppercase',
                fontWeight: 600, cursor: 'pointer', fontFamily: s.sans,
                alignSelf: 'flex-start'
              }}>
                Proceed to secure checkout →
              </button>
              <div style={{ marginTop: 16, display: 'flex', alignItems: 'center', gap: 8 }}>
                <svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M8 1a5 5 0 00-5 5v2a2 2 0 00-1 1.73V13a2 2 0 002 2h8a2 2 0 002-2V9.73A2 2 0 0013 8V6a5 5 0 00-5-5zm-3 5a3 3 0 116 0v2H5V6z" fill={s.gray}/></svg>
                <span style={{ fontSize: 11, color: s.gray }}>Secured by Stripe · Ticket Tailor</span>
              </div>
            </div>

            <div style={{ background: s.bgSoft, border: `1px solid ${s.graySoft}`, padding: mobile ? 24 : 32, display: 'flex', flexDirection: 'column' }}>
              <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.22em', color: s.gold, marginBottom: 12 }}>ORDER SUMMARY</div>
              <div style={{ fontFamily: s.serif, fontSize: mobile ? 22 : 28, fontWeight: 400, lineHeight: 1.1 }}>{f.ticket.name}</div>
              <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.2em', color: s.gold, marginTop: 6 }}>{f.ticket.badge.toUpperCase()}</div>
              <div style={{ height: 1, background: s.graySoft, margin: '20px 0' }} />
              <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13, marginBottom: 10 }}>
                <span style={{ color: s.cream, opacity: 0.75 }}>
                  ${f.unitPrice} × {f.effectiveQty} {f.earlyBird ? <span style={{ color: s.gold, marginLeft: 6 }}>· early bird</span> : null}
                </span>
                <span>{money(f.subtotal)}</span>
              </div>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13, marginBottom: 10 }}>
                <span style={{ color: s.cream, opacity: 0.55 }}>Service fees</span>
                <span style={{ color: s.cream, opacity: 0.8 }}>{money(f.fees)}</span>
              </div>
              <div style={{ flex: 1 }} />
              <div style={{ height: 1, background: s.graySoft, margin: '12px 0' }} />
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
                <span style={{ fontSize: 11, letterSpacing: '0.2em', textTransform: 'uppercase', color: s.gold }}>Total</span>
                <span style={{ fontFamily: s.serif, fontSize: mobile ? 28 : 38, color: s.gold, fontStyle: 'italic' }}>{money(f.total)}</span>
              </div>
              <div style={{ fontSize: 10, color: s.gray, marginTop: 10, letterSpacing: '0.06em' }}>
                {f.ticket.id === 'vip' ? 'The ultimate experience · reserved seating · VIP gift bag.' :
              f.ticket.id === 'gold' ? 'Includes everything · refreshments → after-party · attendee gift bag.' :
              f.ticket.id === 'silver' ? 'Cultural moments · runway · panel · performances · after party.' :
              'After-party access · DJ set · live performances · cash bar.'}
              </div>
            </div>
          </div>
        }
      </div>

      {/* footer */}
      {f.step < 3 &&
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', borderTop: `1px solid ${s.graySoft}`, paddingTop: 20, position: 'relative', zIndex: 2, flexDirection: mobile ? 'column' : 'row', gap: mobile ? 16 : 0 }}>
          <div>
            <div style={{ fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase', color: s.gray }}>Total</div>
            <div style={{ fontFamily: s.serif, fontStyle: 'italic', fontSize: mobile ? 22 : 28, color: s.gold }}>{money(f.total)}</div>
          </div>
          <div style={{ display: 'flex', gap: 14 }}>
            <Btn onClick={f.prev} disabled={f.step === 1}>← Back</Btn>
            <Btn primary onClick={f.next}>Continue →</Btn>
          </div>
        </div>
      }
      {f.step === 3 &&
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', borderTop: `1px solid ${s.graySoft}`, paddingTop: 20, position: 'relative', zIndex: 2, flexDirection: mobile ? 'column' : 'row', gap: mobile ? 16 : 0 }}>
          <div>
            <div style={{ fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase', color: s.gray }}>Total</div>
            <div style={{ fontFamily: s.serif, fontStyle: 'italic', fontSize: mobile ? 22 : 28, color: s.gold }}>{money(f.total)}</div>
          </div>
          <div style={{ display: 'flex', gap: 14 }}>
            <Btn onClick={f.prev}>← Back</Btn>
          </div>
        </div>
      }
    </div>);

}

// ─────────────────────────────────────────────────────────────────────
// FULL-PAGE OBSIDIAN LANDING SECTIONS
// ─────────────────────────────────────────────────────────────────────

// Smooth scroll-reveal hook
function useReveal() {
  const ref = React.useRef(null);
  const [seen, setSeen] = React.useState(false);
  React.useEffect(() => {
    if (!ref.current) return;
    const io = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) {setSeen(true);io.disconnect();}
    }, { threshold: 0.12 });
    io.observe(ref.current);
    return () => io.disconnect();
  }, []);
  return [ref, seen];
}

function Reveal({ children, delay = 0, style = {} }) {
  const [ref, seen] = useReveal();
  return (
    <div ref={ref} style={{
      opacity: seen ? 1 : 0,
      transform: seen ? 'translateY(0)' : 'translateY(24px)',
      transition: `opacity 0.9s cubic-bezier(0.16,1,0.3,1) ${delay}s, transform 0.9s cubic-bezier(0.16,1,0.3,1) ${delay}s`,
      ...style
    }}>{children}</div>);

}

// Nav (sticky, scroll-aware)
// Shared mobile menu overlay
function MobileMenuOverlay({ open, onClose, links, cta, s }) {
  React.useEffect(() => {
    if (open) document.body.style.overflow = 'hidden';
    else document.body.style.overflow = '';
    return () => { document.body.style.overflow = ''; };
  }, [open]);

  return (
    <div style={{
      position: 'fixed', inset: 0, zIndex: 100,
      background: 'rgba(10,9,8,0.97)',
      backdropFilter: 'blur(24px)',
      WebkitBackdropFilter: 'blur(24px)',
      display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 0,
      opacity: open ? 1 : 0, pointerEvents: open ? 'auto' : 'none',
      transition: 'opacity 0.3s ease',
    }}>
      <button onClick={onClose} aria-label="Close menu" style={{
        position: 'absolute', top: 24, right: 24,
        background: 'none', border: 'none', cursor: 'pointer', padding: 8,
        color: s.cream, fontSize: 28, lineHeight: 1,
      }}>✕</button>
      <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 32 }}>
        {links.map(([label, href, active]) => (
          <a key={label} href={href} onClick={onClose} style={{
            fontFamily: s.serif, fontSize: 28, fontWeight: 300,
            color: active ? s.gold : s.cream, textDecoration: 'none',
            letterSpacing: '0.02em', fontStyle: 'italic',
            transition: 'color 0.2s',
          }}>{label}</a>
        ))}
      </div>
      {cta && <div style={{ marginTop: 48 }}>{cta}</div>}
    </div>
  );
}

// Hamburger icon
function HamburgerIcon({ onClick, s }) {
  return (
    <button onClick={onClick} aria-label="Open menu" style={{
      background: 'none', border: 'none', cursor: 'pointer', padding: 4,
      display: 'flex', flexDirection: 'column', gap: 5, justifyContent: 'center',
    }}>
      <span style={{ display: 'block', width: 22, height: 1.5, background: s.cream }} />
      <span style={{ display: 'block', width: 16, height: 1.5, background: s.gold, marginLeft: 'auto' }} />
    </button>
  );
}

function ObsidianNav({ onTickets, onSponsor }) {
  const s = obsidianStyles;
  const { mobile, tablet } = useMobile();
  const px = mobile ? 24 : 56;
  const [scrolled, setScrolled] = React.useState(false);
  const [menuOpen, setMenuOpen] = React.useState(false);
  React.useEffect(() => {
    const on = () => setScrolled(window.scrollY > 32);
    window.addEventListener('scroll', on, { passive: true });
    on();
    return () => window.removeEventListener('scroll', on);
  }, []);

  const navLinks = [
    ['The Evening', '#about'],
    ['About', '#mission'],
    ['Experience', '#experience'],
    ['Partner', '#sponsors'],
    ['Contact', '#footer'],
  ];

  return (<>
    <nav style={{
      position: 'fixed', top: 0, left: 0, right: 0, zIndex: 50,
      padding: scrolled ? `14px ${px}px` : `24px ${px}px`,
      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      background: scrolled ? 'rgba(10,9,8,0.86)' : 'transparent',
      backdropFilter: scrolled ? 'blur(20px) saturate(1.2)' : 'none',
      WebkitBackdropFilter: scrolled ? 'blur(20px) saturate(1.2)' : 'none',
      borderBottom: scrolled ? `1px solid ${s.gold}1f` : '1px solid transparent',
      transition: 'all 0.4s cubic-bezier(0.16,1,0.3,1)',
      fontFamily: s.sans, fontWeight: "400"
    }}>
      <a href="#hero" style={{ display: 'flex', alignItems: 'center', gap: mobile ? 10 : 14, textDecoration: 'none' }}>
        <LogoMark size={scrolled ? 36 : (mobile ? 32 : 44)} style={{ transition: 'all 0.4s cubic-bezier(0.16,1,0.3,1)' }} />
        <span style={{ fontFamily: s.serif, fontStyle: 'italic', color: s.gold, letterSpacing: '0.02em', fontSize: mobile ? "16px" : "20px" }}>Elevate Noir Gala</span>
      </a>
      {!mobile && <div style={{ display: 'flex', gap: 36, fontSize: 11, letterSpacing: '0.18em', textTransform: 'uppercase', color: s.cream, opacity: 0.85 }}>
        <a href="#about" style={{ color: 'inherit', textDecoration: 'none', fontSize: "15px" }}>The Evening</a>
        <a href="#mission" style={{ color: 'inherit', textDecoration: 'none', fontSize: "15px" }}>About</a>
        <a href="#experience" style={{ color: 'inherit', textDecoration: 'none', fontSize: "15px" }}>Experience</a>
        <a href="#sponsors" style={{ color: 'inherit', textDecoration: 'none', fontSize: "15px" }}>Partner</a>
        <a href="#footer" style={{ color: 'inherit', textDecoration: 'none', fontSize: "15px" }}>Contact</a>
      </div>}
      <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
        <button onClick={onTickets} style={{
          background: s.gold, color: s.bg, border: 'none', padding: mobile ? '9px 16px' : '11px 22px',
          letterSpacing: '0.18em', textTransform: 'uppercase', fontWeight: 500, cursor: 'pointer', fontFamily: s.sans,
          transition: 'transform 0.2s, box-shadow 0.2s', fontSize: mobile ? "12px" : "15px"
        }}
        onMouseEnter={(e) => {e.currentTarget.style.transform = 'translateY(-1px)';e.currentTarget.style.boxShadow = `0 8px 30px ${s.gold}40`;}}
        onMouseLeave={(e) => {e.currentTarget.style.transform = 'none';e.currentTarget.style.boxShadow = 'none';}}>
          Reserve</button>
        {mobile && <HamburgerIcon onClick={() => setMenuOpen(true)} s={s} />}
      </div>
    </nav>
    {mobile && <MobileMenuOverlay open={menuOpen} onClose={() => setMenuOpen(false)} s={s}
      links={navLinks.map(([l, h]) => [l, h, false])}
      cta={<button onClick={() => { setMenuOpen(false); onTickets(); }} style={{
        background: s.gold, color: s.bg, border: 'none', padding: '14px 36px',
        letterSpacing: '0.18em', textTransform: 'uppercase', fontWeight: 500, cursor: 'pointer',
        fontFamily: s.sans, fontSize: 13,
      }}>Reserve Tickets</button>}
    />}
  </>);

}

// Tagline + investment statement
function ObsidianTagline() {
  const s = obsidianStyles;
  const { mobile, tablet } = useMobile();
  const px = mobile ? 24 : 56;
  return (
    <section style={{
      padding: mobile ? '80px 24px 80px' : '140px 56px 120px', background: s.bg, color: s.cream, fontFamily: s.sans,
      borderBottom: `1px solid ${s.graySoft}`
    }} id="about">
      <div style={{ maxWidth: 1400, margin: '0 auto', display: 'grid', gridTemplateColumns: mobile ? '1fr' : '1.4fr 1fr', gap: mobile ? 40 : 80, alignItems: 'start' }}>
        <Reveal>
          <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.28em', color: s.gold, marginBottom: 28 }}>◇ THE VISION</div>
          <h2 style={{ fontFamily: s.serif, fontSize: mobile ? 44 : 76, fontWeight: 300, lineHeight: 1.05, letterSpacing: '-0.015em', margin: 0 }}>
            Where Culture, Capital
            <br /><span style={{ fontStyle: 'italic', color: s.gold }}>&</span> Community Connect.
          </h2>
        </Reveal>
        <Reveal delay={0.15}>
          <p style={{ fontFamily: s.serif, fontSize: mobile ? 17 : 19, lineHeight: 1.7, color: s.cream, opacity: 0.85, fontStyle: 'italic', fontWeight: 300, marginTop: 10 }}>
            The Elevate Noir Gala is more than an event — it is a curated cultural experience that brings together influential professionals, creatives, entrepreneurs, and tastemakers for an unforgettable evening of knowledge, empowerment, connection, and visibility.
          </p>
          <p style={{ fontFamily: s.sans, fontSize: 14, lineHeight: 1.8, color: s.cream, opacity: 0.6, marginTop: 24 }}>
            This is not a donation — it's a strategic investment in Black excellence.
          </p>
          <div style={{ marginTop: 30 }}>
            <a href="#experience" style={{
              display: 'inline-flex', alignItems: 'center', gap: 10,
              background: 'transparent', color: s.gold, border: `1px solid ${s.gold}`,
              padding: '13px 28px', fontSize: 11, letterSpacing: '0.2em', textTransform: 'uppercase',
              fontWeight: 500, textDecoration: 'none', fontFamily: s.sans
            }}>Discover the evening →</a>
          </div>
        </Reveal>
      </div>
    </section>);

}

// Stats / 250+ + by the numbers
// Email notify form with submission handling
function NotifyForm({ mobile }) {
  const s = obsidianStyles;
  const [email, setEmail] = React.useState('');
  const [status, setStatus] = React.useState('idle'); // idle | sending | done | error

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (!email || status === 'sending') return;
    setStatus('sending');
    try {
      const res = await fetch('subscribe.php', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email }),
      });
      const data = await res.json();
      if (res.ok) {
        setStatus('done');
        setEmail('');
      } else {
        setStatus('error');
      }
    } catch {
      setStatus('error');
    }
  };

  if (status === 'done') {
    return (
      <div style={{ marginTop: 24, padding: '14px 18px', border: `1px solid ${s.gold}33`, background: `${s.gold}0a` }}>
        <p style={{ fontFamily: s.sans, fontSize: 13, color: s.gold, margin: 0 }}>You're on the list. We'll be in touch.</p>
      </div>
    );
  }

  return (
    <form onSubmit={handleSubmit} style={{ display: 'flex', marginTop: 24, flexDirection: mobile ? 'column' : 'row' }}>
      <input type="email" required value={email} onChange={(e) => setEmail(e.target.value)} placeholder="your@email.com" style={{
        flex: 1, background: s.bg, border: `1px solid ${s.graySoft}`, borderRight: mobile ? `1px solid ${s.graySoft}` : 'none',
        color: s.cream, fontFamily: s.sans, fontSize: 13, padding: '14px 18px', outline: 'none'
      }} />
      <button type="submit" disabled={status === 'sending'} style={{
        background: s.gold, color: s.bg, border: `1px solid ${s.gold}`,
        padding: '14px 24px', fontSize: 11, letterSpacing: '0.2em', textTransform: 'uppercase',
        fontWeight: 500, cursor: 'pointer', fontFamily: s.sans,
        opacity: status === 'sending' ? 0.6 : 1,
      }}>{status === 'sending' ? 'Sending...' : 'Notify me'}</button>
      {status === 'error' && <p style={{ fontFamily: s.sans, fontSize: 12, color: '#e55', margin: '8px 0 0' }}>Something went wrong. Try again.</p>}
    </form>
  );
}

function ObsidianStats({ onTickets }) {
  const s = obsidianStyles;
  const { mobile, tablet } = useMobile();
  const px = mobile ? 24 : 56;
  return (
    <section style={{ padding: mobile ? '40px 24px' : '60px 56px', background: s.bg }}>
      <div style={{ maxWidth: 1400, margin: '0 auto', display: 'grid', gridTemplateColumns: mobile ? '1fr' : '1.4fr 1fr', gap: 18 }}>
        <Reveal>
          <div style={{
            background: `linear-gradient(135deg, ${s.gold}14 0%, ${s.gold}03 100%)`,
            border: `1px solid ${s.gold}24`,
            padding: mobile ? 32 : 56, color: s.cream, position: 'relative', overflow: 'hidden'
          }}>
            <div style={{ position: 'absolute', right: -50, bottom: -50, opacity: 0.06, color: s.gold }}>
              <CrownGlyph size={mobile ? 200 : 320} stroke={0.6} />
            </div>
            <div style={{ position: 'relative' }}>
              <div style={{ fontFamily: s.serif, fontSize: mobile ? 80 : 132, fontWeight: 300, lineHeight: 0.92, letterSpacing: '-0.02em' }}>
                250<span style={{ color: s.gold }}>+</span>
              </div>
              <div style={{ fontSize: 11, letterSpacing: '0.22em', textTransform: 'uppercase', color: s.gold, marginTop: 10, marginBottom: 22 }}>
                Professionals & Entrepreneurs
              </div>
              <p style={{ fontFamily: s.serif, fontSize: mobile ? 15 : 17, lineHeight: 1.7, color: s.cream, opacity: 0.78, maxWidth: 520, fontStyle: 'italic', fontWeight: 300 }}>
                A curated, high-intent audience of business owners, creatives, consultants, and career-driven individuals — the kind of room where conversations turn into companies.
              </p>
              <div style={{ marginTop: 32, display: 'grid', gridTemplateColumns: mobile ? 'repeat(3, auto)' : 'repeat(3, auto)', gap: mobile ? 24 : 48, alignItems: 'baseline' }}>
                {[
                ['07', 'Distinct experiences'],
                ['1', 'Night'],
                ['10+', 'Vendor tables']].
                map(([n, l]) =>
                <div key={l}>
                    <div style={{ fontFamily: s.serif, fontSize: mobile ? 28 : 38, fontWeight: 300, color: s.gold }}>{n}</div>
                    <div style={{ fontSize: 10.5, letterSpacing: '0.18em', textTransform: 'uppercase', color: s.gray, marginTop: 6 }}>{l}</div>
                  </div>
                )}
              </div>
            </div>
          </div>
        </Reveal>
        <Reveal delay={0.15}>
          <div style={{
            background: s.bgSoft, border: `1px solid ${s.graySoft}`,
            padding: mobile ? 32 : 48, color: s.cream, height: '100%', display: 'flex', flexDirection: 'column'
          }} id="tickets">
            <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.22em', color: s.gold, marginBottom: 16 }}>◇ DON'T MISS THIS NIGHT</div>
            <h3 style={{ fontFamily: s.serif, fontSize: mobile ? 32 : 44, fontWeight: 300, lineHeight: 1.05, margin: 0 }}>
              Reserve your <span style={{ fontStyle: 'italic', color: s.gold }}>seat.</span>
            </h3>
            <p style={{ fontSize: 13.5, lineHeight: 1.7, color: s.cream, opacity: 0.7, marginTop: 16 }}>
              Tickets release in waves. Get the night-of program, the after-party address, and first access to early-bird seats.
            </p>
            <div style={{ flex: 1 }} />
            <NotifyForm mobile={mobile} />
            <button onClick={onTickets} style={{
              marginTop: 12, background: 'transparent', color: s.gold, border: 'none',
              padding: '14px 0 0', fontSize: 11, letterSpacing: '0.2em', textTransform: 'uppercase',
              fontWeight: 500, cursor: 'pointer', fontFamily: s.sans, textAlign: 'left'
            }}>Or reserve a seat now →</button>
          </div>
        </Reveal>
      </div>
    </section>);

}

// Mission / Party & Bash about
function ObsidianAbout() {
  const s = obsidianStyles;
  const { mobile, tablet } = useMobile();
  const px = mobile ? 24 : 56;
  return (
    <section style={{
      padding: mobile ? '80px 24px' : '120px 56px', background: s.bg, color: s.cream, fontFamily: s.sans,
      borderTop: `1px solid ${s.graySoft}`, borderBottom: `1px solid ${s.graySoft}`
    }} id="mission">
      <div style={{ maxWidth: 1400, margin: '0 auto', display: 'grid', gridTemplateColumns: mobile ? '1fr' : '1.6fr 1fr', gap: mobile ? 48 : 80 }}>
        <Reveal>
          <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.28em', color: s.gold, marginBottom: 28 }}>◇ THE MISSION</div>
          <p style={{ fontFamily: s.serif, fontSize: mobile ? 24 : 34, fontWeight: 300, fontStyle: 'italic', lineHeight: 1.4, color: s.cream, margin: 0 }}>
            To create a safe space for Black professionals to learn from experts in their field, experience the talents of creatives within Toronto, and foster connections that develop <span style={{ color: s.gold }}>long-term economic growth</span> within the Black community.
          </p>

          <div style={{ marginTop: mobile ? 40 : 64, display: 'grid', gridTemplateColumns: mobile ? '1fr' : 'repeat(3, 1fr)', gap: 24, paddingTop: 32, borderTop: `1px solid ${s.graySoft}` }}>
            {[
            { h: 'The Gap', b: 'Black-owned businesses receive less funding and visibility. Safe, high-quality networking spaces remain limited.' },
            { h: 'The Solution', b: 'A premium environment where attendees connect and are noticed at a high level. A platform where emerging and established voices are amplified together.' },
            { h: 'The Impact', b: 'Meaningful networking that fosters real relationships and opportunity for long-term economic development within the community.' }].
            map((p, i) =>
            <div key={p.h}>
                <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.2em', color: s.gold, marginBottom: 10 }}>{String(i + 1).padStart(2, '0')} ━</div>
                <div style={{ fontFamily: s.serif, fontSize: 22, fontWeight: 400, marginBottom: 10 }}>{p.h}</div>
                <p style={{ fontSize: 13.5, lineHeight: 1.7, color: s.cream, opacity: 0.7, margin: 0 }}>{p.b}</p>
              </div>
            )}
          </div>

          <div style={{ marginTop: 40, display: 'flex', alignItems: 'center', gap: 20, flexWrap: 'wrap' }}>
            <a href="About.html" style={{
              display: 'inline-flex', alignItems: 'center', gap: 12,
              background: s.gold, color: s.bg, border: 'none',
              padding: '16px 32px', fontSize: 11, letterSpacing: '0.22em', textTransform: 'uppercase',
              fontWeight: 500, textDecoration: 'none', fontFamily: s.sans,
              transition: 'all 0.2s',
            }}
            onMouseEnter={(e) => { e.currentTarget.style.transform = 'translateY(-2px)'; e.currentTarget.style.boxShadow = `0 12px 40px ${s.gold}3a`; }}
            onMouseLeave={(e) => { e.currentTarget.style.transform = 'none'; e.currentTarget.style.boxShadow = 'none'; }}
            >Learn more about us →</a>
            <span style={{ fontFamily: s.mono, fontSize: 10.5, letterSpacing: '0.22em', textTransform: 'uppercase', color: s.gray }}>
              Our story · the night · the people behind it
            </span>
          </div>
        </Reveal>

        <Reveal delay={0.15}>
          <div style={{ position: 'sticky', top: 120, background: 'linear-gradient(180deg, #C88B5E08 0%, transparent 100%)', border: '1px solid #C88B5E1a', padding: mobile ? 24 : 32 }}>
            <img src="assets/pb-logo.jpeg" alt="Party & Bash" style={{ height: mobile ? 56 : 68, width: 'auto', display: 'block', borderRadius: 6, marginBottom: 18 }} />
            <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.22em', color: '#E8878C', marginBottom: 10 }}>PRESENTED BY</div>
            <div style={{ fontFamily: s.serif, fontSize: mobile ? 30 : 38, fontWeight: 400, color: '#C88B5E', fontStyle: 'italic', marginBottom: 18 }}>
              Party &amp; Bash
            </div>
            <p style={{ fontSize: 13.5, lineHeight: 1.8, color: s.cream, opacity: 0.75, marginBottom: 18 }}>
              A luxury event planning & decor company creating immersive, intentional experiences across Toronto — from intimate celebrations to large-scale cultural moments.
            </p>
            <p style={{ fontSize: 13.5, lineHeight: 1.8, color: s.cream, opacity: 0.6, marginBottom: 24 }}>
              As the creator of Elevate Noir, Party &amp; Bash partners with Black-owned businesses, creatives, and entrepreneurs across the city to bring the vision to life — from décor to dining, fashion to media.
            </p>
            <a href="https://partyandbash.ca" target="_blank" rel="noopener noreferrer" style={{
              display: 'inline-flex', alignItems: 'center', gap: 10,
              background: 'transparent', color: '#C88B5E', border: '1px solid #C88B5E',
              padding: '12px 24px', fontSize: 10.5, letterSpacing: '0.2em', textTransform: 'uppercase',
              fontWeight: 500, textDecoration: 'none', fontFamily: s.sans
            }}>Visit partyandbash.ca →</a>
          </div>
        </Reveal>
      </div>
    </section>);

}

// Act detail content — extended descriptions
const ACT_DETAILS = {
  '01': 'Explore a curated marketplace of premium Black-owned brands from across the GTA. From fashion and beauty to tech and wellness — discover the entrepreneurs shaping Toronto\'s creative economy.',
  '02': 'A culinary journey through the GTA\'s finest Black-owned restaurants. Taste of Toronto brings together chefs who are redefining the city\'s food scene, one plate at a time.',
  '03': 'Engaging panel discussions on mental health, finance, and entrepreneurship. Hear from industry leaders and community voices at the intersection of knowledge and action.',
  '04': 'A runway celebration of Black Canadian fashion designers. From emerging talent to established names — this is their stage, their moment, their art.',
  '05': 'An evening of live entertainment featuring DJ sets, spoken word artists, dancers, hosts, and musical performances. From dusk to last call, every moment curated for the culture.',
  '06': 'Bid on exclusive experiences and one-of-a-kind items. All proceeds fuel the Party & Bash initiative and future Elevate events.',
  '07': 'The night doesn\'t end — it evolves. A curated soundtrack, continued conversation, and a room that doesn\'t want to leave. DJ-led, late-night, unforgettable.',
};

// Experience grid — full bleed
function ObsidianExperience() {
  const s = obsidianStyles;
  const { mobile, tablet } = useMobile();
  const px = mobile ? 24 : 56;
  const [selectedAct, setSelectedAct] = React.useState(null);
  return (
    <section style={{ padding: mobile ? '80px 24px' : '120px 56px', background: s.bg, color: s.cream, fontFamily: s.sans }} id="experience">
      <div style={{ maxWidth: 1400, margin: '0 auto' }}>
        <Reveal>
          <div style={{ textAlign: 'center', marginBottom: mobile ? 40 : 64 }}>
            <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.28em', color: s.gold, marginBottom: 18 }}>◇ THE EVENING IN SEVEN ACTS</div>
            <h2 style={{ fontFamily: s.serif, fontSize: mobile ? 44 : 76, fontWeight: 300, lineHeight: 1, letterSpacing: '-0.015em', margin: 0 }}>
              Elevate Gala <span style={{ fontStyle: 'italic', color: s.gold }}>Experience.</span>
            </h2>
            <p style={{ fontFamily: s.serif, fontSize: mobile ? 16 : 18, fontStyle: 'italic', color: s.cream, opacity: 0.6, maxWidth: 600, margin: '20px auto 0', lineHeight: 1.6, fontWeight: 300 }}>
              Every moment intentionally designed for connection, culture, and celebration.
            </p>
          </div>
        </Reveal>

        <div style={{ display: 'grid', gridTemplateColumns: mobile ? '1fr' : (tablet ? 'repeat(2, 1fr)' : 'repeat(3, 1fr)'), gap: 18 }}>
          {EXPERIENCES.slice(0, 6).map((e, i) =>
          <Reveal key={e.n} delay={Math.min(i * 0.08, 0.5)}>
              <div onClick={() => setSelectedAct(e)} style={{
              background: s.bgSoft, border: `1px solid ${s.graySoft}`,
              padding: mobile ? 28 : 36, height: '100%', display: 'flex', flexDirection: 'column',
              transition: 'all 0.45s cubic-bezier(0.16,1,0.3,1)',
              cursor: 'pointer', position: 'relative', overflow: 'hidden'
            }}
            onMouseEnter={(ev) => {ev.currentTarget.style.borderColor = `${obsidianStyles.gold}55`;ev.currentTarget.style.transform = 'translateY(-4px)';ev.currentTarget.style.boxShadow = '0 20px 60px rgba(0,0,0,0.4)';}}
            onMouseLeave={(ev) => {ev.currentTarget.style.borderColor = obsidianStyles.graySoft;ev.currentTarget.style.transform = 'none';ev.currentTarget.style.boxShadow = 'none';}}>

                <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: mobile ? 24 : 36 }}>
                  <div style={{ fontFamily: s.serif, fontSize: mobile ? 40 : 56, fontWeight: 300, fontStyle: 'italic', color: s.gold, lineHeight: 1 }}>{e.n}</div>
                  <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.22em', color: s.gray }}>ACT</div>
                </div>
                <div style={{ fontFamily: s.serif, fontSize: mobile ? 22 : 26, fontWeight: 400, marginBottom: 10, color: s.cream }}>{e.name}</div>
                <p style={{ fontSize: 13.5, lineHeight: 1.7, color: s.cream, opacity: 0.7, margin: 0 }}>{e.blurb}</p>
              </div>
            </Reveal>
          )}
        </div>

        {/* Finale — full-width closing act */}
        {EXPERIENCES[6] && (() => {
          const e = EXPERIENCES[6];
          return (
            <Reveal delay={0.2} style={{ marginTop: 18 }}>
              <div onClick={() => setSelectedAct(e)} style={{
                position: 'relative', overflow: 'hidden', cursor: 'pointer',
                background: s.bgSoft, border: `1px solid ${s.gold}33`,
                minHeight: mobile ? 'auto' : 340, display: 'grid', gridTemplateColumns: mobile ? '1fr' : '1.2fr 1fr',
                transition: 'all 0.45s cubic-bezier(0.16,1,0.3,1)'
              }}
              onMouseEnter={(ev) => {ev.currentTarget.style.borderColor = `${obsidianStyles.gold}88`;ev.currentTarget.style.boxShadow = '0 30px 80px rgba(0,0,0,0.5)';}}
              onMouseLeave={(ev) => {ev.currentTarget.style.borderColor = `${obsidianStyles.gold}33`;ev.currentTarget.style.boxShadow = 'none';}}>

                {/* video / atmosphere panel */}
                <div style={{ position: 'relative', overflow: 'hidden', minHeight: mobile ? 200 : 340 }}>
                  <video autoPlay muted loop playsInline
                  style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', opacity: 0.6 }}>
                    <source src="assets/hero-video-2.mp4" type="video/mp4" />
                  </video>
                  <div style={{
                    position: 'absolute', inset: 0,
                    background: mobile
                      ? `linear-gradient(180deg, transparent 0%, ${s.bgSoft} 100%), linear-gradient(180deg, rgba(10,9,8,0.3) 0%, rgba(10,9,8,0.6) 100%)`
                      : `linear-gradient(90deg, transparent 0%, ${s.bgSoft} 100%), linear-gradient(180deg, rgba(10,9,8,0.3) 0%, rgba(10,9,8,0.6) 100%)`
                  }} />
                  <div style={{ position: 'absolute', top: mobile ? 24 : 36, left: mobile ? 24 : 36, zIndex: 2 }}>
                    <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.28em', color: s.gold, marginBottom: 10 }}>FINALE</div>
                    <div style={{ fontFamily: s.serif, fontSize: mobile ? 56 : 88, fontWeight: 300, fontStyle: 'italic', color: s.gold, lineHeight: 0.9 }}>{e.n}</div>
                  </div>
                </div>

                {/* copy panel */}
                <div style={{ padding: mobile ? '32px 24px' : '48px 56px', display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
                  <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.22em', color: s.gray, marginBottom: 14 }}>ACT · CLOSING THE NIGHT</div>
                  <div style={{ fontFamily: s.serif, fontSize: mobile ? 30 : 44, fontWeight: 300, lineHeight: 1.05, marginBottom: 16, color: s.cream }}>
                    {e.name.split(' ').slice(0, -1).join(' ')} <span style={{ fontStyle: 'italic', color: s.gold }}>{e.name.split(' ').slice(-1)[0]}.</span>
                  </div>
                  <p style={{ fontSize: mobile ? 14 : 15, lineHeight: 1.75, color: s.cream, opacity: 0.78, margin: 0, maxWidth: 440 }}>
                    {e.blurb} A curated soundtrack, a continued conversation, and a room that doesn't want to leave.
                  </p>
                  <div style={{ marginTop: 28, display: 'flex', alignItems: 'center', gap: 18, flexWrap: mobile ? 'wrap' : 'nowrap' }}>
                    <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.22em', color: s.gold }}>11 PM — LATE</div>
                    <div style={{ height: 1, flex: 1, background: `${s.gold}33`, display: mobile ? 'none' : 'block' }} />
                    <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.22em', color: s.gold }}>RSVP REQUIRED</div>
                  </div>
                </div>
              </div>
            </Reveal>);

        })()}
      </div>

      {/* Act detail modal */}
      <ObsidianModal open={!!selectedAct} onClose={() => setSelectedAct(null)}>
        {selectedAct && <ActDetailPopup act={selectedAct} onClose={() => setSelectedAct(null)} allActs={EXPERIENCES} onSelectAct={setSelectedAct} />}
      </ObsidianModal>
    </section>);

}

function ActDetailPopup({ act, onClose, allActs, onSelectAct }) {
  const s = obsidianStyles;
  const { mobile } = useMobile();
  const [email, setEmail] = React.useState('');
  const [status, setStatus] = React.useState('idle');

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (!email || status === 'sending') return;
    setStatus('sending');
    try {
      const res = await fetch('subscribe.php', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email, list: 'attendee' }),
      });
      if (res.ok) { setStatus('done'); setEmail(''); }
      else { setStatus('error'); }
    } catch { setStatus('error'); }
  };

  const otherActs = allActs.filter(a => a.n !== act.n);

  return (
    <div style={{
      width: '100%', height: '100%', background: s.bg, color: s.cream, fontFamily: s.sans,
      padding: mobile ? '32px 24px 24px' : '44px 56px 36px', overflowY: 'auto',
      position: 'relative'
    }}>
      <div style={{ maxWidth: 800, margin: '0 auto' }}>
        <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.28em', color: s.gold, marginBottom: 24 }}>
          ◇ ACT {act.n} · THE EVENING IN SEVEN ACTS
        </div>
        <div style={{ fontFamily: s.serif, fontSize: mobile ? 56 : 96, fontWeight: 300, fontStyle: 'italic', color: s.gold, lineHeight: 0.9, marginBottom: 24 }}>
          {act.n}
        </div>
        <h2 style={{ fontFamily: s.serif, fontSize: mobile ? 36 : 64, fontWeight: 300, lineHeight: 1.05, margin: 0, marginBottom: 24 }}>
          {act.name}<span style={{ color: s.gold }}>.</span>
        </h2>
        <p style={{ fontFamily: s.serif, fontSize: mobile ? 17 : 21, lineHeight: 1.7, color: s.cream, opacity: 0.85, fontStyle: 'italic', fontWeight: 300, maxWidth: 680, marginBottom: 16 }}>
          {act.blurb}
        </p>
        <p style={{ fontSize: 15, lineHeight: 1.8, color: s.cream, opacity: 0.7, maxWidth: 680, marginBottom: 48 }}>
          {ACT_DETAILS[act.n] || act.blurb}
        </p>

        <div style={{ height: 1, background: s.graySoft, marginBottom: 48 }} />

        {/* Email signup */}
        <div style={{ maxWidth: 560 }}>
          <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.22em', color: s.gold, marginBottom: 12 }}>◇ STAY UPDATED</div>
          <div style={{ fontFamily: s.serif, fontSize: mobile ? 26 : 36, fontWeight: 300, marginBottom: 12 }}>
            Get notified about <span style={{ fontStyle: 'italic', color: s.gold }}>{act.name.toLowerCase()}.</span>
          </div>
          <p style={{ fontSize: 13.5, color: s.cream, opacity: 0.65, lineHeight: 1.7, marginBottom: 24 }}>
            Be the first to know when we announce performers, vendors, panelists, and more for this experience.
          </p>

          {status === 'done' ? (
            <div style={{ padding: '14px 18px', border: `1px solid ${s.gold}33`, background: `${s.gold}0a` }}>
              <p style={{ fontSize: 13, color: s.gold, margin: 0 }}>You're on the list. We'll keep you posted on {act.name.toLowerCase()}.</p>
            </div>
          ) : (
            <form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: mobile ? 'column' : 'row' }}>
              <input type="email" required value={email} onChange={(e) => setEmail(e.target.value)} placeholder="your@email.com" style={{
                flex: 1, background: s.bg, border: `1px solid ${s.graySoft}`, borderRight: mobile ? `1px solid ${s.graySoft}` : 'none',
                color: s.cream, fontFamily: s.sans, fontSize: 13, padding: '14px 18px', outline: 'none'
              }} />
              <button type="submit" disabled={status === 'sending'} style={{
                background: s.gold, color: s.bg, border: `1px solid ${s.gold}`,
                padding: '14px 24px', fontSize: 11, letterSpacing: '0.2em', textTransform: 'uppercase',
                fontWeight: 500, cursor: 'pointer', fontFamily: s.sans,
                opacity: status === 'sending' ? 0.6 : 1
              }}>{status === 'sending' ? 'Sending...' : 'Notify me'}</button>
            </form>
          )}
          {status === 'error' && <p style={{ fontSize: 12, color: '#e55', marginTop: 8 }}>Something went wrong. Try again.</p>}
        </div>

        <div style={{ height: 1, background: s.graySoft, marginTop: 48, marginBottom: 48 }} />

        {/* Other acts */}
        <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.22em', color: s.gold, marginBottom: 24 }}>◇ MORE EXPERIENCES</div>
        <div style={{ display: 'grid', gridTemplateColumns: mobile ? '1fr' : 'repeat(3, 1fr)', gap: 14 }}>
          {otherActs.map(e => (
            <div key={e.n} onClick={() => onSelectAct(e)} style={{
              color: s.cream, cursor: 'pointer',
              background: s.bgSoft, border: `1px solid ${s.graySoft}`,
              padding: mobile ? 20 : 28, display: 'block',
              transition: 'border-color 0.3s'
            }}>
              <div style={{ fontFamily: s.serif, fontSize: 32, fontStyle: 'italic', color: s.gold, marginBottom: 12 }}>{e.n}</div>
              <div style={{ fontFamily: s.serif, fontSize: 18, fontWeight: 400, marginBottom: 6 }}>{e.name}</div>
              <div style={{ fontSize: 12, opacity: 0.6, lineHeight: 1.5 }}>{e.blurb}</div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// Ticket tiers showcase — Gold / Silver / Bronze with early bird highlight
function ObsidianTicketTiers({ onTickets }) {
  const s = obsidianStyles;
  const { mobile, tablet } = useMobile();
  const px = mobile ? 24 : 56;
  const tierColors = {
    vip: { ring: '#E0C080', glow: '#E0C08033', label: 'VIP' },
    gold: { ring: s.gold, glow: `${s.gold}33`, label: 'GOLD' },
    silver: { ring: '#B8B5AB', glow: '#B8B5AB22', label: 'SILVER' },
    bronze: { ring: '#A66B3A', glow: '#A66B3A22', label: 'BRONZE' }
  };
  return (
    <section style={{
      padding: mobile ? '80px 24px' : '120px 56px', background: s.bg, color: s.cream, fontFamily: s.sans,
      borderTop: `1px solid ${s.graySoft}`, position: 'relative'
    }} id="tickets-section">
      <div style={{ maxWidth: 1400, margin: '0 auto' }}>
        <Reveal>
          <div style={{ display: 'grid', gridTemplateColumns: mobile ? '1fr' : '1fr auto', gap: mobile ? 24 : 56, alignItems: mobile ? 'start' : 'end', marginBottom: mobile ? 36 : 56 }}>
            <div>
              <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.28em', color: s.gold, marginBottom: 18 }}>◇ TICKETS · OCTOBER 17 · 2026</div>
              <h2 style={{ fontFamily: s.serif, fontSize: mobile ? 44 : 76, fontWeight: 300, lineHeight: 1, letterSpacing: '-0.015em', margin: 0 }}>
                Choose how you <span style={{ fontStyle: 'italic', color: s.gold }}>arrive.</span>
              </h2>
            </div>
            <div style={{ textAlign: mobile ? 'left' : 'right' }}>
              <div style={{
                display: 'inline-flex', alignItems: 'center', gap: 12,
                padding: '10px 18px', border: `1px solid ${s.gold}`, background: `${s.gold}0d`
              }}>
                <div style={{ width: 8, height: 8, borderRadius: '50%', background: s.gold, boxShadow: `0 0 12px ${s.gold}99` }} />
                <div style={{ fontFamily: s.mono, fontSize: 10.5, letterSpacing: '0.22em', color: s.gold, textTransform: 'uppercase' }}>
                  Early bird pricing live
                </div>
              </div>
              <div style={{ fontSize: 12, color: s.cream, opacity: 0.6, marginTop: 10 }}>
                Limited release — save up to $55 per ticket
              </div>
            </div>
          </div>
        </Reveal>

        <div style={{ display: 'grid', gridTemplateColumns: mobile ? '1fr' : (tablet ? 'repeat(2, 1fr)' : 'repeat(4, 1fr)'), gap: 18 }}>
          {TICKET_TYPES.map((t, i) => {
            const c = tierColors[t.id];
            const isFeatured = t.id === 'vip';
            return (
              <Reveal key={t.id} delay={Math.min(i * 0.1, 0.3)}>
                <div style={{
                  background: isFeatured ? `linear-gradient(180deg, ${s.gold}14 0%, ${s.bgSoft} 60%)` : s.bgSoft,
                  border: `1px solid ${isFeatured ? `${s.gold}55` : s.graySoft}`,
                  padding: mobile ? 28 : 36, height: '100%', display: 'flex', flexDirection: 'column',
                  position: 'relative', overflow: 'hidden',
                  transition: 'all 0.45s cubic-bezier(0.16,1,0.3,1)'
                }}
                onMouseEnter={(e) => {e.currentTarget.style.borderColor = c.ring;e.currentTarget.style.transform = 'translateY(-4px)';e.currentTarget.style.boxShadow = `0 20px 60px ${c.glow}`;}}
                onMouseLeave={(e) => {e.currentTarget.style.borderColor = isFeatured ? `${s.gold}55` : s.graySoft;e.currentTarget.style.transform = 'none';e.currentTarget.style.boxShadow = 'none';}}>

                  {isFeatured &&
                  <div style={{
                    position: 'absolute', top: 18, right: 18,
                    fontFamily: s.mono, fontSize: 9.5, letterSpacing: '0.22em', color: s.bg,
                    background: s.gold, padding: '5px 10px'
                  }}>MOST POPULAR</div>
                  }
                  <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 18 }}>
                    <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.24em', color: c.ring }}>
                      TIER {String(i + 1).padStart(2, '0')}
                    </div>
                    <div style={{ width: 24, height: 1, background: c.ring, opacity: 0.5 }} />
                    <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.24em', color: c.ring }}>
                      {c.label}
                    </div>
                  </div>
                  <div style={{ fontFamily: s.serif, fontSize: mobile ? 26 : 32, fontWeight: 400, fontStyle: 'italic', color: s.cream, lineHeight: 1.1, marginBottom: 10 }}>
                    {t.name}
                  </div>
                  <p style={{ fontSize: 13, color: s.cream, opacity: 0.65, margin: 0, lineHeight: 1.7, minHeight: mobile ? 'auto' : 66 }}>{t.desc}</p>

                  {/* price */}
                  <div style={{ marginTop: 28, paddingTop: 24, borderTop: `1px solid ${s.graySoft}` }}>
                    <div style={{ display: 'flex', alignItems: 'baseline', gap: 14, marginBottom: 6, flexWrap: mobile ? 'wrap' : 'nowrap' }}>
                      <div style={{ fontFamily: s.serif, fontSize: mobile ? 40 : 56, fontWeight: 300, color: s.gold, fontStyle: 'italic', lineHeight: 0.9 }}>
                        ${t.earlyPrice}
                      </div>
                      <div style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                        <div style={{ fontFamily: s.serif, fontSize: 18, color: s.gray, textDecoration: 'line-through' }}>${t.price}</div>
                        <div style={{ fontFamily: s.mono, fontSize: 9.5, letterSpacing: '0.18em', color: s.gold }}>EARLY BIRD</div>
                      </div>
                    </div>
                    <div style={{ fontSize: 11.5, color: s.cream, opacity: 0.55, letterSpacing: '0.04em' }}>
                      Save {money(t.price - t.earlyPrice)} · regular pricing {money(t.price)} when early bird closes.
                    </div>
                  </div>

                  {/* perks */}
                  <ul style={{ listStyle: 'none', padding: 0, margin: '24px 0 0', display: 'flex', flexDirection: 'column', gap: 8, flex: 1 }}>
                    {t.perks.map((p, j) =>
                    <li key={j} style={{ fontSize: 12.5, lineHeight: 1.55, color: s.cream, opacity: 0.82, display: 'flex', gap: 10 }}>
                        <span style={{ color: c.ring, opacity: 0.9, flexShrink: 0 }}>—</span><span>{p}</span>
                      </li>
                    )}
                  </ul>

                  <button onClick={onTickets} style={{
                    marginTop: 28,
                    background: isFeatured ? s.gold : 'transparent',
                    color: isFeatured ? s.bg : s.gold,
                    border: isFeatured ? 'none' : `1px solid ${s.gold}`,
                    padding: '14px 0', fontSize: 11, letterSpacing: '0.22em', textTransform: 'uppercase',
                    fontWeight: 500, cursor: 'pointer', fontFamily: s.sans,
                    transition: 'all 0.2s'
                  }}
                  onMouseEnter={(e) => {if (!isFeatured) {e.currentTarget.style.background = s.gold;e.currentTarget.style.color = s.bg;}}}
                  onMouseLeave={(e) => {if (!isFeatured) {e.currentTarget.style.background = 'transparent';e.currentTarget.style.color = s.gold;}}}>
                    Reserve this tier →</button>
                </div>
              </Reveal>);

          })}
        </div>

        {/* fine print */}
        <Reveal delay={0.2}>
          <div style={{
            marginTop: 36, padding: mobile ? '16px 20px' : '20px 28px', border: `1px solid ${s.graySoft}`, background: s.bgSoft,
            display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 24, flexWrap: 'wrap',
            flexDirection: mobile ? 'column' : 'row'
          }}>
            <div style={{ fontSize: 12.5, color: s.cream, opacity: 0.7, lineHeight: 1.5 }}>
              All tickets include arrival reception and program. <span style={{ color: s.gold }}>Groups of 4+ in any tier</span> — reach out for complimentary side-by-side seating.
            </div>
            <a href="mailto:tickets@elevatenoirgala.ca" style={{
              fontFamily: s.mono, fontSize: 10.5, letterSpacing: '0.22em', textTransform: 'uppercase',
              color: s.gold, textDecoration: 'none', borderBottom: `1px solid ${s.gold}`, paddingBottom: 2
            }}>tickets@elevatenoirgala.ca →</a>
          </div>
        </Reveal>
      </div>
    </section>);

}

// Sponsor CTA — tiers preview + CTA to flow
function ObsidianSponsorCTA({ onSponsor }) {
  const s = obsidianStyles;
  const { mobile, tablet } = useMobile();
  const px = mobile ? 24 : 56;
  return (
    <section style={{
      padding: mobile ? '80px 24px' : '120px 56px', background: s.bg, color: s.cream, fontFamily: s.sans,
      borderTop: `1px solid ${s.graySoft}`
    }} id="sponsors">
      <div style={{ maxWidth: 1400, margin: '0 auto' }}>
        <Reveal>
          <div style={{ textAlign: 'center', marginBottom: mobile ? 40 : 64 }}>
            <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.28em', color: s.gold, marginBottom: 18 }}>◇ PARTNERSHIP · 2026</div>
            <h2 style={{ fontFamily: s.serif, fontSize: mobile ? 44 : 76, fontWeight: 300, lineHeight: 1, letterSpacing: '-0.015em', margin: 0 }}>
              Become a <span style={{ fontStyle: 'italic', color: s.gold }}>partner.</span>
            </h2>
            <p style={{ fontFamily: s.serif, fontSize: mobile ? 16 : 18, fontStyle: 'italic', color: s.cream, opacity: 0.65, maxWidth: 580, margin: '20px auto 0', lineHeight: 1.6, fontWeight: 300 }}>
              We're securing select brand partners. Spots are limited to maintain exclusivity, intentionality, and value.
            </p>
          </div>
        </Reveal>

        <div style={{ display: 'grid', gridTemplateColumns: mobile ? '1fr' : (tablet ? 'repeat(2, 1fr)' : `repeat(${TIERS.length}, 1fr)`), gap: 14, marginBottom: mobile ? 36 : 56 }}>
          {TIERS.map((t, i) =>
          <Reveal key={t.id} delay={Math.min(i * 0.08, 0.4)}>
              <div onClick={() => onSponsor(t.id)} style={{
              background: s.bgSoft, border: `1px solid ${s.graySoft}`,
              padding: mobile ? '24px 22px' : '32px 28px', textAlign: 'left', height: '100%', display: 'flex', flexDirection: 'column',
              cursor: 'pointer', transition: 'border-color 0.2s'
            }}
            onMouseEnter={(e) => e.currentTarget.style.borderColor = s.gold}
            onMouseLeave={(e) => e.currentTarget.style.borderColor = s.graySoft}>
                <div style={{ fontFamily: s.mono, fontSize: 10, letterSpacing: '0.22em', color: s.gold, marginBottom: 16 }}>
                  {String(i + 1).padStart(2, '0')}
                </div>
                <div style={{ fontFamily: s.serif, fontSize: mobile ? 22 : 26, fontWeight: 400, color: s.cream, marginBottom: 4 }}>
                  {t.name} <span style={{ fontStyle: 'italic', color: s.gold }}>Sponsor</span>
                </div>
                <div style={{ fontFamily: s.serif, fontStyle: 'italic', fontSize: mobile ? 24 : 30, color: s.cream, marginBottom: 18 }}>
                  {money(t.price)}<span style={{ fontSize: 14, color: s.gray }}>+</span>
                </div>
                <div style={{ height: 1, background: s.graySoft, marginBottom: 16 }} />
                <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 8, flex: 1 }}>
                  {t.perks.slice(0, mobile ? 3 : 4).map((p, j) =>
                <li key={j} style={{ fontSize: 11.5, lineHeight: 1.45, color: s.cream, opacity: 0.78, display: 'flex', gap: 8 }}>
                      <span style={{ color: s.gold, opacity: 0.9 }}>—</span><span>{p}</span>
                    </li>
                )}
                </ul>
              </div>
            </Reveal>
          )}
        </div>

        <Reveal>
          <div style={{ marginBottom: mobile ? 36 : 56 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginBottom: 20 }}>
              <div style={{ flex: 1, height: 1, background: s.graySoft }} />
              <span style={{ fontFamily: s.mono, fontSize: 9, letterSpacing: '0.2em', color: s.gray }}>OR</span>
              <div style={{ flex: 1, height: 1, background: s.graySoft }} />
            </div>
            <div onClick={() => onSponsor('donation')} style={{
              background: s.bgSoft, border: `1px solid ${s.graySoft}`,
              padding: mobile ? '20px 22px' : '24px 28px', display: 'flex', alignItems: 'center', gap: mobile ? 14 : 20,
              cursor: 'pointer', transition: 'border-color 0.2s'
            }}
            onMouseEnter={(e) => e.currentTarget.style.borderColor = s.gold}
            onMouseLeave={(e) => e.currentTarget.style.borderColor = s.graySoft}>
              <div style={{ flex: 1 }}>
                <div style={{ fontFamily: s.serif, fontSize: mobile ? 20 : 24, fontWeight: 400, color: s.cream }}>
                  Community <span style={{ fontStyle: 'italic', color: s.gold }}>Donation</span>
                </div>
                <div style={{ fontSize: 11.5, color: s.cream, opacity: 0.6, marginTop: 4 }}>
                  Not sponsoring? Still want to support the movement.
                </div>
              </div>
              <div style={{ fontFamily: s.serif, fontStyle: 'italic', fontSize: mobile ? 24 : 30, color: s.gold }}>$50+</div>
            </div>
          </div>
        </Reveal>

        <Reveal>
          <div style={{ display: 'flex', gap: 16, justifyContent: 'center', flexWrap: 'wrap', flexDirection: mobile ? 'column' : 'row', alignItems: mobile ? 'stretch' : 'center' }}>
            <button onClick={onSponsor} style={{
              background: s.gold, color: s.bg, border: 'none', padding: '16px 38px',
              fontSize: 12, letterSpacing: '0.22em', textTransform: 'uppercase', fontWeight: 500, cursor: 'pointer', fontFamily: s.sans,
              transition: 'all 0.2s', textAlign: 'center'
            }}
            onMouseEnter={(e) => {e.currentTarget.style.transform = 'translateY(-2px)';e.currentTarget.style.boxShadow = `0 12px 40px ${s.gold}3a`;}}
            onMouseLeave={(e) => {e.currentTarget.style.transform = 'none';e.currentTarget.style.boxShadow = 'none';}}>
              Partner with us →</button>
            <a href="mailto:Hello@elevatenoirgala.com" style={{
              background: 'transparent', color: s.gold, border: `1px solid ${s.gold}`,
              padding: '16px 38px', fontSize: 12, letterSpacing: '0.22em', textTransform: 'uppercase',
              fontWeight: 500, cursor: 'pointer', fontFamily: s.sans, textDecoration: 'none', display: 'inline-block',
              textAlign: 'center'
            }}>Hello@elevatenoirgala.com</a>
          </div>
        </Reveal>
      </div>
    </section>);

}

// Footer
function ObsidianFooter() {
  const s = obsidianStyles;
  const { mobile, tablet } = useMobile();
  const px = mobile ? 24 : 56;
  return (
    <footer style={{ padding: mobile ? '48px 24px 0' : '80px 56px 0', background: s.bg, color: s.cream, fontFamily: s.sans, borderTop: `1px solid ${s.graySoft}` }} id="footer">
      <div style={{ maxWidth: 1400, margin: '0 auto' }}>
        <div style={{ display: 'grid', gridTemplateColumns: mobile ? '1fr' : '2fr 1fr 1fr 1fr', gap: mobile ? 32 : 48, paddingBottom: mobile ? 36 : 56, borderBottom: `1px solid ${s.gold}1a` }}>
          <div>
            <div style={{ marginBottom: 18 }}>
              <LogoFull size={mobile ? 110 : 140} />
            </div>
            <p style={{ fontFamily: s.serif, fontSize: 16, fontStyle: 'italic', color: s.cream, opacity: 0.65, maxWidth: 340, margin: 0, fontWeight: 300, lineHeight: 1.5 }}>
              Where Culture, Capital &amp; Community Connect.
            </p>
          </div>
          {[
          { h: 'Contact', items: [['Hello@elevatenoirgala.com', 'mailto:Hello@elevatenoirgala.com']] },
          { h: 'Socials', items: [['@elevatenoirgala', 'https://instagram.com/elevatenoirgala']] },
          { h: 'Presented by', items: [['Party & Bash', 'https://partyandbash.ca']] }].
          map((col) =>
          <div key={col.h} style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              <div style={{ fontFamily: s.mono, fontSize: 9.5, letterSpacing: '0.22em', textTransform: 'uppercase', color: s.gold, marginBottom: 8 }}>{col.h}</div>
              {col.items.map(([label, href]) =>
            <a key={label} href={href} style={{
              fontSize: 13.5, color: s.cream, opacity: 0.75, textDecoration: 'none'
            }}>{label}</a>
            )}
            </div>
          )}
        </div>

        <div style={{ padding: mobile ? '28px 0 20px' : '40px 0 24px', overflow: 'hidden' }}>
          {!mobile && <div style={{
            fontFamily: s.serif, fontSize: 'clamp(80px, 14vw, 200px)', fontWeight: 300, lineHeight: 0.85,
            color: s.bgSoft, textAlign: 'center', letterSpacing: '-0.02em', userSelect: 'none',
            transition: 'color 0.6s', whiteSpace: 'nowrap'
          }}
          onMouseEnter={(e) => {e.currentTarget.style.color = obsidianStyles.graySoft;}}
          onMouseLeave={(e) => {e.currentTarget.style.color = obsidianStyles.bgSoft;}}>

            Elevate <span style={{ fontStyle: 'italic' }}>Noir</span>
          </div>}
          <div style={{ display: 'flex', justifyContent: 'space-between', fontFamily: s.mono, fontSize: 10, letterSpacing: '0.22em', color: s.gray, marginTop: 16, flexWrap: 'wrap', gap: mobile ? 12 : 0 }}>
            <span>© MMXXVI · ELEVATE NOIR GALA</span>
            <a href="terms.html" style={{ color: 'inherit', textDecoration: 'none', transition: 'color 0.3s' }} onMouseEnter={(e) => e.currentTarget.style.color = obsidianStyles.gold} onMouseLeave={(e) => e.currentTarget.style.color = obsidianStyles.gray}>TERMS</a>
            <a href="privacy.html" style={{ color: 'inherit', textDecoration: 'none', transition: 'color 0.3s' }} onMouseEnter={(e) => e.currentTarget.style.color = obsidianStyles.gold} onMouseLeave={(e) => e.currentTarget.style.color = obsidianStyles.gray}>PRIVACY</a>
            <span>TORONTO · CANADA</span>
            <span>BLACK DREAM · VOL · I</span>
          </div>
        </div>
      </div>
    </footer>);

}

function CookieConsent() {
  const s = obsidianStyles;
  const [visible, setVisible] = React.useState(() => !localStorage.getItem('cookie_consent'));
  if (!visible) return null;
  const accept = () => { localStorage.setItem('cookie_consent', 'accepted'); setVisible(false); };
  return (
    <div style={{
      position: 'fixed', bottom: 0, left: 0, right: 0, zIndex: 9999,
      background: s.bgSoft, borderTop: `1px solid ${s.graySoft}`,
      padding: '16px 24px', display: 'flex', alignItems: 'center',
      justifyContent: 'center', gap: 20, flexWrap: 'wrap',
      fontFamily: s.sans, fontSize: 13, color: s.cream
    }}>
      <span style={{ opacity: 0.8, maxWidth: 600 }}>
        We use cookies to improve your experience. By continuing, you agree to our{' '}
        <a href="privacy.html" style={{ color: s.gold, textDecoration: 'underline' }}>Privacy Policy</a>.
      </span>
      <button onClick={accept} style={{
        background: s.gold, color: s.bg, border: 'none', cursor: 'pointer',
        padding: '10px 28px', fontFamily: s.sans, fontWeight: 500, fontSize: 11,
        letterSpacing: '0.12em', textTransform: 'uppercase', whiteSpace: 'nowrap'
      }}>Accept</button>
    </div>
  );
}

function EmailPopup() {
  const s = obsidianStyles;
  const { mobile } = useMobile();
  const [show, setShow] = React.useState(false);
  const [email, setEmail] = React.useState('');
  const [status, setStatus] = React.useState('idle'); // idle | sending | done | error

  React.useEffect(() => {
    if (localStorage.getItem('email_popup_dismissed')) return;

    let scrollTime = 0;
    let scrolling = false;
    let timeout = null;
    let interval = null;

    const onScroll = () => {
      if (!scrolling) {
        scrolling = true;
      }
      clearTimeout(timeout);
      timeout = setTimeout(() => { scrolling = false; }, 200);
    };

    interval = setInterval(() => {
      if (scrolling) {
        scrollTime += 100;
        if (scrollTime >= 3000) {
          setShow(true);
          clearInterval(interval);
          window.removeEventListener('scroll', onScroll);
        }
      }
    }, 100);

    window.addEventListener('scroll', onScroll, { passive: true });

    return () => {
      clearInterval(interval);
      clearTimeout(timeout);
      window.removeEventListener('scroll', onScroll);
    };
  }, []);

  const dismiss = () => {
    setShow(false);
    localStorage.setItem('email_popup_dismissed', 'true');
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (!email || status === 'sending') return;
    setStatus('sending');
    try {
      const res = await fetch('subscribe.php', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email }),
      });
      if (res.ok) {
        setStatus('done');
        localStorage.setItem('email_popup_dismissed', 'true');
      } else {
        setStatus('error');
      }
    } catch {
      setStatus('error');
    }
  };

  if (!show) return null;

  return (
    <div onClick={dismiss} style={{
      position: 'fixed', inset: 0, zIndex: 10000,
      background: 'rgba(5,5,4,0.84)',
      backdropFilter: 'blur(12px)', WebkitBackdropFilter: 'blur(12px)',
      display: 'flex', alignItems: mobile ? 'flex-end' : 'center', justifyContent: 'center',
      padding: mobile ? 0 : 24, animation: 'fadeIn 0.35s ease-out'
    }}>
      <div onClick={(e) => e.stopPropagation()} style={{
        background: s.bgSoft, border: `1px solid ${s.graySoft}`,
        padding: mobile ? '36px 24px 28px' : '48px 40px 36px', maxWidth: 440, width: '100%',
        position: 'relative', textAlign: 'center',
        borderRadius: mobile ? '16px 16px 0 0' : 0,
        borderBottom: mobile ? 'none' : `1px solid ${s.graySoft}`
      }}>
        {/* Close button */}
        <button onClick={dismiss} aria-label="Close" style={{
          position: 'absolute', top: 14, right: 14, background: 'none',
          border: 'none', color: s.gray, cursor: 'pointer', fontSize: 20,
          lineHeight: 1, padding: 4, fontFamily: s.sans
        }}>&times;</button>

        {/* Crown logo */}
        <div style={{ marginBottom: 20, display: 'flex', justifyContent: 'center' }}>
          <LogoMark size={mobile ? 44 : 56} />
        </div>

        {/* Heading */}
        <h2 style={{
          fontFamily: s.serif, fontSize: mobile ? 26 : 32, fontWeight: 400,
          color: s.cream, marginBottom: 12, lineHeight: 1.2
        }}>
          Stay in the <em style={{ color: s.gold, fontStyle: 'italic' }}>Know.</em>
        </h2>

        {/* Subtext */}
        <p style={{
          fontFamily: s.sans, fontSize: 14, color: s.gray,
          lineHeight: 1.6, marginBottom: 28, maxWidth: 340, margin: '0 auto 28px'
        }}>
          Get early access to tickets, lineup reveals, and exclusive updates.
        </p>

        {status === 'done' ? (
          <p style={{
            fontFamily: s.sans, fontSize: 13, color: s.gold,
            letterSpacing: '0.08em', padding: '16px 0'
          }}>You're on the list. See you there.</p>
        ) : (
          <form onSubmit={handleSubmit} style={{
            display: 'flex', flexDirection: mobile ? 'column' : 'row', gap: 0, marginBottom: 16
          }}>
            <input
              type="email"
              required
              value={email}
              onChange={(e) => setEmail(e.target.value)}
              placeholder="Your email"
              style={{
                flex: 1, padding: '13px 16px', fontSize: 13,
                fontFamily: s.sans, background: s.bg, color: s.cream,
                border: `1px solid ${s.graySoft}`,
                borderRight: mobile ? `1px solid ${s.graySoft}` : 'none',
                borderBottom: mobile ? 'none' : `1px solid ${s.graySoft}`,
                outline: 'none', letterSpacing: '0.02em'
              }}
            />
            <button type="submit" disabled={status === 'sending'} style={{
              padding: '13px 24px', fontSize: 11, fontWeight: 500,
              letterSpacing: '0.12em', textTransform: 'uppercase',
              fontFamily: s.sans, background: s.gold, color: s.bg,
              border: 'none', cursor: 'pointer', whiteSpace: 'nowrap',
              opacity: status === 'sending' ? 0.6 : 1
            }}>
              {status === 'sending' ? 'Sending...' : 'Notify Me'}
            </button>
          </form>
        )}

        {status === 'error' && (
          <p style={{
            fontFamily: s.sans, fontSize: 12, color: '#c44',
            marginBottom: 8
          }}>Something went wrong. Please try again.</p>
        )}

        {status !== 'done' && (
          <button onClick={dismiss} style={{
            background: 'none', border: 'none', color: s.gray,
            fontFamily: s.sans, fontSize: 12, cursor: 'pointer',
            letterSpacing: '0.04em', padding: '8px 0',
            textDecoration: 'underline', textUnderlineOffset: 3
          }}>No thanks</button>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { ObsidianModal, ObsidianTicketFlow, ObsidianNav, ObsidianTagline, ObsidianStats, ObsidianAbout, ObsidianExperience, ObsidianTicketTiers, ObsidianSponsorCTA, ObsidianFooter, CookieConsent, EmailPopup });
