/* 1:1 — Landing page
   Single-file page composition. Loads after landing-motion.jsx and the
   app's existing screen mocks (Home, MeetSheet, Discover, AI Builder,
   Brief, Debrief, Group, Notifications). */

const { useEffect, useRef, useState, useMemo, useCallback } = React;

const NOOP = () => {};

// ============================================================
// PhoneFrame — wraps IOSDevice at a chosen render width
// IOSDevice at default scale = ~402x874. We render the frame at
// fullW/fullH and then transform: scale(...) to fit a target width.
// ============================================================
const FRAME_W = 402;
const FRAME_H = 874;

function PhoneFrame({ width = 320, screen, dark = true }) {
  const scale = width / FRAME_W;
  const h = FRAME_H * scale;
  const IOS = window.IOSDevice;
  return (
    <div style={{ width, height: h, position: "relative" }}>
      <div
        className="phone-scaled"
        style={{
          position: "absolute",
          top: 0,
          left: 0,
          width: FRAME_W,
          height: FRAME_H,
          transform: `scale(${scale})`,
        }}
      >
        <IOS width={FRAME_W} height={FRAME_H} dark={dark}>
          {screen}
        </IOS>
      </div>
    </div>
  );
}

// ============================================================
// Screen registry — references actual app mocks, with safe fallbacks
// ============================================================
function getScreen(key) {
  const W = window;
  const noopGo = NOOP;
  switch (key) {
    case "home":
      return W.HomeScreen ? <W.HomeScreen go={noopGo} /> : <Placeholder label="Home" />;
    case "meetSheet":
      return W.MeetSheetScreen ? (
        <W.MeetSheetScreen go={noopGo} onRequest={noopGo} />
      ) : (
        <Placeholder label="Meet Sheet" />
      );
    case "discover":
      return W.DiscoverMobile ? (
        <W.DiscoverMobile go={noopGo} />
      ) : <Placeholder label="Discover" />;
    case "aiBuilder":
      return W.AI && W.AI.AIDrafting ? (
        <W.AI.AIDrafting go={noopGo} />
      ) : <Placeholder label="AI Builder" />;
    case "brief":
      return W.BriefScreen ? <W.BriefScreen go={noopGo} /> : <Placeholder label="Brief" />;
    case "debrief":
      return W.DebriefScreen ? <W.DebriefScreen go={noopGo} /> : <Placeholder label="Debrief" />;
    case "group":
      return W.GroupMemberMobile ? (
        <W.GroupMemberMobile go={noopGo} />
      ) : W.GroupPublicMobile ? (
        <W.GroupPublicMobile go={noopGo} />
      ) : <Placeholder label="Group" />;
    case "notifications":
      return W.NotificationsInbox ? (
        <W.NotificationsInbox go={noopGo} />
      ) : <Placeholder label="Notifications" />;
    default:
      return <Placeholder label={key} />;
  }
}

function Placeholder({ label }) {
  return (
    <div className="screen" style={{ padding: 32, display: "flex", alignItems: "center", justifyContent: "center" }}>
      <div className="eyebrow">{label}</div>
    </div>
  );
}

// ============================================================
// Brand mark (small) — used in nav and footer
// ============================================================
function BrandMark({ size = 42 }) {
  return (
    <img
      src="assets/logo.png"
      alt="1:1"
      style={{ height: size, width: "auto", display: "block" }}
    />
  );
}

// ============================================================
// Store badges (placeholder — swap with official badges at launch)
// ============================================================
function AppleBadge() {
  return (
    <a href="#download" className="store-badge" data-cursor="cta" aria-label="Download on the App Store (placeholder)">
      <svg className="glyph" viewBox="0 0 24 24" fill="none" aria-hidden="true">
        <path d="M14.5 4.5c0-.5.2-1.4.7-2 .6-.6 1.5-.9 2-.9.1.6-.2 1.4-.7 2-.5.6-1.4 1-2 .9zM18 13.5c0-2.5 2-3.6 2.1-3.7-1.2-1.7-3-2-3.7-2-1.6-.2-3 .9-3.8.9-.8 0-2-.9-3.3-.9-1.7 0-3.2 1-4.1 2.5-1.7 3-.4 7.5 1.3 9.9.8 1.2 1.8 2.5 3.1 2.4 1.2 0 1.7-.8 3.2-.8 1.5 0 1.9.8 3.2.8 1.3 0 2.2-1.2 3-2.4.7-.9 1.1-2 1.5-3-.1 0-2.5-1-2.5-3.7z" fill="currentColor"/>
      </svg>
      <div className="stack">
        <span className="small">Download on the</span>
        <span className="big">App Store</span>
      </div>
    </a>
  );
}
function PlayBadge() {
  return (
    <a href="#download" className="store-badge" data-cursor="cta" aria-label="Get it on Google Play (placeholder)">
      <svg className="glyph" viewBox="0 0 24 24" fill="none" aria-hidden="true">
        {/* Generic play-triangle within a stroke; not the brand badge */}
        <path d="M5 3.5v17l13-8.5z" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round" fill="none"/>
      </svg>
      <div className="stack">
        <span className="small">Get it on</span>
        <span className="big">Google Play</span>
      </div>
    </a>
  );
}

function MagneticCTA({ children }) {
  // Simple wrapper; magnetic motion is intentionally omitted (not selected)
  return <>{children}</>;
}

function CTARow({ mode = "live", center = false }) {
  const [status, setStatus] = useState("idle"); // idle | sent
  return (
    <div className="lp-hero-cta-row" style={center ? { justifyContent: "center" } : undefined}>
      {mode === "live" ? (
        <>
          <AppleBadge />
          <PlayBadge />
        </>
      ) : (
        <form
          className="waitlist-row"
          onSubmit={(e) => {
            e.preventDefault();
            const i = e.currentTarget.querySelector("input");
            // Until /api/waitlist is implemented, redirect submissions
            // to the contact email and surface a confirmation. Without
            // this the form silently swallowed entries.
            const value = (i && i.value) ? i.value.trim() : "";
            if (value) {
              const subject = encodeURIComponent("Waitlist");
              const body = encodeURIComponent(`Please add ${value} to the 1:1 waitlist.`);
              window.location.href = `mailto:hello@1-1.app?subject=${subject}&body=${body}`;
            }
            if (i) { i.value = ""; }
            setStatus("sent");
          }}
        >
          <input type="email" required placeholder="your@email.com" aria-label="Email address" />
          <button type="submit" data-cursor="cta">Notify me</button>
          <span role="status" aria-live="polite" className="waitlist-status">
            {status === "sent" ? "Thanks — we'll be in touch." : ""}
          </span>
        </form>
      )}
    </div>
  );
}

// ============================================================
// Nav
// ============================================================
function Nav({ ctaMode }) {
  const ref = useRef(null);
  window.useNavScroll(ref);
  return (
    <nav ref={ref} className="lp-nav" data-scrolled="false">
      <a href="#top" className="lp-nav-mark" data-cursor="link" aria-label="1:1 home">
        <BrandMark size={42} />
      </a>
      <div className="lp-nav-links">
        <a className="lp-nav-link" href="#what" data-cursor="link">What it is</a>
        <a className="lp-nav-link" href="#how" data-cursor="link">How it works</a>
        <a className="lp-nav-link" href="#groups" data-cursor="link">For groups</a>
        <a className="lp-nav-cta" href="#download" data-cursor="cta">
          {ctaMode === "live" ? "Get the app" : "Join waitlist"}
          <svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true">
            <path d="M3 6h6m0 0L6 3m3 3L6 9" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round"/>
          </svg>
        </a>
      </div>
    </nav>
  );
}

// ============================================================
// Hero
// ============================================================
function Hero({ heroScreen, heroComposition, ctaMode }) {
  const stageRef = useRef(null);
  const screenA = useMemo(() => getScreen(heroScreen), [heroScreen]);
  const screenB = useMemo(() => getScreen("meetSheet"), []);
  const screenC = useMemo(() => getScreen("discover"), []);

  return (
    <section className="lp-hero" id="top">
      <window.SageSpotlight scopeRef={stageRef} />
      <div className="lp-hero-grid" ref={stageRef}>
        <div className="lp-hero-copy">
          <Reveal as="div" className="lp-eyebrow">
            <span>EST. 2026 — Gold Coast, Australia</span>
          </Reveal>
          <Reveal as="h1" className="lp-h1" delay={1}>
            Where business
            <br />
            <span className="it">gets done.</span>
          </Reveal>
          <Reveal as="p" className="lp-lede" style={{ maxWidth: 560 }} delay={2}>
            Every meeting structured before it happens. Both parties read in.
            A Debrief drafted the moment it ends. 1:1 is the operating layer
            for business relationships that actually produce outcomes.
          </Reveal>
          <Reveal delay={3}>
            <CTARow mode={ctaMode} />
          </Reveal>
          <Reveal as="div" className="lp-hero-meta" delay={4}>
            <span>For business owners</span>
            <span className="dotsep">·</span>
            <span>Business networking groups · Mastermind groups · Referral teams</span>
            <span className="dotsep">·</span>
            <span>iOS &amp; Android</span>
          </Reveal>
        </div>
        <div className="lp-hero-stage">
          <Reveal delay={2}>
            <div className="hero-phone-stack">
              {heroComposition === "trio" && (
                <window.ParallaxTilt max={2} className="aux">
                  <PhoneFrame width={220} screen={screenC} />
                </window.ParallaxTilt>
              )}
              <window.ParallaxTilt max={4}>
                <PhoneFrame width={heroComposition === "trio" ? 260 : 340} screen={screenA} />
              </window.ParallaxTilt>
              {heroComposition === "trio" && (
                <window.ParallaxTilt max={2} className="aux">
                  <PhoneFrame width={220} screen={screenB} />
                </window.ParallaxTilt>
              )}
            </div>
          </Reveal>
        </div>
      </div>
    </section>
  );
}

// ============================================================
// Three anchors
// ============================================================
const ANCHORS = [
  {
    n: "01",
    kicker: "The Meet Sheet",
    title: ["A profile that reads like a ", "magazine."],
    body: "Both parties walk into the meeting prepared. The Meet Sheet replaces small talk with substance — what you do, who you serve, what you're looking for, what you can offer. Edited by you, drafted with AI, considered like a Monocle profile.",
    screen: "meetSheet",
  },
  {
    n: "02",
    kicker: "The Loop",
    title: ["Request, prepare, ", "meet, debrief."],
    body: "Every meeting flows through the same considered loop. The Brief is generated from both Meet Sheets the night before. The Debrief — summary, action items, attributed outcomes — is drafted automatically while the conversation is still warm.",
    screen: "debrief",
  },
  {
    n: "03",
    kicker: "Reputation",
    title: ["Built by the people ", "you've helped."],
    body: "Your reputation isn't self-reported. Outcomes — connections made, deals introduced, problems solved — are attributed by the other person. Diversity counts. Repeating the same five meetings does nothing for your score.",
    screen: "home",
  },
];

function ThreeAnchors() {
  return (
    <section className="lp-section" id="what">
      <div className="lp-container">
        <Reveal as="div" className="lp-eyebrow">
          <span>What it is</span>
        </Reveal>
        <Reveal as="h2" className="lp-h2" style={{ marginTop: 24, maxWidth: 880 }} delay={1}>
          Three mechanics. One operating
          <br />
          system for meetings <span className="it">that matter.</span>
        </Reveal>

        <div className="lp-anchors">
          {ANCHORS.map((a, i) => {
            const screen = getScreen(a.screen);
            return (
              <Reveal key={a.n} delay={Math.min(i + 1, 5)}>
                <article className="anchor-card" data-cursor="link">
                  <div className="anchor-card-num">
                    <span>{a.n}</span>
                    <span style={{ color: "var(--text-3)" }}>·</span>
                    <span>{a.kicker.toUpperCase()}</span>
                  </div>
                  <h3 className="anchor-card-h">
                    {a.title[0]}<span className="it">{a.title[1]}</span>
                  </h3>
                  <p className="anchor-card-body">{a.body}</p>
                  <div style={{ flex: 1 }}></div>
                  <div className="phone-wrap" style={{ alignSelf: "center" }}>
                    <PhoneFrame width={220} screen={screen} />
                  </div>
                </article>
              </Reveal>
            );
          })}
        </div>
      </div>
    </section>
  );
}

// ============================================================
// How it works — drawn timeline
// ============================================================
const STEPS = [
  { n: "01", t: "Request",  body: "Find someone worth meeting, or respond to one who found you." },
  { n: "02", t: "Accept",   body: "Both profiles open. The conversation starts before the meeting does." },
  { n: "03", t: "Brief",    body: "A two-page read generated the night before — context, intent, common ground." },
  { n: "04", t: "Meet",     body: "In person or video. Recording only begins when both parties agree." },
  { n: "05", t: "Debrief",  body: "A draft summary, action items, and outcome attribution — ready before you've left the room." },
  { n: "06", t: "Rhythm",   body: "One meeting a week, one connection made, two new requests sent. Quiet and consistent." },
];

function StepIcon({ which }) {
  // Simple monoline strokes — no fills, no emoji
  const props = { width: 22, height: 22, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.4, strokeLinecap: "round", strokeLinejoin: "round" };
  switch (which) {
    case "01": return <svg {...props}><path d="M4 12h12M11 7l5 5-5 5"/><circle cx="20" cy="12" r="1.4"/></svg>;
    case "02": return <svg {...props}><path d="M5 12l4 4L19 6"/></svg>;
    case "03": return <svg {...props}><rect x="4" y="5" width="16" height="14" rx="2"/><path d="M8 9h8M8 13h8M8 17h5"/></svg>;
    case "04": return <svg {...props}><rect x="9" y="3" width="6" height="11" rx="3"/><path d="M5 11a7 7 0 0 0 14 0M12 18v3"/></svg>;
    case "05": return <svg {...props}><path d="M5 19l3-1 9-9-2-2-9 9-1 3z"/><path d="M14 5l3 3"/></svg>;
    case "06": return <svg {...props}><path d="M4 12a8 8 0 1 1 14 5"/><path d="M18 13v4h-4"/></svg>;
    default: return null;
  }
}

function HowItWorks() {
  // Path: horizontal hairline connecting step centers on desktop;
  // we draw it as a flat horizontal in viewBox 0..100, 0..100.
  return (
    <section className="lp-section" id="how">
      <div className="lp-container">
        <Reveal as="div" className="lp-eyebrow">
          <span>How it works</span>
        </Reveal>
        <Reveal as="h2" className="lp-h2" style={{ marginTop: 24, maxWidth: 820 }} delay={1}>
          The same six steps. <span className="it">Every time.</span>
        </Reveal>
        <Reveal as="p" className="lp-lede" style={{ marginTop: 24, maxWidth: 580 }} delay={2}>
          A single, deliberate loop. No streaks. No badges. No nagging.
          Just the rhythm of a well-run meeting, repeated.
        </Reveal>

        <div className="lp-loop">
          <window.HairlinePath
            d="M 0 50 L 100 50"
            viewBox="0 0 100 100"
          />
          <div className="lp-loop-grid">
            {STEPS.map((s, i) => (
              <Reveal key={s.n} delay={Math.min(i, 5)} className="lp-step">
                <div className="lp-step-num">
                  <span>{s.n}</span>
                </div>
                <div className="lp-step-icon"><StepIcon which={s.n} /></div>
                <div className="lp-step-title">{s.t}</div>
                <div className="lp-step-body">{s.body}</div>
              </Reveal>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}

// ============================================================
// What it isn't
// ============================================================
const ISNT = [
  { n: "i", h: ["Not a ", "Tinder for business."], b: "Discovery is intentional and structured. There is no swiping." },
  { n: "ii", h: ["Not a ", "notification machine."], b: "Two reminders a week, on the days they matter. That is all." },
  { n: "iii", h: ["Not ", "pay-to-play."], b: "Visibility is earned through real meetings and attributed outcomes, never bought." },
  { n: "iv", h: ["Made for ", "serious operators."], b: "Owners who treat referrals as a sales channel. Consultants and advisors whose careers run on reputation. Group leaders, mastermind members, and brokers who measure what their meetings actually produce. If it's worth taking, it's worth running well." },
];

function WhatItIsnt() {
  return (
    <section className="lp-section" id="isnt">
      <div className="lp-container">
        <Reveal as="div" className="lp-eyebrow">
          <span>What it isn't</span>
        </Reveal>
        <Reveal as="h2" className="lp-h2" style={{ marginTop: 24, maxWidth: 880 }} delay={1}>
          No swiping. No streaks. <span className="it">No notifications begging.</span>
        </Reveal>

        <div className="lp-isnt">
          {ISNT.map((c, i) => (
            <Reveal key={c.n} className="lp-isnt-cell" delay={Math.min(i + 1, 4)}>
              <div className="num">{c.n.toUpperCase()}</div>
              <h4>
                {c.h[0]}<span className="it">{c.h[1]}</span>
              </h4>
              <p>{c.b}</p>
            </Reveal>
          ))}
        </div>
      </div>
    </section>
  );
}

// ============================================================
// For Groups
// ============================================================
function ForGroups() {
  const screen = useMemo(() => getScreen("group"), []);
  return (
    <section className="lp-section" id="groups">
      <div className="lp-container">
        <Reveal as="div" className="lp-eyebrow"><span>For groups</span></Reveal>

        <div className="lp-groups">
          <div className="lp-groups-copy">
            <Reveal as="h2" className="lp-h2" delay={1}>
              The operating layer
              <br />
              for <span className="it">your group.</span>
            </Reveal>
            <Reveal as="p" className="lp-lede" delay={2}>
              If you run a business networking group, mastermind, or referral
              team, 1:1 turns your weekly meeting into a measurable,
              accountable rhythm. Member health, group health, and
              cross-member connections all surface in one calm dashboard.
              No more spreadsheets, no more honour-system attendance.
            </Reveal>
            <Reveal delay={3}>
              <a className="ghost-cta" href="mailto:hello@1-1.app" data-cursor="link">
                Talk to us about your group
                <span className="arr">
                  <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
                    <path d="M3 7h8m0 0L8 4m3 3L8 10" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round"/>
                  </svg>
                </span>
              </a>
            </Reveal>
          </div>
          <div className="lp-groups-stage">
            <Reveal delay={2}>
              <window.ParallaxTilt max={3}>
                <PhoneFrame width={300} screen={screen} />
              </window.ParallaxTilt>
            </Reveal>
          </div>
        </div>
      </div>
    </section>
  );
}

// ============================================================
// Final CTA
// ============================================================
function FinalCTA({ ctaMode }) {
  return (
    <section className="lp-final" id="download">
      <div className="lp-container">
        <Reveal as="h2" className="lp-h2" style={{ fontSize: "clamp(40px, 5vw, 64px)" }}>
          For professionals who take
          <br />
          their meetings <span className="it">seriously.</span>
        </Reveal>
        <Reveal delay={2}>
          <CTARow mode={ctaMode} center />
        </Reveal>
        <Reveal as="div" className="lp-eyebrow no-rule" delay={3} style={{ marginTop: 40, justifyContent: "center", display: "inline-flex" }}>
          <span style={{ color: "var(--text-3)" }}>Free to join. No advertising. No data sold.</span>
        </Reveal>
      </div>
    </section>
  );
}

// ============================================================
// Footer
// ============================================================
function Footer() {
  return (
    <footer className="lp-footer">
      <div className="lp-footer-row">
        <div className="lp-footer-left">
          <BrandMark size={28} />
          <span>© 2026 1:1. Made on the Gold Coast.</span>
          <span className="dotsep" style={{ color: "var(--accent)", opacity: 0.6 }}>·</span>
          <window.BrisbaneClock />
        </div>
        <div className="lp-footer-links">
          {/* Privacy and Terms are not yet published. Link them to the
              contact email so visitors aren't dropped onto a "#" anchor
              that does nothing. Swap to /privacy and /terms once the
              pages are written. */}
          <a href="mailto:hello@1-1.app?subject=Privacy%20policy" data-cursor="link">Privacy</a>
          <a href="mailto:hello@1-1.app?subject=Terms" data-cursor="link">Terms</a>
          <a href="mailto:hello@1-1.app" data-cursor="link">hello@1-1.app</a>
        </div>
      </div>
    </footer>
  );
}

// ============================================================
// Tweaks panel (6 controls)
// ============================================================
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "heroScreen": "debrief",
  "accent": "sage",
  "motion": "off",
  "density": "comfortable",
  "ctaMode": "live",
  "heroComposition": "trio"
}/*EDITMODE-END*/;

const ACCENTS = {
  sage:   { c: "#8FB37A", soft: "#1B2418", ink: "#131A11" },
  ink:    { c: "#9AB4D8", soft: "#15202C", ink: "#0E1620" },
  copper: { c: "#C99A4A", soft: "#241B13", ink: "#1A1209" },
  bone:   { c: "#E2DFD6", soft: "#222019", ink: "#161510" },
};

function applyAccent(name) {
  const a = ACCENTS[name] || ACCENTS.sage;
  document.documentElement.style.setProperty("--accent", a.c);
  document.documentElement.style.setProperty("--accent-soft", a.soft);
  document.documentElement.style.setProperty("--accent-ink", a.ink);
}

function App() {
  const [t, setTweak] = window.useTweaks(TWEAK_DEFAULTS);
  const motion = useMemo(() => ({ level: t.motion }), [t.motion]);

  // Apply accent + density + motion to root
  useEffect(() => { applyAccent(t.accent); }, [t.accent]);
  useEffect(() => { document.documentElement.dataset.density = t.density; }, [t.density]);
  useEffect(() => { document.documentElement.dataset.motion = t.motion; }, [t.motion]);

  // Tweaks panel is a design-time control surface. Hide it by default
  // and only show it when the URL carries ?edit=1 (or in localhost),
  // so production visitors never see it.
  const showTweaks = useMemo(() => {
    if (typeof window === "undefined") return false;
    const params = new URLSearchParams(window.location.search);
    if (params.get("edit") === "1") return true;
    return /^(localhost|127\.0\.0\.1)$/.test(window.location.hostname);
  }, []);

  return (
    <window.MotionContext.Provider value={motion}>
      <window.ScrollProgress />
      <window.EditorialCursor />

      <div className="lp-shell" data-density={t.density}>
        <Nav ctaMode={t.ctaMode} />
        {/* Wrap the editorial sections in <main> so the page exposes a
            single landmark to assistive tech and SEO crawlers. */}
        <main>
          <Hero
            heroScreen={t.heroScreen}
            heroComposition={t.heroComposition}
            ctaMode={t.ctaMode}
          />
          <ThreeAnchors />
          <HowItWorks />
          <WhatItIsnt />
          <ForGroups />
          <FinalCTA ctaMode={t.ctaMode} />
        </main>
        <Footer />
      </div>

      {showTweaks ? (
      <window.TweaksPanel title="Tweaks" defaultOpen={false}>
        <window.TweakSection label="Hero">
          <window.TweakSelect
            label="Featured screen"
            value={t.heroScreen}
            onChange={(v) => setTweak("heroScreen", v)}
            options={[
              { value: "home", label: "Home" },
              { value: "meetSheet", label: "Meet Sheet" },
              { value: "discover", label: "Discover" },
              { value: "aiBuilder", label: "AI Builder" },
              { value: "brief", label: "Brief" },
              { value: "debrief", label: "Debrief" },
              { value: "notifications", label: "Notifications" },
            ]}
          />
          <window.TweakRadio
            label="Composition"
            value={t.heroComposition}
            onChange={(v) => setTweak("heroComposition", v)}
            options={[
              { value: "single", label: "Single" },
              { value: "trio", label: "Trio" },
            ]}
          />
        </window.TweakSection>

        <window.TweakSection label="Brand">
          <window.TweakColor
            label="Accent"
            value={t.accent}
            onChange={(v) => setTweak("accent", v)}
            options={[
              { value: "sage",   color: "#8FB37A" },
              { value: "ink",    color: "#9AB4D8" },
              { value: "copper", color: "#C99A4A" },
              { value: "bone",   color: "#E2DFD6" },
            ]}
          />
          <window.TweakRadio
            label="Density"
            value={t.density}
            onChange={(v) => setTweak("density", v)}
            options={[
              { value: "comfortable", label: "Comfortable" },
              { value: "compact",     label: "Compact" },
            ]}
          />
        </window.TweakSection>

        <window.TweakSection label="Behaviour">
          <window.TweakSelect
            label="Motion"
            value={t.motion}
            onChange={(v) => setTweak("motion", v)}
            options={[
              { value: "full",   label: "Full" },
              { value: "subtle", label: "Subtle" },
              { value: "off",    label: "Off" },
            ]}
          />
          <window.TweakRadio
            label="CTA mode"
            value={t.ctaMode}
            onChange={(v) => setTweak("ctaMode", v)}
            options={[
              { value: "live",     label: "Store badges" },
              { value: "waitlist", label: "Waitlist" },
            ]}
          />
        </window.TweakSection>
      </window.TweaksPanel>
      ) : null}
    </window.MotionContext.Provider>
  );
}

const Reveal = window.Reveal;

window.LandingApp = App;
