// Page-level components: Home, News, Trips, Guides.

// ─────────────────────────── HOME ───────────────────────────
const HomePage = ({ onNav, onOpenArticle, onOpenGallery }) => {
  const layout = window.TWEAKS.homepageLayout;
  const featured = NEWS[0];
  const recentNews = NEWS.slice(1, 4);
  const latestTrip = TRIPS[0];
  const galleryPreview = PHOTOS.slice(1, 5);

  const TRIPTYCH = (
    <div className="reveal-stagger drift triptych">
      {/* Latest News */}
      <GlassBox interactive onClick={() => onOpenArticle(featured)} style={{ padding: 0, minHeight: 520, display: 'flex', flexDirection: 'column' }}>
        <PhotoTile photo={PHOTOS[featured.photo]} showMeta={false} style={{ height: 260, borderRadius: '20px 20px 0 0' }}/>
        <div style={{ padding: 26, flex: 1, display: 'flex', flexDirection: 'column' }}>
          <div className="eyebrow" style={{ marginBottom: 12 }}>Latest News</div>
          <h3 className="display" style={{ fontSize: 22, fontWeight: 500, marginBottom: 12 }}>{featured.title}</h3>
          <p className="serif" style={{ fontSize: 16, color: 'var(--bone-soft)', marginBottom: 20, flex: 1 }}>{featured.dek}</p>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <span className="ui" style={{ fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase', color: 'var(--bone-dim)' }}>{featured.date}</span>
            <span style={{ color: 'var(--bone-soft)' }}><Icon name="arrow-up-right" size={16}/></span>
          </div>
        </div>
      </GlassBox>
      {/* Latest Vacation */}
      <GlassBox interactive onClick={() => onNav('trips')} style={{ padding: 0, minHeight: 520, display: 'flex', flexDirection: 'column' }}>
        <PhotoTile photo={PHOTOS[latestTrip.hero]} showMeta={false} style={{ height: 260, borderRadius: '20px 20px 0 0' }}/>
        <div style={{ padding: 26, flex: 1, display: 'flex', flexDirection: 'column' }}>
          <div className="eyebrow" style={{ marginBottom: 12 }}>Latest Vacation</div>
          <h3 className="display" style={{ fontSize: 22, fontWeight: 500, marginBottom: 8 }}>{latestTrip.title}</h3>
          <p className="serif" style={{ fontSize: 14, color: 'var(--bone-dim)', marginBottom: 14 }}>{latestTrip.subtitle}</p>
          <p className="serif" style={{ fontSize: 15, color: 'var(--bone-soft)', marginBottom: 20, flex: 1 }}>{latestTrip.excerpt}</p>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <span className="ui" style={{ fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase', color: 'var(--bone-dim)' }}>
              {latestTrip.date} · {latestTrip.nights} nights
            </span>
            <span style={{ color: 'var(--bone-soft)' }}><Icon name="arrow-up-right" size={16}/></span>
          </div>
        </div>
      </GlassBox>
      {/* Gallery */}
      <GlassBox interactive onClick={() => onNav('gallery')} style={{ padding: 0, minHeight: 520, display: 'flex', flexDirection: 'column' }}>
        <div style={{ height: 260, display: 'grid', gridTemplateColumns: '1fr 1fr', gridTemplateRows: '1fr 1fr', gap: 2, borderRadius: '20px 20px 0 0', overflow: 'hidden' }}>
          {galleryPreview.map((p, i) => (
            <PhotoTile key={p.id} photo={p} showMeta={false} style={{ borderRadius: 0 }}/>
          ))}
        </div>
        <div style={{ padding: 26, flex: 1, display: 'flex', flexDirection: 'column' }}>
          <div className="eyebrow" style={{ marginBottom: 12 }}>Photography</div>
          <h3 className="display" style={{ fontSize: 22, fontWeight: 500, marginBottom: 8 }}>Fullscreen Galleries</h3>
          <p className="serif" style={{ fontSize: 15, color: 'var(--bone-soft)', marginBottom: 20, flex: 1 }}>
            Disney, framed by light. Browse by park or by trip, or start the slideshow and let it move.
          </p>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <span className="ui" style={{ fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase', color: 'var(--bone-dim)' }}>
              {PHOTOS.length} photographs · {GALLERY_SETS.length} sets
            </span>
            <span style={{ color: 'var(--bone-soft)' }}><Icon name="arrow-up-right" size={16}/></span>
          </div>
        </div>
      </GlassBox>
    </div>
  );

  const STACK = (
    <div className="reveal-stagger drift" style={{ display: 'flex', flexDirection: 'column', gap: 22 }}>
      <ArticleCard news={featured} variant="featured" onClick={() => onOpenArticle(featured)} />
      <div className="lwn-grid-2up" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 22 }}>
        <GlassBox interactive onClick={() => onNav('trips')} style={{ padding: 0, minHeight: 340, display: 'flex', flexDirection: 'column' }}>
          <PhotoTile photo={PHOTOS[latestTrip.hero]} showMeta={false} style={{ height: 180, borderRadius: '20px 20px 0 0' }}/>
          <div style={{ padding: 24 }}>
            <div className="eyebrow" style={{ marginBottom: 10 }}>Latest Trip</div>
            <h3 className="display" style={{ fontSize: 20, fontWeight: 500, marginBottom: 8 }}>{latestTrip.title}</h3>
            <p className="serif" style={{ fontSize: 14, color: 'var(--bone-soft)' }}>{latestTrip.subtitle}</p>
          </div>
        </GlassBox>
        <GlassBox interactive onClick={() => onNav('gallery')} style={{ padding: 0, minHeight: 340 }}>
          <div style={{ height: 180, display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 2, borderRadius: '20px 20px 0 0', overflow: 'hidden' }}>
            {galleryPreview.slice(0,3).map(p => <PhotoTile key={p.id} photo={p} showMeta={false} style={{ borderRadius: 0 }}/>)}
          </div>
          <div style={{ padding: 24 }}>
            <div className="eyebrow" style={{ marginBottom: 10 }}>Photography</div>
            <h3 className="display" style={{ fontSize: 20, fontWeight: 500 }}>Fullscreen Galleries</h3>
          </div>
        </GlassBox>
      </div>
    </div>
  );

  const EDITORIAL = (
    <div className="reveal-stagger drift lwn-grid-editorial" style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 22 }}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 22 }}>
        <ArticleCard news={featured} variant="featured" onClick={() => onOpenArticle(featured)} />
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <Rule label="More Reading" />
        {recentNews.map(n => <ArticleCard key={n.id} news={n} onClick={() => onOpenArticle(n)}/>)}
      </div>
    </div>
  );

  return (
    <div className="page__inner fade-in">
      {/* Masthead */}
      <div style={{ marginBottom: 52 }}>
        <div className="eyebrow" style={{ marginBottom: 12 }}>Issue · April 2026</div>
        <h1 className="display" style={{ fontSize: 'clamp(38px, 6vw, 76px)', fontWeight: 300, letterSpacing: '-0.02em' }}>
          LifeWithNate
        </h1>
        <p className="serif" style={{ fontSize: 'clamp(16px, 1.4vw, 20px)', color: 'var(--bone-soft)', marginTop: 14, maxWidth: 680 }}>
          Disney, quietly. News, trip reports, and photographs from a DVC member at home at Riviera.
        </p>
      </div>

      {layout === 'triptych' && TRIPTYCH}
      {layout === 'stack' && STACK}
      {layout === 'editorial' && EDITORIAL}

      {/* Recent feed below — always present */}
      <div style={{ marginTop: 72 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 22 }}>
          <Rule label="Recent Dispatches" />
          <span style={{ color: 'var(--bone-dim)', fontFamily: 'var(--font-ui)', fontSize: 10, letterSpacing: '0.24em', textTransform: 'uppercase', cursor: 'pointer' }} onClick={() => onNav('news')}>
            All News →
          </span>
        </div>
        <div className="reveal-stagger drift lwn-grid-cards" style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(360px, 1fr))', gap: 16 }}>
          {NEWS.slice(1).map(n => <ArticleCard key={n.id} news={n} onClick={() => onOpenArticle(n)}/>)}
        </div>
      </div>
    </div>
  );
};

// ─────────────────────────── NEWS LIST ───────────────────────────
const NewsPage = ({ onOpenArticle }) => {
  const [filter, setFilter] = React.useState('All');
  const cats = ['All', ...Array.from(new Set(NEWS.map(n => n.category)))];
  const filtered = filter === 'All' ? NEWS : NEWS.filter(n => n.category === filter);
  return (
    <div className="page__inner fade-in">
      <div className="eyebrow" style={{ marginBottom: 12 }}>Section</div>
      <h1 className="display" style={{ fontSize: 'clamp(34px, 5vw, 62px)', marginBottom: 28 }}>Disney News</h1>
      <GlassBox thin className="lwn-news-filter" style={{ display: 'inline-flex', padding: 4, marginBottom: 36 }}>
        {cats.map(c => (
          <button key={c} onClick={() => setFilter(c)} style={{
            background: filter === c ? 'var(--bone)' : 'transparent',
            color: filter === c ? 'var(--ink)' : 'var(--bone-soft)',
            border: 'none',
            padding: '9px 18px',
            fontFamily: 'var(--font-ui)', fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase',
            borderRadius: 10, cursor: 'pointer', transition: 'all 200ms',
          }}>{c}</button>
        ))}
      </GlassBox>
      <div className="reveal-stagger drift lwn-grid-cards" style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(400px, 1fr))', gap: 18 }}>
        {filtered.map(n => <ArticleCard key={n.id} news={n} onClick={() => onOpenArticle(n)}/>)}
      </div>
    </div>
  );
};

// ─────────────────────────── TRIP REPORTS ───────────────────────────
const TripsPage = ({ onOpenTrip }) => {
  return (
    <div className="page__inner fade-in">
      <div className="eyebrow" style={{ marginBottom: 12 }}>Section</div>
      <h1 className="display" style={{ fontSize: 'clamp(34px, 5vw, 62px)', marginBottom: 8 }}>Trip Reports</h1>
      <p className="serif" style={{ fontSize: 18, color: 'var(--bone-soft)', marginBottom: 48, maxWidth: 680 }}>
        Long-form recaps, each with a full photo roll and the notes worth keeping.
      </p>
      <div className="reveal-stagger drift" style={{ display: 'flex', flexDirection: 'column', gap: 26 }}>
        {TRIPS.map((trip, i) => (
          <GlassBox key={trip.id} interactive onClick={() => onOpenTrip(trip)} className="lwn-trip-card" style={{ padding: 0, display: 'grid', gridTemplateColumns: i % 2 === 0 ? '1.2fr 1fr' : '1fr 1.2fr', minHeight: 320 }}>
            {i % 2 === 0 ? (
              <>
                <PhotoTile photo={PHOTOS[trip.hero]} showMeta={false} style={{ borderRadius: '20px 0 0 20px' }}/>
                <TripInner trip={trip}/>
              </>
            ) : (
              <>
                <TripInner trip={trip}/>
                <PhotoTile photo={PHOTOS[trip.hero]} showMeta={false} style={{ borderRadius: '0 20px 20px 0' }}/>
              </>
            )}
          </GlassBox>
        ))}
      </div>
    </div>
  );
};

const TripInner = ({ trip }) => (
  <div className="lwn-trip-card-text" style={{ padding: '40px 44px', display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
    <div className="eyebrow" style={{ marginBottom: 14 }}>{trip.date}</div>
    <h2 className="display" style={{ fontSize: 30, fontWeight: 500, marginBottom: 10 }}>{trip.title}</h2>
    <p className="serif" style={{ fontSize: 17, color: 'var(--bone-soft)', marginBottom: 18 }}>{trip.subtitle}</p>
    <p className="serif" style={{ fontSize: 16, color: 'var(--bone-soft)', lineHeight: 1.6, marginBottom: 24 }}>{trip.excerpt}</p>
    <div style={{ display: 'flex', gap: 18, fontFamily: 'var(--font-ui)', fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase', color: 'var(--bone-dim)' }}>
      <span>{trip.nights} nights</span>
      <span>{trip.parks.join(' · ')}</span>
      <span style={{ marginLeft: 'auto', color: 'var(--bone-soft)', display: 'flex', alignItems: 'center', gap: 6 }}>
        Read the report <Icon name="arrow-right" size={12}/>
      </span>
    </div>
  </div>
);

// ─────────────────────────── GUIDES ───────────────────────────
const GuidesPage = ({ onOpenArticle }) => (
  <div className="page__inner fade-in">
    <div className="eyebrow" style={{ marginBottom: 12 }}>Section</div>
    <h1 className="display" style={{ fontSize: 'clamp(34px, 5vw, 62px)', marginBottom: 8 }}>Park & Resort Guides</h1>
    <p className="serif" style={{ fontSize: 18, color: 'var(--bone-soft)', marginBottom: 48, maxWidth: 680 }}>
      The slow, annotated version. How to stand. When to arrive. Where the light is good.
    </p>
    <div className="reveal-stagger drift lwn-grid-cards" style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: 18 }}>
      {GUIDES.map(g => (
        <GlassBox key={g.id} interactive onClick={() => onOpenArticle({ ...g, eyebrow: 'Guide', category: g.park, title: g.park, dek: g.subtitle, date: '', readTime: '12 min' })} style={{ padding: 0, minHeight: 360, display: 'flex', flexDirection: 'column' }}>
          <PhotoTile photo={PHOTOS[g.photo]} showMeta={false} style={{ height: 220, borderRadius: '20px 20px 0 0' }}/>
          <div style={{ padding: 22, flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
            <div>
              <div className="eyebrow" style={{ marginBottom: 8 }}>Guide</div>
              <h3 className="display" style={{ fontSize: 20, fontWeight: 500, marginBottom: 8 }}>{g.park}</h3>
              <p className="serif" style={{ fontSize: 14.5, color: 'var(--bone-soft)' }}>{g.subtitle}</p>
            </div>
            <div style={{ marginTop: 18, color: 'var(--bone-soft)', display: 'flex', alignItems: 'center', gap: 6, fontFamily: 'var(--font-ui)', fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase' }}>
              Read <Icon name="arrow-right" size={12}/>
            </div>
          </div>
        </GlassBox>
      ))}
    </div>
  </div>
);

// ─────────────────────────── ARTICLE VIEW ───────────────────────────
const parseMarkdown = text => {
  if (!text) return [];
  const chunks = text.split(/\n\n+/);
  const blocks = [];
  let ledeDone = false;
  for (const raw of chunks) {
    const t = raw.trim();
    if (!t) continue;
    if (/^# /.test(t)) continue;
    if (/^#{2,3} /.test(t)) {
      blocks.push({ t: 'h', v: t.replace(/^#{2,3} /, '').replace(/\*\*/g, '') });
    } else if (!ledeDone) {
      blocks.push({ t: 'lede', v: t.replace(/\*\*/g, '') });
      ledeDone = true;
    } else {
      blocks.push({ t: 'p', v: t.replace(/\*\*/g, '') });
    }
  }
  return blocks;
};

const ArticleView = ({ article, onBack }) => {
  const photo = PHOTOS[article.photo] || PHOTOS[0];
  const blocks = Array.isArray(article.content) ? article.content : parseMarkdown(article.content);
  return (
    <div className="page__inner fade-in" style={{ maxWidth: 820 }}>
      <GlassButton icon="arrow-left" onClick={onBack} style={{ marginBottom: 30 }}>Back</GlassButton>
      <div className="eyebrow" style={{ marginBottom: 12 }}>{article.eyebrow} · {article.category}</div>
      <h1 className="display" style={{ fontSize: 'clamp(30px, 4vw, 52px)', fontWeight: 500, marginBottom: 14, letterSpacing: '-0.005em' }}>{article.title}</h1>
      <p className="serif" style={{ fontSize: 'clamp(17px, 1.4vw, 22px)', color: 'var(--bone-soft)', marginBottom: 20 }}>{article.dek}</p>
      <div style={{ display: 'flex', gap: 18, fontFamily: 'var(--font-ui)', fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase', color: 'var(--bone-dim)', marginBottom: 32, paddingBottom: 22, borderBottom: '1px solid var(--glass-border)' }}>
        <span>By Nate</span><span>{article.date}</span><span>{article.readTime} read</span>
      </div>
      <PhotoTile photo={photo} externalUrl={article.externalPhoto} showMeta={false} className="lwn-article-photo" style={{ height: 440, borderRadius: 16, marginBottom: 44 }}/>

      <GlassBox className="lwn-article-body" style={{ padding: 36 }}>
        {blocks.length ? blocks.map((block, i) => {
          if (block.t === 'lede') return (
            <p key={i} className="serif" style={{ fontSize: 19, lineHeight: 1.7, color: 'var(--bone)', marginBottom: 24 }}>
              <span style={{ fontFamily: 'var(--font-display)', fontSize: 54, float: 'left', lineHeight: 0.9, marginRight: 12, marginTop: 6, color: 'var(--bone)' }}>{block.v[0]}</span>
              {block.v.slice(1)}
            </p>
          );
          if (block.t === 'p') return (
            <p key={i} className="serif" style={{ fontSize: 19, lineHeight: 1.7, color: 'var(--bone-soft)', marginBottom: 24 }}>{block.v}</p>
          );
          if (block.t === 'q') return (
            <blockquote key={i} style={{ borderLeft: '2px solid var(--accent)', padding: '8px 0 8px 22px', margin: '32px 0', fontFamily: 'var(--font-display)', fontSize: 22, fontStyle: 'italic', letterSpacing: '0', color: 'var(--bone)' }}>{block.v}</blockquote>
          );
          if (block.t === 'h') return (
            <h3 key={i} style={{ fontFamily: 'var(--font-ui)', fontSize: 11, fontWeight: 500, letterSpacing: '0.22em', textTransform: 'uppercase', color: 'var(--bone-dim)', marginTop: 44, marginBottom: 18, paddingBottom: 12, borderBottom: '1px solid var(--glass-border)' }}>{block.v}</h3>
          );
          return null;
        }) : (<>
          <p className="serif" style={{ fontSize: 19, lineHeight: 1.7, color: 'var(--bone)', marginBottom: 24 }}>
            <span style={{ fontFamily: 'var(--font-display)', fontSize: 54, float: 'left', lineHeight: 0.9, marginRight: 12, marginTop: 6, color: 'var(--bone)' }}>T</span>
            here's a particular light at Magic Kingdom in the hour before the fireworks start. A quiet, amber cast that settles on the spires and turns the whole forecourt into something less like a theme park and more like a memory.
          </p>
          <p className="serif" style={{ fontSize: 19, lineHeight: 1.7, color: 'var(--bone-soft)', marginBottom: 24 }}>
            This is a placeholder paragraph in the real site. In production, Nate will write the actual report here: a few hundred words, maybe more, with inline photographs and the occasional pull-quote. The system is set up to handle body text, drop caps, block quotes, and fullscreen photo inserts.
          </p>
          <p className="serif" style={{ fontSize: 19, lineHeight: 1.7, color: 'var(--bone-soft)', marginBottom: 24 }}>
            The important thing is the pace. This isn't a news site that wants to get you to the next tab. This is a publication that asks you to sit with it for five minutes.
          </p>
          <blockquote style={{ borderLeft: '1px solid var(--bone-faint)', padding: '8px 0 8px 22px', margin: '32px 0', fontFamily: 'var(--font-display)', fontSize: 22, letterSpacing: '0', color: 'var(--bone)' }}>
            Disney World is a place that rewards patience. So does photography. They belong together.
          </blockquote>
          <p className="serif" style={{ fontSize: 19, lineHeight: 1.7, color: 'var(--bone-soft)' }}>
            More to come. For now, thanks for reading. And if you're heading to Magic Kingdom this month, stand on the right side of the forecourt, about forty minutes before dusk. You'll see what I mean.
          </p>
        </>)}
      </GlassBox>
    </div>
  );
};

Object.assign(window, { HomePage, NewsPage, TripsPage, GuidesPage, ArticleView });
