// ReaderDrawerV2 — four-product drawer
//
// Read tab now carries a PRODUCT switcher above the view chips:
//   • Reader's (C) · Castellano  — readable prose; Toggle/Parallel/Interlinear/Layered apply
//   • Analytical (B) · Català     — philological read with hot lemmata and bracketed glosses
//   • Annotated (D) · Català      — Analytical + four toggleable apparatus layers
//   • ✓ Linguist Reviewed (A)     — overlay state that attaches to any product
//
// Every artifact ends with a three-tier action row: primary + secondary + utility icons.

function ReaderDrawerV2({ open, onClose, openStudyId, pericopeMeta, onNavigatePericope, onOpenVaultStudy }) {
  const [mode, setMode] = React.useState('read');
  const [view, setView] = React.useState('toggle');
  const [lang, setLang] = React.useState('GRC');
  const [selectedVerse, setSelectedVerse] = React.useState(28);
  const [pop, setPop] = React.useState(null);
  const [activeStudyId, setActiveStudyId] = React.useState(null);
  const [commissionTarget, setCommissionTarget] = React.useState(null); // { kind: 'ai'|'review', pericope, mode, lang }

  // NEW: product switcher state for the Read tab
  const [product, setProduct] = React.useState('C');          // 'B' | 'C' | 'D'
  const [reviewed, setReviewed] = React.useState(false);       // A overlay toggle
  const [activeLayers, setActiveLayers] = React.useState({
    lex: true, syn: true, rhet: true, rec: true
  });

  React.useEffect(() => {
    if (openStudyId && open) {
      setMode('studies'); setActiveStudyId(openStudyId);
    } else if (!open) {
      setActiveStudyId(null);
    } else if (open && !openStudyId) {
      setActiveStudyId(null); setMode('read');
    }
  }, [openStudyId, open]);

  // Honor initialProduct / initialReviewed when drawer opens
  React.useEffect(() => {
    if (!open || !pericopeMeta) return;
    if (pericopeMeta.initialProduct) setProduct(pericopeMeta.initialProduct);
    if (pericopeMeta.initialReviewed != null) setReviewed(!!pericopeMeta.initialReviewed);
  }, [open, pericopeMeta && pericopeMeta.initialProduct, pericopeMeta && pericopeMeta.initialReviewed]);

  const studies = (window.ANALYTICAL_STUDIES && window.ANALYTICAL_STUDIES.STUDIES) || [];
  const activeStudy = studies.find(s => s.id === activeStudyId);

  // Match studies to the currently-open pericope. Study ids encode book+chapter
  // (e.g. 'rom-9', 'gal-3', 'zech-14', 'didache-1-1-2'). pericopeMeta carries
  // book/chap from the caller. Loose match: same book code (3-letter prefix
  // tolerant) and same chapter.
  const matchingStudies = React.useMemo(() => {
    if (!pericopeMeta) return [];
    const meta = pericopeMeta;
    return studies.filter(s => {
      const parts = (s.id || '').split('-');
      if (parts.length < 2) return false;
      const studyBook = parts[0];
      const studyChap = parseInt(parts[1], 10);
      if (isNaN(studyChap)) return false;
      const bookMatches = (
        meta.book === studyBook ||
        (meta.book && meta.book.slice(0, 3) === studyBook.slice(0, 3))
      );
      return bookMatches && studyChap === Number(meta.chap);   // tolerate string chap (e.g. from typed/Try refs)
    });
  }, [pericopeMeta, studies]);

  // When the Study tab opens and there's exactly one matching study for this
  // pericope, auto-open it. The card-grid picker is no longer the right
  // experience — the user is concentrating on one passage; show its study.
  React.useEffect(() => {
    if (mode === 'studies' && !activeStudyId && matchingStudies.length === 1) {
      setActiveStudyId(matchingStudies[0].id);
    }
  }, [mode, activeStudyId, matchingStudies]);

  // ── Demo study builders ──────────────────────────────────────────
  // Mockup-only. The drawer always renders StudyView. Three demo states
  // showcase what the UI looks like at different authoring depths:
  //
  //   • 'full'             — clone the Romans 9 deep study, retitled for
  //                          the current pericope. All spine sections filled.
  //   • 'translation-only' — only the Reader's translation in the user's
  //                          language is authored. Other 7 sections grayed.
  //   • 'niv-only'         — no Reader's translation yet. Show NIV English
  //                          as a fallback panel above the spine. All 8
  //                          spine sections (including Translation) grayed.

  const DEMO_NIV_VERSES = [
    { n: 28, t: 'And we know that in all things God works for the good of those who love him, who have been called according to his purpose.' },
    { n: 29, t: 'For those God foreknew he also predestined to be conformed to the image of his Son, that he might be the firstborn among many brothers and sisters.' },
    { n: 30, t: 'And those he predestined, he also called; those he called, he also justified; those he justified, he also glorified.' }
  ];

  // Look up the canonical rom-9 study so we can clone it as a "full" demo.
  const rom9Study = studies.find(s => s.id === 'rom-9') || null;

  const buildDemoFullStudy = (m) => {
    if (!m || !rom9Study) return null;
    const baseLabel = m.label || 'Pericope';
    const langLabel = m.lang ? langLabelFor(m.lang) : rom9Study.langLabel;
    // Agency-reviewed (sealed) pericopes carry the reviewer + agency seals
    // so the cover card can show "Reviewed by [agency] on [date]".
    return Object.assign({}, rom9Study, {
      id: 'demo-full-' + (m.book || 'na') + '-' + (m.chap || ''),
      ref: baseLabel,
      title: baseLabel,
      subtitle: 'Sample layout — the analysis of ' + baseLabel + ' has not been produced yet',
      langLabel: langLabel,
      reviewedBy: {
        agency: 'La BEC',
        agencyCode: 'bec',
        seals: ['bib', 'bec'],
        reviewerName: rom9Study.completedBy || 'Marta Vilà',
        reviewerCredential: 'Credentialed linguist · Asociación Bíblica Española',
        date: rom9Study.completedOn || '2026-03-14',
        scope: 'Translation accuracy and analytical apparatus'
      }
    });
  };

  // Partial state — heat-map state 'b' (Analytical apparatus). Translation
  // is authored AND a deterministic subset of analytical sections; the rest
  // appear grayed in the rail. The hash on book+chap keeps the subset stable
  // per pericope (so reloads don't shuffle it).
  const buildDemoPartialStudy = (m) => {
    if (!m || !rom9Study) return null;
    const baseLabel = m.label || 'Pericope';
    const optionalIds = ['retrans', 'patristic', 'library', 'structure', 'word', 'compare'];
    const hashSrc = (m.book || '') + (m.chap || 0);
    let h = 0;
    for (let i = 0; i < hashSrc.length; i++) h = (h * 31 + hashSrc.charCodeAt(i)) | 0;
    const includeCount = 2 + (Math.abs(h) % 3); // 2, 3, or 4
    const startIdx = Math.abs(h) % optionalIds.length;
    const includeIds = new Set(['standard']);
    for (let i = 0; i < includeCount; i++) {
      includeIds.add(optionalIds[(startIdx + i) % optionalIds.length]);
    }
    const partialSections = (rom9Study.sections || []).filter(s => includeIds.has(s.id));
    const authoredCount = partialSections.length;
    const langLabel = m.lang ? langLabelFor(m.lang) : rom9Study.langLabel;
    return {
      id: 'demo-partial-' + (m.book || 'na') + '-' + (m.chap || ''),
      ref: baseLabel,
      title: baseLabel,
      subtitle: authoredCount + ' of 8 sections authored — analytical apparatus in progress.',
      langLabel: langLabel,
      baseText: rom9Study.baseText,
      modeLabel: '',
      readingTime: '',
      signature: '',
      completedOn: null,
      completedBy: null,
      stats: [
        { n: String(authoredCount), l: 'authored' },
        { n: String(8 - authoredCount), l: 'to commission' },
        { n: '0', l: 'agency seal' },
        { n: authoredCount + '/8', l: 'sections' }
      ],
      traditionClass: rom9Study.traditionClass || 'greek',
      sections: partialSections
    };
  };

  const buildDemoTranslationOnlyStudy = (m) => {
    if (!m) return null;
    const RP = window.ROM8_PRODUCTS || {};
    const readers = RP.readersES || RP.readersEN || null;
    const readerVerses = readers && readers.passage
      ? readers.passage.map(v => ({ n: v.n, t: v.text }))
      : [];
    // Light-blue heat-map cells (state 'c') include BOTH the Reader's
    // translation AND the AI-generated Analytical Draft. Borrow rom-9's
    // retrans section as demo content for the second slot.
    const rom9Retrans = rom9Study && rom9Study.sections
      ? rom9Study.sections.find(s => s.id === 'retrans')
      : null;
    const sections = [];
    if (readerVerses.length > 0) {
      sections.push({
        id: 'standard',
        kind: 'passage-plain',
        heading: 'Translation',
        note: 'Reader’s translation in your language.',
        verses: readerVerses
      });
    }
    if (rom9Retrans) {
      sections.push(Object.assign({}, rom9Retrans, {
        heading: 'Analytical Draft',
        note: 'AI-generated grammar-faithful rendering with bracketed glosses where the Greek is stronger. Awaiting linguist review.'
      }));
    }
    const authoredCount = sections.length;
    const langLabel = m.lang ? langLabelFor(m.lang) : ((readers && readers.lang) || 'Castellano');
    return {
      id: 'demo-translation-' + (m.book || 'na') + '-' + (m.chap || ''),
      ref: m.label || 'Pericope',
      title: m.label || '',
      subtitle: '',
      langLabel: langLabel,
      baseText: '',
      modeLabel: '',
      readingTime: '',
      signature: '',
      completedOn: null,
      completedBy: null,
      stats: [
        { n: String(readerVerses.length || 0), l: readerVerses.length === 1 ? 'verse' : 'verses' },
        { n: String(authoredCount), l: 'sections' },
        { n: '0', l: 'voices' },
        { n: authoredCount + '/8', l: 'sections authored' }
      ],
      traditionClass: 'greek',
      sections: sections
    };
  };

  // Language metadata per coverage-language code.
  //   displayName  — used in copy ("No translation in Catalan yet")
  //   langLabel    — used in study.langLabel; readLabelFor() in StudyView
  //                  uses this string to pick the rail label (BEC / NVI / NIV)
  //   bibleName    — the default Bible edition for that language
  const LANG_META = {
    ca: { displayName: 'Catalan',     bibleName: 'BEC', langLabel: 'Català (BEC)' },
    en: { displayName: 'English',     bibleName: 'NIV', langLabel: 'English (NIV)' },
    es: { displayName: 'Spanish',     bibleName: 'NVI', langLabel: 'Castellano (NVI)' },
    fr: { displayName: 'French',      bibleName: 'NEG', langLabel: 'Français (NEG)' },
    it: { displayName: 'Italian',     bibleName: 'CEI', langLabel: 'Italiano (CEI)' },
    pt: { displayName: 'Portuguese',  bibleName: 'ARA', langLabel: 'Português (ARA)' },
    de: { displayName: 'German',      bibleName: 'LUT', langLabel: 'Deutsch (LUT)' },
    nl: { displayName: 'Dutch',       bibleName: 'HSV', langLabel: 'Nederlands (HSV)' },
    ko: { displayName: 'Korean',      bibleName: 'NKR', langLabel: '한국어 (NKR)' },
    zh: { displayName: 'Chinese',     bibleName: 'CUV', langLabel: '中文 (CUV)' },
    ja: { displayName: 'Japanese',    bibleName: 'JCB', langLabel: '日本語 (JCB)' },
    ar: { displayName: 'Arabic',      bibleName: 'NAV', langLabel: 'العربية (NAV)' },
    he: { displayName: 'Hebrew',      bibleName: 'HMV', langLabel: 'עברית (HMV)' },
    sw: { displayName: 'Swahili',     bibleName: 'SUV', langLabel: 'Kiswahili (SUV)' }
  };
  const langDisplayName = (code) => (LANG_META[code] && LANG_META[code].displayName) || 'your language';
  const langLabelFor    = (code) => (LANG_META[code] && LANG_META[code].langLabel)    || 'Your language';

  const buildDemoNIVStudy = (m) => {
    if (!m) return null;
    const langName = langDisplayName(m.lang);
    return {
      id: 'demo-niv-' + (m.book || 'na') + '-' + (m.chap || ''),
      ref: m.label || 'Pericope',
      title: m.label || '',
      subtitle: '',
      langLabel: 'No translation in ' + langName + ' yet',
      baseText: '',
      modeLabel: '',
      readingTime: '',
      signature: '',
      completedOn: null,
      completedBy: null,
      stats: [
        { n: '0', l: 'Reader’s' },
        { n: '0', l: 'voices' },
        { n: '0', l: 'parallels' },
        { n: '0/8', l: 'sections authored' }
      ],
      traditionClass: 'greek',
      // NIV English fallback — rendered as a panel above the spine in StudyView.
      nivFallback: {
        label: 'Default NIV — no Reader’s commissioned in ' + langName + ' yet',
        verses: DEMO_NIV_VERSES,
        ctaLabel: 'Commission a Reader’s translation in ' + langName + ' →'
      },
      sections: []
    };
  };

  // Demo state for the current pericope. Maps the heat-map's 4-state legend
  // ('empty' / 'c' / 'b' / 'sealed') to four authoring depths. Resolution:
  //   1. Explicit demoState wins (chevron sequence)
  //   2. Map heat-map state:
  //        'sealed' (agency-reviewed)   → 'full'      (all 8 sections)
  //        'b'      (analytical, no seal)→ 'partial'  (translation + 2-4 sections)
  //        'c'      (translation only)   → 'translation-only'
  //        'empty'  (no work)            → 'niv-only' (NIV English fallback)
  //   3. Hash spread for any unrecognized click
  const getDemoState = (m) => {
    if (!m) return null;
    if (m.demoState) return m.demoState;
    if (m.state === 'sealed') return 'full';
    if (m.state === 'b')      return 'partial';
    if (m.state === 'c')      return 'translation-only';
    if (m.state === 'empty')  return 'niv-only';
    const hashSrc = (m.book || '') + (m.chap || 0);
    let h = 0;
    for (let i = 0; i < hashSrc.length; i++) h = (h * 31 + hashSrc.charCodeAt(i)) | 0;
    const states = ['full', 'partial', 'translation-only', 'niv-only'];
    return states[Math.abs(h) % 4];
  };

  // The single study object the drawer renders.
  let studyToShow = activeStudy
    || (matchingStudies.length === 1 ? matchingStudies[0] : null);

  if (!studyToShow && pericopeMeta) {
    const state = getDemoState(pericopeMeta);
    if (state === 'full')                      studyToShow = buildDemoFullStudy(pericopeMeta);
    else if (state === 'partial')              studyToShow = buildDemoPartialStudy(pericopeMeta);
    else if (state === 'translation-only')     studyToShow = buildDemoTranslationOnlyStudy(pericopeMeta);
    else if (state === 'niv-only')             studyToShow = buildDemoNIVStudy(pericopeMeta);
    else                                       studyToShow = buildDemoTranslationOnlyStudy(pericopeMeta);
  }

  // audit rank 5: make the study drawer a real dialog — Escape closes, Tab is
  // trapped inside the open drawer, focus moves in on open and returns to the
  // opener on close (keyboard users could previously Tab into the page behind
  // the backdrop).
  const openerRef = React.useRef(null);
  React.useEffect(() => {
    if (!open) {
      if (openerRef.current && openerRef.current.focus) { openerRef.current.focus(); openerRef.current = null; }
      return;
    }
    const focusables = () => {
      const d = document.querySelector('.amos-drawer.open');
      if (!d) return [];
      return Array.prototype.slice.call(
        d.querySelectorAll('a[href],button:not([disabled]),input:not([disabled]),select,textarea,[tabindex]:not([tabindex="-1"])')
      ).filter(el => el.offsetParent !== null);
    };
    const onKey = (e) => {
      if (e.key === 'Escape') { onClose(); return; }
      if (e.key === 'Tab') {
        const f = focusables(); if (!f.length) return;
        const first = f[0], last = f[f.length - 1];
        if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }
        else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }
      }
    };
    window.addEventListener('keydown', onKey, true);
    const t = setTimeout(() => { const f = focusables(); if (f[0] && f[0].focus) f[0].focus(); }, 60);
    return () => { window.removeEventListener('keydown', onKey, true); clearTimeout(t); };
  }, [open, onClose]);

  // Capture the opener while it still has focus (during the open render, before
  // the drawer moves focus inside), so focus returns there on close. — rank 5
  if (open && !openerRef.current) openerRef.current = document.activeElement;

  const meta = pericopeMeta || { label: 'Romans 8:28–30', hasLumo: false };
  const R = window.ROM8_PRODUCTS || {};

  // Greek verses (for Toggle/Parallel/Interlinear under Reader's)
  const verses = {
    GRC: [
      { n:28, words:[
        {t:'οἴδαμεν', lemma:'οἶδα', m:['V','PAI','1P'], g:'we know'},
        {t:'δὲ'},{t:'ὅτι'},{t:'τοῖς'},
        {t:'ἀγαπῶσιν', lemma:'ἀγαπάω', m:['V','PAP','DPM'], g:'to those loving'},
        {t:'τὸν'},{t:'θεὸν', lemma:'θεός', m:['N','ASM'], g:'God'},
        {t:'πάντα', lemma:'πᾶς', m:['A','NPN'], g:'all things'},
        {t:'συνεργεῖ', lemma:'συνεργέω', m:['V','PAI','3S'], g:'works together', hot:true},
        {t:'εἰς'},{t:'ἀγαθόν,', lemma:'ἀγαθός', m:['A','ASN'], g:'good'},
        {t:'τοῖς'},{t:'κατὰ'},{t:'πρόθεσιν', lemma:'πρόθεσις', m:['N','ASF'], g:'purpose, set-intention', hot:true},
        {t:'κλητοῖς', lemma:'κλητός', m:['A','DPM'], g:'called (ones)'},
        {t:'οὖσιν.'}
      ]},
      { n:29, words:[
        {t:'ὅτι'},{t:'οὓς'},
        {t:'προέγνω,', lemma:'προγινώσκω', m:['V','AAI','3S'], g:'foreknew', hot:true},
        {t:'καὶ'},
        {t:'προώρισεν', lemma:'προορίζω', m:['V','AAI','3S'], g:'predestined', hot:true},
        {t:'συμμόρφους', lemma:'σύμμορφος', m:['A','APM'], g:'conformed (to)'},
        {t:'τῆς'},{t:'εἰκόνος', lemma:'εἰκών', m:['N','GSF'], g:'image'},
        {t:'τοῦ'},{t:'υἱοῦ'},{t:'αὐτοῦ,'},
        {t:'εἰς'},{t:'τὸ'},{t:'εἶναι'},{t:'αὐτὸν'},
        {t:'πρωτότοκον', lemma:'πρωτότοκος', m:['A','ASM'], g:'firstborn'},
        {t:'ἐν'},{t:'πολλοῖς'},{t:'ἀδελφοῖς·'}
      ]},
      { n:30, words:[
        {t:'οὓς'},{t:'δὲ'},{t:'προώρισεν,'},{t:'τούτους'},{t:'καὶ'},
        {t:'ἐκάλεσεν·'},{t:'καὶ'},{t:'οὓς'},{t:'ἐκάλεσεν,'},{t:'τούτους'},{t:'καὶ'},
        {t:'ἐδικαίωσεν·'},{t:'οὓς'},{t:'δὲ'},{t:'ἐδικαίωσεν,'},{t:'τούτους'},{t:'καὶ'},
        {t:'ἐδόξασεν.'}
      ]}
    ],
    EN: [
      { n:28, text:'And we know that ', em:'for those who love God all things work together unto good', tail:', for those who are called according to his purpose.' },
      { n:29, text:'Because those he ', em:'foreknew', tail:', he also ', em2:'foreordained', tail2:' to be conformed to the image of his Son, so that he might be the firstborn among many brothers.' },
      { n:30, text:'And those he foreordained, these he also called; and those he called, these he also justified; and those he justified, these he also glorified.' }
    ]
  };

  const showPop = (w, ev) => {
    if (!w.lemma) return;
    const r = ev.currentTarget.getBoundingClientRect();
    setPop({ w, x: Math.min(r.left, window.innerWidth-360), y: r.bottom + 8 });
  };

  const witnesses = [
    { name:'TAGNT',   lang:'GRC', seals:[] },
    { name:'THGNT',   lang:'GRC', seals:['ubs'] },
    { name:'SBLGNT',  lang:'GRC', seals:[] },
    { name:'Vulgate', lang:'LAT', seals:[] },
    { name:'Peshitta',lang:'SYR', seals:[] },
    { name:'ESV',     lang:'EN',  seals:['bib'] },
    { name:'RV1960',  lang:'ES',  seals:['abs'] },
    { name:'BCI',     lang:'CA',  seals:['bec'] },
  ];

  // ── availability gated by coverage state ──
  //   'sealed' → C, B, D + Reviewed
  //   'b'      → C, B
  //   'c'      → C only
  const state = (meta && meta.state) || 'sealed';
  const avail = {
    C: true,
    B: state === 'sealed' || state === 'b',
    D: state === 'sealed',
    reviewed: state === 'sealed',
  };

  // If the selected product is no longer available (user came in with an
  // initialProduct that doesn't exist for this pericope), clamp to C.
  React.useEffect(() => {
    if (!open) return;
    if (product === 'B' && !avail.B) setProduct('C');
    if (product === 'D' && !avail.D) setProduct('C');
    if (reviewed && !avail.reviewed) setReviewed(false);
  }, [open, state]);

  // ── reviewed badge (replaces the old product/A-toggle rail at the top of the Read tab).
  // Regular readers don't think in B/C/D products — they think "read" or "study deeper".
  // The Read tab now just shows Reader's; switching to the Analytical product happens
  // by clicking the "Study" tab. The Linguist Reviewed state shows here as a passive
  // trust badge — clickable to toggle if available, or to request a review if not.
  const productRail = React.createElement('div', { className:'reviewed-badge-row' },
    React.createElement('button', {
      className: 'review-toggle compact ' + (reviewed ? 'on' : '') + (avail.reviewed ? '' : ' is-unavailable'),
      disabled: !avail.reviewed,
      onClick: () => avail.reviewed ? setReviewed(r => !r) : setCommissionTarget({ kind:'review', pericope: pericopeMeta && pericopeMeta.label }),
      title: avail.reviewed ? (reviewed ? 'Reviewed by linguist' : 'Toggle the Linguist Reviewed overlay') : 'Not yet reviewed — click to request a linguist review'
    },
      React.createElement('span', { className:'rt-box' }, reviewed ? '✓' : ''),
      React.createElement('span', { className:'rt-label' },
        avail.reviewed ? (reviewed ? 'Reviewed by linguist' : 'Show linguist review') : 'Request linguist review'
      )
    )
  );

  // ── review header strip (shown above passage when `reviewed` is on)
  const reviewStrip = reviewed && R.reviewedOverlay
    ? React.createElement('div', { className:'review-strip' },
        React.createElement('div', { className:'rs-top' },
          React.createElement('span', { className:'rs-check' }, '✓'),
          React.createElement('span', { className:'rs-label' }, 'Revisada por lingüista'),
          React.createElement('span', { className:'rs-dot' }, '·'),
          React.createElement('span', { className:'rs-name' }, R.reviewedOverlay.reviewer.name),
          React.createElement('span', { className:'rs-dot' }, '·'),
          React.createElement('em', { className:'rs-aff' }, R.reviewedOverlay.reviewer.affiliation),
          React.createElement('span', { className:'rs-dot' }, '·'),
          React.createElement('span', { className:'rs-date' }, R.reviewedOverlay.reviewer.date)
        ),
        React.createElement('div', { className:'rs-scope' },
          'Scope: ' + R.reviewedOverlay.reviewer.scope + '. Observaciones del revisor abajo.'
        )
      )
    : null;

  // ── observaciones block (below passage when reviewed)
  const observacionesBlock = reviewed && R.reviewedOverlay
    ? React.createElement('div', { className:'obs-block' },
        React.createElement('h6', null, R.reviewedOverlay.observacionesH),
        R.reviewedOverlay.observaciones.map((o, i) =>
          React.createElement('p', { key: i }, o)
        )
      )
    : null;

  // ── action-row builder
  const ActionRow = (props) => React.createElement('div', { className:'action-row' },
    React.createElement('button', { className:'ar-primary', onClick: props.primaryOnClick }, props.primary, ' ', window.I.arrowRight(13)),
    React.createElement('div', { className:'ar-secondary' },
      (props.secondary || []).map((s, i) => React.createElement('button', { key: i, className:'ar-sec-btn', onClick: s.onClick }, s.label))
    ),
    React.createElement('div', { className:'ar-utils' },
      React.createElement('button', { className:'ar-util', title:'Download as PDF' }, window.I.download ? window.I.download(14) : '↓'),
      React.createElement('button', { className:'ar-util', title:'Share' }, window.I.share ? window.I.share(14) : '↗'),
      React.createElement('button', { className:'ar-util', title:'Bookmark' }, window.I.bookmark(14))
    )
  );

  // ─────────────────────────────────────────────────────────
  // PRODUCT · C · Reader's · Castellano
  // ─────────────────────────────────────────────────────────
  const renderReadersC = () => {
    const d = R.readersES;
    if (!d) return null;
    return React.createElement(React.Fragment, null,
      reviewStrip,
      React.createElement('div', { className:'prod-header' },
        React.createElement('div', { className:'prod-header-left' },
          React.createElement('span', { className:'prod-header-letter' }, 'C'),
          React.createElement('div', null,
            React.createElement('div', { className:'prod-header-name' }, "Reader's"),
            React.createElement('div', { className:'prod-header-lang' }, d.lang)
          )
        ),
        React.createElement('div', { className:'prod-header-meta' }, d.baseLabel)
      ),
      React.createElement('div', { className:'reader-view-sw compact' },
        // Simplified view modes: regular readers want "with notes" or "plain".
        // Parallel and Interlinear are kept in the code but live behind a "more views" toggle.
        ['layered','toggle'].map(v =>
          React.createElement('button', { key:v, className:view===v?'on':'', onClick:()=>setView(v) },
            ({layered:'With notes', toggle:'Plain'})[v]
          )
        ),
        React.createElement('button', {
          className:'view-more-toggle',
          title:'More views (Parallel, Interlinear)',
          onClick:()=>{
            // Cycle: layered -> toggle -> parallel -> interlinear -> layered
            const order = ['layered','toggle','parallel','interlinear'];
            const cur = order.indexOf(view);
            setView(order[(cur+1) % order.length]);
          }
        }, '⋯')
      ),
      view==='toggle' && React.createElement('div', { className:'reader-passage readers-passage' },
        d.passage.map(v => React.createElement('div', { key:v.n, className:'verse' },
          React.createElement('span', { className:'v-num' }, v.n),
          v.text
        ))
      ),
      view==='parallel' && React.createElement('div', { className:'reader-parallel' },
        React.createElement('div', null,
          React.createElement('h5', null, "READER'S · CASTELLANO"),
          React.createElement('div', { className:'reader-passage' },
            d.passage.map(v => React.createElement('div', { key:v.n, className:'verse' },
              React.createElement('span', { className:'v-num' }, v.n), v.text
            ))
          )
        ),
        React.createElement('div', null,
          React.createElement('h5', null, 'GREEK · TAGNT'),
          React.createElement('div', { className:'reader-passage' },
            verses.GRC.map(v => React.createElement('div', { key:v.n, className:'verse' },
              React.createElement('span', { className:'v-num' }, v.n),
              v.words.map(w=>w.t).join(' ')
            ))
          )
        )
      ),
      view==='interlinear' && React.createElement('div', null,
        verses.GRC.map(v => React.createElement('div', { key:v.n, style:{marginBottom:8} },
          React.createElement('div', { className:'reader-ref', style:{marginBottom:4} }, 'verse ' + v.n),
          React.createElement('div', { className:'reader-interlinear' },
            v.words.filter(w=>w.lemma).map((w,i) => React.createElement('div', { key:i, className:'ili' },
              React.createElement('div', { className:'gk' }, w.t),
              React.createElement('div', { className:'morph' }, (w.m||[]).join(' · ')),
              React.createElement('div', { className:'gloss' }, w.g)
            ))
          )
        ))
      ),
      view==='layered' && React.createElement('div', null,
        React.createElement('div', { className:'reader-passage', style:{marginBottom:18} },
          d.passage.map(v => React.createElement('div', { key:v.n, className:'verse' },
            React.createElement('span', { className:'v-num' }, v.n), v.text
          ))
        ),
        React.createElement('div', { className:'apparatus-box' },
          React.createElement('div', { className:'apparatus-layer' },
            React.createElement('h6', null, 'Donde el griego es más fuerte'),
            React.createElement('p', null, 'συνεργεῖ es activo, 3sg — "cooperan." La voz activa sostiene una agencia más directa. Para la versión con soporte gramatical completo, consulte la Analítica catalana.')
          )
        )
      ),
      observacionesBlock,
      React.createElement('details', { className:'prod-notes', open:false },
        React.createElement('summary', null, d.notesHeader),
        d.notes.map((n,i) => React.createElement('p', { key:i }, n))
      ),
      React.createElement(ActionRow, {
        primary: 'Open Analytical (Català)',
        secondary: [
          { label: 'Commission in another language', onClick: () => setCommissionTarget({ kind:'ai', pericope: pericopeMeta && pericopeMeta.label, mode: 'C', lang: 'en' }) },
          { label: reviewed ? 'Request a second opinion' : 'Request Linguist Review',
            onClick: () => setCommissionTarget({ kind:'review', pericope: pericopeMeta && pericopeMeta.label }) },
        ]
      })
    );
  };

  // ─────────────────────────────────────────────────────────
  // PRODUCT · B · Analytical · Català
  // ─────────────────────────────────────────────────────────
  const renderAnalyticalB = () => {
    const d = R.analyticalCA;
    if (!d) return null;
    return React.createElement(React.Fragment, null,
      reviewStrip,
      React.createElement('div', { className:'prod-header' },
        React.createElement('div', { className:'prod-header-left' },
          React.createElement('span', { className:'prod-header-letter' }, 'B'),
          React.createElement('div', null,
            React.createElement('div', { className:'prod-header-name' }, 'Analytical'),
            React.createElement('div', { className:'prod-header-lang' }, d.lang)
          )
        ),
        React.createElement('div', { className:'prod-header-meta' }, d.baseLabel)
      ),
      React.createElement('div', { className:'reader-passage analytical-passage' },
        d.verses.map(v => React.createElement('div', { key:v.n, className:'verse' },
          React.createElement('span', { className:'v-num' }, v.n),
          v.tokens.map((tok, i) => {
            if (tok.t) return React.createElement('span', { key:i }, tok.t);
            if (tok.gloss) return React.createElement('span', { key:i, className:'gloss-bracket' }, tok.gloss);
            if (tok.hot) return React.createElement('span', {
              key: i,
              className: 'w hot',
              onClick: (e) => {
                e.stopPropagation();
                showPop({ t: tok.lemma, lemma: tok.lemma, m: (tok.morph||'').split(/\s+/), g: tok.note }, e);
              }
            }, tok.hot);
            return null;
          })
        ))
      ),
      React.createElement('div', { className:'obs-block' },
        React.createElement('h6', null, d.observacionsH),
        d.observacions.map((o,i) => React.createElement('p', { key:i }, React.createElement('em', null, o)))
      ),
      observacionesBlock,
      React.createElement(ActionRow, {
        primary: 'Activate Annotated',
        secondary: [
          { label: "Commission Reader's in another language", onClick: () => setCommissionTarget({ kind:'ai', pericope: pericopeMeta && pericopeMeta.label, mode: 'C', lang: 'en' }) },
          { label: reviewed ? 'Request a second opinion' : 'Request Linguist Review',
            onClick: () => setCommissionTarget({ kind:'review', pericope: pericopeMeta && pericopeMeta.label }) },
          { label: 'Compare against Augustine / Calvin' },
        ]
      })
    );
  };

  // ─────────────────────────────────────────────────────────
  // PRODUCT · D · Annotated · Català
  // ─────────────────────────────────────────────────────────
  const renderAnnotatedD = () => {
    const d = R.annotatedCA;
    if (!d) return null;
    const a = d.analytical;
    const toggle = (k) => setActiveLayers(L => ({ ...L, [k]: !L[k] }));
    return React.createElement(React.Fragment, null,
      reviewStrip,
      React.createElement('div', { className:'prod-header' },
        React.createElement('div', { className:'prod-header-left' },
          React.createElement('span', { className:'prod-header-letter' }, 'D'),
          React.createElement('div', null,
            React.createElement('div', { className:'prod-header-name' }, 'Annotated'),
            React.createElement('div', { className:'prod-header-lang' }, d.lang)
          )
        ),
        React.createElement('div', { className:'prod-header-meta' }, d.baseLabel)
      ),
      // Analytical passage (same rendering)
      React.createElement('div', { className:'reader-passage analytical-passage' },
        a.verses.map(v => React.createElement('div', { key:v.n, className:'verse' },
          React.createElement('span', { className:'v-num' }, v.n),
          v.tokens.map((tok, i) => {
            if (tok.t) return React.createElement('span', { key:i }, tok.t);
            if (tok.gloss) return React.createElement('span', { key:i, className:'gloss-bracket' }, tok.gloss);
            if (tok.hot) return React.createElement('span', {
              key: i, className: 'w hot',
              onClick: (e) => { e.stopPropagation();
                showPop({ t: tok.lemma, lemma: tok.lemma, m: (tok.morph||'').split(/\s+/), g: tok.note }, e);
              }
            }, tok.hot);
            return null;
          })
        ))
      ),
      // Layer toggle strip
      React.createElement('div', { className:'layer-strip' },
        d.layers.map(L => React.createElement('button', {
          key: L.key,
          className: 'layer-chip ' + (activeLayers[L.key] ? 'on' : ''),
          onClick: () => toggle(L.key)
        },
          React.createElement('span', { className:'lc-tick' }, activeLayers[L.key] ? '●' : '○'),
          React.createElement('span', { className:'lc-title' }, L.title),
          React.createElement('span', { className:'lc-count' }, L.count)
        ))
      ),
      // Active layer content
      React.createElement('div', { className:'layers-body' },
        d.layers.filter(L => activeLayers[L.key]).map(L =>
          React.createElement('div', { key: L.key, className:'layer-block layer-' + L.key },
            React.createElement('div', { className:'layer-block-head' },
              React.createElement('span', { className:'lb-dot' }),
              React.createElement('span', { className:'lb-title' }, L.title),
              React.createElement('span', { className:'lb-sub' }, L.count + ' notes')
            ),
            L.notes.map((n, i) => React.createElement('div', { key: i, className:'layer-note' },
              React.createElement('div', { className:'ln-anchor' }, n.anchor),
              React.createElement('div', { className:'ln-body' }, n.body)
            ))
          )
        )
      ),
      observacionesBlock,
      React.createElement(ActionRow, {
        primary: 'Request Linguist Review of this apparatus',
        primaryOnClick: () => setCommissionTarget({ kind:'review', pericope: pericopeMeta && pericopeMeta.label }),
        secondary: [
          { label: 'Open in Analytical studies view' },
          { label: 'Export pericope with full apparatus' },
        ]
      })
    );
  };

  const readView =
    product === 'B' ? renderAnalyticalB() :
    product === 'D' ? renderAnnotatedD() :
                      renderReadersC();

  // ── prev/next pericope navigation ────────────────────────
  // Demo sequence cycles through the three demo states so prev/next shows
  // the full range of authoring depths. Each entry tags itself with a
  // demoState that the drawer's studyToShow logic honors.
  const DEMO_SEQUENCE = [
    { book:'rom',     chap:9,  v1:1,  v2:33,  studyId:'rom-9',     demoState:'full' },             // real authored
    { book:'rom',     chap:8,  v1:28, v2:30,                       demoState:'translation-only' }, // BEC/NVI Read only
    { book:'rom',     chap:10, v1:1,  v2:21,                       demoState:'partial' },          // analytical apparatus, some sections authored
    { book:'rom',     chap:11, v1:1,  v2:32,                       demoState:'niv-only' },         // NIV fallback
    { book:'gal',     chap:3,  v1:10, v2:14,                       demoState:'full' },             // full demo (cloned from rom-9)
    { book:'gal',     chap:4,  v1:1,  v2:7,                        demoState:'partial' },
    { book:'zec',     chap:14, v1:16, v2:19,                       demoState:'translation-only' },
    { book:'didache', chap:1,  v1:1,  v2:2,                        demoState:'niv-only' },
  ];
  const currentIdx = pericopeMeta
    ? DEMO_SEQUENCE.findIndex(p =>
        p.book === pericopeMeta.book &&
        p.chap === pericopeMeta.chap &&
        (pericopeMeta.v1 == null || p.v1 === pericopeMeta.v1)
      )
    : -1;
  const prevPericope = currentIdx > 0 ? DEMO_SEQUENCE[currentIdx - 1]
    : currentIdx === 0 ? DEMO_SEQUENCE[DEMO_SEQUENCE.length - 1]
    : null;
  const nextPericope = currentIdx >= 0 && currentIdx < DEMO_SEQUENCE.length - 1
    ? DEMO_SEQUENCE[currentIdx + 1]
    : currentIdx === DEMO_SEQUENCE.length - 1 ? DEMO_SEQUENCE[0]
    : null;
  const navHandler = (target) => () => {
    if (!target) return;
    if (onNavigatePericope) onNavigatePericope(target);
  };

  // Floating prev/next chevrons positioned at the inner edges of the drawer.
  const navChevrons = open && pericopeMeta && currentIdx >= 0 && [
    React.createElement('button', {
      key: 'prev-pericope',
      className: 'pericope-nav-chevron prev',
      onClick: navHandler(prevPericope),
      disabled: !prevPericope,
      title: 'Previous pericope',
      style: {
        position: 'absolute', left: 6, top: '50%', transform: 'translateY(-50%)',
        zIndex: 50, width: 36, height: 56, borderRadius: 6,
        background: 'rgba(255,255,255,.92)', border: '1px solid rgba(6,42,48,.15)',
        cursor: prevPericope ? 'pointer' : 'not-allowed',
        opacity: prevPericope ? 1 : 0.35,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        boxShadow: '0 2px 8px -3px rgba(6,42,48,.18)',
        font: '600 22px/1 system-ui', color: 'var(--tan-cyan-700, #062A30)'
      }
    }, '‹'),
    React.createElement('button', {
      key: 'next-pericope',
      className: 'pericope-nav-chevron next',
      onClick: navHandler(nextPericope),
      disabled: !nextPericope,
      title: 'Next pericope',
      style: {
        position: 'absolute', right: 6, top: '50%', transform: 'translateY(-50%)',
        zIndex: 50, width: 36, height: 56, borderRadius: 6,
        background: 'rgba(255,255,255,.92)', border: '1px solid rgba(6,42,48,.15)',
        cursor: nextPericope ? 'pointer' : 'not-allowed',
        opacity: nextPericope ? 1 : 0.35,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        boxShadow: '0 2px 8px -3px rgba(6,42,48,.18)',
        font: '600 22px/1 system-ui', color: 'var(--tan-cyan-700, #062A30)'
      }
    }, '›')
  ];

  // ── Unified render ──────────────────────────────────────────
  // The drawer always shows the StudyView with the canonical 8-section
  // spine. Authored sections render in full; unauthored ones gray out in
  // the menu and show a Commission card in the body. The old Read/Study
  // tab split is gone — every pericope opens the same shape.
  if (open && studyToShow) {
    return React.createElement(React.Fragment, null,
      React.createElement('div', { className:'amos-drawer-backdrop '+(open?'open':''), onClick: onClose }),
      React.createElement('aside', { className:'amos-drawer '+(open?'open':'')+' study-open',
        role:'dialog', 'aria-modal':'true', 'aria-label':'Analytical study' },
        navChevrons,
        // Floating close button — color-keyed to the heat-map cell of the
        // current pericope so the user has a consistent visual signal of
        // "what authoring depth this passage has":
        //   empty   → light gray
        //   c       → light teal
        //   b       → mid teal
        //   sealed  → deep teal (close glyph turns white)
        (() => {
          const stateColor = (() => {
            const s = pericopeMeta && pericopeMeta.state;
            if (s === 'sealed') return { bg: '#0a3f48', border: '#0a3f48',          fg: '#ffffff' };
            if (s === 'b')      return { bg: '#26828f', border: '#26828f',          fg: '#ffffff' };
            if (s === 'c')      return { bg: '#bfe2e8', border: 'rgba(38,130,143,.4)', fg: '#0a3f48' };
            if (s === 'empty')  return { bg: '#e7eaeb', border: 'rgba(6,31,39,.18)',   fg: 'rgba(6,31,39,.55)' };
            // Fallback (no state info) — neutral white chip
            return { bg: 'var(--tan-bg)', border: 'var(--tan-border-2)', fg: 'inherit' };
          })();
          return React.createElement('button', {
            className: 'amos-icon-btn drawer-close-state',
            onClick: onClose,
            title: 'Close',
            style: {
              position: 'absolute', top: 14, right: 14, zIndex: 60,
              width: 32, height: 32, borderRadius: 6,
              background: stateColor.bg,
              border: '1px solid ' + stateColor.border,
              color: stateColor.fg,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              cursor: 'pointer',
              boxShadow: '0 1px 3px rgba(6,31,39,.12)'
            }
          }, window.I.x(16));
        })(),
        // Real analyses from the vault for this pericope's chapter (only renders
        // when the local review API is alive and has matches).
        window.VaultAnalysesStrip && pericopeMeta && React.createElement('div', {
          style: { padding: '14px 18px 0' }
        },
          React.createElement(window.VaultAnalysesStrip, {
            book: pericopeMeta.book,
            chapter: pericopeMeta.chap,
            onOpenVaultStudy
          })
        ),
        React.createElement(window.StudyView, {
          study: studyToShow,
          // No back button — there's no separate document layer to go back to.
          onBack: null,
          onCommissionSection: (info) => setCommissionTarget({
            kind: 'ai',
            pericope: pericopeMeta && pericopeMeta.label,
            section: info.label,
            mode: 'B',
            lang: 'ca'
          }),
          onCommissionAll: (info) => setCommissionTarget({
            kind: 'ai',
            pericope: pericopeMeta && pericopeMeta.label,
            section: 'all remaining sections (' + info.missing.length + ')',
            mode: 'B',
            lang: 'ca'
          })
        })
      ),
      commissionTarget && window.PericopeCommissionModal && React.createElement(window.PericopeCommissionModal, {
        target: commissionTarget,
        onClose: () => setCommissionTarget(null),
        onSubmit: () => setCommissionTarget(null)
      })
    );
  }

  // Legacy render path — kept for now but unreachable while open && studyToShow
  // are both truthy (which is the steady state). If a future pericope arrives
  // with no Reader's data, this fallback still renders the old tab UI.
  return React.createElement(React.Fragment, null,
    React.createElement('div', { className:'amos-drawer-backdrop '+(open?'open':''), onClick: onClose }),
    React.createElement('aside', { className:'amos-drawer '+(open?'open':'')+(activeStudy?' study-open':''),
      role:'dialog', 'aria-modal':'true', 'aria-label': (meta && meta.label) ? ('Reader · ' + meta.label) : 'Reader' },
      navChevrons,
      activeStudy
        ? React.createElement(window.StudyView, {
            study: activeStudy,
            onBack: () => setActiveStudyId(null)
          })
        : React.createElement(React.Fragment, null,
      React.createElement('div', { className:'amos-drawer-head' },
        React.createElement('div', null,
          React.createElement('div', { className:'amos-drawer-eyebrow' }, 'Paul · Epistle to the Romans · ' + meta.label),
          React.createElement('div', { className:'amos-drawer-title' }, meta.label,
            React.createElement('em', null, '  · election · hardening · divine co-working'))
        ),
        React.createElement('div', { className:'amos-drawer-actions' },
          React.createElement(window.CiteButton, { compact:true, refFor: () => ({
            kind:'study',
            title:'Paul · Romans · ' + (meta.label || ''),
            subtitle:'Pericope deep study',
            edition:'Amos Project Analytical Studies',
            editor:'World Mission Media',
            year:2026,
            url:'https://worldmission.media/study/' + (meta.label || '').toLowerCase().replace(/\W+/g,'-'),
            description:'Analytical commentary: election · hardening · divine co-working.',
            collectionKey:'greek'
          }) }),
          React.createElement(window.ShareButton, { compact:true, refFor: () => ({
            kind:'study',
            title:'Romans ' + (meta.label || ''),
            subtitle:'Deep study on The Amos Project',
            edition:'Amos Project Analytical Studies',
            editor:'World Mission Media',
            year:2026,
            url:'https://worldmission.media/study/' + (meta.label || '').toLowerCase().replace(/\W+/g,'-'),
            collectionKey:'greek'
          }) }),
          React.createElement('button', { className:'amos-icon-btn' }, window.I.bookmark(16)),
          React.createElement('button', { className:'amos-icon-btn' }, window.I.sparkle(16)),
          React.createElement('button', { className:'amos-icon-btn', onClick:onClose }, window.I.x(16))
        )
      ),
      React.createElement('div', { className:'amos-drawer-modes' },
        // Simplified tab row: Read / Study. Translations, Study tools, and
        // Apparatus are still in the codebase; they migrate to a "Source" /
        // expert-mode surface later. Most readers want two doors, not five.
        ['read','studies'].map(k =>
          React.createElement('div', { key:k, className:'amos-drawer-mode '+(mode===k?'on':''), onClick:()=>setMode(k) },
            ({read:'Read', studies:'Study'})[k],
            // Badge shows the count of studies matching THIS pericope, not the
            // global total. Hide entirely when there are zero — empty state
            // does the talking inside the tab.
            k==='studies' && matchingStudies.length > 0 && React.createElement('span', { className:'mode-count' }, matchingStudies.length)
          )
        )
      ),
      React.createElement('div', { className:'amos-drawer-body', onClick:()=>setPop(null) },
        mode==='read' && React.createElement(React.Fragment, null,
          React.createElement(window.ReferenceMediaStrip, {
            hasLumo: meta.hasLumo,
            pericopeLabel: meta.label,
            lang: meta.displayLang || 'English'
          }),
          productRail,
          readView
        ),
        mode==='translations' && React.createElement('div', null,
          React.createElement('h5', { style:{font:'600 10.5px Figtree',letterSpacing:'.14em',textTransform:'uppercase',color:'rgba(6,31,39,.5)',margin:'0 0 14px'} }, 'Witnesses open for ' + meta.label),
          witnesses.map(w =>
            React.createElement('div', { key: w.name, className:'citation', style:{cursor:'pointer'} },
              React.createElement('div', { className:'by' },
                w.name + ' (' + w.lang + ')',
                w.seals.length > 0 && React.createElement('span', { className: 'reader-witness-seals' },
                  w.seals.map(s => React.createElement(window.SealBadge, { key: s, code: s, sm: true }))
                )
              ),
              React.createElement('div', { className:'quote' }, 'opens parallel pane →')
            )
          )
        ),
        mode==='tools' && React.createElement('div', null,
          React.createElement('div', { className:'tools-section' },
            React.createElement('h5', null, window.I.cite(14), 'Patristic citations of v. 28', React.createElement('span', { className:'count' }, '7')),
            [
              { by:'Irenaeus', date:'c. 180', ref:'Adv. Haer. IV.37.4', q:'He calls those who love him according to his foreknowledge…' },
              { by:'Origen', date:'c. 246', ref:'Comm. Rom. VII.7', q:'Non enim omnibus cooperatur, sed iis tantum qui diligunt Deum…' },
              { by:'Clement', date:'c. 198', ref:'Strom. IV.14', q:'γινώσκει γὰρ ὁ θεὸς τοὺς ἰδίους πρὸ καταβολῆς κόσμου…' },
              { by:'Tertullian', date:'c. 207', ref:'Adv. Marc. V.14', q:'omnia in bonum cooperari diligentibus Deum…' },
            ].map((c,i)=>React.createElement('div', { key:i, className:'citation' },
              React.createElement('div', { className:'by' }, c.by, React.createElement('span', { className:'date' }, c.date)),
              React.createElement('div', { className:'ref' }, c.ref),
              React.createElement('div', { className:'quote' }, c.q)
            ))
          )
        ),
        mode==='apparatus' && React.createElement('div', { className:'apparatus-box' },
          ['Pericope identification','Base text & witness','Word-by-word analysis','Four-layer apparatus','Where the Greek is stronger','Retranslation'].map((h,i)=>
            React.createElement('div', { key:i, className:'apparatus-layer' },
              React.createElement('h6', null, h),
              React.createElement('p', null,
                i===0 && 'Romans 8:28–30 · Paul\u2019s chain of divine agency. Sits within 8:18–39 (suffering → glory). Pericope boundary confirmed by T4T, GNT, and patristic grouping.',
                i===1 && 'Base: TAGNT with morphological markup. Witnesses: ℵ A B C D, 𝔓⁴⁶, Vulgate, Peshitta. Variant at 28 (addition of ὁ θεός) is external but likely scribal clarification.',
                i===2 && 'συνεργέω (28) — present active indicative 3sg. Subject ambiguous: θεός (𝔓⁴⁶) or πάντα (ℵ A B). Middle-voice force of the cognate family. προέγνω (29) — aorist active, no cognitive gloss in patristic reception.',
                i===3 && 'Lexical · Syntactic · Rhetorical · Reception. Each layer resolved against the library. Reception: 7 pre-Nicene fathers cite v. 28 with explicit "God" reading.',
                i===4 && 'English "work together for good" loses the active, intentional cooperation encoded in συνεργεῖ. Spanish RV "ayudan a bien" weakens further.',
                i===5 && '“And we know that God actively co-works all things into good for those who love him, those called according to his set-intention…”'
              )
            )
          )
        ),
        mode==='studies' && matchingStudies.length === 0 && React.createElement('div', { className:'studies-picker' },
          React.createElement('h5', { className:'sp-kicker' }, 'No deep study yet'),
          React.createElement('p', { className:'sp-intro' },
            'A deep study for this pericope hasn’t been authored yet. Want to commission one? An analytical study covers translation, what the early church taught, library connections, structure, the Greek up close, and where later traditions diverged.'
          ),
          React.createElement('div', { style: { display: 'flex', gap: 12, marginTop: 16 } },
            React.createElement('button', {
              className: 'btn btn-primary',
              onClick: () => setCommissionTarget({ kind:'ai', pericope: pericopeMeta && pericopeMeta.label, mode: 'B', lang: 'ca' })
            }, 'Commission a deep study')
          )
        ),
        mode==='studies' && matchingStudies.length > 1 && React.createElement('div', { className:'studies-picker' },
          React.createElement('h5', { className:'sp-kicker' }, 'Deep studies for this pericope'),
          React.createElement('p', { className:'sp-intro' },
            'More than one study is available for this passage. Pick one to enter the study view.'
          ),
          React.createElement('div', { className:'sp-grid' },
            matchingStudies.map(s =>
              React.createElement('article', {
                key: s.id,
                className: 'sp-card tradition-' + s.traditionClass,
                onClick: () => setActiveStudyId(s.id)
              },
                React.createElement('div', { className:'spc-top' },
                  React.createElement('span', { className:'spc-badge' }, 'Deep study'),
                  React.createElement('span', { className:'spc-lang' }, s.langLabel),
                  React.createElement('span', { className:'spc-time' }, s.readingTime)
                ),
                React.createElement('h3', { className:'spc-ref' }, s.ref),
                React.createElement('p',  { className:'spc-sub' }, s.subtitle),
                React.createElement('blockquote', { className:'spc-sig' }, '“', s.signature, '”'),
                React.createElement('div', { className:'spc-foot' },
                  React.createElement('div', { className:'spc-by' },
                    React.createElement('span', { className:'spc-av' }, s.completedBy.split(' ').map(x=>x[0]).join('').slice(0,2)),
                    s.completedBy
                  ),
                  React.createElement('span', { className:'spc-open' }, 'Open study →')
                )
              )
            )
          )
        )
      )
    )
    ),
    pop && React.createElement('div', { className:'word-pop', style:{ left:pop.x, top:pop.y }, onClick:(e)=>e.stopPropagation() },
      React.createElement('div', { className:'wp-head' },
        React.createElement('div', { className:'wp-greek' }, pop.w.t),
        React.createElement('div', { className:'wp-lemma' }, 'lemma · ', pop.w.lemma)
      ),
      React.createElement('div', { className:'wp-morph-row' }, (pop.w.m||[]).map((m,i)=>React.createElement('span',{key:i},m))),
      React.createElement('div', { className:'wp-gloss' }, pop.w.g),
      React.createElement('div', { className:'wp-foot' },
        React.createElement('button', { className:'btn btn-outline btn-sm' }, 'Full entry'),
        React.createElement('button', { className:'btn btn-ghost btn-sm' }, 'Concordance')
      )
    ),
    commissionTarget && window.PericopeCommissionModal && React.createElement(window.PericopeCommissionModal, {
      target: commissionTarget,
      onClose: () => setCommissionTarget(null),
      onSubmit: () => setCommissionTarget(null)
    })
  );
}
Object.assign(window, { ReaderDrawerV2 });
