/* global React, ReactDOM, useTweaks, TweaksPanel, TweakSection, TweakColor, TweakRadio, TweakSelect */
const { useState, useEffect, useRef, useContext, createContext, useCallback } = React;

// ─────────────────────────────────────────────────────────────
// Config — single-edit values
// ─────────────────────────────────────────────────────────────
const CTA_CONFIG = {
  label: "Join the waitlist",
  href: "#waitlist-section",
};

const FOUNDING_CONFIG = {
  href: "https://buy.stripe.com/28E00iadL0jS3GPdU35Rm00",
  price: "$199",
  label: "Become a Founding Member",
};

const WAITLIST_API = "/api/waitlist";

// ─────────────────────────────────────────────────────────────
// Tweak defaults
// ─────────────────────────────────────────────────────────────
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accentPalette": ["#3EB7FF", "#6FD0FF"],
  "heroCopy": "measured",
  "featLayout": "asymmetric"
}/*EDITMODE-END*/;

const ACCENT_PALETTES = [
  ["#3EB7FF", "#6FD0FF"],
  ["#2FD6BB", "#5FEAD0"],
  ["#3E7EFF", "#6FA5FF"],
];

const TweakCtx   = createContext(TWEAK_DEFAULTS);
const WaitlistCtx = createContext(() => {});

// ─────────────────────────────────────────────────────────────
// Small primitives
// ─────────────────────────────────────────────────────────────
function CTA({ variant = "primary", size, children, className = "" }) {
  const v = variant === "ghost" ? "btn-ghost" : "btn-primary";
  const s = size === "sm" ? "btn-sm" : "";
  return (
    <a className={`btn ${v} ${s} ${className}`} href={CTA_CONFIG.href}>
      <span>{children || CTA_CONFIG.label}</span>
      <span className="arrow" aria-hidden="true">↗</span>
    </a>
  );
}

function FoundingCTA({ size, className = "" }) {
  const s = size === "sm" ? "btn-sm" : "";
  return (
    <a
      className={`btn btn-primary ${s} ${className}`}
      href={FOUNDING_CONFIG.href}
      target="_blank"
      rel="noopener noreferrer"
    >
      <span>{FOUNDING_CONFIG.label}</span>
      <span className="arrow" aria-hidden="true">↗</span>
    </a>
  );
}

function WaitlistSecondary() {
  const openWaitlist = useContext(WaitlistCtx);
  return (
    <button onClick={openWaitlist} className="waitlist-secondary" type="button">
      Not ready? Join the free waitlist.
    </button>
  );
}

function Eyebrow({ children }) {
  return <span className="eyebrow">{children}</span>;
}

function useReveal() {
  useEffect(() => {
    const els = document.querySelectorAll(".reveal");
    const io = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            e.target.classList.add("in");
            io.unobserve(e.target);
          }
        });
      },
      { threshold: 0.12, rootMargin: "0px 0px -40px 0px" }
    );
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, []);
}

function Mark({ size = 36 }) {
  return (
    <img
      src="assets/logo-mark.png"
      className="mark"
      alt=""
      aria-hidden="true"
      style={{ width: size, height: size, display: "block", flexShrink: 0 }}
    />
  );
}

// ─────────────────────────────────────────────────────────────
// Social icons
// ─────────────────────────────────────────────────────────────
function IconInstagram() {
  return (
    <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <rect x="2" y="2" width="20" height="20" rx="5" />
      <circle cx="12" cy="12" r="4.5" />
      <circle cx="17.5" cy="6.5" r="1.25" fill="currentColor" stroke="none" />
    </svg>
  );
}

function IconTikTok() {
  return (
    <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
      <path d="M16.6 5.82A4.28 4.28 0 0 1 15.54 3h-3.09v12.4a2.59 2.59 0 0 1-2.59 2.5 2.59 2.59 0 0 1-2.59-2.5 2.59 2.59 0 0 1 2.59-2.5c.28 0 .54.04.79.1V9.01a6.17 6.17 0 0 0-.79-.05A6.33 6.33 0 0 0 3.53 15.3a6.33 6.33 0 0 0 6.33 6.33 6.33 6.33 0 0 0 6.32-6.33V8.79a8.18 8.18 0 0 0 4.83 1.55V6.83a4.18 4.18 0 0 1-2.44-1.01z" />
    </svg>
  );
}

function IconYouTube() {
  return (
    <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <rect x="2" y="5" width="20" height="14" rx="4" />
      <polygon points="10 9 16 12 10 15" fill="currentColor" stroke="none" />
    </svg>
  );
}

function IconThreads() {
  return (
    <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <circle cx="12" cy="12" r="4" />
      <path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-3.92 7.94" />
    </svg>
  );
}

function SocialLink({ href, label, children, quiet = false }) {
  return (
    <a
      href={href}
      target="_blank"
      rel="noopener noreferrer"
      className={quiet ? "social-link social-link--quiet" : "social-link"}
      aria-label={label}
    >
      {children}
    </a>
  );
}

function SocialRow({ quiet = false }) {
  return (
    <div className={quiet ? "social-row social-row--quiet" : "social-row"}>
      <SocialLink href="https://instagram.com/trackora.app" label="Trackora on Instagram" quiet={quiet}><IconInstagram /></SocialLink>
      <SocialLink href="https://tiktok.com/@trackora.app"   label="Trackora on TikTok"    quiet={quiet}><IconTikTok /></SocialLink>
      <SocialLink href="https://youtube.com/@trackora"      label="Trackora on YouTube"   quiet={quiet}><IconYouTube /></SocialLink>
      <SocialLink href="https://www.threads.com/@trackora.app" label="Trackora on Threads" quiet={quiet}><IconThreads /></SocialLink>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// 1. Sticky navbar
// ─────────────────────────────────────────────────────────────
function Nav() {
  const [scrolled, setScrolled] = useState(false);
  const openWaitlist = useContext(WaitlistCtx);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 12);
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  return (
    <nav className={`nav ${scrolled ? "scrolled" : ""}`}>
      <div className="container nav-inner">
        <a href="#top" className="wordmark">
          <Mark />
          <span>Trackora</span>
        </a>
        <div className="nav-links">
          <a href="#features" className="link-hide-mobile">Features</a>
          <a href="#pricing" className="link-hide-mobile">Pricing</a>
          <a href="#waitlist-section" className="link-hide-mobile">Waitlist</a>
          <FoundingCTA size="sm" />
        </div>
      </div>
    </nav>
  );
}

// ─────────────────────────────────────────────────────────────
// Hero copy variants
// ─────────────────────────────────────────────────────────────
const HERO_COPY = {
  measured: {
    eyebrow: "A Premium iOS Discipline App",
    h1: (<>{"Structured\u00a0growth,"}<br /><span className="glow">{"one\u00a0day\u00a0at\u00a0a\u00a0time."}</span></>),
    sub: "Trackora is a calm, founder\u2019s dashboard for your own life. Set a goal, log the work, and move forward. Lone Wolf mode or Partner mode. No streaks. No feeds. No noise.",
    cta2: "See how it works",
  },
  direct: {
    eyebrow: "A Premium iOS Discipline App",
    h1: (<>The founder\u2019s dashboard<br />for <span className="glow">your own life.</span></>),
    sub: "Set a goal. Log the work. Move forward. Trackora gives you one private space to track what matters, solo or alongside one person who holds you to the same standard.",
    cta2: "How it works",
  },
  minimal: {
    eyebrow: "Lone Wolf mode \u00b7 Pair mode",
    h1: (<>Private discipline.<br /><span className="glow">No noise. No games.</span></>),
    sub: "Trackora strips goal tracking down to its core: a goal, a daily log, and one optional partner. No social feed. No gamification. No audience.",
    cta2: "Explore features",
  },
};

// ─────────────────────────────────────────────────────────────
// 2. Hero
// ─────────────────────────────────────────────────────────────
function Hero() {
  const { heroCopy } = useContext(TweakCtx);
  const copy = HERO_COPY[heroCopy] || HERO_COPY.measured;
  return (
    <header className="hero" id="top">
      <div className="hero-video-wrap">
        <video
          className="hero-video"
          src="assets/hero-loop.mp4"
          poster="assets/hero-still.png"
          autoPlay
          muted
          loop
          playsInline
          preload="auto"
          aria-hidden="true"
          title="Trackora ambient background — abstract light motion on dark navy"
        />
      </div>
      <div className="hero-overlay" />

      <div className="container hero-inner">
        <div className="hero-copy">
          <Eyebrow>{copy.eyebrow}</Eyebrow>
          <h1>{copy.h1}</h1>
          <p className="hero-sub">{copy.sub}</p>
          <div className="hero-cta-row">
            <a className="btn btn-primary" href="#how-it-works">
              <span>See how it works</span>
              <span className="arrow" aria-hidden="true">↗</span>
            </a>
          </div>
          <div className="hero-app-store">
            <div className="app-store-badge">
              <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                <path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.8-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z"/>
              </svg>
              <span>Coming soon to the App Store</span>
            </div>
          </div>
        </div>
      </div>

      <div className="hero-scroll" aria-hidden="true">
        <span>Scroll</span>
        <span>↓</span>
      </div>
    </header>
  );
}

// ─────────────────────────────────────────────────────────────
// 3. The problem — visitor's real experience
// ─────────────────────────────────────────────────────────────
function Problem() {
  return (
    <section id="problem">
      <div className="container">
        <div className="section-head reveal">
          <Eyebrow>The problem</Eyebrow>
          <h2>You have started this goal before.</h2>
          <p className="lead">
            Most people who abandon a goal are not undisciplined. They had no clear
            structure to follow and no one to notice when they stopped showing up.
            Those two things, not willpower, are why goals fall apart.
          </p>
        </div>

        <div className="problem-grid">
          <div className="problem-card reveal">
            <div className="kicker">Sound familiar</div>
            <h3>You start strong. Then drift.</h3>
            <p>
              You set the goal, log a few days, then life interrupts. You restart a
              month later. You drift again. The cycle repeats, more than once. This
              is not a character flaw. It is what happens when structure is absent.
            </p>
          </div>
          <div className="problem-card reveal delay-1">
            <div className="kicker">The real issue</div>
            <h3>No structure means no system.</h3>
            <p>
              A goal without clear daily actions depends entirely on motivation.
              Motivation is unreliable. A system is not. Most tools give you
              streaks and points, not an actual plan.
            </p>
          </div>
          <div className="problem-card highlight reveal delay-2">
            <div className="kicker">The missing piece</div>
            <h3>No one is watching.</h3>
            <p>
              When only you know about a goal, there is no quiet pressure to
              show up. One person who notices your progress changes the whole
              equation. Nothing on the App Store is built for that quiet pact.
            </p>
          </div>
        </div>
      </div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────
// 3b. How it works
// ─────────────────────────────────────────────────────────────
function HowItWorks() {
  return (
    <section id="how-it-works">
      <div className="container">
        <div className="how-grid">
          <div className="how-copy reveal">
            <Eyebrow>The solution</Eyebrow>
            <h2>A long-term goal, turned into something you do every day.</h2>
            <p className="how-body">
              Trackora takes the goal you keep restarting and breaks it into
              clear daily actions. You log what you do, watch your progress
              build, and stay accountable, on your own or with one partner
              who is in it with you. Built on the Kaizen idea of small,
              continuous improvement that scales with your real capacity,
              not a streak that punishes you when you miss a day.
            </p>
          </div>

          <div className="how-mock reveal delay-1" aria-hidden="true">
            <div className="phone">
              <div className="phone-notch" />
              <div className="phone-screen">
                <div className="phone-status">
                  <span>9:41</span>
                  <span className="phone-status-right">
                    <span className="phone-dot" />
                    <span className="phone-dot" />
                  </span>
                </div>

                <div className="phone-eyebrow">Active goal</div>
                <h3 className="phone-goal">Write the first 20,000 words.</h3>

                <div className="phone-progress">
                  <div className="phone-progress-row">
                    <span className="phone-progress-label">Progress</span>
                    <span className="phone-progress-val">62%</span>
                  </div>
                  <div className="phone-progress-bar">
                    <div className="phone-progress-fill" style={{ width: "62%" }} />
                  </div>
                  <div className="phone-progress-meta">
                    <span>Day 28 of 90</span>
                    <span>12,400 / 20,000 words</span>
                  </div>
                </div>

                <div className="phone-actions-head">Today</div>
                <div className="phone-actions">
                  <div className="phone-action done">
                    <span className="phone-check" aria-hidden="true">✓</span>
                    <span>Write for 45 minutes</span>
                  </div>
                  <div className="phone-action done">
                    <span className="phone-check" aria-hidden="true">✓</span>
                    <span>Log word count</span>
                  </div>
                  <div className="phone-action">
                    <span className="phone-circle" aria-hidden="true" />
                    <span>Read one chapter</span>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────
// 4. Why accountability works — sourced research cards
// ─────────────────────────────────────────────────────────────
function ResearchCard({ figure, caption, source, delay }) {
  return (
    <div className={`stat-card research-card reveal delay-${delay}`}>
      <span className="arrow-up" aria-hidden="true">↑</span>
      <div className="research-figure">{figure}</div>
      <div className="research-caption">{caption}</div>
      <div className="research-source">{source}</div>
    </div>
  );
}

function Stats() {
  return (
    <section id="proof">
      <div className="container">
        <div className="section-head reveal">
          <Eyebrow>Why accountability works</Eyebrow>
          <h2>Structure and accountability predict follow-through.</h2>
          <p className="lead">
            Writing a goal down and having someone to answer to are the two factors
            that consistently separate goals that stick from goals that don't.
            Trackora is built around both.
          </p>
        </div>

        <div className="stats stats--three">
          <ResearchCard
            figure="70%+"
            caption="of people who wrote down their goals and sent weekly progress to a friend achieved them, versus 35% who kept their goals to themselves."
            source="Dominican University study, 267 participants"
            delay={1}
          />
          <ResearchCard
            figure="33–42%"
            caption="more likely to achieve a goal when you write it down."
            source="Dr. Gail Matthews, Dominican University"
            delay={2}
          />
          <ResearchCard
            figure="2x"
            caption="more likely to reach a health goal with an accountability partner."
            source="American Journal of Lifestyle Medicine"
            delay={3}
          />
        </div>
      </div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────
// 5. Two modes
// ─────────────────────────────────────────────────────────────
function Modes() {
  return (
    <section id="modes">
      <div className="container">
        <div className="section-head reveal">
          <Eyebrow>Two modes</Eyebrow>
          <h2>Move alone, or move with one other person.</h2>
          <p className="lead">
            Trackora is built around two simple shapes. Pick the one that matches
            how you work. Switch later if you want.
          </p>
        </div>

        <div className="modes-grid">
          <div className="mode reveal">
            <div className="mode-tag">
              <span>● Lone Wolf</span>
            </div>
            <h3>Lone Wolf.</h3>
            <p>
              Solo mode for people who do their best work in private. Your goals,
              your plan, your daily log. Nothing public, nothing shared, nothing
              competing for your attention.
            </p>
            <div className="mode-art glyph">
              <svg viewBox="0 0 400 160" preserveAspectRatio="none">
                <defs>
                  <linearGradient id="loneGrad" x1="0" x2="1">
                    <stop offset="0" stopColor="#3EB7FF" stopOpacity="0.0" />
                    <stop offset="0.5" stopColor="#3EB7FF" stopOpacity="0.8" />
                    <stop offset="1" stopColor="#6FD0FF" stopOpacity="1" />
                  </linearGradient>
                </defs>
                <path
                  d="M10 130 C 80 130, 130 110, 170 90 S 280 50, 390 20"
                  fill="none"
                  stroke="url(#loneGrad)"
                  strokeWidth="2"
                />
                <circle cx="390" cy="20" r="5" fill="#6FD0FF" />
              </svg>
            </div>
          </div>

          <div className="mode pair reveal delay-1">
            <div className="mode-tag">
              <span>● Pair · max 2 forever</span>
            </div>
            <h3>Pair.</h3>
            <p>
              A best friend, a sibling, a spouse, a roommate, a co-founder.
              Two people, one shared direction. You see each other&rsquo;s progress,
              read each other&rsquo;s journal entries, and feel the quiet pressure of
              someone showing up too. Capped at two on purpose. Only the initiator
              pays. The second person joins free.
            </p>
            <div className="mode-art glyph">
              <svg viewBox="0 0 400 160" preserveAspectRatio="none">
                <defs>
                  <linearGradient id="pairGradA" x1="0" x2="1">
                    <stop offset="0" stopColor="#3EB7FF" stopOpacity="0.0" />
                    <stop offset="1" stopColor="#6FD0FF" stopOpacity="1" />
                  </linearGradient>
                  <linearGradient id="pairGradB" x1="0" x2="1">
                    <stop offset="0" stopColor="#3EB7FF" stopOpacity="0.0" />
                    <stop offset="1" stopColor="#3EB7FF" stopOpacity="0.85" />
                  </linearGradient>
                </defs>
                <path
                  d="M10 140 C 80 140, 140 90, 200 70 S 320 35, 390 18"
                  fill="none"
                  stroke="url(#pairGradA)"
                  strokeWidth="2"
                />
                <path
                  d="M10 120 C 80 120, 130 100, 200 85 S 320 60, 390 38"
                  fill="none"
                  stroke="url(#pairGradB)"
                  strokeWidth="2"
                  opacity="0.7"
                />
                <circle cx="390" cy="18" r="5" fill="#6FD0FF" />
                <circle cx="390" cy="38" r="5" fill="#3EB7FF" />
              </svg>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────
// 6. AI-powered onboarding
// ─────────────────────────────────────────────────────────────
function Onboarding() {
  return (
    <section id="onboarding">
      <div className="container">
        <div className="onboard">
          <div className="onboard-mock reveal">
            <div className="chat">
              <div className="bubble ai">
                What is the one goal you want to move forward over the next 90 days?
              </div>
              <div className="bubble user">
                Write the first 20,000 words of my book.
              </div>
              <div className="bubble ai">
                Understood. I will structure this as a daily writing practice with two
                weekly review points. Confirm your available window each morning.
              </div>
              <div className="bubble plan">
                <div className="plan-head">Your plan · 90 days</div>
                <div className="plan-row">
                  <span>Daily writing, 45 min, before 9am</span>
                  <span className="check">✓</span>
                </div>
                <div className="plan-row">
                  <span>Weekly review, Sunday, 20 min</span>
                  <span className="check">✓</span>
                </div>
                <div className="plan-row">
                  <span>Word target, 220 / day · 1,540 / week</span>
                  <span className="check">✓</span>
                </div>
                <div className="plan-row">
                  <span>Journal prompt, after every session</span>
                  <span className="check">✓</span>
                </div>
              </div>
            </div>
          </div>

          <div className="onboard-copy reveal delay-1">
            <Eyebrow>AI-powered onboarding</Eyebrow>
            <h2>A personalized plan, written in five minutes.</h2>
            <p>
              Tell Trackora what you actually want to move forward. The onboarding
              translates a vague intention into a concrete, structured plan. The kind
              a careful coach would write for you.
            </p>
            <ol className="onboard-steps">
              <li>
                <span className="n">01</span>
                <span>
                  <div className="t">Name the goal in your own words.</div>
                  <div className="d">No templates, no categories. One sentence is enough.</div>
                </span>
              </li>
              <li>
                <span className="n">02</span>
                <span>
                  <div className="t">Trackora drafts the structure.</div>
                  <div className="d">Daily actions, weekly reviews, and a clear measure of progress.</div>
                </span>
              </li>
              <li>
                <span className="n">03</span>
                <span>
                  <div className="t">You approve, edit, or rewrite.</div>
                  <div className="d">The plan is yours from day one. The AI is a starting point, not a manager.</div>
                </span>
              </li>
            </ol>
          </div>
        </div>
      </div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────
// 7. Features grid
// ─────────────────────────────────────────────────────────────
function FeatureArt({ kind }) {
  if (kind === "private") {
    return (
      <svg viewBox="0 0 320 80" preserveAspectRatio="none" width="100%" height="100%">
        <rect x="0" y="58" width="56" height="14" rx="3" fill="#0B172C" stroke="#1a2a44" />
        <rect x="64" y="44" width="56" height="28" rx="3" fill="#0B172C" stroke="#1a2a44" />
        <rect x="128" y="28" width="56" height="44" rx="3" fill="#0B172C" stroke="#3EB7FF" strokeOpacity="0.4" />
        <rect x="192" y="14" width="56" height="58" rx="3" fill="#0B172C" stroke="#3EB7FF" strokeOpacity="0.7" />
        <rect x="256" y="2" width="56" height="70" rx="3" fill="url(#bargrad)" />
        <defs>
          <linearGradient id="bargrad" x1="0" y1="1" x2="0" y2="0">
            <stop offset="0" stopColor="#3EB7FF" />
            <stop offset="1" stopColor="#6FD0FF" />
          </linearGradient>
        </defs>
      </svg>
    );
  }
  if (kind === "log") {
    return (
      <svg viewBox="0 0 320 80" preserveAspectRatio="none" width="100%" height="100%">
        {Array.from({ length: 28 }).map((_, i) => {
          const filled = [0,1,2,4,5,7,8,9,10,12,14,15,16,18,20,21,22,24,25,26].includes(i);
          const x = (i % 14) * 22 + 6;
          const y = i < 14 ? 14 : 44;
          return (
            <rect key={i} x={x} y={y} width="16" height="22" rx="3"
              fill={filled ? "#3EB7FF" : "#0B172C"} stroke="#1a2a44" opacity={filled ? 0.85 : 1} />
          );
        })}
      </svg>
    );
  }
  if (kind === "journal") {
    return (
      <svg viewBox="0 0 320 80" preserveAspectRatio="none" width="100%" height="100%">
        <rect x="0" y="10" width="320" height="60" rx="6" fill="#0B172C" stroke="#1a2a44" />
        <line x1="14" y1="26" x2="220" y2="26" stroke="#3EB7FF" strokeOpacity="0.55" strokeWidth="2" />
        <line x1="14" y1="38" x2="280" y2="38" stroke="#B8CFE0" strokeOpacity="0.25" strokeWidth="2" />
        <line x1="14" y1="50" x2="200" y2="50" stroke="#B8CFE0" strokeOpacity="0.25" strokeWidth="2" />
        <line x1="14" y1="62" x2="160" y2="62" stroke="#B8CFE0" strokeOpacity="0.25" strokeWidth="2" />
      </svg>
    );
  }
  if (kind === "graph") {
    return (
      <svg viewBox="0 0 320 80" preserveAspectRatio="none" width="100%" height="100%">
        <defs>
          <linearGradient id="grph" x1="0" x2="0" y1="0" y2="1">
            <stop offset="0" stopColor="#6FD0FF" stopOpacity="0.35" />
            <stop offset="1" stopColor="#6FD0FF" stopOpacity="0" />
          </linearGradient>
          <linearGradient id="grphline" x1="0" x2="1">
            <stop offset="0" stopColor="#3EB7FF" />
            <stop offset="1" stopColor="#6FD0FF" />
          </linearGradient>
        </defs>
        <path d="M0 70 C 50 64, 90 58, 130 46 S 220 30, 320 8 L 320 80 L 0 80 Z" fill="url(#grph)" />
        <path d="M0 70 C 50 64, 90 58, 130 46 S 220 30, 320 8" fill="none" stroke="url(#grphline)" strokeWidth="2" />
        <circle cx="320" cy="8" r="3" fill="#6FD0FF" />
      </svg>
    );
  }
  if (kind === "consistency") {
    return (
      <svg viewBox="0 0 320 80" preserveAspectRatio="none" width="100%" height="100%">
        {[0,1,2,3,4,5,6].map((i) => {
          const filled = [0,1,2,4,5].includes(i);
          return (
            <g key={i} transform={`translate(${i * 44 + 4}, 14)`}>
              <rect width="36" height="52" rx="4" fill="#0B172C"
                stroke={filled ? "#3EB7FF" : "#1a2a44"} strokeOpacity={filled ? 0.7 : 1} />
              {filled && <circle cx="18" cy="26" r="6" fill="#3EB7FF" />}
              {!filled && <line x1="10" y1="26" x2="26" y2="26" stroke="#1a2a44" strokeWidth="2" />}
            </g>
          );
        })}
      </svg>
    );
  }
  return null;
}

const FEAT_CLS = {
  asymmetric: ["small", "small", "small", "half",  "half"],
  uniform:    ["small", "small", "small", "small", "small"],
  list:       ["wide",  "wide",  "wide",  "wide",  "wide" ],
};

const FEAT_GRID_STYLE = {
  asymmetric: {},
  uniform:    { gridTemplateColumns: "repeat(3, 1fr)" },
  list:       { gridTemplateColumns: "1fr" },
};

function Features() {
  const { featLayout } = useContext(TweakCtx);
  const layout = FEAT_CLS[featLayout] ? featLayout : "asymmetric";
  const clsList = FEAT_CLS[layout];

  const items = [
    { tag: "Goals",           title: "Private and shared goals.",                        body: "Hold a goal entirely to yourself, or commit one openly to your partner. Each goal has its own plan, log, and quiet progress signal.",                                             art: "private"     },
    { tag: "Daily log",       title: "Action logging, not streak chasing.",              body: "Log the work you actually did, in your own words. Trackora records the action. It never punishes the gap.",                                                                       art: "log"         },
    { tag: "Journal",         title: "Shared journal.",                                  body: "Write your reflection at the end of the day. In Pair mode, your partner reads it the next morning.",                                                                              art: "journal"     },
    { tag: "Progress graph",  title: "One global progress line, always rising in direction.", body: "All of your goals roll up into a single, calm trajectory, designed so you can read your last 90 days at a glance.",                                                      art: "graph"       },
    { tag: "Consistency",     title: "Surfaced quietly.",                                body: "Trackora highlights when you have shown up 5 of the last 7 days. A calm observation, never a streak.",                                                                          art: "consistency" },
  ];

  return (
    <section id="features">
      <div className="container">
        <div className="section-head reveal">
          <Eyebrow>Features</Eyebrow>
          <h2>The dashboard, not the game.</h2>
          <p className="lead">
            Five quiet primitives, deliberately chosen. Nothing else competes for
            your attention.
          </p>
        </div>

        <div className="features" style={FEAT_GRID_STYLE[layout]}>
          {items.map((it, i) => (
            <article key={it.title} className={`feature ${clsList[i]} reveal delay-${(i % 4) + 1}`}>
              <div className="feature-tag">{it.tag}</div>
              <h3>{it.title}</h3>
              <p>{it.body}</p>
              <div className="feature-art">
                <FeatureArt kind={it.art} />
              </div>
            </article>
          ))}
        </div>
      </div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────
// 7b. How Trackora compares
// ─────────────────────────────────────────────────────────────
const COMPARE_ROWS = [
  {
    option: "Going it alone",
    get: "Willpower, and usually the same restart cycle.",
    cost: "Free, but it has not worked yet.",
  },
  {
    option: "A habit-tracker app",
    get: "Streaks and points, easy to abandon, no real accountability.",
    cost: "A few dollars a month.",
  },
  {
    option: "A life coach",
    get: "Personalized structure and accountability from a professional.",
    cost: "Often $300 or more a month.",
  },
  {
    option: "Trackora",
    get: "Structure and accountability, on your own or with one partner.",
    cost: "$99 a year, or $199 once as a Founding Member.",
    highlight: true,
  },
];

function Compare() {
  return (
    <section id="compare">
      <div className="container">
        <div className="section-head reveal">
          <Eyebrow>How Trackora compares</Eyebrow>
          <h2>Structured accountability, without the cost of a coach.</h2>
          <p className="lead">
            There are a few ways to get the structure and accountability that
            make goals stick. Here is how they compare.
          </p>
        </div>

        <div className="compare reveal delay-1">
          <div className="compare-head" role="row">
            <span role="columnheader">Option</span>
            <span role="columnheader">What you get</span>
            <span role="columnheader">Cost</span>
          </div>
          {COMPARE_ROWS.map((r, i) => (
            <div
              key={r.option}
              className={`compare-row${r.highlight ? " compare-row--highlight" : ""}`}
              role="row"
            >
              <div className="compare-cell compare-option">
                <span className="compare-label" aria-hidden="true">Option</span>
                <span className="compare-option-name">
                  {r.highlight && <span className="compare-pip" aria-hidden="true" />}
                  {r.option}
                </span>
              </div>
              <div className="compare-cell compare-get">
                <span className="compare-label" aria-hidden="true">What you get</span>
                <span>{r.get}</span>
              </div>
              <div className="compare-cell compare-cost">
                <span className="compare-label" aria-hidden="true">Cost</span>
                <span>{r.cost}</span>
              </div>
            </div>
          ))}
        </div>

        <p className="compare-close reveal delay-2">
          A coach can do more, and costs far more. A full year of Trackora costs
          less than a single month with a coach.
        </p>
      </div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────
// 8. Pricing
// ─────────────────────────────────────────────────────────────
function Pricing() {
  return (
    <section id="pricing">
      <div className="container">
        <div className="section-head reveal" style={{ textAlign: "center", margin: "0 auto 64px" }}>
          <div style={{ display: "inline-block" }}>
            <Eyebrow>Pricing</Eyebrow>
          </div>
          <h2>Lock in lifetime access now.</h2>
          <p className="lead" style={{ margin: "22px auto 0" }}>
            A founding deal for the people who commit early. Standard plans available after launch.
          </p>
        </div>

        <div className="founding-card reveal">
          <div className="founding-left">
            <div className="plan-badge-row">
              <span className="badge founding-badge">Founding Lifetime</span>
              <span className="badge save">Limited · 100 spots</span>
            </div>
            <h3 className="founding-title">Founding Lifetime</h3>
            <div className="founding-price">
              <span className="founding-amount glow">{FOUNDING_CONFIG.price}</span>
              <span className="founding-once">once. Lifetime access, never billed again.</span>
            </div>
            <div className="founding-what-label">What you get</div>
            <ul className="founding-features">
              <li><span className="tick">↑</span><span>Lifetime access, billed once and never again</span></li>
              <li><span className="tick">↑</span><span>Pair a partner in for free, forever, with the full Partner tier included (normally $149 a year)</span></li>
              <li><span className="tick">↑</span><span>First access on launch day</span></li>
              <li><span className="tick">↑</span><span>Permanent Founding Member status</span></li>
              <li><span className="tick">↑</span><span>A direct line to the founder to help shape the app</span></li>
            </ul>
          </div>
          <div className="founding-right">
            <FoundingCTA />
            <p className="founding-refund">Full refund anytime before launch, no questions asked.</p>
            <p className="scarcity founding-scarcity">Limited to the first 100 members.</p>
          </div>
        </div>

        <div className="std-plans-label reveal">Standard pricing after launch</div>
        <div className="pricing">
          <div className="plan reveal">
            <div className="plan-badge-row">
              <span className="badge save">Solo</span>
            </div>
            <h3>Lone Wolf</h3>
            <p className="plan-sub">Solo mode, private goals.</p>
            <div className="price">
              <span className="amount">$99.99</span>
              <span className="per">/ year</span>
            </div>
            <div className="breakdown">Billed annually · works out to 12 × $8.33 / mo. Monthly available at $19.99.</div>
            <ul>
              <li><span className="tick">↑</span><span>Unlimited private goals and daily actions</span></li>
              <li><span className="tick">↑</span><span>AI-powered onboarding and plan drafting</span></li>
              <li><span className="tick">↑</span><span>Personal journal with daily prompts</span></li>
              <li><span className="tick">↑</span><span>Global progress graph across all goals</span></li>
            </ul>
            <CTA variant="ghost">Join the waitlist</CTA>
          </div>

          <div className="plan reveal delay-1">
            <div className="plan-badge-row">
              <span className="badge save">Pair</span>
            </div>
            <h3>Partner</h3>
            <p className="plan-sub">Two people, one shared direction. Capped at 2 forever.</p>
            <div className="price">
              <span className="amount">$149.99</span>
              <span className="per">/ year</span>
            </div>
            <div className="breakdown">Billed annually · works out to 12 × $12.50 / mo. Monthly available at $29.99. Only the initiator pays. The second person joins free.</div>
            <ul>
              <li><span className="tick">↑</span><span>Everything in Lone Wolf</span></li>
              <li><span className="tick">↑</span><span>Shared goals and shared daily log</span></li>
              <li><span className="tick">↑</span><span>Shared journal. Read your partner&rsquo;s reflection the next morning</span></li>
              <li><span className="tick">↑</span><span>Calm consistency signals between the two of you</span></li>
              <li><span className="tick">↑</span><span>One quiet pair, no groups, no leaderboards</span></li>
            </ul>
            <CTA variant="ghost">Join the waitlist</CTA>
          </div>
        </div>
      </div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────
// 8. Vision and Mission
// ─────────────────────────────────────────────────────────────
function VisionMission() {
  return (
    <section id="vision">
      <div className="container">
        <div className="section-head reveal">
          <Eyebrow>Purpose</Eyebrow>
          <h2>Trackora's Aspirations.</h2>
        </div>
        <div className="vm-grid">
          <div className="vm-card reveal delay-1">
            <div className="vm-label">Vision</div>
            <div className="vm-number glow">1,000,000</div>
            <p className="vm-statement">people achieving a dream they once gave up on.</p>
          </div>
          <div className="vm-card vm-card--two reveal delay-2">
            <div className="vm-label">Mission</div>
            <div className="vm-number">100,000</div>
            <p className="vm-statement">people reaching a long-term goal they kept restarting.</p>
          </div>
        </div>
      </div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────
// 9. FAQ
// ─────────────────────────────────────────────────────────────
// FAQ_ITEMS is loaded from faq-data.js (window global, set before this script runs).
const FAQ_ITEMS = window.FAQ_ITEMS;

function FAQ() {
  const [open, setOpen] = useState(null);
  const [revealed, setRevealed] = useState(() => new Set());
  const toggle = (i) => setOpen((prev) => (prev === i ? null : i));
  const itemRefs = useRef([]);

  useEffect(() => {
    const els = itemRefs.current.filter(Boolean);
    const io = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            const idx = parseInt(e.target.dataset.faqIdx, 10);
            setRevealed((prev) => {
              const next = new Set(prev);
              next.add(idx);
              return next;
            });
            io.unobserve(e.target);
          }
        });
      },
      { threshold: 0.12, rootMargin: "0px 0px -40px 0px" }
    );
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, []);

  return (
    <section id="faq">
      <div className="container">
        <div className="section-head reveal" style={{ maxWidth: 640 }}>
          <Eyebrow>FAQ</Eyebrow>
          <h2 style={{ marginTop: 18 }}>Common questions.</h2>
        </div>
        <div className="faq-list">
          {FAQ_ITEMS.map((item, i) => {
            const isOpen = open === i;
            const isRevealed = revealed.has(i);
            const delay = (i % 4) + 1;
            return (
              <div
                key={i}
                ref={(el) => { itemRefs.current[i] = el; }}
                data-faq-idx={i}
                className={`faq-item reveal delay-${delay}${isRevealed ? " in" : ""}${isOpen ? " faq-item--open" : ""}`}
              >
                <h3 className="faq-q-heading">
                  <button
                    className="faq-q"
                    onClick={() => toggle(i)}
                    aria-expanded={isOpen}
                  >
                    <span>{item.q}</span>
                    <span className="faq-icon" aria-hidden="true">{isOpen ? "\u2212" : "+"}</span>
                  </button>
                </h3>
                <div className="faq-a-wrap" style={{ maxHeight: isOpen ? "400px" : "0px" }}>
                  <p className="faq-a">{item.a}</p>
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────
// 10. Final CTA
// ─────────────────────────────────────────────────────────────
function FinalCTA() {
  return (
    <section className="final-cta" id="cta">
      <div className="container">
        <div className="reveal" style={{ display: "inline-block" }}>
          <Eyebrow>The founding window</Eyebrow>
        </div>
        <h2 className="reveal delay-1">
          Transforming lives <span className="glow">one day at a time.</span>
        </h2>
        <p className="reveal delay-2">
          Founding access is limited to 100 people. Pay once, keep Trackora for life.
          The founding price closes when the first cohort is full.
        </p>
        <div className="reveal delay-3 final-cta-actions">
          <FoundingCTA />
          <p className="founding-refund">Full refund anytime before launch, no questions asked.</p>
          <span className="scarcity">Limited to the first 100 members.</span>
        </div>
      </div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────
// Smooth scroll helper
// ─────────────────────────────────────────────────────────────
function smoothScrollTo(el, offset = 80) {
  if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
    window.scrollTo(0, el.getBoundingClientRect().top + window.scrollY - offset);
    return;
  }
  const start = window.scrollY;
  const target = el.getBoundingClientRect().top + window.scrollY - offset;
  const distance = target - start;
  const duration = 750;
  let startTime = null;
  function ease(t) {
    return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
  }
  function step(ts) {
    if (!startTime) startTime = ts;
    const progress = Math.min((ts - startTime) / duration, 1);
    window.scrollTo(0, start + distance * ease(progress));
    if (progress < 1) requestAnimationFrame(step);
  }
  requestAnimationFrame(step);
}

// ─────────────────────────────────────────────────────────────
// 11b. Waitlist mini-section
// ─────────────────────────────────────────────────────────────
function WaitlistSection() {
  const openWaitlist = useContext(WaitlistCtx);
  return (
    <section id="waitlist-section" className="waitlist-section">
      <div className="container">
        <div className="waitlist-mini reveal">
          <p className="waitlist-mini-text">
            Not ready to commit? Join the free waitlist and we'll let you know the day Trackora launches.
          </p>
          <button onClick={openWaitlist} className="btn btn-primary" type="button">
            <span>Join the waitlist</span>
            <span className="arrow" aria-hidden="true">↗</span>
          </button>
        </div>
      </div>
    </section>
  );
}

// ─────────────────────────────────────────────────────────────
// 12. Footer — with social icons
// ─────────────────────────────────────────────────────────────
function Footer() {
  return (
    <footer id="waitlist">
      <div className="container">
        <div className="foot-row">
          <div className="col">
            <a href="#top" className="wordmark">
              <Mark size={28} />
              <span>Trackora</span>
            </a>
            <p className="dim" style={{ maxWidth: 320 }}>
              A premium iOS discipline app for structured self-improvement.
            </p>
          </div>
          <div className="col">
            <h4>Product</h4>
            <a href="#features">Features</a>
            <a href="#pricing">Pricing</a>
          </div>
          <div className="col">
            <h4>Legal</h4>
            <a href="/privacy">Privacy</a>
            <a href="/terms">Terms</a>
            <a href="/faq">FAQ</a>
          </div>
          <div className="col">
            <h4>Follow</h4>
            <SocialRow quiet={true} />
          </div>
          <div className="col">
            <h4>Get the app</h4>
            <CTA size="sm">Join the waitlist</CTA>
          </div>
        </div>
        <div className="foot-bottom">
          <span>© 2026 Trackora. All rights reserved.</span>
          <span className="dim">Made for the quiet ones.</span>
        </div>
      </div>
    </footer>
  );
}

// ─────────────────────────────────────────────────────────────
// Waitlist modal (Part 3)
// ─────────────────────────────────────────────────────────────
function WaitlistModal({ isOpen, onClose }) {
  const [email, setEmail]       = useState("");
  const [submitted, setSubmitted] = useState(false);
  const [loading, setLoading]   = useState(false);
  const [error, setError]       = useState("");
  const inputRef = useRef(null);

  // Keyboard close + body scroll lock
  useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    if (isOpen) {
      document.addEventListener("keydown", onKey);
      document.body.style.overflow = "hidden";
      setTimeout(() => inputRef.current && inputRef.current.focus(), 80);
    }
    return () => {
      document.removeEventListener("keydown", onKey);
      document.body.style.overflow = "";
    };
  }, [isOpen, onClose]);

  // Reset state when closed
  useEffect(() => {
    if (!isOpen) {
      setTimeout(() => {
        setEmail("");
        setSubmitted(false);
        setLoading(false);
        setError("");
      }, 300);
    }
  }, [isOpen]);

  if (!isOpen) return null;

  const handleSubmit = async (e) => {
    e.preventDefault();
    setError("");
    setLoading(true);
    try {
      const res = await fetch(WAITLIST_API, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ email }),
      });
      if (!res.ok) {
        const data = await res.json().catch(() => ({}));
        throw new Error(data.error || "Something went wrong. Please try again.");
      }
      setSubmitted(true);
    } catch (err) {
      setError(err.message || "Something went wrong. Please try again.");
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="modal-backdrop" onClick={onClose} role="presentation">
      <div
        className="modal"
        onClick={(e) => e.stopPropagation()}
        role="dialog"
        aria-modal="true"
        aria-labelledby="modal-title"
      >
        <button className="modal-close" onClick={onClose} aria-label="Close">
          <svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true">
            <path d="M1 1l10 10M11 1L1 11" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" />
          </svg>
        </button>

        {!submitted ? (
          <>
            <h2 id="modal-title" className="modal-title">Join the waitlist</h2>
            <p className="modal-sub">
              Be the first to know when Trackora launches. We will email you once, on launch day.
            </p>
            <form onSubmit={handleSubmit} noValidate={false}>
              <input
                ref={inputRef}
                type="email"
                className="modal-input"
                placeholder="your@email.com"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                required
                autoComplete="email"
              />
              <button type="submit" className="btn btn-primary modal-submit" disabled={loading}>
                <span>{loading ? "Joining..." : "Join the waitlist"}</span>
                {!loading && <span className="arrow" aria-hidden="true">↗</span>}
              </button>
              {error && (
                <p className="modal-error" role="alert">{error}</p>
              )}
            </form>
          </>
        ) : (
          <>
            <h2 id="modal-title" className="modal-title">You are on the list</h2>
            <p className="modal-sub">
              We will email you the day Trackora launches. Until then, follow along:
            </p>
            <SocialRow />
          </>
        )}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// App — reordered sections, modal state
// ─────────────────────────────────────────────────────────────
function App() {
  const [t, setTweak]         = useTweaks(TWEAK_DEFAULTS);
  const [modalOpen, setModal] = useState(false);
  const openWaitlist  = useCallback(() => setModal(true),  []);
  const closeWaitlist = useCallback(() => setModal(false), []);
  useReveal();

  // Smooth scrolling for all same-page anchor links
  useEffect(() => {
    const handleClick = (e) => {
      const anchor = e.target.closest('a[href^="#"]');
      if (!anchor) return;
      const id = anchor.getAttribute("href").slice(1);
      if (!id) return;
      const el = document.getElementById(id);
      if (!el) return;
      e.preventDefault();
      smoothScrollTo(el);
    };
    document.addEventListener("click", handleClick);
    return () => document.removeEventListener("click", handleClick);
  }, []);

  // Cascade accent palette into CSS custom properties
  useEffect(() => {
    const [accent, accentHi] = Array.isArray(t.accentPalette)
      ? t.accentPalette
      : [t.accentPalette, t.accentPalette];
    const root = document.documentElement;
    root.style.setProperty("--accent", accent);
    root.style.setProperty("--accent-hi", accentHi || accent);
    const hex = accent.replace("#", "");
    const r = parseInt(hex.slice(0, 2), 16);
    const g = parseInt(hex.slice(2, 4), 16);
    const b = parseInt(hex.slice(4, 6), 16);
    root.style.setProperty("--accent-glow", `rgba(${r},${g},${b},0.30)`);
  }, [t.accentPalette]);

  return (
    <WaitlistCtx.Provider value={openWaitlist}>
      <TweakCtx.Provider value={t}>
        <Nav />

        {/* Conversion arc: hook → problem → evidence → solution → how → ask */}
        <Hero />
        <Problem />
        <HowItWorks />
        <Stats />
        <Modes />
        <Onboarding />
        <Features />
        <VisionMission />
        <Compare />
        <Pricing />
        <FAQ />
        <FinalCTA />
        <WaitlistSection />
        <Footer />

        <WaitlistModal isOpen={modalOpen} onClose={closeWaitlist} />

        <TweaksPanel title="Tweaks">
          <TweakSection label="Brand accent" />
          <TweakColor
            label="Accent palette"
            value={t.accentPalette}
            options={ACCENT_PALETTES}
            onChange={(v) => setTweak("accentPalette", v)}
          />
          <TweakSection label="Hero copy" />
          <TweakSelect
            label="Variant"
            value={t.heroCopy}
            options={[
              { value: "measured", label: "Measured: structured growth" },
              { value: "direct",   label: "Direct: founder's dashboard" },
              { value: "minimal",  label: "Minimal: private discipline" },
            ]}
            onChange={(v) => setTweak("heroCopy", v)}
          />
          <TweakSection label="Features grid" />
          <TweakRadio
            label="Layout"
            value={t.featLayout}
            options={[
              { value: "asymmetric", label: "Asymmetric" },
              { value: "uniform",    label: "Uniform" },
              { value: "list",       label: "List" },
            ]}
            onChange={(v) => setTweak("featLayout", v)}
          />
        </TweaksPanel>
      </TweakCtx.Provider>
    </WaitlistCtx.Provider>
  );
}

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