// Blog index — gallery-style listing
const { useState: useStateBI, useMemo: useMemoBI, useEffect: useEffectBI, useRef: useRefBI } = React;

const POSTS = [
  {
    "id": "01-stopped-ozempic-weight-back",
    "title": "You Stopped Ozempic and the Weight Came Back. Here's the Biology Behind Why.",
    "excerpt": "Weight regain after stopping GLP-1 medication is not simply a willpower issue — it is strongly shaped by physiology. Understanding the mechanism is the first step to changing the outcome.",
    "category": "Science",
    "readTime": 9,
    "date": "May 18, 2026",
    "direction": "Editorial hero image for You Stopped Ozempic and the Weight Came Back. Here's the Biology Behind Why.",
    "image": "blog-images/01-stopped-ozempic-weight-back/hero.jpg",
    "author": {
      "name": "KeepAfter Clinical Review",
      "role": "Clinical review"
    },
    "featured": true,
    "seedQuestion": "I stopped Ozempic 6 weeks ago and I'm already up 8 pounds. Is this rebound or am I doing something wrong?"
  },
  {
    "id": "02-how-keep-weight-off-after-ozempic",
    "title": "How to Actually Keep the Weight Off After Stopping Ozempic",
    "excerpt": "The research is clear — lifestyle habits built during GLP-1 treatment are the one important predictor of what happens after. Here's the evidence-based framework for making them stick.",
    "category": "Habits",
    "readTime": 10,
    "date": "May 14, 2026",
    "direction": "Editorial hero image for How to Actually Keep the Weight Off After Stopping Ozempic",
    "image": "blog-images/02-how-keep-weight-off-after-ozempic/hero.jpg",
    "author": {
      "name": "KeepAfter Clinical Review",
      "role": "Clinical review"
    },
    "featured": false,
    "seedQuestion": "What's the one habit that actually keeps the weight off after stopping Ozempic?"
  },
  {
    "id": "03-life-after-glp1",
    "title": "Life After GLP-1: What No One Tells You About the Months Ahead",
    "excerpt": "The hunger comes back. So does something else — a chance to understand your body in a way the medication never required you to. A month-by-month guide to what life after GLP-1 actually looks like.",
    "category": "Voice",
    "readTime": 9,
    "date": "May 11, 2026",
    "direction": "Editorial hero image for Life After GLP-1: What No One Tells You About the Months Ahead",
    "image": "blog-images/03-life-after-glp1/hero.jpg",
    "author": {
      "name": "KeepAfter Editorial Team",
      "role": "Editorial team"
    },
    "featured": false,
    "seedQuestion": "The food noise is coming back. What does week 4 off Wegovy actually feel like?"
  },
  {
    "id": "04-post-glp1-plate",
    "title": "The Post-GLP-1 Plate: A Philosophy of Eating for the Long Game",
    "excerpt": "After stopping Ozempic or Wegovy, what you eat matters — but how you think about eating matters more. A practical, beautiful guide to nutrition after GLP-1.",
    "category": "Food",
    "readTime": 8,
    "date": "May 7, 2026",
    "direction": "Editorial hero image for The Post-GLP-1 Plate: A Philosophy of Eating for the Long Game",
    "image": "blog-images/04-post-glp1-plate/hero.jpg",
    "author": {
      "name": "KeepAfter Editorial Team",
      "role": "Editorial team"
    },
    "featured": false,
    "seedQuestion": "I keep eating like I'm still on Mounjaro and I'm hungry by 4pm. What should my plate actually look like now?"
  },
  {
    "id": "05-week-one-off-semaglutide",
    "title": "What Happens in Your Body the Week You Stop Semaglutide",
    "excerpt": "Appetite surges, energy dips, and the occasional wave of nausea — week one off Ozempic or Wegovy follows a predictable physiological script. Here's what the science says, day by day.",
    "category": "Science",
    "readTime": 9,
    "date": "May 4, 2026",
    "direction": "Editorial hero image for What Happens in Your Body the Week You Stop Semaglutide",
    "image": "blog-images/05-week-one-off-semaglutide/hero.jpg",
    "author": {
      "name": "KeepAfter Clinical Review",
      "role": "Clinical review"
    },
    "featured": false,
    "seedQuestion": "It's day 5 off Ozempic and I'm exhausted and ravenous. Is this normal?"
  },
  {
    "id": "06-mounjaro-regain",
    "title": "Mounjaro, Zepbound, and Weight Regain: What the Data Actually Show",
    "excerpt": "SURMOUNT-4 found substantial average weight regain after tirzepatide withdrawal compared with continued treatment. That number is real — and it deserves an honest conversation about what comes next.",
    "category": "Science",
    "readTime": 9,
    "date": "April 30, 2026",
    "direction": "Editorial hero image for Mounjaro, Zepbound, and Weight Regain: What the Data Actually Show",
    "image": "blog-images/06-mounjaro-regain/hero.jpg",
    "author": {
      "name": "KeepAfter Clinical Review",
      "role": "Clinical review"
    },
    "featured": false,
    "seedQuestion": "The SURMOUNT-4 data scared me. How much weight am I actually going to regain off Zepbound?"
  },
  {
    "id": "07-weight-maintenance-habits",
    "title": "The 5 Daily Habits That Actually Keep the Weight Off After GLP-1",
    "excerpt": "Behavioral research on long-term weight maintenance keeps circling back to the same handful of practices. Here is what women who succeed at keeping weight off after GLP-1 do differently — every single day.",
    "category": "Habits",
    "readTime": 8,
    "date": "April 26, 2026",
    "direction": "Editorial hero image for The 5 Daily Habits That Actually Keep the Weight Off After GLP-1",
    "image": "blog-images/07-weight-maintenance-habits/hero.jpg",
    "author": {
      "name": "KeepAfter Editorial Team",
      "role": "Editorial team"
    },
    "featured": false,
    "seedQuestion": "What's the single most important habit for keeping weight off after GLP-1?"
  },
  {
    "id": "08-glp1-alternatives",
    "title": "After GLP-1: What Actually Works for Weight Maintenance When You Stop",
    "excerpt": "GLP-1 medications work. That is the uncomfortable starting point for any honest conversation about what comes next. Here is a clear-eyed look at the lifestyle behaviors, medications, and support structures that can fill some of that gap.",
    "category": "Science",
    "readTime": 9,
    "date": "April 22, 2026",
    "direction": "Editorial hero image for After GLP-1: What Actually Works for Weight Maintenance When You Stop",
    "image": "blog-images/08-glp1-alternatives/hero.jpg",
    "author": {
      "name": "KeepAfter Clinical Review",
      "role": "Clinical review"
    },
    "featured": false,
    "seedQuestion": "Are there any actual natural alternatives to Ozempic that work, or is that just diet culture nonsense?"
  },
  {
    "id": "09-jennifer-18-months",
    "title": "Eighteen Months After Stopping Wegovy: What Maintenance Can Look Like",
    "excerpt": "A non-fiction maintenance scenario based on published discontinuation data and common clinical patterns — no invented patient, no fake interview quotes.",
    "category": "Stories",
    "readTime": 8,
    "date": "April 19, 2026",
    "direction": "Editorial hero image for Eighteen Months After Stopping Wegovy: What Maintenance Can Look Like",
    "image": "blog-images/09-jennifer-18-months/hero.jpg",
    "author": {
      "name": "KeepAfter Editorial Team",
      "role": "Editorial team"
    },
    "featured": false,
    "seedQuestion": "What does life actually look like 18 months after stopping Wegovy?"
  },
  {
    "id": "10-set-point-science",
    "title": "Your Brain Has a Number. Here's What Happens When You Try to Change It.",
    "excerpt": "Set-point theory has been misunderstood for decades. New research on GLP-1 medications is finally clarifying why weight comes back after stopping — and what that means for the people who want to prevent it.",
    "category": "Science",
    "readTime": 9,
    "date": "April 15, 2026",
    "direction": "Editorial hero image for Your Brain Has a Number. Here's What Happens When You Try to Change It.",
    "image": "blog-images/10-set-point-science/hero.jpg",
    "author": {
      "name": "KeepAfter Clinical Review",
      "role": "Clinical review"
    },
    "featured": false,
    "seedQuestion": "Can I keep my weight at the new lower set point after Ozempic, or will my body always pull me back up?"
  }
];

const CATEGORIES = ["All", "Science", "Habits", "Food", "Voice", "Stories"];

// ─── Hero header ─────────────────────────────────────
function BlogHero() {
  return (
    <section style={{ maxWidth: 1240, margin: '0 auto', padding: '40px 32px 28px' }}>
      <Reveal>
        <BlogEyebrow>Field notes</BlogEyebrow>
      </Reveal>
      <Reveal delay={80}>
        <h1 style={{
          fontFamily: '"DM Serif Display", Georgia, serif',
          fontSize: 'clamp(48px, 6vw, 92px)',
          lineHeight: 1.02, letterSpacing: '-.02em',
          color: BS.black,
          margin: '18px 0 24px',
          textWrap: 'balance',
          maxWidth: 1100,
        }}>
          Reading for <em style={{ color: BS.green, fontStyle: 'italic' }}>the after.</em>
        </h1>
      </Reveal>
      <Reveal delay={160}>
        <p style={{
          fontFamily: '"DM Sans"', fontSize: 19, lineHeight: 1.55, color: BS.gray,
          maxWidth: 620, margin: 0, textWrap: 'pretty',
        }}>
          Slow, specific, clinical-adjacent writing for the part nobody else writes about — the months after you stop.
        </p>
      </Reveal>
    </section>
  );
}

// ─── Featured post (large hero card) ────────────────
function FeaturedCard({ post }) {
  const [hover, setHover] = useStateBI(false);
  return (
    <Reveal delay={220}>
      <a href={`blog-post.html?id=${post.id}`} style={{ textDecoration: 'none', color: 'inherit', display: 'block' }}>
        <article
          onMouseEnter={() => setHover(true)}
          onMouseLeave={() => setHover(false)}
          style={{
            margin: '32px auto 0', maxWidth: 1240,
            display: 'grid', gridTemplateColumns: '1.15fr 1fr',
            gap: 56, alignItems: 'center',
            padding: '0 32px',
          }}
          className="bi-featured"
        >
          <div style={{
            transform: hover ? 'scale(1.005)' : 'scale(1)',
            transition: 'transform .6s cubic-bezier(.22,.61,.36,1)',
          }}>
            <EditorialImage
              id={`feat-${post.id}`}
              ratio="5 / 4"
              kicker="Featured"
              src={post.image}
              direction={post.direction}
              radius={20}
              style={{
                boxShadow: hover ? '0 24px 60px -28px rgba(15,15,15,.25)' : '0 12px 40px -24px rgba(15,15,15,.15)',
                transition: 'box-shadow .5s ease',
              }}
            />
          </div>
          <div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 18 }}>
              <BlogEyebrow>{post.category}</BlogEyebrow>
              <span style={{ width: 18, height: 1, background: BS.border }} />
              <span style={{ fontFamily: '"DM Sans"', fontSize: 13, color: BS.gray }}>{post.readTime} min read</span>
            </div>
            <h2 style={{
              fontFamily: '"DM Serif Display", Georgia, serif',
              fontSize: 'clamp(34px, 3.6vw, 52px)',
              lineHeight: 1.08, letterSpacing: '-.015em',
              color: BS.black,
              margin: '0 0 20px',
              textWrap: 'balance',
            }}>{post.title}</h2>
            <p style={{
              fontFamily: '"DM Sans"', fontSize: 17, lineHeight: 1.6,
              color: BS.gray, margin: '0 0 28px', textWrap: 'pretty',
              maxWidth: 520,
            }}>{post.excerpt}</p>
            <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
              <div style={{
                width: 36, height: 36, borderRadius: '50%',
                background: BS.greenLight, border: `1px solid ${BS.border}`,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontFamily: '"DM Serif Display", Georgia, serif',
                color: BS.greenDark, fontSize: 15,
              }}>{post.author.name.split(' ').map(s => s[0]).slice(0,2).join('')}</div>
              <div>
                <div style={{ fontFamily: '"DM Sans"', fontSize: 13, fontWeight: 600, color: BS.black }}>{post.author.name}</div>
                <div style={{ fontFamily: '"DM Sans"', fontSize: 12, color: BS.gray }}>{post.date}</div>
              </div>
              <div style={{
                marginLeft: 'auto',
                display: 'inline-flex', alignItems: 'center', gap: 10,
                fontFamily: '"DM Sans"', fontSize: 14, fontWeight: 600,
                color: hover ? BS.green : BS.black,
                transition: 'color .25s ease',
              }}>
                Read
                <span style={{
                  display: 'inline-block',
                  transform: hover ? 'translateX(6px)' : 'translateX(0)',
                  transition: 'transform .3s cubic-bezier(.22,.61,.36,1)',
                }}>→</span>
              </div>
            </div>
          </div>
        </article>
      </a>
    </Reveal>
  );
}

// ─── Filter pills ────────────────────────────────────
function CategoryFilter({ active, onChange, counts }) {
  return (
    <div style={{
      maxWidth: 1240, margin: '0 auto', padding: '64px 32px 24px',
      display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap',
      borderBottom: `1px solid ${BS.border}`,
    }}>
      <div style={{
        fontFamily: '"DM Sans"', fontSize: 11, fontWeight: 600,
        color: BS.gray, letterSpacing: '.14em', textTransform: 'uppercase',
        marginRight: 12,
      }}>Filter by</div>
      {CATEGORIES.map(c => {
        const isActive = c === active;
        return (
          <button
            key={c}
            onClick={() => onChange(c)}
            style={{
              padding: '8px 16px',
              fontFamily: '"DM Sans"', fontSize: 13, fontWeight: 500,
              color: isActive ? BS.cream : BS.black,
              background: isActive ? BS.green : 'transparent',
              border: `1px solid ${isActive ? BS.green : BS.border}`,
              borderRadius: 999,
              cursor: 'pointer',
              transition: 'all .2s cubic-bezier(.22,.61,.36,1)',
              display: 'inline-flex', alignItems: 'center', gap: 8,
            }}
            onMouseEnter={e => { if (!isActive) { e.currentTarget.style.borderColor = BS.green; e.currentTarget.style.color = BS.green; } }}
            onMouseLeave={e => { if (!isActive) { e.currentTarget.style.borderColor = BS.border; e.currentTarget.style.color = BS.black; } }}
          >
            {c}
            {counts && (
              <span style={{
                fontSize: 11, opacity: .65,
                color: 'inherit',
              }}>{counts[c]}</span>
            )}
          </button>
        );
      })}
    </div>
  );
}

// ─── Post card (grid item) ──────────────────────────
function PostCard({ post, delay = 0 }) {
  const [hover, setHover] = useStateBI(false);
  return (
    <Reveal delay={delay}>
      <a href={`blog-post.html?id=${post.id}`} style={{ textDecoration: 'none', color: 'inherit', display: 'block' }}>
        <article
          onMouseEnter={() => setHover(true)}
          onMouseLeave={() => setHover(false)}
          style={{
            display: 'flex', flexDirection: 'column', gap: 18,
            cursor: 'pointer',
          }}
        >
          <div style={{
            overflow: 'hidden', borderRadius: 16,
            transform: hover ? 'translateY(-4px)' : 'translateY(0)',
            transition: 'transform .4s cubic-bezier(.22,.61,.36,1)',
          }}>
            <div style={{
              transform: hover ? 'scale(1.04)' : 'scale(1)',
              transition: 'transform .7s cubic-bezier(.22,.61,.36,1)',
            }}>
              <EditorialImage
                id={`post-${post.id}`}
                ratio="4 / 3"
                src={post.image}
                direction={post.direction}
                radius={16}
              />
            </div>
          </div>
          <div style={{ padding: '0 4px' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10 }}>
              <BlogEyebrow>{post.category}</BlogEyebrow>
              <span style={{ width: 14, height: 1, background: BS.border }} />
              <span style={{ fontFamily: '"DM Sans"', fontSize: 12, color: BS.gray }}>{post.readTime} min</span>
            </div>
            <h3 style={{
              fontFamily: '"DM Serif Display", Georgia, serif',
              fontSize: 24, lineHeight: 1.18, letterSpacing: '-.01em',
              color: hover ? BS.green : BS.black,
              transition: 'color .25s ease',
              margin: '0 0 10px',
              textWrap: 'balance',
            }}>{post.title}</h3>
            <p style={{
              fontFamily: '"DM Sans"', fontSize: 14.5, lineHeight: 1.55,
              color: BS.gray, margin: 0, textWrap: 'pretty',
            }}>{post.excerpt}</p>
            <div style={{
              marginTop: 18, paddingTop: 16,
              borderTop: `1px solid ${BS.border}`,
              display: 'flex', alignItems: 'center', justifyContent: 'space-between',
              fontFamily: '"DM Sans"', fontSize: 12, color: BS.gray,
            }}>
              <span>{post.author.name}</span>
              <span>{post.date}</span>
            </div>
          </div>
        </article>
      </a>
    </Reveal>
  );
}

// ─── Newsletter banner ──────────────────────────────
function NewsletterBanner() {
  return (
    <Reveal>
      <section style={{ maxWidth: 1240, margin: '88px auto 0', padding: '0 32px' }}>
        <div style={{
          background: BS.greenLighter,
          border: `1px solid ${BS.border}`,
          borderRadius: 24,
          padding: '56px 56px',
          display: 'grid', gridTemplateColumns: '1.2fr 1fr',
          gap: 40, alignItems: 'center',
        }} className="bi-news">
          <div>
            <BlogEyebrow>Field notes by email</BlogEyebrow>
            <h2 style={{
              fontFamily: '"DM Serif Display", Georgia, serif',
              fontSize: 'clamp(28px, 3vw, 40px)',
              lineHeight: 1.15, letterSpacing: '-.015em',
              color: BS.black,
              margin: '14px 0 12px',
              textWrap: 'balance',
            }}>One slow letter, every other Sunday.</h2>
            <p style={{
              fontFamily: '"DM Sans"', fontSize: 15.5, lineHeight: 1.6,
              color: BS.gray, margin: 0, maxWidth: 460,
            }}>
              What we're reading, what members are asking, and the small clinical things we wish more people knew.
            </p>
          </div>
          <form onSubmit={e => e.preventDefault()} style={{ display: 'flex', gap: 10 }}>
            <input
              type="email"
              placeholder="your@email.com"
              style={{
                flex: 1, minWidth: 0,
                padding: '14px 18px',
                background: BS.cream, color: BS.black,
                border: `1px solid ${BS.border}`,
                borderRadius: 12,
                fontFamily: '"DM Sans"', fontSize: 15,
                outline: 'none',
                transition: 'border-color .2s ease',
              }}
              onFocus={e => e.currentTarget.style.borderColor = BS.green}
              onBlur={e => e.currentTarget.style.borderColor = BS.border}
            />
            <button type="submit" style={{
              padding: '14px 22px',
              background: BS.black, color: BS.cream,
              border: 'none',
              borderRadius: 12,
              fontFamily: '"DM Sans"', fontSize: 14, fontWeight: 600,
              cursor: 'pointer',
              transition: 'background .2s ease',
              whiteSpace: 'nowrap',
            }}
              onMouseEnter={e => e.currentTarget.style.background = BS.green}
              onMouseLeave={e => e.currentTarget.style.background = BS.black}
            >Subscribe</button>
          </form>
        </div>
      </section>
    </Reveal>
  );
}

// ─── Main grid ──────────────────────────────────────
function PostGrid({ posts }) {
  return (
    <section style={{ maxWidth: 1240, margin: '0 auto', padding: '40px 32px 0' }}>
      <div style={{
        display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)',
        gap: '56px 32px',
      }} className="bi-grid">
        {posts.map((p, i) => <PostCard key={p.id} post={p} delay={i * 60}/>)}
      </div>
    </section>
  );
}

// ─── Page ───────────────────────────────────────────
function BlogIndex() {
  const [cat, setCat] = useStateBI('All');
  const featured = POSTS.find(p => p.featured);
  const rest = POSTS.filter(p => p !== featured);

  const counts = useMemoBI(() => {
    const c = { All: POSTS.length };
    POSTS.forEach(p => { c[p.category] = (c[p.category] || 0) + 1; });
    return c;
  }, []);

  const filtered = useMemoBI(() => {
    if (cat === 'All') return rest;
    return rest.filter(p => p.category === cat);
  }, [cat, rest]);

  return (
    <div>
      <BlogNav active="blog" />
      <BlogHero />
      <FeaturedCard post={featured} />
      <CategoryFilter active={cat} onChange={setCat} counts={counts}/>
      <PostGrid posts={filtered} />
      <NewsletterBanner />
      <BlogFooter />
    </div>
  );
}

Object.assign(window, { BlogIndex, POSTS, CATEGORIES, PostCard });
