// DidacheReader.jsx — dedicated full-page long-form reader for the Didache.
//
// Surface:
//   • Full page (rendered in place of LibraryMainV2, like CollectionPage)
//   • Breadcrumb back to the Pre-Nicene Fathers collection
//   • Sticky chapter nav (1–16) across the top of the reading column
//   • Centered English body — modern minimal serif, comfortable measure
//   • Pinnable Greek panel — lazy-fetches from TANhub /document?id=didache&lang=grc&chapter=N
//   • Marginal commentary column (editorial voice)
//   • Inline footnotes — hover preview, click anchors to ref
//   • Per-pericope "Deep study →" opens the existing ReaderDrawerV2
//   • Toolbar: highlight+save, share/export markdown, audio order (ElevenLabs), reception timeline
//
// Data: window.DIDACHE_DATA (english + commentary + footnotes + reception)
// API:  window.tanhubApi.getGreek(chapter)  — simulated lazy fetch

function DidacheReader({ onBack, onOpenCollection, onOpenPericope, docMeta, gotoChapter, gotoVerse, returnTo, onReturn, onOpenVaultStudy, crumbs }) {
  const DIDACHE = window.DIDACHE_DATA;
  const I = window.useI18n ? window.useI18n() : null;

  // When docMeta is set, we're rendering a non-Didache Pre-Nicene / Parabiblical book.
  // If docMeta.chapters is supplied, we render exactly those chapters (some may be stubs).
  // A variant doc with NO chapters gets an honest "not available" stub —
  // never another work's text as placeholder.
  const isVariant = !!docMeta;
  const hasOwnChapters = !!(docMeta && docMeta.chapters);
  const NO_TEXT_STUB = docMeta ? [{
    n: 1, stub: true, title: 'Text not available',
    section: ((docMeta.collection || '')).toUpperCase(), summary: '',
    stubEyebrow: 'Not yet in the library',
    stubText: (docMeta.lede || 'The text of this work is not yet held in the library.'),
    en: [{ v: 1, text: (docMeta.lede || 'The text of this work is not yet held in the library.') }]
  }] : null;
  const CHAPTERS = (docMeta && docMeta.chapters) || (isVariant ? NO_TEXT_STUB : DIDACHE.CHAPTERS);
  const persistId = (docMeta && docMeta.id) || 'didache';
  const chapterKey = 'reader:' + persistId + ':cur';
  const highlightKey = 'reader:' + persistId + ':highlights';

  // ── State ────────────────────────────────────
  const [currentCh, setCurrentCh] = React.useState(() => {
    const saved = parseInt(sessionStorage.getItem(chapterKey) || '1', 10);
    const first = CHAPTERS[0] ? CHAPTERS[0].n : 1;
    const last = CHAPTERS[CHAPTERS.length-1] ? CHAPTERS[CHAPTERS.length-1].n : 16;
    return (saved >= first && saved <= last) ? saved : first;
  });
  const [greekPinned, setGreekPinned] = React.useState(false);
  const docLanguages = (docMeta && docMeta.languages) || null;
  const [bodyLang, setBodyLang] = React.useState(() => {
    // No language metadata → English body (Didache / placeholder stubs).
    // One or more languages → adopt the first language's key so its font + direction
    // bind even when there is only a single original-script column (no toggle shown).
    if (!docLanguages || docLanguages.length < 1) return 'en';
    const saved = sessionStorage.getItem('reader:' + persistId + ':bodyLang');
    if (saved && docLanguages.some(l => l.key === saved)) return saved;
    return docLanguages[0].key;
  });
  React.useEffect(() => {
    if (docLanguages) sessionStorage.setItem('reader:' + persistId + ':bodyLang', bodyLang);
  }, [bodyLang, persistId, docLanguages]);
  const activeLang = docLanguages ? (docLanguages.find(l => l.key === bodyLang) || docLanguages[0]) : null;
  const [greekByCh, setGreekByCh] = React.useState({});     // { [n]: { loading, verses, notice, error } }
  const [hoverFn, setHoverFn] = React.useState(null);       // { key, rect }
  const [highlights, setHighlights] = React.useState(() => {
    try { return JSON.parse(localStorage.getItem(highlightKey) || '{}'); }
    catch(e) { return {}; }
  });
  const [showReception, setShowReception] = React.useState(false);
  const [showAudioModal, setShowAudioModal] = React.useState(false);
  const [toast, setToast] = React.useState(null);

  // ── Effects ──────────────────────────────────
  React.useEffect(() => {
    sessionStorage.setItem(chapterKey, String(currentCh));
  }, [currentCh, chapterKey]);

  React.useEffect(() => {
    try { localStorage.setItem(highlightKey, JSON.stringify(highlights)); } catch(e) {}
  }, [highlights, highlightKey]);

  // Scrollspy — update currentCh as chapters pass into view
  React.useEffect(() => {
    const els = CHAPTERS.map(c => document.getElementById('ddc-ch-' + c.n)).filter(Boolean);
    if (!els.length) return;
    const obs = new IntersectionObserver((entries) => {
      const visible = entries.filter(e => e.isIntersecting)
        .sort((a,b) => b.intersectionRatio - a.intersectionRatio);
      if (visible[0]) {
        const n = parseInt(visible[0].target.dataset.ch, 10);
        if (n && n !== currentCh) setCurrentCh(n);
      }
    }, { rootMargin: '-30% 0px -60% 0px', threshold: [0, 0.25, 0.5, 0.75, 1] });
    els.forEach(el => obs.observe(el));
    return () => obs.disconnect();
  }, []);

  // Lazy fetch Greek when panel is pinned and chapter changes
  React.useEffect(() => {
    if (!greekPinned) return;
    if (isVariant) return; // Only the Didache has a simulated Greek endpoint
    if (greekByCh[currentCh]) return;
    setGreekByCh(s => ({ ...s, [currentCh]: { loading: true } }));
    window.tanhubApi.getGreek(currentCh).then(res => {
      setGreekByCh(s => ({ ...s, [currentCh]: { loading: false, verses: res.verses, notice: res.notice, cached: res.cached } }));
    }).catch(err => {
      setGreekByCh(s => ({ ...s, [currentCh]: { loading: false, error: String(err) } }));
    });
  }, [greekPinned, currentCh, isVariant]);

  // Keyboard nav: j/k, [ ]
  React.useEffect(() => {
    const h = (e) => {
      if (e.target && (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA')) return;
      if (document.body.classList.contains('vsheet-open')) return; // a vault sheet owns the keys
      const first = CHAPTERS[0] ? CHAPTERS[0].n : 1;
      const last = CHAPTERS[CHAPTERS.length-1] ? CHAPTERS[CHAPTERS.length-1].n : 16;
      if (e.key === 'j' || e.key === ']') { e.preventDefault(); jumpToCh(Math.min(last, currentCh + 1)); }
      else if (e.key === 'k' || e.key === '[') { e.preventDefault(); jumpToCh(Math.max(first, currentCh - 1)); }
      else if (e.key === 'g' && !isVariant) { setGreekPinned(p => !p); }
    };
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, [currentCh, isVariant]);

  // ── Helpers ──────────────────────────────────
  function jumpToCh(n) {
    const el = document.getElementById('ddc-ch-' + n);
    if (el) {
      const y = el.getBoundingClientRect().top + window.scrollY - 140;
      window.scrollTo({ top: y, behavior: 'smooth' });
    }
    setCurrentCh(n);
  }

  function toggleHighlight(chN, vN) {
    const key = chN + ':' + vN;
    setHighlights(h => {
      const next = { ...h };
      if (next[key]) delete next[key];
      else next[key] = { at: Date.now() };
      return next;
    });
  }

  function openPericopeStudy(chN, vStart, vEnd) {
    if (!onOpenPericope) { flashToast('Deep study isn\u2019t available here.'); return; }
    // Didache 1:1-2 has a full analytical study. Other verses open the pericope
    // drawer without a specific study attached (the drawer falls back to its default content).
    const isDidache11 = chN === 1 && vStart === 1 && (vEnd === 2 || vEnd === 1);
    onOpenPericope({
      book: 'didache',
      chap: chN,
      v1: vStart,
      v2: vEnd,
      label: 'Didache ' + chN + (vEnd && vEnd !== vStart ? (':' + vStart + '–' + vEnd) : (':' + vStart)),
      studyId: isDidache11 ? 'didache-1-1-2' : null
    });
  }

  function flashToast(msg) {
    setToast(msg);
    setTimeout(() => setToast(null), 2600);
  }

  function exportChapterMarkdown(chN) {
    const ch = CHAPTERS.find(c => c.n === chN);
    if (!ch) return;
    const lines = [];
    lines.push('# Didache ' + chN + '. ' + ch.title);
    lines.push('');
    lines.push('*' + ch.section + ' — ' + ch.summary + '*');
    lines.push('');
    ch.en.forEach(vv => { lines.push('**' + vv.v + '.** ' + vv.text); lines.push(''); });
    if (ch.commentary && ch.commentary.length) {
      lines.push('## Commentary');
      lines.push('');
      ch.commentary.forEach(c => lines.push('- (v. ' + c.anchor + ') ' + c.text));
    }
    const md = lines.join('\n');
    navigator.clipboard.writeText(md).then(
      () => flashToast('Chapter ' + chN + ' copied to clipboard as Markdown'),
      () => flashToast('Copy blocked — select and copy manually')
    );
  }

  // ── Render ───────────────────────────────────
  const currentChapter = CHAPTERS.find(c => c.n === currentCh) || CHAPTERS[0];

  return React.createElement('div', { className:'amos-main ddc-main' },
    // ── Topbar (matching the shell) ────────────
    React.createElement('div', { className:'amos-topbar ddc-topbar' },
      React.createElement('button', {
        className: 'amos-sidebar-toggle',
        onClick: () => window.dispatchEvent(new CustomEvent('amos:toggle-sidebar')),
        title: 'Toggle sidebar  ([)',
        'aria-label': 'Toggle sidebar'
      },
        React.createElement('svg', { width:16, height:16, viewBox:'0 0 24 24', fill:'none', stroke:'currentColor', strokeWidth:'2', strokeLinecap:'round', strokeLinejoin:'round' },
          React.createElement('rect', { x:'3', y:'4', width:'18', height:'16', rx:'2' }),
          React.createElement('line', { x1:'9', y1:'4', x2:'9', y2:'20' })
        )
      ),
      React.createElement('div', { className:'amos-crumbs' },
        React.createElement('span', null, 'The Amos Project'),
        React.createElement('span', { className:'sep' }, '›'),
        React.createElement('a', { className:'crumb-link', onClick: onBack }, I ? I.t('reader.crumb_library') : 'Library'),
        // custom trail (stitched Bible editions: New Testament › Book) or the
        // default single collection chip (church documents)
        ...(crumbs && crumbs.length
          ? crumbs.flatMap((c, i) => [
              React.createElement('span', { key: 'cs' + i, className: 'sep' }, '›'),
              React.createElement('a', { key: 'cl' + i, className: 'crumb-link', onClick: c.onClick }, c.label)
            ])
          : [
              React.createElement('span', { key: 'ds', className: 'sep' }, '›'),
              React.createElement('a', { key: 'dl', className: 'crumb-link', onClick: () => onOpenCollection && onOpenCollection((docMeta && docMeta.collectionKey) || 'patristic') }, (docMeta && docMeta.collection) || 'Pre-Nicene Fathers')
            ]),
        React.createElement('span', { className:'sep' }, '›'),
        React.createElement('span', { className:'here' }, (docMeta && docMeta.hereLabel) || (docMeta && docMeta.title) || 'Didache')
      ),
      React.createElement('div', { className:'amos-topbar-right' },
        // (the TANhub endpoint badge lived here — implementation chrome, removed)
        React.createElement('div', { className:'amos-sc-pair', style:{ marginLeft: 8 } },
          React.createElement(window.CiteButton,  { refFor: () => ({
            kind:'work',
            title: (docMeta && docMeta.title) || 'Didache',
            subtitle: (docMeta && docMeta.subtitle) || 'The Teaching of the Twelve Apostles',
            section: 'Chapter ' + currentCh,
            edition: isVariant ? ((docMeta && docMeta.edition) || 'Amos Project edition 2026') : 'Niederwimmer 1998 · Amos Project 2024',
            editor: 'World Mission Media',
            year: 2024,
            doi: '10.70001/' + ((docMeta && docMeta.id) || 'didache') + '.2024',
            url: 'https://worldmission.media/read/' + ((docMeta && docMeta.id) || 'didache') + '/ch' + currentCh,
            description: (docMeta && docMeta.lede) || 'Critical edition of the Didache.',
            collectionKey: (docMeta && docMeta.collectionKey) || 'patristic'
          }) }),
          React.createElement(window.ShareButton, { refFor: () => ({
            kind:'work',
            title: (docMeta && docMeta.title) || 'Didache',
            subtitle: (docMeta && docMeta.subtitle) || 'The Teaching of the Twelve Apostles',
            section: 'Chapter ' + currentCh,
            edition: isVariant ? ((docMeta && docMeta.edition) || 'Amos Project edition 2026') : 'Niederwimmer 1998 · Amos Project 2024',
            editor: 'World Mission Media',
            year: 2024,
            url: 'https://worldmission.media/read/' + ((docMeta && docMeta.id) || 'didache') + '/ch' + currentCh,
            description: (docMeta && docMeta.lede) || 'Critical edition of the Didache.',
            collectionKey: (docMeta && docMeta.collectionKey) || 'patristic'
          }) })
        )
      )
    ),

    // ── Highlight-to-share pill (mounts once; auto-tracks selection) ──
    React.createElement(window.HighlightSharePill, {
      container: '.ddc-column',
      shareRefBuilder: (text, chN) => ({
        kind:'work',
        title: (docMeta && docMeta.title) || 'Didache',
        subtitle: (docMeta && docMeta.subtitle) || '',
        section: chN ? ('Chapter ' + chN) : ('Chapter ' + currentCh),
        edition: isVariant ? ((docMeta && docMeta.edition) || 'Amos Project edition 2026') : 'Niederwimmer 1998 · Amos Project 2024',
        editor: 'World Mission Media',
        year: 2024,
        url: 'https://worldmission.media/read/' + ((docMeta && docMeta.id) || 'didache') + '/ch' + (chN || currentCh),
        collectionKey: (docMeta && docMeta.collectionKey) || 'patristic'
      })
    }),

    // ── Editorial hero ──────────────────────────
    React.createElement('section', { className:'ddc-hero' },
      isVariant && !hasOwnChapters && React.createElement('div', { className:'ddc-hero-note', style:{ fontSize:12, letterSpacing:'.06em', textTransform:'uppercase', color:'#94938c', marginBottom:10 } },
        'The text of this work is not yet held in the library — this page carries its catalog record only'
      ),
      hasOwnChapters && React.createElement('div', { className:'ddc-hero-note', style:{ fontSize:12, letterSpacing:'.06em', textTransform:'uppercase', color: (docMeta && docMeta.editionNote) ? '#1f6b3a' : '#94938c', marginBottom:10 } },
        (docMeta && docMeta.editionNote) || 'Partial edition · selected chapters available in this edition; other chapters in preparation'
      ),
      React.createElement('div', { className:'ddc-hero-tag' },
        React.createElement('span', { className:'num' }, '14'),
        React.createElement('span', null, ((docMeta && docMeta.collection) || 'Pre-Nicene Fathers').toUpperCase()),
        React.createElement('span', { className:'dot' }),
        React.createElement('span', null, hasOwnChapters ? ((docMeta && docMeta.fullLoaded) ? 'FULL EDITION · COMPLETE TEXT' : ((docMeta && docMeta.editionNote) || 'PARTIAL EDITION · SELECTED CHAPTERS')) : (isVariant ? 'TEXT NOT YET IN THE LIBRARY' : 'COMPLETE · CRITICAL EDITION'))
      ),
      React.createElement('h1', { className:'ddc-hero-title' }, (docMeta && docMeta.title) || 'Didache'),
      React.createElement('div', { className:'ddc-hero-sub' }, (docMeta && docMeta.subtitle) || 'The Teaching of the Twelve Apostles'),
      React.createElement('p', { className:'ddc-hero-lede' },
        (docMeta && docMeta.lede) ||
        'A short handbook of moral instruction, liturgy, and church order, compiled in Greek between roughly 50 and 120 CE. Lost for over a millennium, then recovered in 1873 in a monastery in Constantinople. Sixteen chapters. About 2,300 words. The earliest explicit Christian testimony we have on baptism, the eucharist, fasting, itinerant ministry, and the Lord\u2019s Day.'
      ),
      React.createElement('div', { className:'ddc-hero-meta' },
        React.createElement('div', { className:'ddc-metastat' },
          React.createElement('span', { className:'lbl' }, 'Source manuscript'),
          React.createElement('span', { className:'val' }, isVariant ? ((docMeta && docMeta.manuscript) || 'Manuscript tradition not yet documented') : 'Codex Hierosolymitanus (1056 CE)')
        ),
        React.createElement('div', { className:'ddc-metastat' },
          React.createElement('span', { className:'lbl' }, 'Critical edition'),
          React.createElement('span', { className:'val' }, isVariant ? ((docMeta && docMeta.edition) || 'World Mission Media 2024') : 'Niederwimmer 1998 · Milavec 2003 · World Mission Media 2024')
        ),
        React.createElement('div', { className:'ddc-metastat' },
          React.createElement('span', { className:'lbl' }, 'Languages available'),
          React.createElement('span', { className:'val' }, isVariant ? ((docMeta && docMeta.langs) || 'Greek · English (pending)') : 'Greek · English · Spanish · Catalan (pending)')
        ),
        React.createElement('div', { className:'ddc-metastat' },
          React.createElement('span', { className:'lbl' }, 'License'),
          React.createElement('span', { className:'val' }, isVariant ? ('CC BY 4.0 · Amos Project DOI 10.70001/' + ((docMeta && docMeta.id) || 'work') + '.pending') : 'CC BY 4.0 · Amos Project DOI 10.70001/didache.2024')
        )
      )
    ),

    // ── Sticky chapter nav ──────────────────────
    React.createElement('div', { className:'ddc-chapnav' },
      React.createElement('div', { className:'ddc-chapnav-inner' },
        React.createElement('div', { className:'ddc-chapnav-label' }, 'Ch.'),
        React.createElement('div', { className:'ddc-chapnav-list' },
          CHAPTERS.map(c =>
            React.createElement('button', {
              key: c.n,
              className: 'ddc-chipnum' + (c.n === currentCh ? ' active' : ''),
              onClick: () => jumpToCh(c.n),
              title: c.title
            }, c.n)
          )
        ),
        React.createElement('div', { className:'ddc-chapnav-tools' },
          docLanguages && docLanguages.length >= 2 && React.createElement('div', { className:'ddc-langtoggle', role:'group', 'aria-label':'Body text language' },
            docLanguages.map(l =>
              React.createElement('button', {
                key: l.key,
                className: 'ddc-langtoggle-btn' + (bodyLang === l.key ? ' active' : ''),
                onClick: () => setBodyLang(l.key),
                title: l.sub ? (l.label + ' — ' + l.sub) : l.label
              }, l.label)
            )
          ),
          !docLanguages && React.createElement('button', {
            className: 'ddc-tool' + (greekPinned ? ' active' : ''),
            onClick: () => setGreekPinned(p => !p),
            title: 'Pin Greek panel (g)'
          },
            React.createElement('span', { className:'ddc-tool-ico' }, 'Ελ'),
            React.createElement('span', null, greekPinned ? 'Greek pinned' : 'Show Greek')
          ),
          React.createElement('button', {
            className: 'ddc-tool' + (showReception ? ' active' : ''),
            onClick: () => setShowReception(s => !s),
            title: 'Reception timeline'
          },
            React.createElement('span', { className:'ddc-tool-ico' }, '◷'),
            React.createElement('span', null, 'Reception')
          ),
          React.createElement('button', {
            className: 'ddc-tool',
            onClick: () => setShowAudioModal(true),
            title: 'Order an audio narration'
          },
            React.createElement('span', { className:'ddc-tool-ico' }, '♪'),
            React.createElement('span', null, 'Audio')
          )
        )
      )
    ),

    // ── Reading column + side rails ─────────────
    React.createElement('div', { className:'ddc-layout' + (greekPinned ? ' greek-pinned' : '') + (showReception ? ' reception-open' : '') },

      // LEFT: reception timeline (optional)
      showReception && React.createElement('aside', { className:'ddc-reception' },
        React.createElement('div', { className:'ddc-reception-head' },
          React.createElement('span', null, 'Reception'),
          React.createElement('button', {
            className:'ddc-reception-close',
            onClick: () => setShowReception(false),
            title:'Close'
          }, '×')
        ),
        React.createElement('div', { className:'ddc-reception-sub' }, 'Where this chapter surfaces in later tradition'),
        (currentChapter.reception && currentChapter.reception.length
          ? currentChapter.reception.map((r, i) =>
              React.createElement(r.studyId && onOpenVaultStudy ? 'button' : 'div', {
                key: i,
                className: 'ddc-recept-item' + (r.studyId && onOpenVaultStudy ? ' clickable' : ''),
                style: r.studyId && onOpenVaultStudy
                  ? { textAlign: 'left', width: '100%', font: 'inherit', cursor: 'pointer',
                      background: 'none', border: 'none', borderBottom: '1px solid var(--line,#eee6d8)' }
                  : undefined,
                onClick: r.studyId && onOpenVaultStudy ? (() => onOpenVaultStudy(r.studyId)) : undefined,
                title: r.studyId ? 'Open the analysis where this witness is cited' : undefined
              },
                React.createElement('div', { className:'era era-'+String(r.era).toLowerCase().replace(/[^a-z0-9-]+/g,'-') }, r.era),
                React.createElement('div', { className:'src' }, r.source),
                React.createElement('div', { className:'note' }, r.note)
              )
            )
          : React.createElement('div', { className:'ddc-recept-empty' }, 'No cataloged citations for this chapter yet.')
        ),
        React.createElement('div', { className:'ddc-reception-foot' },
          React.createElement('span', null, 'From The Amos Project trust ledger — every claim graded.')
        )
      ),

      // CENTER: the reading column
      React.createElement('div', { className:'ddc-column' },
        CHAPTERS.map(ch =>
          React.createElement(ChapterBlock, {
            key: ch.n,
            ch,
            activeLang,
            bodyLang,
            greek: greekByCh[ch.n],
            greekPinned,
            highlights,
            onToggleHighlight: toggleHighlight,
            onOpenStudy: openPericopeStudy,
            // Study hooks only where an analytical study actually exists (Didache, or a
            // docMeta that opts in). Text-only corpus books hide them rather than open a
            // mislabeled/empty drawer.
            showStudy: !isVariant || !!(docMeta && docMeta.hasStudies),
            onExportMarkdown: exportChapterMarkdown,
            onHoverFootnote: setHoverFn,
            onOpenVaultStudy
          })
        ),
        React.createElement('div', { className:'ddc-end' },
          React.createElement('div', { className:'ddc-end-ornament' }, '✢'),
          React.createElement('div', { className:'ddc-end-text' },
            (docMeta && docMeta.endText) ||
            (isVariant ? ('End of preview. ' + ((docMeta && docMeta.title) || 'This work') + ' will be released in the World Mission Media edition under CC BY 4.0.') : 'End of the Didache. Read in the World Mission Media edition, CC BY 4.0.')),
          React.createElement('button', { className:'ddc-end-back', onClick: onBack }, I ? I.t('reader.back_library') : '← Back to the Library')
        )
      ),

      // RIGHT: pinnable Greek panel
      greekPinned && React.createElement('aside', { className:'ddc-greek' },
        React.createElement('div', { className:'ddc-greek-head' },
          React.createElement('span', { className:'ddc-greek-title' },
            React.createElement('span', { className:'ddc-greek-label' }, 'Ἑλληνικά'),
            React.createElement('span', { className:'ddc-greek-sub' }, 'Chapter ' + currentCh)
          ),
          React.createElement('button', {
            className:'ddc-greek-close',
            onClick: () => setGreekPinned(false),
            title:'Close'
          }, '×')
        ),
        React.createElement('div', { className:'ddc-greek-api' },
        ),
        React.createElement('div', { className:'ddc-greek-body' },
          (!greekByCh[currentCh] || greekByCh[currentCh].loading)
            ? React.createElement('div', { className:'ddc-greek-shimmer' },
                React.createElement('div', { className:'sh sh-1' }),
                React.createElement('div', { className:'sh sh-2' }),
                React.createElement('div', { className:'sh sh-3' }),
                React.createElement('div', { className:'sh sh-1' })
              )
            : greekByCh[currentCh].verses
              ? greekByCh[currentCh].verses.map(v =>
                  React.createElement('p', { key: v.v, className:'ddc-greek-verse' },
                    React.createElement('span', { className:'ddc-greek-vn' }, v.v),
                    React.createElement('span', { className:'ddc-greek-text' }, v.text)
                  )
                )
              : React.createElement('div', { className:'ddc-greek-notice' }, greekByCh[currentCh].notice || 'Greek text not available for this chapter.')
        )
      )
    ),

    // ── Footnote hover-card ─────────────────────
    hoverFn && React.createElement(FootnoteCard, { hover: hoverFn, chapters: CHAPTERS }),

    // ── Audio commission modal ──────────────────
    showAudioModal && React.createElement(AudioCommissionModal, {
      onClose: () => setShowAudioModal(false),
      onConfirm: (opts) => { setShowAudioModal(false); flashToast('Audio narration ordered — you\u2019ll be notified when it\u2019s ready.'); }
    }),

    // ── Toast ───────────────────────────────────
    toast && React.createElement('div', { className:'ddc-toast' }, toast)
  );
}

// ─────────────────────────────────────────────────
// ChapterBlock — renders one chapter with English, commentary, footnote hooks.
// ─────────────────────────────────────────────────
function ChapterBlock({ ch, activeLang, bodyLang, greek, greekPinned, highlights, onToggleHighlight, onOpenStudy, showStudy, onExportMarkdown, onHoverFootnote, onOpenVaultStudy }) {
  // Resolve which language array to render. Default is the English `en` field.
  const langKey = bodyLang || 'en';
  const verses = (langKey !== 'en' && Array.isArray(ch[langKey])) ? ch[langKey] : ch.en;
  const langPending = (langKey !== 'en' && !Array.isArray(ch[langKey]) && ch[langKey + '_pending']);
  const langStyle = (activeLang && activeLang.key === langKey && activeLang.fontFamily)
    ? {
        fontFamily: activeLang.fontFamily,
        // Ethiopic/Ge'ez needs tighter leading than Latin prose and must be
        // allowed to break anywhere because syllabic words can be very long
        // and don't hyphenate.
        lineHeight: 1.45,
        wordBreak: 'normal',
        overflowWrap: 'anywhere'
      }
    : null;
  // Build a map of verse -> commentary anchor
  const commentaryAt = {};
  (ch.commentary || []).forEach(c => { commentaryAt[c.anchor] = c; });

  // keyed by position, not verse number — stitched editions repeat verse
  // numbers where pericope ranges overlap, and grouped markers share a parse
  const renderVerse = (v, vi) => {
    const hi = highlights[ch.n + ':' + v.v];
    // Pericope head — used by stitched editions (plain analytical books):
    // a quiet unit header with the doorway into the full analysis.
    const head = v.head && React.createElement('div', {
      key: 'h' + vi, className: 'ddc-peri-head'
    },
      React.createElement('span', { className: 'ddc-peri-title' }, v.head.title || ''),
      v.head.ref && React.createElement('span', { className: 'ddc-peri-ref' }, v.head.ref),
      v.head.studyId && onOpenVaultStudy && React.createElement('button', {
        className: 'ddc-peri-open',
        onClick: () => onOpenVaultStudy(v.head.studyId),
        title: 'Open the full analysis — Greek text, word analysis, reception, variants'
      }, 'Full analysis →')
    );
    const verseEl = React.createElement('div', {
      key: 'v' + vi,
      className: 'ddc-verse' + (hi ? ' highlighted' : ''),
      id: 'ddc-' + ch.n + '-' + v.v
    },
      React.createElement('button', {
        className: 'ddc-verse-num',
        onClick: () => onToggleHighlight(ch.n, v.v),
        title: hi ? 'Remove highlight' : 'Highlight this verse',
        'data-v': v.v
      }, v.vl || v.v),
      React.createElement('div', { className:'ddc-verse-body' },
        React.createElement('span', { className:'ddc-verse-text' }, v.text,
          v.fn && React.createElement('sup', {
            className:'ddc-fn-ref',
            onMouseEnter: (e) => {
              const rect = e.currentTarget.getBoundingClientRect();
              onHoverFootnote({ key: v.fn, chN: ch.n, rect, text: ch.footnotes[v.fn] });
            },
            onMouseLeave: () => onHoverFootnote(null),
            onClick: (e) => { e.preventDefault(); }
          }, '[', Object.keys(ch.footnotes).indexOf(v.fn) + 1, ']')
        ),
        // Inline "study" hook — appears on hover (only where a study exists)
        showStudy && React.createElement('button', {
          className:'ddc-verse-study',
          onClick: () => onOpenStudy(ch.n, v.v, v.v),
          title:'Open analytical study for this verse'
        }, 'Deep study ', window.I && window.I.arrowRight ? window.I.arrowRight(11) : '→')
      )
    );
    return head ? React.createElement(React.Fragment, { key: 'f' + vi }, head, verseEl) : verseEl;
  };

  return React.createElement('article', {
    id: 'ddc-ch-' + ch.n,
    'data-ch': ch.n,
    className:'ddc-chapter' + (ch.stub ? ' ddc-chapter-stub' : '')
  },
    // Chapter head
    React.createElement('header', { className:'ddc-ch-head' },
      React.createElement('div', { className:'ddc-ch-eyebrow' },
        React.createElement('span', { className:'ddc-ch-section' }, ch.section),
        React.createElement('span', { className:'sep' }, '·'),
        React.createElement('span', { className:'ddc-ch-num' }, 'Chapter ' + ch.n)
      ),
      React.createElement('h2', { className:'ddc-ch-title' }, ch.title),
      React.createElement('p', { className:'ddc-ch-summary' }, ch.summary),
      !ch.stub && React.createElement('div', { className:'ddc-ch-actions' },
        showStudy && React.createElement('button', {
          className:'ddc-ch-action',
          onClick: () => onOpenStudy(ch.n, ch.en[0].v, ch.en[ch.en.length-1].v)
        }, 'Open full chapter in study drawer ', window.I && window.I.arrowRight ? window.I.arrowRight(11) : '→'),
        React.createElement('button', {
          className:'ddc-ch-action ghost',
          onClick: () => onExportMarkdown(ch.n),
          title:'Copy as Markdown'
        }, 'Share as Markdown')
      )
    ),

    // Stub placeholder
    ch.stub && React.createElement('div', {
      className:'ddc-ch-body',
      style: { display:'block' }
    },
      React.createElement('div', {
        style: {
          border: '1px dashed #d5d0c4',
          borderRadius: 8,
          padding: '28px 32px',
          background: '#faf8f2',
          color: '#6b6758',
          maxWidth: 720,
          margin: '8px auto'
        }
      },
        React.createElement('div', {
          style: { fontSize: 11, letterSpacing: '.08em', textTransform: 'uppercase', color: '#9a958a', marginBottom: 10 }
        }, ch.stubEyebrow || 'In preparation'),
        React.createElement('div', {
          style: { fontFamily: 'Georgia, serif', fontSize: 17, lineHeight: 1.55, color: '#3a3a34' }
        }, ch.stubText || (ch.en && ch.en[0] && ch.en[0].text) || 'This chapter is not yet available in this edition. Chapters are published as they clear editorial review — check back soon, or commission a priority translation to move this work up the queue.')
      )
    ),

    // Body: prose + marginalia side by side
    !ch.stub && React.createElement('div', { className:'ddc-ch-body' },
      React.createElement('div', { className:'ddc-prose', style: langStyle, lang: langKey, dir: (activeLang && activeLang.dir) || 'ltr' },
        langPending
          ? React.createElement('div', {
              style: {
                border: '1px dashed #d5d0c4',
                borderRadius: 8,
                padding: '22px 26px',
                background: '#faf8f2',
                color: '#6b6758',
                margin: '8px 0 20px'
              }
            },
              React.createElement('div', { style: { fontSize: 11, letterSpacing:'.08em', textTransform:'uppercase', color:'#9a958a', marginBottom: 8 } },
                'Geʼez text in preparation'),
              React.createElement('div', { style: { fontFamily: 'Georgia, serif', fontSize: 16, lineHeight: 1.55 } },
                'The Geʼez text for this chapter is being established from the Bodleian mss and collated against Nickelsburg’s Hermeneia edition. English is shown below.'),
              React.createElement('div', { style: { marginTop: 14, paddingTop: 14, borderTop: '1px solid #e7e1d0' } },
                ch.en.map(renderVerse))
            )
          : verses.map(renderVerse)
      ),
      React.createElement('aside', { className:'ddc-marginalia' },
        (ch.commentary || []).length === 0
          ? null
          : React.createElement('div', { className:'ddc-margin-head' }, 'Commentary'),
        (ch.commentary || []).map((c, i) =>
          React.createElement('div', { key:i, className:'ddc-margin-item' },
            React.createElement('a', {
              className:'ddc-margin-anchor',
              href: '#ddc-' + ch.n + '-' + c.anchor,
              onClick: (e) => {
                e.preventDefault();
                const el = document.getElementById('ddc-' + ch.n + '-' + c.anchor);
                if (el) {
                  el.classList.add('flash');
                  setTimeout(() => el.classList.remove('flash'), 1400);
                  const y = el.getBoundingClientRect().top + window.scrollY - 180;
                  window.scrollTo({ top: y, behavior:'smooth' });
                }
              }
            }, 'v. ' + c.anchor),
            React.createElement('div', { className:'ddc-margin-text' }, c.text)
          )
        )
      )
    )
  );
}

// ─────────────────────────────────────────────────
// FootnoteCard — hover preview of a footnote.
// ─────────────────────────────────────────────────
function FootnoteCard({ hover }) {
  if (!hover || !hover.text) return null;
  const style = {
    position:'fixed',
    top: (hover.rect.bottom + 8) + 'px',
    left: Math.min(window.innerWidth - 340, hover.rect.left - 120) + 'px',
    width: '320px',
    zIndex: 120
  };
  return React.createElement('div', { className:'ddc-fn-card', style },
    React.createElement('div', { className:'ddc-fn-card-head' }, 'Note · Didache ' + hover.chN),
    React.createElement('div', { className:'ddc-fn-card-body' }, hover.text)
  );
}

// ─────────────────────────────────────────────────
// AudioCommissionModal — framing for the ElevenLabs order.
// ─────────────────────────────────────────────────
function AudioCommissionModal({ onClose, onConfirm }) {
  const [voice, setVoice] = React.useState('richard');
  const [speed, setSpeed] = React.useState('standard');
  const [withGreek, setWithGreek] = React.useState(false);

  const VOICES = [
    { id:'richard', name:'Richard Caldwell', kind:'Baritone · scholarly', sample:'28 min' },
    { id:'maria',   name:'Maria Ortiz',       kind:'Alto · reverent',       sample:'26 min' },
    { id:'thomas',  name:'Thomas Beaumont',   kind:'Tenor · pastoral',      sample:'30 min' }
  ];

  const basePrice = 4.90;
  const greekAdd = withGreek ? 3.50 : 0;
  const total = (basePrice + greekAdd).toFixed(2);

  return React.createElement('div', { className:'ddc-modal-backdrop', onClick: onClose },
    React.createElement('div', { className:'ddc-modal', onClick: e => e.stopPropagation() },
      React.createElement('div', { className:'ddc-modal-head' },
        React.createElement('div', null,
          React.createElement('div', { className:'ddc-modal-eyebrow' }, 'Order narrated audio'),
          React.createElement('h3', { className:'ddc-modal-title' }, 'Didache · English narration')
        ),
        React.createElement('button', { className:'ddc-modal-close', onClick: onClose }, '×')
      ),
      React.createElement('div', { className:'ddc-modal-body' },
        React.createElement('p', { className:'ddc-modal-lede' },
          'Narration is generated on demand with licensed voices suited to scholarly reading. You\u2019ll own the resulting MP3 and a time-aligned transcript. Delivery in about 8 minutes.'
        ),

        React.createElement('div', { className:'ddc-field-group' },
          React.createElement('div', { className:'ddc-field-label' }, 'Voice'),
          React.createElement('div', { className:'ddc-voice-list' },
            VOICES.map(v =>
              React.createElement('label', {
                key: v.id,
                className: 'ddc-voice-card' + (voice === v.id ? ' selected' : '')
              },
                React.createElement('input', {
                  type:'radio', name:'voice', value:v.id,
                  checked: voice === v.id,
                  onChange: () => setVoice(v.id)
                }),
                React.createElement('div', { className:'ddc-voice-name' }, v.name),
                React.createElement('div', { className:'ddc-voice-kind' }, v.kind),
                React.createElement('button', {
                  type:'button',
                  className:'ddc-voice-sample',
                  onClick: e => e.preventDefault()
                }, '▶ Sample · ' + v.sample)
              )
            )
          )
        ),

        React.createElement('div', { className:'ddc-field-group' },
          React.createElement('div', { className:'ddc-field-label' }, 'Pace'),
          React.createElement('div', { className:'ddc-seg' },
            ['slow', 'standard', 'brisk'].map(s =>
              React.createElement('button', {
                key: s,
                className:'ddc-seg-btn' + (speed === s ? ' active' : ''),
                onClick: () => setSpeed(s)
              }, s[0].toUpperCase() + s.slice(1))
            )
          )
        ),

        React.createElement('label', { className:'ddc-check' },
          React.createElement('input', {
            type:'checkbox',
            checked: withGreek,
            onChange: e => setWithGreek(e.target.checked)
          }),
          React.createElement('span', null, 'Include Greek readings alongside English (+$3.50)')
        ),

        React.createElement('div', { className:'ddc-price-line' },
          React.createElement('div', null,
            React.createElement('div', { className:'ddc-price-total' }, '$' + total),
            React.createElement('div', { className:'ddc-price-sub' }, 'One-time · licensed for personal + scholarly use')
          ),
          React.createElement('button', {
            className:'ddc-price-cta',
            onClick: () => onConfirm({ voice, speed, withGreek, total })
          }, 'Confirm order')
        )
      )
    )
,
    React.createElement(window.Footer, null)
  )
}

Object.assign(window, { DidacheReader });
