// JournalIndex + ArticlePage — the R+D journal's two views. The journal is the
// "r+d" sub of material, but it renders as a blog rather than the project-card
// grid that SubcategoryPage shows. Content + derived helpers come from
// journal-data.jsx (window.JOURNAL_POSTS / journalSorted / journalDate /
// journalReadTime). Shared chrome (CrumbBar, A_Footer, CP_statusColor) comes
// from category-page.jsx / direction-a.jsx, so this file loads AFTER both.
//
// Routes used:
//   index list  → { page:'subcategory', cat:'material', sub:'rd' }  (intercepted in app.jsx)
//   article     → { page:'article', slug }

const JR_RULE = 'var(--rule)', JR_INK = 'var(--ink)', JR_INK2 = 'var(--ink-2)',
      JR_INK3 = 'var(--ink-3)', JR_PAPER = 'var(--paper)', JR_PAPER2 = 'var(--paper-2)';

const jrStatusColor = () => (window.CP_statusColor || (() => JR_INK));

// --- inline text: **bold** and `code` ---------------------------------------
function jrInline(text) {
  if (text == null) return null;
  const parts = String(text).split(/(\*\*[^*]+\*\*|`[^`]+`)/g);
  return parts.map((seg, i) => {
    if (/^\*\*[^*]+\*\*$/.test(seg))
      return <strong key={i} style={{ fontWeight: 600, color: JR_INK }}>{seg.slice(2, -2)}</strong>;
    if (/^`[^`]+`$/.test(seg))
      return <code key={i} className="mono" style={{ fontSize: '0.88em', background: JR_PAPER2,
        border: `1px solid ${JR_RULE}`, padding: '1px 5px', borderRadius: 2 }}>{seg.slice(1, -1)}</code>;
    return <React.Fragment key={i}>{seg}</React.Fragment>;
  });
}

// =============================================================================
// INDEX
// =============================================================================

function JR_Entry({ post, navigate, mobile }) {
  const [h, setH] = React.useState(false);
  const d = window.journalDate(post.date);
  const rt = window.journalReadTime(post);
  const sc = jrStatusColor();
  return (
    <div onClick={() => navigate({ page: 'article', slug: post.slug })}
      onMouseEnter={() => setH(true)} onMouseLeave={() => setH(false)}
      style={{ cursor: 'pointer', borderBottom: `1px solid ${JR_RULE}`,
        background: h ? JR_PAPER2 : 'transparent', transition: 'background .15s',
        display: 'grid', gridTemplateColumns: mobile ? '1fr' : '128px 1fr 150px',
        gap: mobile ? 10 : 28, padding: mobile ? '22px 22px' : '26px 56px', alignItems: 'baseline' }}>
      {/* date */}
      <div className="mono tnum" style={{ fontSize: 12, color: JR_INK3, letterSpacing: 0.3, paddingTop: mobile ? 0 : 4 }}>
        {d.mono}
      </div>
      {/* title + dek + tags */}
      <div>
        <div style={{ fontSize: mobile ? 19 : 22, fontWeight: 500, letterSpacing: -0.5, lineHeight: 1.15,
          color: JR_INK, marginBottom: 8, display: 'flex', alignItems: 'baseline', gap: 10 }}>
          <span>{post.title}</span>
          <span className="mono" style={{ fontSize: 13, color: h ? JR_INK : JR_INK3, transition: 'color .15s',
            flexShrink: 0 }}>→</span>
        </div>
        <div style={{ fontSize: mobile ? 14 : 15, color: JR_INK2, lineHeight: 1.55, maxWidth: 560,
          marginBottom: 12, textWrap: 'pretty' }}>{post.summary}</div>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
          {post.tags.map((t) => (
            <span key={t} className="mono" style={{ fontSize: 10.5, color: JR_INK3, letterSpacing: 0.3,
              border: `1px solid ${JR_RULE}`, padding: '3px 7px', textTransform: 'lowercase' }}>{t}</span>
          ))}
        </div>
      </div>
      {/* status + read time */}
      <div className="mono" style={{ display: 'flex', flexDirection: mobile ? 'row' : 'column',
        alignItems: mobile ? 'center' : 'flex-end', gap: mobile ? 14 : 8,
        fontSize: 11, color: JR_INK3, paddingTop: mobile ? 2 : 4 }}>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, color: JR_INK2 }}>
          <span style={{ width: 7, height: 7, background: sc(post.status) }} />{post.status}
        </span>
        <span>{rt} min read</span>
      </div>
    </div>
  );
}

function JournalIndex({ navigate }) {
  const cat = window.CATEGORIES.find((c) => c.word === 'material');
  const sub = (cat && cat.subs.find((s) => s.id === 'rd')) || { label: 'r+d journal', meta: 'ongoing' };
  const Footer = window.A_Footer;
  const CrumbBar = window.CrumbBar;
  const mobile = window.useIsMobile();
  const posts = window.journalSorted();

  const [tag, setTag] = React.useState('all');
  const allTags = React.useMemo(() => {
    const s = new Set();
    posts.forEach((p) => p.tags.forEach((t) => s.add(t)));
    return ['all', ...[...s].sort()];
  }, [posts]);
  const shown = tag === 'all' ? posts : posts.filter((p) => p.tags.indexOf(tag) !== -1);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', minHeight: '100vh' }}>
      <CrumbBar section="04" navigate={navigate}
        trail={[
          { label: 'index', to: { page: 'index' } },
          { label: 'material', to: { page: 'category', cat: 'material' } },
          { label: 'r+d journal' },
        ]} />

      {/* hero */}
      <div style={{ padding: mobile ? '34px 22px 24px' : '48px 56px 30px', borderBottom: `1px solid ${JR_RULE}` }}>
        <div className="mono" style={{ fontSize: mobile ? 9.5 : 11, color: JR_INK3, letterSpacing: 0.5,
          textTransform: 'uppercase', marginBottom: 14 }}>§ 04 · journal</div>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: mobile ? 11 : 16, flexWrap: 'wrap', marginBottom: mobile ? 14 : 16 }}>
          <div style={{ fontSize: mobile ? 'clamp(30px, 8vw, 40px)' : 60, fontWeight: 500, letterSpacing: -2, lineHeight: 0.95 }}>r+d journal</div>
          <div className="mono" style={{ fontSize: mobile ? 13 : 16, color: JR_INK3 }}>· {sub.meta}</div>
        </div>
        <div style={{ fontSize: mobile ? 14 : 16, color: JR_INK2, lineHeight: 1.55, maxWidth: 600, textWrap: 'pretty' }}>
          Working notes from the shop — experiments, finishes, failed pours, and the occasional bit of code. Written down so I (and maybe you) don't have to relearn them the expensive way.
        </div>
      </div>

      {/* tag filter */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 14, flexWrap: 'wrap',
        padding: mobile ? '14px 22px' : '14px 56px', borderBottom: `1px solid ${JR_RULE}`, background: JR_PAPER2 }}>
        <span className="mono" style={{ fontSize: 10.5, color: JR_INK3, letterSpacing: 0.5, textTransform: 'uppercase' }}>filter</span>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 7 }}>
          {allTags.map((t) => {
            const on = tag === t;
            return (
              <button key={t} className="mono" onClick={() => setTag(t)}
                style={{ fontFamily: 'var(--font-mono)', fontSize: 11.5, padding: '5px 11px', cursor: 'pointer',
                  minHeight: mobile ? 32 : 'auto', letterSpacing: 0.2,
                  border: `1px solid ${on ? JR_INK : JR_RULE}`, background: on ? JR_INK : 'transparent',
                  color: on ? JR_PAPER : JR_INK2, transition: 'background .12s, color .12s, border-color .12s' }}
                onMouseEnter={(e) => { if (!on) { e.currentTarget.style.borderColor = JR_INK; e.currentTarget.style.color = JR_INK; } }}
                onMouseLeave={(e) => { if (!on) { e.currentTarget.style.borderColor = JR_RULE; e.currentTarget.style.color = JR_INK2; } }}>
                {t}
              </button>
            );
          })}
        </div>
        <span className="mono tnum" style={{ marginLeft: 'auto', fontSize: 12, color: JR_INK3 }}>
          {String(shown.length).padStart(2, '0')} {shown.length === 1 ? 'entry' : 'entries'}
        </span>
      </div>

      {/* list */}
      <div style={{ flex: 1 }}>
        {shown.map((p) => <JR_Entry key={p.slug} post={p} navigate={navigate} mobile={mobile} />)}
      </div>

      {Footer ? <Footer /> : null}
    </div>
  );
}

// =============================================================================
// ARTICLE
// =============================================================================

function JR_Figure({ block, figures, index, mobile }) {
  const [h, setH] = React.useState(false);
  const open = () => {
    if (window.openImageLightbox)
      window.openImageLightbox(figures.map((f) => ({ src: f.src, tag: f.tag, title: f.caption })), index);
  };
  return (
    <figure style={{ margin: mobile ? '26px 0' : '34px 0' }}>
      <div onClick={open} onMouseEnter={() => setH(true)} onMouseLeave={() => setH(false)}
        style={{ position: 'relative', aspectRatio: '16 / 10', backgroundColor: JR_PAPER,
          backgroundImage: block.src ? `url(${block.src})` : 'repeating-linear-gradient(135deg, transparent 0 7px, var(--paper-2) 7px 8px)',
          backgroundSize: 'cover', backgroundPosition: 'center',
          border: `1px solid ${h ? JR_INK : JR_RULE}`, cursor: 'zoom-in',
          display: 'flex', alignItems: 'flex-end', transition: 'border-color .15s' }}>
        {!block.src && (
          <div className="mono" style={{ fontSize: 10, color: JR_INK3, padding: '7px 9px',
            letterSpacing: 0.4, textTransform: 'uppercase' }}>[{block.tag}]</div>
        )}
        <div className="mono" style={{ position: 'absolute', top: 8, right: 8, width: 24, height: 24,
          display: 'flex', alignItems: 'center', justifyContent: 'center', background: JR_INK, color: JR_PAPER,
          fontSize: 12, opacity: h ? 1 : 0, transform: h ? 'scale(1)' : 'scale(.8)', transition: 'opacity .15s, transform .15s' }}>⤢</div>
      </div>
      <figcaption className="mono" style={{ fontSize: 11, color: JR_INK3, marginTop: 8, letterSpacing: 0.2,
        lineHeight: 1.5 }}>{block.caption}</figcaption>
    </figure>
  );
}

function JR_Block({ block, hIndex, figures, figIndex, mobile }) {
  switch (block.type) {
    case 'h':
      return (
        <h2 id={`h-${hIndex}`} style={{ scrollMarginTop: 90, fontSize: mobile ? 22 : 26, fontWeight: 600,
          letterSpacing: -0.6, lineHeight: 1.2, color: JR_INK, margin: mobile ? '34px 0 12px' : '44px 0 14px' }}>
          {block.text}
        </h2>
      );
    case 'p':
      return (
        <p style={{ fontSize: mobile ? 16.5 : 18, lineHeight: 1.72, color: JR_INK2, margin: '0 0 22px',
          letterSpacing: -0.1, textWrap: 'pretty' }}>{jrInline(block.text)}</p>
      );
    case 'figure':
      return <JR_Figure block={block} figures={figures} index={figIndex} mobile={mobile} />;
    case 'code':
      return (
        <div style={{ margin: '24px 0', border: `1px solid ${JR_RULE}`, background: JR_PAPER2, position: 'relative' }}>
          {block.lang && (
            <div className="mono" style={{ position: 'absolute', top: 0, right: 0, fontSize: 10, color: JR_INK3,
              letterSpacing: 0.5, textTransform: 'uppercase', padding: '6px 10px',
              borderLeft: `1px solid ${JR_RULE}`, borderBottom: `1px solid ${JR_RULE}` }}>{block.lang}</div>
          )}
          <pre className="mono" style={{ margin: 0, padding: mobile ? '16px' : '18px 20px', overflowX: 'auto',
            fontSize: mobile ? 12.5 : 13.5, lineHeight: 1.65, color: JR_INK,
            whiteSpace: 'pre', tabSize: 2 }}>{block.code}</pre>
        </div>
      );
    case 'steps':
      return (
        <ol style={{ listStyle: 'none', counterReset: 'jr', margin: '8px 0 26px', padding: 0,
          display: 'flex', flexDirection: 'column', gap: 14 }}>
          {(block.items || []).map((it, i) => (
            <li key={i} style={{ counterIncrement: 'jr', display: 'grid',
              gridTemplateColumns: '32px 1fr', gap: 14, alignItems: 'baseline' }}>
              <span className="mono tnum" style={{ fontSize: 13, color: JR_INK3, textAlign: 'right' }}>
                {String(i + 1).padStart(2, '0')}
              </span>
              <span style={{ fontSize: mobile ? 16 : 17, lineHeight: 1.6, color: JR_INK2, textWrap: 'pretty' }}>{jrInline(it)}</span>
            </li>
          ))}
        </ol>
      );
    case 'quote':
      return (
        <blockquote style={{ margin: mobile ? '28px 0' : '34px 0', paddingLeft: mobile ? 18 : 24,
          borderLeft: `2px solid ${JR_INK}` }}>
          <div style={{ fontSize: mobile ? 20 : 23, lineHeight: 1.4, color: JR_INK, fontWeight: 400,
            letterSpacing: -0.4, textWrap: 'pretty' }}>{block.text}</div>
          {block.cite && (
            <div className="mono" style={{ fontSize: 12, color: JR_INK3, marginTop: 12, letterSpacing: 0.2 }}>— {block.cite}</div>
          )}
        </blockquote>
      );
    case 'materials':
      return (
        <div style={{ margin: '24px 0', border: `1px solid ${JR_RULE}`, background: JR_PAPER2, padding: mobile ? '16px' : '18px 20px' }}>
          <div className="mono" style={{ fontSize: 10.5, color: JR_INK3, letterSpacing: 0.5,
            textTransform: 'uppercase', marginBottom: 12 }}>{block.title || 'Materials'}</div>
          <div style={{ display: 'grid', gridTemplateColumns: mobile ? '1fr' : '1fr 1fr', gap: '0 28px' }}>
            {(block.items || []).map(([k, v], i) => (
              <div key={i} className="mono" style={{ display: 'flex', justifyContent: 'space-between', gap: 14,
                fontSize: 12, padding: '8px 0', borderBottom: `1px solid ${JR_RULE}` }}>
                <span style={{ color: JR_INK3, letterSpacing: 0.3, textTransform: 'uppercase', fontSize: 11 }}>{k}</span>
                <span style={{ color: JR_INK, textAlign: 'right' }}>{v}</span>
              </div>
            ))}
          </div>
        </div>
      );
    case 'note':
      return (
        <div style={{ margin: '24px 0', padding: mobile ? '14px 16px' : '16px 20px', background: JR_PAPER2,
          borderLeft: `2px solid ${JR_INK3}` }}>
          <span className="mono" style={{ fontSize: 10.5, color: JR_INK3, letterSpacing: 0.5,
            textTransform: 'uppercase', marginRight: 10 }}>note</span>
          <span style={{ fontSize: mobile ? 15 : 16, lineHeight: 1.6, color: JR_INK2, textWrap: 'pretty' }}>{jrInline(block.text)}</span>
        </div>
      );
    default:
      return null;
  }
}

// Side-rail table of contents with scroll-spy.
function JR_Toc({ headings, activeId }) {
  const jump = (id) => {
    const el = document.getElementById(id);
    if (!el) return;
    const top = el.getBoundingClientRect().top + window.scrollY - 78;
    window.scrollTo({ top, behavior: 'smooth' });
  };
  return (
    <nav style={{ position: 'sticky', top: 32, alignSelf: 'start' }}>
      <div className="mono" style={{ fontSize: 10.5, color: JR_INK3, letterSpacing: 0.5,
        textTransform: 'uppercase', marginBottom: 14 }}>Contents</div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 2, borderLeft: `1px solid ${JR_RULE}` }}>
        {headings.map((h) => {
          const on = activeId === h.id;
          return (
            <button key={h.id} onClick={() => jump(h.id)}
              style={{ textAlign: 'left', background: 'transparent', border: 'none', cursor: 'pointer',
                font: 'inherit', fontSize: 12.5, lineHeight: 1.4, padding: '5px 0 5px 14px', marginLeft: -1,
                borderLeft: `2px solid ${on ? JR_INK : 'transparent'}`,
                color: on ? JR_INK : JR_INK3, transition: 'color .15s, border-color .15s' }}
              onMouseEnter={(e) => { if (!on) e.currentTarget.style.color = JR_INK2; }}
              onMouseLeave={(e) => { if (!on) e.currentTarget.style.color = JR_INK3; }}>
              {h.text}
            </button>
          );
        })}
      </div>
    </nav>
  );
}

function ArticlePage({ slug, navigate }) {
  const Footer = window.A_Footer;
  const CrumbBar = window.CrumbBar;
  const mobile = window.useIsMobile();
  const all = window.journalSorted();
  const idx = all.findIndex((p) => p.slug === slug);
  const post = all[idx];

  // Build a stable heading list + per-figure index for the lightbox.
  const headings = [];
  const figures = [];
  let hCount = 0;
  const blocks = (post ? post.body : []).map((b) => {
    const meta = {};
    if (b.type === 'h') { meta.hIndex = hCount; headings.push({ id: `h-${hCount}`, text: b.text }); hCount++; }
    if (b.type === 'figure') { meta.figIndex = figures.length; figures.push(b); }
    return { b, meta };
  });

  const [activeId, setActiveId] = React.useState(headings[0] ? headings[0].id : null);
  React.useEffect(() => {
    if (!headings.length || typeof IntersectionObserver === 'undefined') return;
    const els = headings.map((h) => document.getElementById(h.id)).filter(Boolean);
    const obs = new IntersectionObserver((entries) => {
      const vis = entries.filter((e) => e.isIntersecting)
        .sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top);
      if (vis[0]) setActiveId(vis[0].target.id);
    }, { rootMargin: '-72px 0px -65% 0px', threshold: 0 });
    els.forEach((el) => obs.observe(el));
    return () => obs.disconnect();
  }, [slug]);

  if (!post) {
    return (
      <div style={{ display: 'flex', flexDirection: 'column', minHeight: '100vh' }}>
        <CrumbBar section="04" navigate={navigate}
          trail={[{ label: 'index', to: { page: 'index' } }, { label: 'r+d journal', to: { page: 'subcategory', cat: 'material', sub: 'rd' } }, { label: 'not found' }]} />
        <div style={{ flex: 1, padding: '60px 56px' }}>
          <div style={{ fontSize: 22, color: JR_INK, marginBottom: 12 }}>That entry isn't here.</div>
          <button className="mono" onClick={() => navigate({ page: 'subcategory', cat: 'material', sub: 'rd' })}
            style={{ font: 'inherit', fontFamily: 'var(--font-mono)', fontSize: 13, background: 'transparent',
              border: `1px solid ${JR_INK}`, color: JR_INK, padding: '10px 14px', cursor: 'pointer' }}>
            ← back to the journal
          </button>
        </div>
        {Footer ? <Footer /> : null}
      </div>
    );
  }

  const d = window.journalDate(post.date);
  const rt = window.journalReadTime(post);
  const sc = jrStatusColor();
  const newer = all[idx - 1]; // newest-first → previous index is newer
  const older = all[idx + 1];
  const hasToc = !mobile && headings.length >= 2;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', minHeight: '100vh' }}>
      <CrumbBar section="04" navigate={navigate}
        trail={[
          { label: 'index', to: { page: 'index' } },
          { label: 'material', to: { page: 'category', cat: 'material' } },
          { label: 'r+d journal', to: { page: 'subcategory', cat: 'material', sub: 'rd' } },
          { label: post.title },
        ]} />

      {/* hero */}
      <div style={{ padding: mobile ? '32px 22px 26px' : '52px 56px 34px', borderBottom: `1px solid ${JR_RULE}` }}>
        <div style={{ maxWidth: 760 }}>
          <div className="mono" style={{ fontSize: 11.5, color: JR_INK3, letterSpacing: 0.3, marginBottom: 18,
            display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 14 }}>
            <span className="tnum">{d.long}</span>
            <span style={{ opacity: 0.4 }}>·</span>
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, color: JR_INK2 }}>
              <span style={{ width: 7, height: 7, background: sc(post.status) }} />{post.status}
            </span>
            <span style={{ opacity: 0.4 }}>·</span>
            <span>{rt} min read</span>
          </div>
          <h1 style={{ fontSize: mobile ? 'clamp(28px, 8vw, 36px)' : 48, fontWeight: 500, letterSpacing: mobile ? -1 : -1.8,
            lineHeight: 1.05, color: JR_INK, margin: '0 0 18px', textWrap: 'balance' }}>{post.title}</h1>
          <div style={{ fontSize: mobile ? 16 : 19, lineHeight: 1.5, color: JR_INK2, marginBottom: 20,
            maxWidth: 640, textWrap: 'pretty' }}>{post.summary}</div>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 7, alignItems: 'center' }}>
            {post.tags.map((t) => (
              <span key={t} className="mono" style={{ fontSize: 11, color: JR_INK3, letterSpacing: 0.3,
                border: `1px solid ${JR_RULE}`, padding: '4px 8px' }}>{t}</span>
            ))}
            {post.related && (
              <button className="mono" onClick={() => navigate(post.related.to)}
                style={{ marginLeft: mobile ? 0 : 6, font: 'inherit', fontFamily: 'var(--font-mono)', fontSize: 11,
                  background: 'transparent', border: `1px solid ${JR_RULE}`, color: JR_INK2, padding: '4px 8px',
                  cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: 6 }}
                onMouseEnter={(e) => { e.currentTarget.style.borderColor = JR_INK; e.currentTarget.style.color = JR_INK; }}
                onMouseLeave={(e) => { e.currentTarget.style.borderColor = JR_RULE; e.currentTarget.style.color = JR_INK2; }}>
                related: {post.related.label} →
              </button>
            )}
          </div>
        </div>
      </div>

      {/* body */}
      <div style={{ flex: 1, padding: mobile ? '30px 22px 50px' : '44px 56px 64px' }}>
        <div style={{ display: hasToc ? 'grid' : 'block',
          gridTemplateColumns: hasToc ? '180px minmax(0, 720px)' : undefined,
          gap: hasToc ? 56 : 0, justifyContent: 'center', maxWidth: hasToc ? 'none' : 720, margin: '0 auto' }}>
          {hasToc && <JR_Toc headings={headings} activeId={activeId} />}
          <article style={{ minWidth: 0 }}>
            {blocks.map(({ b, meta }, i) => (
              <JR_Block key={i} block={b} hIndex={meta.hIndex} figures={figures} figIndex={meta.figIndex} mobile={mobile} />
            ))}

            {/* prev / next */}
            <div style={{ marginTop: mobile ? 40 : 56, borderTop: `1px solid ${JR_RULE}`,
              display: 'grid', gridTemplateColumns: '1fr 1fr', gap: mobile ? 12 : 20 }}>
              <JR_PrevNext post={newer} dir="newer" navigate={navigate} mobile={mobile} />
              <JR_PrevNext post={older} dir="older" navigate={navigate} mobile={mobile} />
            </div>
          </article>
        </div>
      </div>

      {Footer ? <Footer /> : null}
    </div>
  );
}

function JR_PrevNext({ post, dir, navigate, mobile }) {
  const right = dir === 'older';
  if (!post) return <div />;
  const [h, setH] = React.useState(false);
  return (
    <div onClick={() => navigate({ page: 'article', slug: post.slug })}
      onMouseEnter={() => setH(true)} onMouseLeave={() => setH(false)}
      style={{ cursor: 'pointer', padding: mobile ? '18px 0' : '22px 0', textAlign: right ? 'right' : 'left',
        borderRight: right ? 'none' : `1px solid ${JR_RULE}`, paddingRight: right ? 0 : 20,
        paddingLeft: right ? 20 : 0 }}>
      <div className="mono" style={{ fontSize: 10.5, color: JR_INK3, letterSpacing: 0.5, textTransform: 'uppercase',
        marginBottom: 8 }}>{right ? 'older →' : '← newer'}</div>
      <div style={{ fontSize: mobile ? 15 : 17, fontWeight: 500, letterSpacing: -0.3, lineHeight: 1.25,
        color: h ? JR_INK : JR_INK2, transition: 'color .15s' }}>{post.title}</div>
    </div>
  );
}

Object.assign(window, { JournalIndex, ArticlePage });
