import { useEffect, useMemo, useRef, useState, useCallback } from 'react'
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom'
import type { SiteContent, StudyProgram, StudySection } from './content'
import { DEFAULT_COLOSSIANS_STUDY_SECTIONS } from './colossiansStudyData'
import { usePageMeta } from './hooks/usePageMeta'
import { Breadcrumbs } from './components/Breadcrumbs'
import { StudyCertificate } from './components/StudyCertificate'
import { EpisodeAudioPlayer } from './components/EpisodeAudioPlayer'
import { NoteCard } from './components/NoteCard'
import { StudySectionComments } from './components/StudySectionComments'

type Props = { content: SiteContent }

type StudyAuthState = {
  checked: boolean
  authenticated: boolean
  username: string
  enrolledStudySlugs?: string[]
  displayName?: string
  subscribeNewsletter?: boolean
  studyRemindersEnabled?: boolean
  avatarUrl?: string
  totpEnabled?: boolean
  twoFaMethod?: 'app' | 'email' | null
  totpRecoveryCodesRemaining?: number
}

type StudyAuthStatusResponse = {
  authenticated: boolean
  username: string
  enrolledStudySlugs?: string[]
  displayName?: string
  subscribeNewsletter?: boolean
  studyRemindersEnabled?: boolean
  avatarUrl?: string
  totpEnabled?: boolean
  twoFaMethod?: 'app' | 'email' | null
  totpRecoveryCodesRemaining?: number
}

type StudyAccountOverview = {
  profile: {
    username: string
    displayName: string
    subscribeNewsletter: boolean
    studyRemindersEnabled: boolean
    avatarUrl?: string
  }
  stats: {
    noteCount: number
    memberSince: string
    lastLoginAt: string | null
    currentStreak: number
    longestStreak: number
    lastStudiedDate: string | null
  }
  studies: Array<{
    slug: string
    title: string
    status: 'active' | 'planned'
    enrolled: boolean
    totalLessons: number
    completedLessons: number
    noteCount: number
  }>
}

type StudyNotesMap = Record<string, string>

type StudyProgress = {
  completedSectionIds: string[]
}

type StudyCommunityReply = {
  id: string
  authorName: string
  authorAvatarUrl?: string
  message: string
  createdAt: string
}

type StudyCommunityPost = {
  id: string
  studySlug: string
  sectionId: string
  authorName: string
  authorAvatarUrl?: string
  message: string
  createdAt: string
  replies: StudyCommunityReply[]
  pending?: boolean
}

function getLegacyColossiansStudy(content: SiteContent): StudyProgram {
  const legacySections = content.colossiansStudySections?.length ? content.colossiansStudySections : DEFAULT_COLOSSIANS_STUDY_SECTIONS
  return {
    id: 'study-colossians',
    slug: 'colossians',
    title: 'Colossians: Rooted in Christ',
    description: 'Walk through Colossians in guided lessons with commentary, Greek notes, and discussion prompts.',
    status: 'active',
    difficulty: 'intermediate',
    estimatedHours: 12,
    completionBadge: 'Colossians Completion',
    numberOfChapters: 4,
    sections: legacySections,
  }
}

function getStudies(content: SiteContent): StudyProgram[] {
  if (Array.isArray(content.studies) && content.studies.length > 0) return content.studies
  return [getLegacyColossiansStudy(content)]
}

function getStudyBySlug(studies: StudyProgram[], slug: string | undefined) {
  const safeSlug = (slug ?? 'colossians').trim().toLowerCase()
  return studies.find(study => study.slug === safeSlug)
}

function getSectionById(sections: StudySection[], sectionId: string | undefined) {
  if (!sectionId) return undefined
  return sections.find(section => section.id === sectionId)
}

function getLessonNumber(sections: StudySection[], sectionId: string | undefined) {
  const index = sections.findIndex(item => item.id === sectionId)
  return index >= 0 ? index + 1 : 0
}

function getPrimaryQuestion(section: StudySection) {
  if (section.focusQuestion?.trim()) return section.focusQuestion.trim()
  return section.studyQuestions.length > 0 ? section.studyQuestions[0] : 'How does this passage shape the way we follow Christ this week?'
}

function getChapterSummaries(study: StudyProgram) {
  const highestSectionChapter = study.sections.reduce((max, section) => Math.max(max, section.chapter), 0)
  const totalChapters = Math.max(study.numberOfChapters, highestSectionChapter)
  return Array.from({ length: totalChapters }, (_, index) => {
    const chapter = index + 1
    const lessonCount = study.sections.filter(section => section.chapter === chapter).length
    return { chapter, lessonCount }
  })
}

function getSectionReleaseDate(section: StudySection): Date | null {
  const candidateValues = [
    section?.releasedAt,
    (section as StudySection & { releaseDate?: string }).releaseDate,
    (section as StudySection & { availableAt?: string }).availableAt,
    (section as StudySection & { publishAt?: string }).publishAt,
  ]

  for (const candidate of candidateValues) {
    if (typeof candidate !== 'string' || !candidate.trim()) continue
    const parsed = new Date(candidate)
    if (!Number.isNaN(parsed.getTime())) return parsed
  }

  return null
}

function isNewLesson(section: StudySection): boolean {
  const releaseDate = getSectionReleaseDate(section)
  if (!releaseDate) return false
  const now = new Date()
  const daysSinceRelease = (now.getTime() - releaseDate.getTime()) / (1000 * 60 * 60 * 24)
  return daysSinceRelease >= 0 && daysSinceRelease <= 14
}

function isComingSoon(section: StudySection): boolean {
  const releaseDate = getSectionReleaseDate(section)
  if (!releaseDate) return false
  const now = new Date()
  return releaseDate > now
}

function isSectionReleased(section: StudySection): boolean {
  const releaseDate = getSectionReleaseDate(section)
  if (!releaseDate) return false
  return releaseDate <= new Date()
}

function getReleaseDateDisplay(section: StudySection): string {
  const date = getSectionReleaseDate(section)
  if (!date) return ''
  const now = new Date()
  const diffMs = date.getTime() - now.getTime()
  const diffDays = Math.ceil(diffMs / (1000 * 60 * 60 * 24))
  if (diffDays === 1) return 'tomorrow'
  if (diffDays > 1 && diffDays <= 14) return `in ${diffDays} days`
  return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })
}

function getNoteId(studySlug: string, sectionId: string) {
  return `${studySlug}--${sectionId}`
}

const NOTE_ANCHORS = [
  { id: 'scripture', label: 'Scripture Text' },
  { id: 'commentary', label: 'Commentary' },
  { id: 'questions', label: 'Reflection Questions' },
] as const

type NoteAnchorId = typeof NOTE_ANCHORS[number]['id'] | 'general'

const ANCHOR_LABELS: Record<string, string> = {
  scripture: 'Scripture Text',
  commentary: 'Commentary',
  questions: 'Reflection Questions',
  general: 'General Notes',
}

function parseNoteMap(raw: string): Record<string, string> {
  if (!raw?.trim()) return {}
  try {
    const parsed = JSON.parse(raw)
    if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
      return parsed as Record<string, string>
    }
  } catch {}
  return { general: raw }
}

function getDisplayName(auth: StudyAuthState) {
  return auth.displayName?.trim() || auth.username.split('@')[0] || 'student'
}

function formatCommunityDate(value: string) {
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return ''
  return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })
}

function CommunityBoard({
  study,
  auth,
  isEnrolled,
  sectionFilter,
}: {
  study: StudyProgram
  auth: StudyAuthState
  isEnrolled: boolean
  sectionFilter?: string
}) {
  const [posts, setPosts] = useState<StudyCommunityPost[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState('')
  const [message, setMessage] = useState('')
  const [replyDrafts, setReplyDrafts] = useState<Record<string, string>>({})
  const [replyingTo, setReplyingTo] = useState<string | null>(null)
  const [submitting, setSubmitting] = useState(false)
  const [newPost, setNewPost] = useState('')
  const [activeSection, setActiveSection] = useState<string>(sectionFilter ?? '')

  const canParticipate = auth.authenticated && isEnrolled
  const communityDisplayName = getDisplayName(auth)

  const releasedSections = study.sections.filter(isSectionReleased)
  const visiblePosts = activeSection
    ? posts.filter(p => p.sectionId === activeSection)
    : posts

  useEffect(() => {
    let cancelled = false

    async function load() {
      if (!canParticipate) {
        setPosts([])
        setLoading(false)
        return
      }

      setLoading(true)
      setError('')
      try {
        const data = await readJson<{ posts?: StudyCommunityPost[] }>('/api/study-community?' + new URLSearchParams({ studySlug: study.slug }).toString())
        if (cancelled) return
        setPosts(Array.isArray(data.posts) ? data.posts : [])
      } catch (err) {
        if (cancelled) return
        setError(err instanceof Error ? err.message : 'Unable to load the community right now.')
      } finally {
        if (cancelled) return
        setLoading(false)
      }
    }

    void load()
    return () => {
      cancelled = true
    }
  }, [canParticipate, study.slug])

  async function submitPost() {
    if (!newPost.trim() || !canParticipate) return
    setSubmitting(true)
    setMessage('')
    setError('')
    const optimisticId = `pending-${Date.now()}`
    const optimisticPost: StudyCommunityPost = {
      id: optimisticId,
      studySlug: study.slug,
      sectionId: activeSection,
      authorName: communityDisplayName,
      authorAvatarUrl: auth.avatarUrl || undefined,
      message: newPost,
      createdAt: new Date().toISOString(),
      replies: [],
      pending: true,
    }
    setPosts(prev => [optimisticPost, ...prev])
    const postedMessage = newPost
    setNewPost('')
    try {
      const data = await readJson<{ post?: StudyCommunityPost }>('/api/study-community/posts', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ studySlug: study.slug, sectionId: activeSection, message: postedMessage }),
      })
      setPosts(prev => data.post
        ? prev.map(p => p.id === optimisticId ? { ...data.post!, pending: false } : p)
        : prev.filter(p => p.id !== optimisticId))
      setMessage('')
    } catch (err) {
      setPosts(prev => prev.filter(p => p.id !== optimisticId))
      setNewPost(postedMessage)
      setError(err instanceof Error ? err.message : 'Unable to post right now.')
    } finally {
      setSubmitting(false)
    }
  }

  async function submitReply(postId: string) {
    const reply = replyDrafts[postId]?.trim()
    if (!reply || !canParticipate) return
    setSubmitting(true)
    setError('')
    try {
      const data = await readJson<{ reply?: StudyCommunityReply }>(`/api/study-community/posts/${encodeURIComponent(postId)}/replies`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ message: reply }),
      })
      if (data.reply) {
        setPosts(prev => prev.map(post => post.id === postId ? { ...post, replies: [...(post.replies ?? []), data.reply!] } : post))
      }
      setReplyDrafts(prev => ({ ...prev, [postId]: '' }))
      setReplyingTo(null)
      setMessage('Reply posted.')
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Unable to post your reply.')
    } finally {
      setSubmitting(false)
    }
  }

  return (
    <div className="study-community-board">
      {/* Section filter tabs */}
      {releasedSections.length > 1 && canParticipate && (
        <div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap', marginBottom: '1rem' }}>
          <button
            type="button"
            className={`qa-topic-btn${activeSection === '' ? ' qa-topic-btn--active' : ''}`}
            onClick={() => setActiveSection('')}
          >All lessons</button>
          {releasedSections.map(s => (
            <button
              key={s.id}
              type="button"
              className={`qa-topic-btn${activeSection === s.id ? ' qa-topic-btn--active' : ''}`}
              onClick={() => setActiveSection(s.id)}
            >{s.title}</button>
          ))}
        </div>
      )}

      {!auth.checked && <p className="study-note-status">Checking your account status...</p>}
      {auth.checked && !auth.authenticated && (
        <div className="study-auth-box">
          <p className="study-auth-why">Sign in to join the study community.</p>
          <div className="study-auth-actions">
            <Link to="/study/signup" className="btn-primary">Create Account</Link>
            <Link to="/study/account" className="btn-secondary">My Account</Link>
          </div>
        </div>
      )}
      {auth.checked && auth.authenticated && !isEnrolled && (
        <div className="study-auth-box">
          <p className="study-auth-why">Enroll in {study.title} to participate in the community.</p>
          <div className="study-auth-actions">
            <Link to="/study/account" className="btn-primary">Go to My Account</Link>
          </div>
        </div>
      )}

      {canParticipate && (
        <div style={{ marginBottom: '1.5rem' }}>
          {activeSection && (
            <p style={{ fontSize: '0.875rem', color: '#7a7060', marginBottom: '0.5rem' }}>
              Posting to: <strong style={{ color: '#e0c070' }}>{releasedSections.find(s => s.id === activeSection)?.title ?? 'this lesson'}</strong>
            </p>
          )}
          <textarea
            rows={4}
            value={newPost}
            onChange={e => setNewPost(e.target.value)}
            onInput={e => {
              const el = e.currentTarget
              el.style.height = 'auto'
              el.style.height = `${el.scrollHeight}px`
            }}
            placeholder={activeSection ? `Share a thought about ${releasedSections.find(s => s.id === activeSection)?.title ?? 'this lesson'}...` : 'Share a thought with the community...'}
            style={{ width: '100%', padding: '0.85rem 1rem', borderRadius: '12px', border: '1px solid #2a2518', background: '#14130f', color: '#f0ead8', marginBottom: '0.75rem', resize: 'none', overflow: 'hidden', boxSizing: 'border-box' }}
          />
          <div className="study-auth-actions">
            <button type="button" className="btn-primary" disabled={submitting || !newPost.trim()} onClick={submitPost}>
              {submitting ? 'Posting...' : 'Post to Community'}
            </button>
          </div>
        </div>
      )}

      {message && <p className="study-note-status" style={{ marginBottom: '0.75rem' }}>{message}</p>}
      {error && <p className="study-note-status" style={{ marginBottom: '0.75rem' }}>{error}</p>}

      {canParticipate && (
        <div style={{ display: 'grid', gap: '0.85rem' }}>
          {loading ? (
            <p className="study-detail-copy">Loading community posts...</p>
          ) : visiblePosts.length === 0 ? (
            <p className="study-detail-copy">No posts yet{activeSection ? ' for this lesson' : ''}. Be the first to start the conversation.</p>
          ) : visiblePosts.map(post => {
            const postSection = study.sections.find(s => s.id === post.sectionId)
            return (
              <div key={post.id} style={{ border: '1px solid #2a2518', borderRadius: '14px', padding: '1.15rem', background: '#11100d', opacity: post.pending ? 0.65 : 1, transition: 'opacity 300ms' }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem', flexWrap: 'wrap', marginBottom: '0.4rem' }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: '0.65rem', flexWrap: 'wrap' }}>
                    {post.authorAvatarUrl ? (
                      <img src={post.authorAvatarUrl} alt={`${post.authorName || 'Student'} avatar`} width={28} height={28} style={{ borderRadius: '50%', border: '1px solid #2a2518' }} />
                    ) : (
                      <div style={{ width: 28, height: 28, borderRadius: '50%', background: '#2a2518', display: 'grid', placeItems: 'center', color: '#f0ead8', fontSize: '0.85rem', fontWeight: 700 }}>
                        {post.authorName?.slice(0, 1).toUpperCase() || 'S'}
                      </div>
                    )}
                    <strong style={{ color: '#e0c070' }}>{post.authorName || 'Student'}</strong>
                    {postSection && !activeSection && (
                      <button
                        type="button"
                        className="qa-topic-btn"
                        style={{ padding: '0.2rem 0.6rem', fontSize: '0.78rem' }}
                        onClick={() => setActiveSection(postSection.id)}
                      >{postSection.title}</button>
                    )}
                  </div>
                  <span className="study-note-status">{formatCommunityDate(post.createdAt)}</span>
                </div>
                <p className="study-detail-copy" style={{ marginTop: 0, whiteSpace: 'pre-wrap' }}>{post.message}</p>
                <div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap', marginTop: '0.75rem' }}>
                  <button type="button" className="btn-secondary" style={{ fontSize: '0.85rem', padding: '0.35rem 0.85rem' }} onClick={() => setReplyingTo(curr => curr === post.id ? null : post.id)}>
                    {replyingTo === post.id ? 'Cancel' : `Reply${post.replies?.length ? ` (${post.replies.length})` : ''}`}
                  </button>
                </div>
                {replyingTo === post.id && canParticipate && (
                  <div style={{ marginTop: '0.85rem' }}>
                    <textarea
                      rows={3}
                      value={replyDrafts[post.id] ?? ''}
                      onChange={e => setReplyDrafts(prev => ({ ...prev, [post.id]: e.target.value }))}
                      onInput={e => {
                        const el = e.currentTarget
                        el.style.height = 'auto'
                        el.style.height = `${el.scrollHeight}px`
                      }}
                      placeholder={`Reply to ${post.authorName || communityDisplayName}...`}
                      style={{ width: '100%', padding: '0.8rem 1rem', borderRadius: '12px', border: '1px solid #2a2518', background: '#14130f', color: '#f0ead8', marginBottom: '0.75rem', resize: 'none', overflow: 'hidden' }}
                    />
                    <button type="button" className="btn-primary" style={{ fontSize: '0.9rem' }} disabled={submitting || !(replyDrafts[post.id] ?? '').trim()} onClick={() => submitReply(post.id)}>Post Reply</button>
                  </div>
                )}
                {Array.isArray(post.replies) && post.replies.length > 0 && (
                  <div style={{ marginTop: '1rem', display: 'grid', gap: '0.65rem' }}>
                    {post.replies.map(reply => (
                      <div key={reply.id} style={{ borderLeft: '2px solid #2a2518', paddingLeft: '0.85rem' }}>
                        <div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem', flexWrap: 'wrap' }}>
                          <div style={{ display: 'flex', alignItems: 'center', gap: '0.55rem', flexWrap: 'wrap' }}>
                      {reply.authorAvatarUrl ? (
                        <img src={reply.authorAvatarUrl} alt={`${reply.authorName || 'Student'} avatar`} width={22} height={22} style={{ borderRadius: '50%', border: '1px solid #2a2518' }} />
                      ) : (
                        <div style={{ width: 22, height: 22, borderRadius: '50%', background: '#2a2518', display: 'grid', placeItems: 'center', color: '#f0ead8', fontSize: '0.75rem', fontWeight: 700 }}>
                          {reply.authorName?.slice(0, 1).toUpperCase() || 'S'}
                        </div>
                      )}
                      <strong style={{ color: '#c9a84c', fontSize: '0.95rem' }}>{reply.authorName || 'Student'}</strong>
                    </div>
                          <span className="study-note-status">{formatCommunityDate(reply.createdAt)}</span>
                        </div>
                        <p className="study-detail-copy" style={{ margin: '0.25rem 0 0', whiteSpace: 'pre-wrap' }}>{reply.message}</p>
                      </div>
                    ))}
                  </div>
                )}
              </div>
            )
          })}
        </div>
      )}
    </div>
  )
}

async function readJson<T>(url: string, init?: RequestInit): Promise<T> {
  const response = await fetch(url, init)
  const data = await response.json().catch(() => ({})) as T & { message?: string }
  if (!response.ok) {
    throw new Error((data as { message?: string }).message ?? 'Request failed')
  }
  return data as T
}

function normalizeEnrolledStudySlugs(value: unknown): string[] {
  if (!Array.isArray(value)) return []
  return value.filter(item => typeof item === 'string' && item.trim()).map(item => item.trim().toLowerCase())
}

function isEnrolledInStudy(auth: StudyAuthState, studySlug: string | undefined): boolean {
  if (!auth.authenticated || !studySlug) return false
  const normalized = studySlug.trim().toLowerCase()
  if (!normalized) return false
  return normalizeEnrolledStudySlugs(auth.enrolledStudySlugs).includes(normalized)
}

export function StudyLandingPage({ content }: Props) {
  const [auth, setAuth] = useState<StudyAuthState>({ checked: false, authenticated: false, username: '', enrolledStudySlugs: [], displayName: '', subscribeNewsletter: true, studyRemindersEnabled: false, avatarUrl: '' })
  const [overview, setOverview] = useState<StudyAccountOverview | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState('')
  const [studyModal, setStudyModal] = useState<'none' | 'enrollments' | 'browseTracks'>('none')
  const [enrollBusySlug, setEnrollBusySlug] = useState('')
  const [enrollMessage, setEnrollMessage] = useState('')
  const [showNewsletterNudge, setShowNewsletterNudge] = useState(false)
  const [confirmLeaveSlug, setConfirmLeaveSlug] = useState<string | null>(null)
  const [newsletterNudgeDone, setNewsletterNudgeDone] = useState(false)

  const studies = getStudies(content)
  const activeStudies = studies.filter(study => study.status !== 'planned')
  const plannedStudies = studies.filter(study => study.status === 'planned')
  const firstActiveStudy = activeStudies[0]
  const firstActiveStudyFirstReleasedSection = firstActiveStudy?.sections.find(isSectionReleased)

  async function refreshOverview() {
    if (!auth.authenticated) return
    try {
      const dashboard = await readJson<StudyAccountOverview>('/api/study-account/overview')
      setOverview(dashboard)
    } catch (err) {
      console.error(err)
    }
  }

  async function handleEnrollmentToggle(studySlug: string, enrolled: boolean) {
    if (!auth.authenticated) {
      setEnrollMessage('Sign in to change your enrollments.')
      return
    }

    setEnrollBusySlug(studySlug)
    setEnrollMessage('')
    try {
      const data = await readJson<{ enrolledStudySlugs?: string[]; studyTitle?: string }>(`/api/study-enrollment/${encodeURIComponent(studySlug)}`, {
        method: enrolled ? 'DELETE' : 'POST',
      })
      const slugs = normalizeEnrolledStudySlugs(data.enrolledStudySlugs)
      setAuth(prev => ({ ...prev, enrolledStudySlugs: slugs }))
      setEnrollMessage(enrolled ? `Unenrolled from ${data.studyTitle ?? studySlug}.` : `Enrolled in ${data.studyTitle ?? studySlug}.`)
      if (!enrolled && !auth.subscribeNewsletter) setShowNewsletterNudge(true)
      await refreshOverview()
    } catch (err) {
      setEnrollMessage(err instanceof Error ? err.message : 'Unable to update enrollment.')
    } finally {
      setEnrollBusySlug('')
    }
  }

  function closeStudyModal() {
    setStudyModal('none')
    setEnrollMessage('')
  }

  useEffect(() => {
    if (studyModal === 'none') return
    function onKeyDown(e: KeyboardEvent) {
      if (e.key === 'Escape') closeStudyModal()
    }
    document.addEventListener('keydown', onKeyDown)
    return () => document.removeEventListener('keydown', onKeyDown)
  }, [studyModal])

  useEffect(() => {
    let cancelled = false

    async function load() {
      setLoading(true)
      setError('')
      try {
        const authData = await readJson<StudyAuthStatusResponse>('/api/study-auth/status')
        if (cancelled) return
        setAuth({
          checked: true,
          authenticated: Boolean(authData.authenticated),
          username: authData.username ?? '',
          displayName: authData.displayName ?? '',
          subscribeNewsletter: authData.subscribeNewsletter !== false,
          studyRemindersEnabled: authData.studyRemindersEnabled === true,
          avatarUrl: authData.avatarUrl ?? '',
          enrolledStudySlugs: normalizeEnrolledStudySlugs(authData.enrolledStudySlugs),
        })

        if (authData.authenticated) {
          const dashboard = await readJson<StudyAccountOverview>('/api/study-account/overview')
          if (cancelled) return
          setOverview(dashboard)
        }
      } catch (err) {
        if (cancelled) return
        setError(err instanceof Error ? err.message : 'Unable to load your study dashboard.')
      } finally {
        if (cancelled) return
        setLoading(false)
      }
    }

    void load()
    return () => {
      cancelled = true
    }
  }, [])

  const enrolledStudies = overview?.studies.filter(study => study.enrolled) ?? []
  const availableStudies = overview?.studies ?? []
  const totalEnrolled = enrolledStudies.length
  const totalCompletedLessons = enrolledStudies.reduce((sum, study) => sum + study.completedLessons, 0)
  const totalLessons = enrolledStudies.reduce((sum, study) => sum + study.totalLessons, 0)

  if (loading) {
    return (
      <main className="study-index-page" aria-label="Study hub">
        <section className="section-study-course-hero">
          <div className="section-inner study-course-hero-inner">
            <p className="eyebrow">Study Dashboard</p>
            <h1>Loading your study progress…</h1>
            <p className="study-course-hero-copy">Hang tight while we gather your enrolled tracks and lesson progress.</p>
          </div>
        </section>
      </main>
    )
  }

  if (auth.authenticated && overview) {
    return (
      <main className="study-index-page" aria-label="Study dashboard">
        <section className="section-study-course-hero">
          <div className="section-inner study-course-hero-inner" style={{ alignItems: 'flex-start' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: '1rem', flexWrap: 'wrap' }}>
              {auth.avatarUrl ? (
                <img src={auth.avatarUrl} alt="Your avatar" width={76} height={76} style={{ borderRadius: '50%', border: '1px solid #2a2518' }} />
              ) : (
                <div style={{ width: 76, height: 76, borderRadius: '50%', background: '#2a2518', display: 'grid', placeItems: 'center', color: '#f0ead8', fontWeight: 700, fontSize: '1.75rem' }}>
                  {auth.displayName?.slice(0, 1).toUpperCase() || auth.username.slice(0, 1).toUpperCase()}
                </div>
              )}
              <div>
                <p className="eyebrow">Welcome back</p>
                <h1 style={{ marginTop: 0 }}>{auth.displayName || auth.username.split('@')[0]}</h1>
                <p className="study-course-hero-copy">Your progress, enrollments, and classroom resources are all in one place.</p>
              </div>
            </div>

            <div className="study-course-meta" style={{ marginTop: '1.5rem', gap: '0.75rem' }}>
              <span>{totalEnrolled} enrolled track{totalEnrolled === 1 ? '' : 's'}</span>
              <span>{totalCompletedLessons}/{totalLessons} lessons completed</span>
              <span>{overview.stats.noteCount} notes saved</span>
              {auth.studyRemindersEnabled ? <span>Lesson reminders enabled</span> : <span>Reminders off</span>}
            </div>
            {error && <p className="study-note-status" style={{ marginTop: '0.75rem' }}>{error}</p>}

            <div className="study-course-hero-actions" style={{ marginTop: '1.5rem' }}>
              <Link to="/study/account" className="btn-primary">Open My Account</Link>
              <button type="button" className="btn-secondary" onClick={() => setStudyModal('enrollments')}>View Enrollments</button>
              <button type="button" className="btn-secondary" onClick={() => setStudyModal('browseTracks')}>Browse All Tracks</button>
            </div>
          </div>
        </section>
        {studyModal !== 'none' && (
          <div style={{ position: 'fixed', inset: 0, zIndex: 1000, background: 'rgba(5, 5, 5, 0.86)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '1.25rem' }}>
            <div style={{ width: '100%', maxWidth: '760px', maxHeight: 'calc(100vh - 2rem)', overflowY: 'auto', background: '#11100d', border: '1px solid #3a3320', borderRadius: '18px', padding: '1.4rem', position: 'relative' }} role="dialog" aria-modal="true" aria-labelledby="study-modal-heading">
              <button type="button" onClick={closeStudyModal} style={{ position: 'absolute', top: '1rem', right: '1rem', background: 'transparent', border: 'none', color: '#f0ead8', fontSize: '1.35rem', cursor: 'pointer' }} aria-label="Close study modal">×</button>
              <h2 id="study-modal-heading">{studyModal === 'enrollments' ? 'Manage Enrollments' : 'Browse All Tracks'}</h2>
              <p style={{ marginTop: '0.5rem', marginBottom: '1rem', color: '#b9b09b' }}>
                {studyModal === 'enrollments'
                  ? 'Review and change the study tracks you are enrolled in. Use the buttons below to join or leave each track.'
                  : 'See every study track available now. Enroll in a study directly from this popup and start right away.'}
              </p>
              {auth.authenticated && overview ? (
                studyModal === 'enrollments' ? (
                  enrolledStudies.length > 0 ? (
                    <div style={{ display: 'grid', gap: '1rem' }}>
                      {enrolledStudies.map(studyInfo => (
                        <div key={studyInfo.slug} style={{ padding: '1rem', borderRadius: '12px', background: '#14130f', border: '1px solid #2a2518' }}>
                          <div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem', alignItems: 'flex-start' }}>
                            <div>
                              <p style={{ margin: 0, fontSize: '0.9rem', color: '#b09e79' }}>{studyInfo.status === 'active' ? 'Active study' : 'Planned study'}</p>
                              <h3 style={{ margin: '0.35rem 0 0' }}>{studyInfo.title}</h3>
                              <p style={{ margin: '0.4rem 0 0', fontSize: '0.9rem' }}>{studyInfo.completedLessons}/{studyInfo.totalLessons} lessons completed · {studyInfo.noteCount} notes</p>
                            </div>
                            {confirmLeaveSlug === studyInfo.slug ? (
                              <div style={{ display: 'flex', gap: '0.5rem', alignItems: 'center', flexWrap: 'wrap' }}>
                                <span style={{ fontSize: '0.85rem', color: '#b9b09b' }}>Are you sure?</span>
                                <button
                                  type="button"
                                  className="btn-admin-remove"
                                  disabled={enrollBusySlug === studyInfo.slug}
                                  onClick={() => { setConfirmLeaveSlug(null); handleEnrollmentToggle(studyInfo.slug, true) }}
                                >{enrollBusySlug === studyInfo.slug ? 'Working…' : 'Yes, leave'}</button>
                                <button type="button" className="btn-secondary" style={{ fontSize: '0.85rem', padding: '0.3rem 0.75rem' }} onClick={() => setConfirmLeaveSlug(null)}>Cancel</button>
                              </div>
                            ) : (
                              <button
                                type="button"
                                className="btn-admin-remove"
                                disabled={enrollBusySlug === studyInfo.slug}
                                onClick={() => setConfirmLeaveSlug(studyInfo.slug)}
                              >
                                Leave
                              </button>
                            )}
                          </div>
                        </div>
                      ))}
                    </div>
                  ) : (
                    <div style={{ padding: '1rem', background: '#14130f', borderRadius: '12px', border: '1px solid #2a2518' }}>
                      <p style={{ margin: 0 }}>You are not enrolled in any tracks yet. Use Browse All Tracks to find a study and enroll.</p>
                      <button type="button" className="btn-primary" style={{ marginTop: '1rem' }} onClick={() => setStudyModal('browseTracks')}>Browse All Tracks</button>
                    </div>
                  )
                ) : (
                  <div style={{ display: 'grid', gap: '1rem' }}>
                    {availableStudies.map(studyInfo => (
                      <div key={studyInfo.slug} style={{ padding: '1rem', borderRadius: '12px', background: '#14130f', border: '1px solid #2a2518' }}>
                        <div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem', alignItems: 'flex-start' }}>
                          <div>
                            <p style={{ margin: 0, fontSize: '0.9rem', color: '#b09e79' }}>{studyInfo.status === 'active' ? 'Active study' : 'Planned study'}</p>
                            <h3 style={{ margin: '0.35rem 0 0' }}>{studyInfo.title}</h3>
                            <p style={{ margin: '0.4rem 0 0', fontSize: '0.9rem' }}>{studyInfo.completedLessons}/{studyInfo.totalLessons} lessons completed · {studyInfo.noteCount} notes</p>
                          </div>
                          {studyInfo.enrolled && confirmLeaveSlug === studyInfo.slug ? (
                            <div style={{ display: 'flex', gap: '0.5rem', alignItems: 'center', flexWrap: 'wrap' }}>
                              <span style={{ fontSize: '0.85rem', color: '#b9b09b' }}>Are you sure?</span>
                              <button
                                type="button"
                                className="btn-admin-remove"
                                disabled={enrollBusySlug === studyInfo.slug}
                                onClick={() => { setConfirmLeaveSlug(null); handleEnrollmentToggle(studyInfo.slug, true) }}
                              >{enrollBusySlug === studyInfo.slug ? 'Working…' : 'Yes, leave'}</button>
                              <button type="button" className="btn-secondary" style={{ fontSize: '0.85rem', padding: '0.3rem 0.75rem' }} onClick={() => setConfirmLeaveSlug(null)}>Cancel</button>
                            </div>
                          ) : (
                            <button
                              type="button"
                              className={studyInfo.enrolled ? 'btn-admin-remove' : 'btn-primary'}
                              disabled={enrollBusySlug === studyInfo.slug}
                              onClick={() => studyInfo.enrolled ? setConfirmLeaveSlug(studyInfo.slug) : handleEnrollmentToggle(studyInfo.slug, false)}
                            >
                              {enrollBusySlug === studyInfo.slug ? 'Working…' : studyInfo.enrolled ? 'Leave' : 'Enroll'}
                            </button>
                          )}
                        </div>
                      </div>
                    ))}
                  </div>
                )
              ) : auth.authenticated ? (
                <p>No study information is available yet. Please refresh the page or visit your account to load your enrollments.</p>
              ) : (
                <div style={{ padding: '1rem', background: '#14130f', borderRadius: '12px', border: '1px solid #2a2518' }}>
                  <p style={{ margin: 0 }}>Sign in to manage your enrollments and browse tracks from within the app.</p>
                  <div style={{ marginTop: '1rem', display: 'flex', gap: '0.75rem', flexWrap: 'wrap' }}>
                    <Link to="/study/signup" className="btn-primary">Sign In</Link>
                    <button type="button" className="btn-secondary" onClick={closeStudyModal}>Close</button>
                  </div>
                </div>
              )}
              {enrollMessage && <p className="study-note-status" style={{ marginTop: '1rem' }}>{enrollMessage}</p>}
              {showNewsletterNudge && !newsletterNudgeDone && (
                <div className="study-newsletter-nudge" style={{ marginTop: '1rem', background: '#1a1a12', border: '1px solid rgba(201,168,76,0.25)', borderRadius: '8px', padding: '1rem', fontSize: '0.9rem' }}>
                  <p style={{ margin: '0 0 0.5rem' }}>Want episode updates and study announcements by email?</p>
                  <div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap' }}>
                    <button type="button" className="btn-primary" style={{ fontSize: '0.85rem', padding: '0.4rem 1rem' }} onClick={async () => {
                      try {
                        await fetch('/api/study-account/preferences', { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ subscribeNewsletter: true, studyRemindersEnabled: auth.studyRemindersEnabled === true }) })
                        setAuth(prev => ({ ...prev, subscribeNewsletter: true }))
                      } catch {
                        // Silently continue — preference will sync on next account load
                      }
                      setNewsletterNudgeDone(true)
                      setShowNewsletterNudge(false)
                    }}>Yes, subscribe me</button>
                    <button type="button" className="btn-secondary" style={{ fontSize: '0.85rem', padding: '0.4rem 1rem' }} onClick={() => setShowNewsletterNudge(false)}>No thanks</button>
                  </div>
                </div>
              )}
            </div>
          </div>
        )}

        <section id="my-tracks" className="section-study-module" aria-label="Your enrolled tracks" style={{ paddingTop: '1rem' }}>
          <div className="section-inner">
            <div className="study-module-header">
              <p>Your Classroom</p>
              <h2>Enrolled Tracks</h2>
            </div>

            {totalEnrolled === 0 ? (
              <article className="study-class-block">
                <h2>No enrollments yet</h2>
                <p className="study-detail-copy">You are signed in, but you have not enrolled in any study track yet. Browse the available tracks and join the one you want to start.</p>
                <button type="button" className="btn-primary" onClick={() => setStudyModal('browseTracks')}>Browse Tracks</button>
              </article>
            ) : (
              <div className="study-module-list">
                {enrolledStudies.map(study => {
                  const studyMeta = getStudyBySlug(studies, study.slug)
                  const progress = study.totalLessons > 0 ? Math.round((study.completedLessons / study.totalLessons) * 100) : 0
                  return (
                    <div key={study.slug}>
                    <article className="study-module-row">
                      <div className="study-module-row-left">
                        <p className="study-module-lesson">{study.enrolled ? 'Enrolled' : 'Track'}</p>
                        <h3>{study.title}</h3>
                        <p>{studyMeta?.description ?? 'Continue your study with the lessons and notes available in this track.'}</p>
                        <div style={{ display: 'flex', gap: '1rem', flexWrap: 'wrap', marginTop: '0.75rem' }}>
                          <span style={{ color: '#7a7060', fontSize: '0.9rem' }}>{study.completedLessons}/{study.totalLessons} lessons completed</span>
                          <span style={{ color: '#7a7060', fontSize: '0.9rem' }}>{study.noteCount} notes</span>
                        </div>
                        <div style={{ marginTop: '0.75rem', height: '10px', width: '100%', background: '#27231b', borderRadius: '999px', overflow: 'hidden' }}>
                          <div style={{ width: `${progress}%`, height: '100%', background: '#e0c070' }} />
                        </div>
                      </div>
                      <div className="study-module-row-right" style={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between' }}>
                        <div>
                          <p className="study-module-focus">Progress</p>
                          <p>{progress}% complete</p>
                        </div>
                        <div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap', marginTop: '1rem' }}>
                          <Link to={`/study/${study.slug}`} className="btn-primary">Continue</Link>
                          <Link to={`/study/${study.slug}/notes`} className="btn-secondary">My Notes</Link>
                          <Link to={`/study/${study.slug}/community`} className="btn-secondary">Community</Link>
                        </div>
                      </div>
                    </article>
                    {progress === 100 && (
                      <StudyCertificate studySlug={study.slug} />
                    )}
                    </div>
                  )
                })}
              </div>
            )}
          </div>
        </section>

      </main>
    )
  }

  return (
    <main className="study-index-page" aria-label="Study hub">
      <section className="section-study-course-hero">
        <div className="section-inner study-course-hero-inner">
          <p className="eyebrow">Self-Paced Bible Academy</p>
          <h1>Study at Your Own Pace</h1>
          <p className="study-course-hero-copy">Pick a study track, move lesson by lesson on your own schedule, and keep personal notes as you grow through each passage.</p>
          <div className="study-course-meta">
            <span>{studies.length} study tracks</span>
            <span>Self-paced flow</span>
            <span>Personal notes</span>
            <span>Audio + commentary</span>
          </div>
          <div className="study-course-hero-actions">
            {firstActiveStudyFirstReleasedSection && <Link to={`/study/${firstActiveStudy.slug}/${firstActiveStudyFirstReleasedSection.id}`} className="btn-primary">Start Learning</Link>}
            <Link to="/study/signup" className="btn-primary">Create Account or Login</Link>
            <Link to="/study/account" className="btn-secondary">My Account</Link>
          </div>
        </div>
      </section>

      <section className="section-study-hub-flow" aria-label="How self-paced study works">
        <div className="section-inner">
          <div className="study-module-header">
            <p>How It Works</p>
            <h2>A Simple Self-Paced Rhythm</h2>
          </div>
          <div className="study-hub-flow-grid">
            <article className="study-hub-flow-card">
              <p className="study-module-lesson">Step 1</p>
              <h3>Choose Your Track</h3>
              <p>Start with any active study and begin at lesson one, or jump back in where you left off.</p>
            </article>
            <article className="study-hub-flow-card">
              <p className="study-module-lesson">Step 2</p>
              <h3>Work Each Lesson</h3>
              <p>Read the text, listen to audio, review commentary, and process key Greek word notes.</p>
            </article>
            <article className="study-hub-flow-card">
              <p className="study-module-lesson">Step 3</p>
              <h3>Save Notes and Continue</h3>
              <p>Keep personal notes per lesson and build your own study archive over time.</p>
            </article>
          </div>
        </div>
      </section>

      <section id="study-tracks" className="section-study-module" aria-label="Available studies">
        <div className="section-inner">
          <div className="study-module-header">
            <p>Available Now</p>
            <h2>Current Study Tracks</h2>
          </div>
          <div className="study-module-list">
            {activeStudies.map(study => (
                (() => {
                  const releasedCount = study.sections.filter(isSectionReleased).length
                  return (
              <Link key={study.id} to={`/study/${study.slug}`} className="study-module-row">
                <div className="study-module-row-left">
                  <div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem', marginBottom: '0.5rem', flexWrap: 'wrap' }}>
                    <p className="study-module-lesson">Start Anytime</p>
                    {study.difficulty && <span style={{ backgroundColor: study.difficulty === 'advanced' ? '#d32f2f' : (study.difficulty === 'intermediate' ? '#f57c00' : '#388e3c'), color: '#fff', padding: '0.25rem 0.75rem', borderRadius: '16px', fontSize: '0.75rem', fontWeight: '600', textTransform: 'capitalize' }}>{study.difficulty}</span>}
                  </div>
                  <h3>{study.title}</h3>
                  <p>{study.description}</p>
                  {study.estimatedHours && <p style={{ fontSize: '0.875rem', color: '#666', marginTop: '0.5rem' }}>⏱ {study.estimatedHours} hours</p>}
                </div>
                <div className="study-module-row-right">
                  <p className="study-module-focus">Track Snapshot</p>
                      <p>{releasedCount > 0 ? `${releasedCount} lessons available now` : 'Lessons will be published soon.'}</p>
                      <p>{study.sections.length > 0 ? 'Estimated pace: every other Monday' : 'Pacing details coming with first lesson release.'}</p>
                </div>
              </Link>
                  )
                })()
              ))}
          </div>
        </div>
      </section>

      {plannedStudies.length > 0 && (
        <section className="section-study-module" aria-label="Upcoming studies">
          <div className="section-inner">
            <div className="study-module-header">
              <p>Coming Soon</p>
              <h2>Next Study Tracks</h2>
            </div>
            <div className="study-module-list">
              {plannedStudies.map(study => (
                <article key={study.id} className="study-module-row study-module-row--disabled" aria-disabled="true">
                  <div className="study-module-row-left">
                    <p className="study-module-lesson">Planned</p>
                    <h3>{study.title}</h3>
                    <p>{study.description}</p>
                  </div>
                  <div className="study-module-row-right">
                    <p className="study-module-focus">Status</p>
                    <p>Preparing lesson structure and media.</p>
                  </div>
                </article>
              ))}
            </div>
          </div>
        </section>
      )}

      <section className="section-study-module" aria-label="Q&A">
        <div className="section-inner" style={{ textAlign: 'center', padding: '3rem 1rem' }}>
          <p className="eyebrow">Have a question from the Word?</p>
          <h2 style={{ fontSize: '1.5rem', fontWeight: 700, margin: '0.5rem 0 0.75rem', color: '#f0e9cc' }}>Ask Nate a Question</h2>
          <p style={{ color: '#8a7f5a', maxWidth: '480px', margin: '0 auto 1.5rem', fontSize: '0.95rem' }}>
            Submit a Bible or theology question and it may be answered in a future episode or the Q&amp;A archive.
          </p>
          <div style={{ display: 'flex', gap: '0.75rem', justifyContent: 'center', flexWrap: 'wrap' }}>
            <a href="/questions" className="btn-primary">Browse Q&amp;A Archive →</a>
            <a href="/contact" className="btn-secondary">Submit a Question</a>
          </div>
        </div>
      </section>

    </main>
  )
}

const EMAIL_REGEX = /^[a-zA-Z0-9._%+\-]{1,64}@[a-zA-Z0-9.\-]{1,253}\.[a-zA-Z]{2,}$/

export function StudySignupPage() {
  const navigate = useNavigate()
  const [mode, setMode] = useState<'signup' | 'login'>('login')
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const [subscribeNewsletter, setSubscribeNewsletter] = useState(true)
  const [busy, setBusy] = useState(false)
  const [message, setMessage] = useState('')
  const [done, setDone] = useState(false)
  const [loggedInAs, setLoggedInAs] = useState('')
  const [fieldErrors, setFieldErrors] = useState<{ email?: string; password?: string }>({})
  // 2FA state
  const [totpPendingToken, setTotpPendingToken] = useState('')
  const [totpCode, setTotpCode] = useState('')
  const [totpMethod, setTotpMethod] = useState<'app' | 'email' | null>(null)
  const [resendStatus, setResendStatus] = useState<'idle' | 'sending' | 'sent'>('idle')

  useEffect(() => {
    readJson<StudyAuthStatusResponse>('/api/study-auth/status')
      .then(data => {
        if (data.authenticated) {
          setDone(true)
          setLoggedInAs(data.username ?? '')
        }
      })
      .catch(() => {})
  }, [])

  const submit = useCallback(async () => {
    if (!email.trim() || !password.trim()) {
      setMessage('Please enter your email and password.')
      return
    }
    if (!EMAIL_REGEX.test(email.trim())) {
      setMessage('Please enter a valid email address.')
      return
    }
    setBusy(true)
    setMessage('')
    try {
      const data = await readJson<{ username?: string; enrolledStudySlugs?: string[]; totpRequired?: boolean; pendingToken?: string }>(`/api/study-auth/${mode}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ username: email, password, ...(mode === 'signup' ? { subscribe: subscribeNewsletter } : {}) }),
      })
      if (data.totpRequired && data.pendingToken) {
        setTotpPendingToken(data.pendingToken)
        setTotpMethod((data as { method?: 'app' | 'email' }).method ?? 'app')
        return
      }
      setDone(true)
      setLoggedInAs(data.username ?? email.trim().toLowerCase())
      navigate('/study')
    } catch (err) {
      setMessage(err instanceof Error ? err.message : 'Something went wrong. Please try again.')
    } finally {
      setBusy(false)
    }
  }, [mode, email, password, subscribeNewsletter])

  const submitTotp = useCallback(async () => {
    if (!totpCode.trim()) { setMessage('Please enter your 6-digit code.'); return }
    setBusy(true)
    setMessage('')
    try {
      const data = await readJson<{ ok?: boolean; username?: string; usedRecoveryCode?: boolean }>('/api/study-auth/totp-verify', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ pendingToken: totpPendingToken, code: totpCode }),
      })
      setDone(true)
      setLoggedInAs(data.username ?? email.trim().toLowerCase())
      navigate('/study')
    } catch (err) {
      setMessage(err instanceof Error ? err.message : 'Invalid code. Please try again.')
    } finally {
      setBusy(false)
    }
  }, [totpPendingToken, totpCode, email])

  return (
    <main className="thanks-page" aria-label={mode === 'signup' ? 'Create account' : 'Sign in'}>
      <div className="thanks-card study-signup-page-card">
        <p className="eyebrow">Free Student Account</p>
        <h1>{mode === 'signup' ? 'Create Your Account' : 'Welcome Back'}</h1>

        {done ? (
          <>
            <p className="study-signup-success">You're signed in as <strong>{loggedInAs}</strong>.</p>
            <p style={{ color: '#b09e79', marginBottom: '1.5rem', fontSize: '0.95rem' }}>Head to the study hub to enroll in a track and begin your first lesson.</p>
            <div className="study-signup-actions" style={{ flexDirection: 'column', alignItems: 'stretch', gap: '0.75rem' }}>
              <button type="button" className="btn-primary" style={{ justifyContent: 'center' }} onClick={() => navigate('/study')}>Browse & Enroll in a Study →</button>
              <Link to="/study/account" className="btn-secondary" style={{ justifyContent: 'center' }}>My Account</Link>
            </div>
          </>
        ) : totpPendingToken ? (
          <div className="study-signup-form">
            {totpMethod === 'email' ? (
              <p style={{ color: '#a89a6a', marginBottom: '1.25rem', fontSize: '0.95rem' }}>
                📧 A 6-digit code was sent to your email address. Enter it below to sign in.
              </p>
            ) : (
              <p style={{ color: '#a89a6a', marginBottom: '1.25rem', fontSize: '0.95rem' }}>
                🔐 Open your authenticator app and enter the 6-digit code below.
              </p>
            )}
            <label htmlFor="totp-code">{totpMethod === 'email' ? 'Email Code' : 'Authenticator Code'}</label>
            <input
              id="totp-code"
              type="text"
              inputMode="numeric"
              autoComplete="one-time-code"
              value={totpCode}
              onChange={e => setTotpCode(e.target.value.replace(/\D/g, '').slice(0, 6))}
              placeholder="000000"
              autoFocus
              onKeyDown={e => e.key === 'Enter' && submitTotp()}
              style={{ letterSpacing: '0.3em', fontSize: '1.4rem', textAlign: 'center' }}
            />
            {message && <p className="study-signup-error">{message}</p>}
            <div className="study-signup-actions">
              <button type="button" className="btn-primary" disabled={busy} onClick={submitTotp}>
                {busy ? 'Verifying…' : 'Verify'}
              </button>
              <button type="button" className="btn-secondary" onClick={() => { setTotpPendingToken(''); setMessage(''); setTotpCode('') }}>Back</button>
            </div>
            {totpMethod === 'email' && (
              <p style={{ fontSize: '0.82rem', color: '#5a5440', marginTop: '1rem' }}>
                Didn't get it?{' '}
                <button type="button" disabled={resendStatus !== 'idle'} style={{ background: 'none', border: 'none', color: resendStatus === 'sent' ? '#7abf7a' : '#c9a84c', cursor: resendStatus === 'idle' ? 'pointer' : 'default', fontSize: 'inherit', textDecoration: 'underline', padding: 0 }} onClick={async () => {
                  setResendStatus('sending')
                  try {
                    await fetch('/api/study-auth/email-otp-resend', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ pendingToken: totpPendingToken }) })
                    setResendStatus('sent')
                    setTimeout(() => setResendStatus('idle'), 30000)
                  } catch { setResendStatus('idle') }
                }}>
                  {resendStatus === 'sending' ? 'Sending…' : resendStatus === 'sent' ? 'Code sent ✓' : 'Resend code'}
                </button>
              </p>
            )}
            {totpMethod === 'app' && (
              <p style={{ fontSize: '0.8rem', color: '#5a5440', marginTop: '1rem' }}>Lost access to your app? Enter one of your recovery codes instead.</p>
            )}
          </div>
        ) : (
          <>
            <div className="study-signup-form">
              <label htmlFor="signup-email">Email</label>
              <input
                id="signup-email"
                type="email"
                value={email}
                onChange={e => { setEmail(e.target.value); if (fieldErrors.email) setFieldErrors(prev => ({ ...prev, email: undefined })) }}
                onBlur={() => {
                  if (email.trim() && !EMAIL_REGEX.test(email.trim())) {
                    setFieldErrors(prev => ({ ...prev, email: 'Please enter a valid email address.' }))
                  } else {
                    setFieldErrors(prev => ({ ...prev, email: undefined }))
                  }
                }}
                placeholder="your@email.com"
                autoComplete="email"
                autoFocus
              />
              {fieldErrors.email && <p className="study-signup-field-error">{fieldErrors.email}</p>}
              <label htmlFor="signup-password">Password</label>
              <input
                id="signup-password"
                type="password"
                value={password}
                onChange={e => { setPassword(e.target.value); if (fieldErrors.password) setFieldErrors(prev => ({ ...prev, password: undefined })) }}
                onBlur={() => {
                  if (mode === 'signup' && password && password.length < 8) {
                    setFieldErrors(prev => ({ ...prev, password: 'Password must be at least 8 characters.' }))
                  } else {
                    setFieldErrors(prev => ({ ...prev, password: undefined }))
                  }
                }}
                placeholder="At least 8 characters"
                autoComplete={mode === 'signup' ? 'new-password' : 'current-password'}
                onKeyDown={e => e.key === 'Enter' && submit()}
              />
              {fieldErrors.password && <p className="study-signup-field-error">{fieldErrors.password}</p>}
              {mode === 'signup' && (
                <label className="contact-consent" style={{ marginTop: '0.75rem' }}>
                  <input
                    type="checkbox"
                    checked={subscribeNewsletter}
                    onChange={e => setSubscribeNewsletter(e.target.checked)}
                  />
                  <span>Send me updates from Verse by Verse with Nate. I can unsubscribe anytime.</span>
                </label>
              )}
              {message && <p className="study-signup-error">{message}</p>}
              <div className="study-signup-actions">
                <button type="button" className="btn-primary" disabled={busy} onClick={submit}>
                  {busy ? (mode === 'signup' ? 'Creating...' : 'Signing in...') : (mode === 'signup' ? 'Create Account' : 'Sign In')}
                </button>
              </div>
              <div className="study-signup-actions" style={{ marginTop: '1rem' }}>
                {mode === 'login' && (
                  <button type="button" className="btn-secondary" onClick={() => { setMode('signup'); setMessage('') }}>
                    Don't have an account? Sign up here
                  </button>
                )}
                {mode === 'signup' && (
                  <button type="button" className="btn-secondary" onClick={() => { setMode('login'); setMessage('') }}>
                    Already have an account? Sign in instead
                  </button>
                )}
              </div>
            </div>

            <div className="study-signup-why-grid" style={{ marginTop: '2rem' }}>
              <article className="study-signup-why-card">
                <p className="study-signup-why-icon" aria-hidden="true">📝</p>
                <h3>Notes on Every Lesson</h3>
                <p>Save your own notes per lesson — up to 500 notes across all tracks.</p>
              </article>
              <article className="study-signup-why-card">
                <p className="study-signup-why-icon" aria-hidden="true">📖</p>
                <h3>Space to Go Deep</h3>
                <p>Each note holds ~2,000 words so you can write as much as you need.</p>
              </article>
              <article className="study-signup-why-card">
                <p className="study-signup-why-icon" aria-hidden="true">🔒</p>
                <h3>Private to You</h3>
                <p>Your notes are tied to your account. Nobody else can read them.</p>
              </article>
              <article className="study-signup-why-card">
                <p className="study-signup-why-icon" aria-hidden="true">⚡</p>
                <h3>Free Forever</h3>
                <p>Just an email and password. No charge, no ads. Stay signed in 30 days.</p>
              </article>
            </div>
          </>
        )}

        <div className="study-signup-actions" style={{ marginTop: '1.5rem' }}>
          <Link to="/study/account" className="btn-secondary">My Account</Link>
          <Link to="/study" className="btn-secondary">Back to Studies</Link>
        </div>
      </div>
    </main>
  )
}

export function ColossiansStudyIndexPage({ content }: Props) {
  const { studySlug } = useParams<{ studySlug?: string }>()
  const studies = getStudies(content)
  const study = getStudyBySlug(studies, studySlug)
  const [auth, setAuth] = useState<StudyAuthState>({ checked: false, authenticated: false, username: '', enrolledStudySlugs: [] })
  const [enrolling, setEnrolling] = useState(false)
  const [enrollMessage, setEnrollMessage] = useState('')
  const [studyProgress, setStudyProgress] = useState<StudyProgress>({ completedSectionIds: [] })
  const [progressLoading, setProgressLoading] = useState(false)

  useEffect(() => {
    let cancelled = false
    readJson<StudyAuthStatusResponse>('/api/study-auth/status')
      .then(data => {
        if (cancelled) return
        setAuth({
          checked: true,
          authenticated: Boolean(data.authenticated),
          username: data.username ?? '',
          enrolledStudySlugs: normalizeEnrolledStudySlugs(data.enrolledStudySlugs),
        })
      })
      .catch(() => {
        if (cancelled) return
        setAuth({ checked: true, authenticated: false, username: '', enrolledStudySlugs: [] })
      })
    return () => {
      cancelled = true
    }
  }, [])

  if (!study) {
    return (
      <main className="thanks-page" aria-label="Study not found">
        <div className="thanks-card">
          <p className="eyebrow">Study Hub</p>
          <h1>Study not found</h1>
          <p>The study you requested is not available yet.</p>
          <Link to="/study" className="btn-primary">Back to Studies</Link>
        </div>
      </main>
    )
  }

  const sections = study.sections
  const chapterSummaries = getChapterSummaries(study)
  const releasedSections = sections.filter(isSectionReleased)
  const firstReleasedSection = releasedSections[0]
  const populatedChapterCount = chapterSummaries.filter(chapter => chapter.lessonCount > 0).length
  const enrolled = isEnrolledInStudy(auth, study.slug)

  useEffect(() => {
    if (!auth.checked || !auth.authenticated || !study || !enrolled) return
    let cancelled = false
    setProgressLoading(true)

    readJson<{ studySlug: string; completedSectionIds: string[] }>(`/api/study-progress/${encodeURIComponent(study.slug)}`)
      .then(data => {
        if (cancelled) return
        setStudyProgress({ completedSectionIds: Array.isArray(data.completedSectionIds) ? data.completedSectionIds : [] })
      })
      .catch(() => {
        if (cancelled) return
        setStudyProgress({ completedSectionIds: [] })
      })
      .finally(() => {
        if (cancelled) return
        setProgressLoading(false)
      })

    return () => {
      cancelled = true
    }
  }, [auth.checked, auth.authenticated, study, enrolled])

  async function enrollInStudy() {
    if (!study) return
    setEnrollMessage('')
    setEnrolling(true)
    try {
      const response = await readJson<{ enrolledStudySlugs?: string[]; studyTitle?: string }>(`/api/study-enrollment/${encodeURIComponent(study.slug)}`, {
        method: 'POST',
      })
      setAuth(prev => ({
        ...prev,
        enrolledStudySlugs: normalizeEnrolledStudySlugs(response.enrolledStudySlugs),
      }))
      setEnrollMessage(response.studyTitle ? `You are enrolled in ${response.studyTitle}.` : 'You are now enrolled.')
    } catch (err) {
      setEnrollMessage(err instanceof Error ? err.message : 'Unable to enroll right now.')
    } finally {
      setEnrolling(false)
    }
  }

  usePageMeta(
    `${study.title} | Bible Study`,
    study.description,
  )

  return (
    <main className="study-index-page" aria-label={`${study.title} study`}>
      <section className="section-study-course-hero">
        <div className="section-inner study-course-hero-inner">
          <Breadcrumbs items={[{ label: 'Home', href: '/' }, { label: 'Studies', href: '/study' }, { label: study.title }]} />
          <p className="eyebrow">Online Bible Class</p>
          <h1>{study.title}</h1>
          <p className="study-course-hero-copy">{study.description}</p>
          <div className="study-course-meta">
            <span>{releasedSections.length} lessons available now</span>
            <span>{chapterSummaries.length} chapters</span>
            <span>{populatedChapterCount} chapters with lessons</span>
            {enrolled && !progressLoading ? (
              <span>{studyProgress.completedSectionIds.length} lessons completed</span>
            ) : null}
            <span>Text + commentary + discussion</span>
            <span>Student notes enabled</span>
          </div>
          <div className="study-course-hero-actions">
            {enrolled && firstReleasedSection && <Link to={`/study/${study.slug}/${firstReleasedSection.id}`} className="btn-primary">Start Class</Link>}
            {!auth.authenticated && <Link to="/study/signup" className="btn-primary">Sign In to Enroll</Link>}
            {auth.authenticated && !enrolled && (
              <button type="button" className="btn-primary" disabled={enrolling} onClick={enrollInStudy}>
                {enrolling ? 'Enrolling...' : 'Enroll in This Study'}
              </button>
            )}
            {auth.authenticated && <Link to="/study/account" className="btn-secondary">My Account</Link>}
            {enrolled && <Link to={`/study/${study.slug}/notes`} className="btn-secondary">My Notes</Link>}
            {enrolled && <Link to={`/study/${study.slug}/community`} className="btn-secondary">Community</Link>}
            <Link to="/study" className="btn-secondary">Back to Studies</Link>
          </div>
          {enrollMessage && <p className="study-note-status" style={{ marginTop: '0.75rem' }}>{enrollMessage}</p>}
        </div>
      </section>

      {auth.checked && auth.authenticated && !enrolled && (
        <section className="section-study-module" aria-label="Enrollment required">
          <div className="section-inner">
            <article className="study-module-row study-module-row--disabled" aria-disabled="true">
              <div className="study-module-row-left">
                <p className="study-module-lesson">Enrollment Required</p>
                <h3>Enroll before entering lessons</h3>
                <p>You must enroll in this study before opening lessons or notes.</p>
                <div style={{ marginTop: '0.75rem' }}>
                  <button type="button" className="btn-primary" disabled={enrolling} onClick={enrollInStudy}>
                    {enrolling ? 'Enrolling...' : `Enroll in ${study.title}`}
                  </button>
                </div>
              </div>
            </article>
          </div>
        </section>
      )}

      {sections.length === 0 && (
        <section className="section-study-module">
          <div className="section-inner">
            <article className="study-module-row study-module-row--disabled" aria-disabled="true">
              <div className="study-module-row-left">
                <p className="study-module-lesson">Planned</p>
                <h3>Lessons are being prepared</h3>
                <p>Use the admin Studies editor to add section lessons and publish when ready.</p>
              </div>
            </article>
          </div>
        </section>
      )}

      {sections.length > 0 && (
        <section className="section-study-module" aria-label="Course lessons">
          <div className="section-inner">
            <div className="study-module-header">
              <p>Course Lessons</p>
              <h2>{study.title}</h2>
            </div>
            <div className="study-module-list">
              {sections.map((section, sectionIdx) => {
                const lessonNumber = getLessonNumber(sections, section.id)
                const isNew = isNewLesson(section)
                const coming = isComingSoon(section)
                const prevSection = sectionIdx > 0 ? sections[sectionIdx - 1] : null
                const prevCompleted = !prevSection || studyProgress.completedSectionIds.includes(prevSection.id)
                const lockedByProgress = enrolled && !coming && sectionIdx > 0 && !prevCompleted && !studyProgress.completedSectionIds.includes(section.id)
                const isDisabled = coming || !enrolled || lockedByProgress

                return (
                  <Link key={section.id} to={isDisabled ? '#' : `/study/${study.slug}/${section.id}`} className={`study-module-row${isDisabled ? ' study-module-row--disabled' : ''}`} onClick={e => isDisabled && e.preventDefault()}>
                    <div className="study-module-row-left">
                      <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', marginBottom: '0.25rem' }}>
                        <p className="study-module-lesson">Lesson {lessonNumber}</p>
                        {isNew && <span style={{ backgroundColor: '#4caf50', color: '#fff', padding: '0.2rem 0.5rem', borderRadius: '3px', fontSize: '0.75rem', fontWeight: '600' }}>New</span>}
                        {coming && <span style={{ backgroundColor: '#ffb74d', color: '#333', padding: '0.2rem 0.5rem', borderRadius: '3px', fontSize: '0.75rem', fontWeight: '600' }}>Coming {getReleaseDateDisplay(section)}</span>}
                        {!coming && !enrolled && <span style={{ backgroundColor: '#ef5350', color: '#fff', padding: '0.2rem 0.5rem', borderRadius: '3px', fontSize: '0.75rem', fontWeight: '600' }}>Enroll to open</span>}
                        {lockedByProgress && <span style={{ backgroundColor: '#5a5440', color: '#f0e9cc', padding: '0.2rem 0.5rem', borderRadius: '3px', fontSize: '0.75rem', fontWeight: '600' }}>Complete previous lesson</span>}
                        {enrolled && !lockedByProgress && studyProgress.completedSectionIds.includes(section.id) && (
                          <span style={{ display: 'inline-flex', alignItems: 'center', gap: '0.3rem', backgroundColor: '#1a3a2a', color: '#6fcf97', padding: '0.2rem 0.55rem', borderRadius: '3px', fontSize: '0.75rem', fontWeight: '600' }}>
                            <svg width="13" height="13" viewBox="0 0 13 13" fill="none" aria-hidden="true">
                              <circle cx="6.5" cy="6.5" r="6" stroke="#6fcf97" strokeWidth="1.2" />
                              <path d="M3.5 6.5l2 2 3.5-3.5" stroke="#6fcf97" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
                            </svg>
                            Completed
                          </span>
                        )}
                      </div>
                      <h3>{section.title}</h3>
                      <p>{section.summary}</p>
                    </div>
                    <div className="study-module-row-right">
                      <p className="study-section-reference">{section.reference}</p>
                      <p className="study-module-focus">Focus question</p>
                      <p>{getPrimaryQuestion(section)}</p>
                    </div>
                  </Link>
                )
              })}
            </div>
          </div>
        </section>
      )}
    </main>
  )
}

export function ColossiansStudySectionPage({ content }: Props) {
  const { studySlug, sectionId } = useParams<{ studySlug?: string; sectionId: string }>()
  const studies = getStudies(content)
  const study = getStudyBySlug(studies, studySlug)
  const sections = study?.sections ?? []
  const section = getSectionById(sections, sectionId)
  const sectionIndex = sections.findIndex(item => item.id === sectionId)
  const lessonNumber = getLessonNumber(sections, sectionId)
  const previousSection = sectionIndex > 0 ? sections[sectionIndex - 1] : null
  const nextSection = sectionIndex >= 0 && sectionIndex < sections.length - 1 ? sections[sectionIndex + 1] : null
  const sectionIsReleased = section ? isSectionReleased(section) : false

  const [auth, setAuth] = useState<StudyAuthState>({ checked: false, authenticated: false, username: '', enrolledStudySlugs: [] })
  const [usernameInput, setUsernameInput] = useState('')
  const [passwordInput, setPasswordInput] = useState('')
  const [authBusy, setAuthBusy] = useState(false)
  const [authMessage, setAuthMessage] = useState('')
  const [enrollBusy, setEnrollBusy] = useState(false)
  const [enrollMessage, setEnrollMessage] = useState('')

  const [noteMap, setNoteMap] = useState<Record<string, string>>({})
  const [openAnchor, setOpenAnchor] = useState<NoteAnchorId | null>(null)
  const [noteLoading, setNoteLoading] = useState(false)
  const [noteMessage, setNoteMessage] = useState('')
  const noteMapDirtyRef = useRef(false)
  const [contextNoteMenu, setContextNoteMenu] = useState<{ x: number; y: number; text: string; anchor: NoteAnchorId } | null>(null)
  const [completedSectionIds, setCompletedSectionIds] = useState<string[]>([])
  const [progressSaving, setProgressSaving] = useState(false)
  const [progressMessage, setProgressMessage] = useState('')
  const [checkpointAnswers, setCheckpointAnswers] = useState<Record<number, string>>({})
  const [showCelebration, setShowCelebration] = useState(false)
  const [bannerDismissed, setBannerDismissed] = useState(() => localStorage.getItem('study-banner-dismissed-v1') === '1')
  const [autoSaveMsg, setAutoSaveMsg] = useState('')
  const [_checkpointReflection, _setCheckpointReflection] = useState('')
  const [bsbPassage, setBsbPassage] = useState<string | null>(null)
  const [bsbPassageLoading, setBsbPassageLoading] = useState(false)

  const savedNoteCount = Object.values(noteMap).filter(v => v?.trim()).length
  const lessonAudioEmbedUrl = useMemo(() => {
    const trimmed = section?.audioEmbedUrl?.trim() ?? ''
    if (!trimmed) return ''
    return /^https?:\/\//i.test(trimmed) ? trimmed : ''
  }, [section?.audioEmbedUrl])

  const currentStudySlug = study?.slug ?? 'colossians'
  const noteId = section?.id ? getNoteId(currentStudySlug, section.id) : ''
  const isEnrolled = isEnrolledInStudy(auth, currentStudySlug)
  const lessonCompleted = section?.id ? completedSectionIds.includes(section.id) : false

  usePageMeta(
    section && study ? `${section.title} | ${study.title}` : 'Study',
    section?.summary,
  )

  useEffect(() => {
    let cancelled = false
    readJson<StudyAuthStatusResponse>('/api/study-auth/status')
      .then(data => {
        if (cancelled) return
        setAuth({
          checked: true,
          authenticated: Boolean(data.authenticated),
          username: data.username ?? '',
          enrolledStudySlugs: normalizeEnrolledStudySlugs(data.enrolledStudySlugs),
        })
      })
      .catch(() => {
        if (cancelled) return
        setAuth({ checked: true, authenticated: false, username: '', enrolledStudySlugs: [] })
      })

    return () => {
      cancelled = true
    }
  }, [])

  useEffect(() => {
    if (!section?.reference || !currentStudySlug) return
    let cancelled = false
    setBsbPassage(null)
    setBsbPassageLoading(true)
    const bookKey = (study?.bibleBook?.trim() || currentStudySlug).toLowerCase()
    const params = new URLSearchParams({ book: bookKey, reference: section.reference })
    fetch(`/api/bible-passage?${params}`)
      .then(r => r.json() as Promise<{ text?: string }>)
      .then(data => { if (!cancelled && data.text) setBsbPassage(data.text) })
      .catch(() => {})
      .finally(() => { if (!cancelled) setBsbPassageLoading(false) })
    return () => { cancelled = true }
  }, [section?.id, section?.reference, currentStudySlug, study?.bibleBook])

  useEffect(() => {
    if (!auth.checked || !auth.authenticated || !study || !isEnrolled) return
    let cancelled = false
    setProgressMessage('')

    readJson<{ studySlug: string; completedSectionIds: string[] }>(`/api/study-progress/${encodeURIComponent(currentStudySlug)}`)
      .then(data => {
        if (cancelled) return
        setCompletedSectionIds(Array.isArray(data.completedSectionIds) ? data.completedSectionIds : [])
      })
      .catch(() => {
        if (cancelled) return
        setCompletedSectionIds([])
      })
      .finally(() => {
        if (cancelled) return
      })

    return () => {
      cancelled = true
    }
  }, [auth.checked, auth.authenticated, study, isEnrolled, currentStudySlug])

  useEffect(() => {
    setCheckpointAnswers({})
  }, [section?.id])

  useEffect(() => {
    if (!auth.authenticated || !noteId || !isEnrolled) {
      setNoteMap({})
      noteMapDirtyRef.current = false
      return
    }

    let cancelled = false
    setNoteLoading(true)
    setNoteMessage('')

    readJson<{ note: string }>(`/api/study-notes/${encodeURIComponent(noteId)}`)
      .then(data => {
        if (cancelled) return
        setNoteMap(parseNoteMap(data.note ?? ''))
        noteMapDirtyRef.current = false
      })
      .catch(err => {
        if (cancelled) return
        setNoteMessage(err instanceof Error ? err.message : 'Unable to load your note.')
      })
      .finally(() => {
        if (cancelled) return
        setNoteLoading(false)
      })

    return () => {
      cancelled = true
    }
  }, [auth.authenticated, noteId, isEnrolled])

  async function submitAuth(mode: 'login' | 'signup') {
    setAuthBusy(true)
    setAuthMessage('')

    try {
      const payload = { username: usernameInput, password: passwordInput }
      const data = await readJson<{ username: string; enrolledStudySlugs?: string[] }>(`/api/study-auth/${mode}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      })
      setAuth({
        checked: true,
        authenticated: true,
        username: data.username ?? usernameInput.trim().toLowerCase(),
        enrolledStudySlugs: normalizeEnrolledStudySlugs(data.enrolledStudySlugs),
      })
      setUsernameInput('')
      setPasswordInput('')
      setAuthMessage(mode === 'signup' ? 'Account created. You can now save notes for each lesson.' : 'Signed in successfully.')
    } catch (err) {
      setAuthMessage(err instanceof Error ? err.message : 'Sign-in failed.')
    } finally {
      setAuthBusy(false)
    }
  }

  function updateNote(anchor: NoteAnchorId, html: string) {
    noteMapDirtyRef.current = true
    setNoteMap(prev => ({ ...prev, [anchor]: html }))
  }


  useEffect(() => {
    if (!openAnchor) return
    function onKeyDown(e: KeyboardEvent) {
      if (e.key === 'Escape') setOpenAnchor(null)
    }
    document.addEventListener('keydown', onKeyDown)
    return () => document.removeEventListener('keydown', onKeyDown)
  }, [openAnchor])

  useEffect(() => {
    if (!auth.authenticated || !noteId || noteLoading) return
    if (!noteMapDirtyRef.current) return
    const timer = setTimeout(async () => {
      if (!noteMapDirtyRef.current) return
      noteMapDirtyRef.current = false
      try {
        await readJson<{ ok: boolean }>(`/api/study-notes/${encodeURIComponent(noteId)}`, {
          method: 'PUT',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ note: JSON.stringify(noteMap) }),
        })
        setAutoSaveMsg('Auto-saved.')
        setTimeout(() => setAutoSaveMsg(''), 3000)
      } catch {
        noteMapDirtyRef.current = true
      }
    }, 2000)
    return () => clearTimeout(timer)
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [noteMap, noteId, auth.authenticated, noteLoading])

  useEffect(() => {
    if (!showCelebration) return
    function onKeyDown(e: KeyboardEvent) {
      if (e.key === 'Escape') setShowCelebration(false)
    }
    document.addEventListener('keydown', onKeyDown)
    return () => document.removeEventListener('keydown', onKeyDown)
  }, [showCelebration])

  function appendSelectedTextToNotes(selectedText: string, anchor: NoteAnchorId = 'general') {
    if (!selectedText.trim()) return
    const existing = noteMap[anchor] ?? ''
    const appended = existing
      ? `${existing}<p>${selectedText.trim()}</p>`
      : `<p>${selectedText.trim()}</p>`
    updateNote(anchor, appended)
    setOpenAnchor(anchor)
  }

  function handleLessonContentContextMenu(e: React.MouseEvent<HTMLDivElement>) {
    if (!auth.checked || !auth.authenticated || !isEnrolled || !study || !section) return
    const selection = window.getSelection()
    const selectedText = selection?.toString().trim() ?? ''
    if (!selectedText) {
      setContextNoteMenu(null)
      return
    }
    e.preventDefault()
    const anchorEl = (e.target as Element).closest('[data-note-anchor]')
    const anchor = (anchorEl?.getAttribute('data-note-anchor') ?? 'general') as NoteAnchorId
    setContextNoteMenu({ x: e.clientX + 4, y: e.clientY + 4, text: selectedText, anchor })
  }

  useEffect(() => {
    if (!contextNoteMenu) return
    const handleClick = () => setContextNoteMenu(null)
    window.addEventListener('mousedown', handleClick)
    return () => window.removeEventListener('mousedown', handleClick)
  }, [contextNoteMenu])

  function checkAndShowCelebration(newIds: string[], wasAlreadyComplete: boolean) {
    if (wasAlreadyComplete) return
    if (sections.length > 0 && newIds.length >= sections.length) {
      setShowCelebration(true)
    }
  }

  async function submitCheckpoint() {
    if (!study || !section?.id || progressSaving) return
    const checkpointQuestions = section.checkpointQuestions ?? []
    const allAnswered = checkpointQuestions.every((_, index) => (checkpointAnswers[index] ?? '').trim().length > 0)

    if (!allAnswered) {
      setProgressMessage('Please answer all checkpoint questions to mark this lesson complete.')
      return
    }

    setProgressSaving(true)
    setProgressMessage('')
    try {
      const data = await readJson<{ ok: boolean; completedSectionIds: string[] }>(`/api/study-progress/${encodeURIComponent(study.slug)}/${encodeURIComponent(section.id)}`, {
        method: 'POST',
      })
      const newIds = Array.isArray(data.completedSectionIds) ? data.completedSectionIds : []
      setCompletedSectionIds(newIds)
      setProgressMessage('')
      checkAndShowCelebration(newIds, lessonCompleted)
    } catch (err) {
      setProgressMessage(err instanceof Error ? err.message : 'Unable to save. Please try again.')
    } finally {
      setProgressSaving(false)
    }
  }

  async function enrollInCurrentStudy() {
    if (!study) return
    setEnrollMessage('')
    setEnrollBusy(true)
    try {
      const response = await readJson<{ enrolledStudySlugs?: string[]; studyTitle?: string }>(`/api/study-enrollment/${encodeURIComponent(study.slug)}`, { method: 'POST' })
      setAuth(prev => ({ ...prev, enrolledStudySlugs: normalizeEnrolledStudySlugs(response.enrolledStudySlugs) }))
      setEnrollMessage(response.studyTitle ? `You are enrolled in ${response.studyTitle}.` : 'You are now enrolled.')
    } catch (err) {
      setEnrollMessage(err instanceof Error ? err.message : 'Unable to enroll right now.')
    } finally {
      setEnrollBusy(false)
    }
  }

  if (!study || !section) {
    return (
      <main className="thanks-page" aria-label="Section not found">
        <div className="thanks-card">
          <p className="eyebrow">Study Hub</p>
          <h1>Section not found</h1>
          <p>The section you requested is not available yet.</p>
          <Link to="/study" className="btn-primary">Back to Studies</Link>
        </div>
      </main>
    )
  }

  if (!sectionIsReleased) {
    const releaseDateDisplay = getReleaseDateDisplay(section)
    return (
      <main className="thanks-page" aria-label="Lesson not yet available">
        <div className="thanks-card">
          <p className="eyebrow">{study.title}</p>
          <h1>Lesson Coming Soon</h1>
          <p>{releaseDateDisplay ? `This lesson will be available on ${releaseDateDisplay}.` : 'This lesson will be available soon.'}</p>
          <Link to={`/study/${study.slug}`} className="btn-primary">Back to Lessons</Link>
        </div>
      </main>
    )
  }

  if (!auth.checked) {
    return (
      <main className="thanks-page" aria-label="Loading">
        <div className="thanks-card">
          <p className="eyebrow">{study.title}</p>
          <p>Loading lesson...</p>
        </div>
      </main>
    )
  }

  if (!auth.authenticated) {
    return (
      <main className="thanks-page" aria-label="Sign in required">
        <div className="thanks-card">
          <p className="eyebrow">{study.title}</p>
          <h1>Sign In to Continue</h1>
          <p>Create a free account or sign in to access lessons and save your personal notes.</p>
          <div className="study-signup-actions" style={{ marginTop: '1.5rem' }}>
            <Link to="/study/signup" className="btn-primary">Create Account or Sign In</Link>
            <Link to="/study/account" className="btn-secondary">My Account</Link>
            <Link to={`/study/${study.slug}`} className="btn-secondary">Back to Lessons</Link>
          </div>
        </div>
      </main>
    )
  }

  if (!isEnrolled) {
    return (
      <main className="thanks-page" aria-label="Enrollment required">
        <div className="thanks-card">
          <p className="eyebrow">{study.title}</p>
          <h1>Enrollment Required</h1>
          <p>You need to enroll in this study before entering lessons.</p>
          <div className="study-signup-actions" style={{ marginTop: '1.5rem' }}>
            <button type="button" className="btn-primary" disabled={enrollBusy} onClick={enrollInCurrentStudy}>
              {enrollBusy ? 'Enrolling...' : `Enroll in ${study.title}`}
            </button>
            <Link to="/study/account" className="btn-secondary">My Account</Link>
            <Link to={`/study/${study.slug}`} className="btn-secondary">Back to Study</Link>
          </div>
          {enrollMessage && <p className="study-note-status" style={{ marginTop: '0.75rem' }}>{enrollMessage}</p>}
        </div>
      </main>
    )
  }

  return (
    <main className="study-section-page" aria-label={section.title}>
      {section.announcement && !bannerDismissed && (
        <div className="study-lesson-announcement-banner" role="alert">
          <span className="study-lesson-announcement-icon" aria-hidden="true">📢</span>
          <div className="study-lesson-announcement-body">
            <strong className="study-lesson-announcement-label">Announcement</strong>
            <p className="study-lesson-announcement-text">{section.announcement}</p>
          </div>
          <button
            type="button"
            className="study-lesson-announcement-close"
            aria-label="Dismiss announcement"
            onClick={() => {
              setBannerDismissed(true)
              localStorage.setItem('study-banner-dismissed-v1', '1')
            }}
          >×</button>
        </div>
      )}

      {showCelebration && study && (
        <div className="study-modal-overlay" role="dialog" aria-modal="true" aria-labelledby="celebrate-heading">
          <div className="study-modal-box" style={{ textAlign: 'center', maxWidth: '480px' }}>
            <p style={{ fontSize: '2.5rem', margin: '0 0 0.5rem' }}>🎉</p>
            <h2 id="celebrate-heading" style={{ margin: '0 0 0.75rem' }}>You finished {study.title}!</h2>
            <p style={{ color: '#b09e79', marginBottom: '1.5rem' }}>Your certificate of completion is ready on the study dashboard.</p>
            <div className="study-auth-actions" style={{ justifyContent: 'center' }}>
              <Link to="/study/account" className="btn-primary" onClick={() => setShowCelebration(false)}>View Certificate</Link>
              <button type="button" className="btn-secondary" onClick={() => setShowCelebration(false)}>Continue</button>
            </div>
          </div>
        </div>
      )}
      <section className="section-study-classroom" onContextMenu={handleLessonContentContextMenu}>
        <div className="section-inner study-classroom-shell">
          <div className="study-classroom-main">
            <Breadcrumbs items={[{ label: 'Home', href: '/' }, { label: 'Studies', href: '/study' }, { label: study.title, href: `/study/${study.slug}` }, { label: `Lesson ${lessonNumber}` }]} />
            <Link to={`/study/${study.slug}`} className="study-detail-back">Back to {study.title}</Link>
            <p className="study-lesson-label">Lesson {lessonNumber} of {sections.length}</p>
            <h1>{section.title}</h1>
            <p className="study-detail-reference">{section.reference}</p>
            <p className="study-detail-summary">{section.summary}</p>

            {lessonAudioEmbedUrl && (
              <article className="study-class-block">
                <h2>Lesson Audio</h2>
                {lessonAudioEmbedUrl.includes('spotify.com') ? (
                  <div className="study-audio-embed-wrap">
                    <iframe
                      src={lessonAudioEmbedUrl}
                      title={`${section.title} audio`}
                      width="100%"
                      height="152"
                      frameBorder="0"
                      allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture"
                      loading="lazy"
                    />
                  </div>
                ) : (
                  <EpisodeAudioPlayer src={lessonAudioEmbedUrl} title={section.title} size="compact" spotifyUrl={content.platformSpotifyUrl} />
                )}
              </article>
            )}

            <article className="study-class-block study-class-block--anchored" data-note-anchor="scripture">
              {isEnrolled && (
                <button
                  type="button"
                  className={`note-anchor-btn${noteMap['scripture']?.trim() ? ' note-anchor-btn--has-note' : ''}${openAnchor === 'scripture' ? ' note-anchor-btn--open' : ''}`}
                  onClick={() => setOpenAnchor(curr => curr === 'scripture' ? null : 'scripture')}
                  title={noteMap['scripture']?.trim() ? 'Edit scripture note' : 'Add note to Scripture'}
                  aria-pressed={openAnchor === 'scripture'}
                >✎</button>
              )}
              <h2>Scripture Text</h2>
              {bsbPassageLoading
                ? <p className="study-detail-copy" style={{ opacity: 0.5 }}>Loading passage…</p>
                : (bsbPassage ?? section.passageText)
                  ? (bsbPassage ?? section.passageText).split('\n\n').map((para, i) => (
                      <p key={i} className="study-detail-copy study-detail-copy--scripture">
                        {para.split('\n').map((line, j, arr) => j < arr.length - 1 ? <>{line}<br /></> : line)}
                      </p>
                    ))
                  : <p className="study-detail-copy" style={{ opacity: 0.5 }}>Passage text not available.</p>
              }
              {bsbPassage && <p style={{ fontSize: '0.78rem', color: '#5a5440', marginTop: '0.5rem' }}>Berean Standard Bible (BSB)</p>}
              {isEnrolled && openAnchor === 'scripture' && (
                <NoteCard
                  anchorLabel="Scripture Text"
                  html={noteMap['scripture'] ?? ''}
                  autoSaveMsg={autoSaveMsg}
                  onChange={html => updateNote('scripture', html)}
                  onClose={() => setOpenAnchor(null)}
                />
              )}
            </article>

            <article className="study-class-block study-class-block--anchored" data-note-anchor="commentary">
              {isEnrolled && (
                <button
                  type="button"
                  className={`note-anchor-btn${noteMap['commentary']?.trim() ? ' note-anchor-btn--has-note' : ''}${openAnchor === 'commentary' ? ' note-anchor-btn--open' : ''}`}
                  onClick={() => setOpenAnchor(curr => curr === 'commentary' ? null : 'commentary')}
                  title={noteMap['commentary']?.trim() ? 'Edit commentary note' : 'Add note to Commentary'}
                  aria-pressed={openAnchor === 'commentary'}
                >✎</button>
              )}
              <h2>Instructor Commentary</h2>
              {section.commentary.split(/\n{2,}/).map((para, i) => (
                <p key={i} className="study-detail-copy">
                  {para.split('\n').map((line, j, arr) => (
                    j < arr.length - 1 ? <>{line}<br /></> : line
                  ))}
                </p>
              ))}
              {isEnrolled && openAnchor === 'commentary' && (
                <NoteCard
                  anchorLabel="Commentary"
                  html={noteMap['commentary'] ?? ''}
                  autoSaveMsg={autoSaveMsg}
                  onChange={html => updateNote('commentary', html)}
                  onClose={() => setOpenAnchor(null)}
                />
              )}
            </article>

            <article className="study-class-block study-class-block--anchored" data-note-anchor="questions">
              {isEnrolled && (
                <button
                  type="button"
                  className={`note-anchor-btn${noteMap['questions']?.trim() ? ' note-anchor-btn--has-note' : ''}${openAnchor === 'questions' ? ' note-anchor-btn--open' : ''}`}
                  onClick={() => setOpenAnchor(curr => curr === 'questions' ? null : 'questions')}
                  title={noteMap['questions']?.trim() ? 'Edit reflection note' : 'Add note to Reflection Questions'}
                  aria-pressed={openAnchor === 'questions'}
                >✎</button>
              )}
              <h2>Reflection Questions</h2>
              <p className="study-detail-copy" style={{ marginBottom: '0.75rem', color: '#8a7f5a', fontSize: '0.9rem' }}>
                Work through these on your own, then share your thoughts in the Discussion below.
              </p>
              <ol className="study-detail-list">
                {section.studyQuestions.map((question, index) => (
                  <li key={index}>{question}</li>
                ))}
              </ol>
              <div style={{ marginTop: '1rem', display: 'flex', gap: '0.75rem', flexWrap: 'wrap' }}>
                <Link to={`/study/${study.slug}/${section.id}/quiz`} className="btn-secondary">Write My Answers</Link>
                <Link to={`/study/${study.slug}/community`} className="btn-primary">Go to Community</Link>
                <Link to={`/contact?source=community&study=${encodeURIComponent(study.title)}`} className="btn-secondary">Ask Nate</Link>
              </div>
              {isEnrolled && openAnchor === 'questions' && (
                <NoteCard
                  anchorLabel="Reflection Questions"
                  html={noteMap['questions'] ?? ''}
                  autoSaveMsg={autoSaveMsg}
                  onChange={html => updateNote('questions', html)}
                  onClose={() => setOpenAnchor(null)}
                />
              )}
            </article>

            {isEnrolled && !(section.checkpointQuestions && section.checkpointQuestions.length > 0) && (
              <article className="study-class-block" style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexWrap: 'wrap', gap: '1rem' }}>
                <div>
                  <h2 style={{ margin: 0 }}>Lesson Progress</h2>
                  <p style={{ margin: '0.25rem 0 0', fontSize: '0.85rem', color: '#5a5440' }}>No checkpoint questions for this lesson.</p>
                </div>
                <button
                  type="button"
                  className={lessonCompleted ? 'btn-secondary' : 'btn-primary'}
                  style={lessonCompleted ? { borderColor: '#2196f3', color: '#2196f3' } : {}}
                  disabled={progressSaving}
                  onClick={async () => {
                    if (!study || !section?.id) return
                    setProgressSaving(true)
                    const wasComplete = lessonCompleted
                    try {
                      const method = wasComplete ? 'DELETE' : 'POST'
                      const data = await readJson<{ ok: boolean; completedSectionIds: string[] }>(
                        `/api/study-progress/${encodeURIComponent(study.slug)}/${encodeURIComponent(section.id)}`,
                        { method }
                      )
                      const newIds = Array.isArray(data.completedSectionIds) ? data.completedSectionIds : []
                      setCompletedSectionIds(newIds)
                      if (!wasComplete) checkAndShowCelebration(newIds, false)
                    } catch { /* ignore */ }
                    finally { setProgressSaving(false) }
                  }}
                >
                  {progressSaving ? '…' : lessonCompleted ? '✓ Completed' : 'Mark as Completed'}
                </button>
              </article>
            )}

            {(section.checkpointQuestions && section.checkpointQuestions.length > 0) && (() => {
              const allAnswered = section.checkpointQuestions!.every((_, i) => (checkpointAnswers[i] ?? '').trim().length > 0)
              return (
                <article className="study-class-block">
                  <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexWrap: 'wrap', gap: '0.5rem', marginBottom: '1rem' }}>
                    <h2 style={{ margin: 0 }}>Checkpoint</h2>
                    {lessonCompleted && (
                      <span style={{ background: '#1565c0', color: '#fff', padding: '0.2rem 0.65rem', borderRadius: '4px', fontSize: '0.8rem', fontWeight: 600 }}>
                        ✓ Completed
                      </span>
                    )}
                  </div>
                  {section.checkpointPrompt && <p className="study-detail-copy">{section.checkpointPrompt}</p>}
                  <div style={{ display: 'grid', gap: '1rem', marginTop: section.checkpointPrompt ? '1rem' : undefined }}>
                    {section.checkpointQuestions!.map((question, index) => (
                      <div key={index}>
                        <p style={{ margin: '0 0 0.5rem', fontWeight: 600 }}>{question}</p>
                        <textarea
                          rows={3}
                          value={checkpointAnswers[index] ?? ''}
                          onChange={e => setCheckpointAnswers(prev => ({ ...prev, [index]: e.target.value }))}
                          placeholder="Write your answer here..."
                          style={{ width: '100%', boxSizing: 'border-box', resize: 'vertical', padding: '0.85rem 1rem', borderRadius: '12px', border: `1px solid ${(checkpointAnswers[index] ?? '').trim() ? '#2a4a2a' : '#2a2518'}`, background: '#14130f', color: '#f0ead8' }}
                        />
                      </div>
                    ))}
                  </div>
                  <div style={{ marginTop: '1.25rem', display: 'flex', gap: '0.75rem', flexWrap: 'wrap', alignItems: 'center' }}>
                    <button
                      type="button"
                      className="btn-primary"
                      onClick={submitCheckpoint}
                      disabled={!isEnrolled || progressSaving || !allAnswered}
                    >
                      {progressSaving ? 'Saving…' : lessonCompleted ? 'Update Answers' : 'Mark as Completed'}
                    </button>
                    {!allAnswered && (
                      <span style={{ fontSize: '0.85rem', color: '#5a5440' }}>Answer all questions to mark this lesson complete.</span>
                    )}
                    {progressMessage && <span style={{ fontSize: '0.85rem', color: '#e07a7a' }}>{progressMessage}</span>}
                  </div>
                </article>
              )
            })()}

            <article className="study-class-block">
              <h2>Lesson Discussion</h2>
              <p className="study-detail-copy" style={{ fontSize: '0.88rem', color: '#7a7060', margin: '0 0 1rem' }}>
                Share a thought or reaction with other students in this lesson.{' '}
                <Link to={`/study/${study.slug}/community`} style={{ color: '#e0b840' }}>See all community posts →</Link>
              </p>
              <StudySectionComments studySlug={currentStudySlug} sectionId={section.id} isEnrolled={isEnrolled} />
            </article>
          </div>

          <aside className="study-classroom-sidebar" aria-label="Lesson tools">
            <article className="study-class-side-block">
              <h3>Study Track</h3>
              <p>{study.title}</p>
              <p>{study.description}</p>
            </article>

            <article className="study-class-side-block">
              <h3>Greek Word Study</h3>
              {section.greekNotes.length > 0 ? (
                <ul className="study-detail-list">
                  {section.greekNotes.map((note, index) => (
                    <li key={index}>{note}</li>
                  ))}
                </ul>
              ) : (
                <p className="study-detail-copy">Greek notes will be added for this lesson.</p>
              )}
            </article>

            <article className="study-class-side-block">
              <h3>Student Notes</h3>
              {!auth.checked && <p className="study-detail-copy">Checking sign-in status...</p>}
              {auth.checked && !auth.authenticated && (
                <div className="study-auth-box">
                  <p className="study-auth-why">Sign in to save notes for this lesson.</p>
                  <label htmlFor="study-email">Email</label>
                  <input id="study-email" type="email" value={usernameInput} onChange={e => setUsernameInput(e.target.value)} placeholder="your@email.com" autoComplete="email" />
                  <label htmlFor="study-password">Password</label>
                  <input id="study-password" type="password" value={passwordInput} onChange={e => setPasswordInput(e.target.value)} placeholder="At least 8 characters" autoComplete="current-password" />
                  <div className="study-auth-actions">
                    <button type="button" className="btn-secondary" disabled={authBusy} onClick={() => submitAuth('login')}>Sign In</button>
                    <button type="button" className="btn-primary" disabled={authBusy} onClick={() => submitAuth('signup')}>Create Account</button>
                  </div>
                </div>
              )}
              {auth.checked && auth.authenticated && (
                <div className="study-notes-box">
                  <p className="study-notes-user">Signed in as {auth.username}</p>
                  <Link to="/study/account" className="btn-secondary" style={{ marginBottom: '0.5rem', display: 'inline-block' }}>My Account</Link>
                  {noteLoading ? (
                    <p style={{ color: '#7a7060', fontSize: '0.85rem', marginTop: '0.5rem' }}>Loading notes…</p>
                  ) : (
                    <>
                      {savedNoteCount > 0 && (
                        <p style={{ fontSize: '0.82rem', color: '#7a9c6a', marginBottom: '0.5rem' }}>
                          {savedNoteCount} note{savedNoteCount !== 1 ? 's' : ''} saved ✓
                        </p>
                      )}
                      <div className="note-anchor-list">
                        {NOTE_ANCHORS.map(({ id, label }) => {
                          const hasNote = !!(noteMap[id]?.trim())
                          return (
                            <button
                              key={id}
                              type="button"
                              className={`note-anchor-list-item${hasNote ? ' note-anchor-list-item--has' : ''}${openAnchor === id ? ' note-anchor-list-item--open' : ''}`}
                              onClick={() => setOpenAnchor(curr => curr === id ? null : id as NoteAnchorId)}
                            >
                              <span>{label}</span>
                              {hasNote && <span className="note-anchor-dot" aria-hidden="true">●</span>}
                            </button>
                          )
                        })}
                      </div>
                      <p style={{ margin: '0.5rem 0 0', color: '#7a7060', fontSize: '0.82rem' }}>Click a section above to add notes. Right-click lesson text to append a selection.</p>
                    </>
                  )}
                </div>
              )}
              {(authMessage || noteMessage || progressMessage) && <p className="study-note-status">{authMessage || noteMessage || progressMessage}</p>}
            </article>

            <article className="study-class-side-block">
              <h3>Lesson Navigation</h3>
              <div className="study-detail-nav">
                {previousSection ? (
                  <Link to={`/study/${study.slug}/${previousSection.id}`} className="btn-secondary">Previous Lesson</Link>
                ) : <span className="study-nav-placeholder" />}
                {nextSection && !isSectionReleased(nextSection) ? (
                  <span className="study-nav-placeholder">Available {getReleaseDateDisplay(nextSection)}</span>
                ) : nextSection && !lessonCompleted ? (
                  <span className="study-nav-placeholder" title="Complete this lesson's checkpoint to unlock the next one">🔒 Complete checkpoint first</span>
                ) : nextSection ? (
                  <Link to={`/study/${study.slug}/${nextSection.id}`} className="btn-secondary">Next Lesson</Link>
                ) : <span className="study-nav-placeholder" />}
              </div>
            </article>
          </aside>

          {contextNoteMenu && (
            <div
              style={{
                position: 'fixed',
                left: contextNoteMenu.x,
                top: contextNoteMenu.y,
                zIndex: 50,
                backgroundColor: '#1f1d19',
                border: '1px solid #3f3b2f',
                borderRadius: '12px',
                padding: '0.75rem',
                boxShadow: '0 10px 30px rgba(0,0,0,0.25)',
                minWidth: '220px',
              }}
              onMouseDown={e => e.stopPropagation()}
            >
              <p style={{ margin: '0 0 0.35rem', color: '#ece3c6', fontSize: '0.95rem' }}>Add to <strong style={{ color: '#c9a84c' }}>{ANCHOR_LABELS[contextNoteMenu.anchor] ?? 'Notes'}</strong>:</p>
              <div style={{ marginBottom: '0.75rem', maxHeight: '100px', overflow: 'auto', color: '#f0ead8', fontSize: '0.9rem' }}>
                {contextNoteMenu.text}
              </div>
              <button
                type="button"
                className="btn-primary"
                onClick={() => {
                  appendSelectedTextToNotes(contextNoteMenu.text, contextNoteMenu.anchor)
                  setContextNoteMenu(null)
                }}
              >
                Add to Notes
              </button>
            </div>
          )}

        </div>
      </section>
    </main>
  )
}

export function ColossiansStudyNotesPage({ content }: Props) {
  const { studySlug } = useParams<{ studySlug?: string }>()
  const studies = getStudies(content)
  const study = getStudyBySlug(studies, studySlug)
  const [auth, setAuth] = useState<StudyAuthState>({ checked: false, authenticated: false, username: '', enrolledStudySlugs: [] })
  const [notes, setNotes] = useState<StudyNotesMap>({})
  const [loading, setLoading] = useState(true)
  const [message, setMessage] = useState('')
  const [activeNoteTab, setActiveNoteTab] = useState('')

  usePageMeta(
    study ? `My Notes | ${study.title}` : 'My Study Notes',
    study ? `Your personal lesson notes for ${study.title}.` : undefined,
  )

  useEffect(() => {
    let cancelled = false

    async function load() {
      try {
        const authData = await readJson<StudyAuthStatusResponse>('/api/study-auth/status')
        if (cancelled) return

        if (!authData.authenticated) {
          setAuth({ checked: true, authenticated: false, username: '', enrolledStudySlugs: [] })
          setLoading(false)
          return
        }

        const enrolledStudySlugs = normalizeEnrolledStudySlugs(authData.enrolledStudySlugs)
        setAuth({
          checked: true,
          authenticated: true,
          username: authData.username ?? '',
          enrolledStudySlugs,
        })

        if (!enrolledStudySlugs.includes((study?.slug ?? '').toLowerCase())) {
          setLoading(false)
          return
        }

        const notesData = await readJson<{ notes: StudyNotesMap }>('/api/study-notes')
        if (cancelled) return
        setNotes(notesData.notes ?? {})
      } catch (err) {
        if (cancelled) return
        setMessage(err instanceof Error ? err.message : 'Unable to load notes.')
      } finally {
        if (cancelled) return
        setLoading(false)
      }
    }

    load()
    return () => {
      cancelled = true
    }
  }, [])

  if (!study) {
    return (
      <main className="thanks-page" aria-label="Study not found">
        <div className="thanks-card">
          <p className="eyebrow">Study Hub</p>
          <h1>Study not found</h1>
          <p>The study you requested is not available yet.</p>
          <Link to="/study" className="btn-primary">Back to Studies</Link>
        </div>
      </main>
    )
  }

  const prefix = `${study.slug}--`
  const enrolled = isEnrolledInStudy(auth, study.slug)
  const entries = Object.entries(notes)
    .filter(([key]) => key.startsWith(prefix))
    .map(([key, note]) => {
      const sectionId = key.slice(prefix.length)
      const section = study.sections.find(item => item.id === sectionId)
      return { sectionId, section, note }
    })
    .filter(item => item.note && item.note.trim())

  const enrolledStudies = !loading && auth.authenticated
    ? getStudies(content).filter(s => (auth.enrolledStudySlugs ?? []).includes(s.slug.toLowerCase()))
    : []

  return (
    <main className="study-section-page" aria-label="My study notes">
      <section className="section-study-classroom">
        <div className="section-inner">
          <Breadcrumbs items={[{ label: 'Home', href: '/' }, { label: 'Studies', href: '/study' }, { label: study.title, href: `/study/${study.slug}` }, { label: 'My Notes' }]} />
          <Link to={`/study/${study.slug}`} className="study-detail-back">Back to {study.title}</Link>
          <p className="study-lesson-label">Student Workspace</p>
          <h1>My Lesson Notes</h1>
          {!loading && auth.authenticated && <p className="study-detail-summary">Signed in as {auth.username}</p>}
          {enrolledStudies.length > 1 && (
            <div className="study-track-switcher">
              <p className="study-lesson-label">Switch Track</p>
              <div className="study-track-switcher-tabs">
                {enrolledStudies.map(s => (
                  <Link
                    key={s.slug}
                    to={`/study/${s.slug}/notes`}
                    className={`study-track-tab${s.slug === study.slug ? ' study-track-tab--active' : ''}`}
                  >
                    {s.title}
                  </Link>
                ))}
              </div>
            </div>
          )}
          {!loading && auth.authenticated && (
            <div className="study-signup-actions" style={{ marginBottom: '1rem' }}>
              <Link to="/study/account" className="btn-secondary">My Account</Link>
              <Link to={`/study/${study.slug}`} className="btn-secondary">Back to Lessons</Link>
            </div>
          )}

          {loading && <p className="study-detail-copy">Loading your notes...</p>}
          {!loading && !auth.authenticated && (
            <article className="study-class-block">
              <h2>Sign In Required</h2>
              <p className="study-detail-copy">Open any lesson and sign in from the Student Notes panel to see your saved notes here.</p>
              <Link to="/study/signup" className="btn-primary">Create Account or Sign In</Link>
            </article>
          )}
          {!loading && auth.authenticated && !enrolled && (
            <article className="study-class-block">
              <h2>Enrollment Required</h2>
              <p className="study-detail-copy">You need to enroll in this study before accessing your notes.</p>
              <Link to={`/study/${study.slug}`} className="btn-primary">Go to Study Enrollment</Link>
            </article>
          )}
          {!loading && auth.authenticated && enrolled && entries.length === 0 && (
            <article className="study-class-block">
              <h2>No Notes Yet</h2>
              <p className="study-detail-copy">You have not saved notes yet. Open a lesson and use the Student Notes area to start.</p>
              {study.sections[0] && <Link to={`/study/${study.slug}/${study.sections[0].id}`} className="btn-primary">Open First Lesson</Link>}
            </article>
          )}
          {!loading && auth.authenticated && enrolled && entries.length > 0 && (() => {
            const sorted = [...entries].sort((a, b) => {
              const aNum = a.section ? getLessonNumber(study.sections, a.section.id) : 0
              const bNum = b.section ? getLessonNumber(study.sections, b.section.id) : 0
              return aNum - bNum
            })
            const active = sorted.find(item => item.sectionId === activeNoteTab) ?? sorted[0]
            return (
              <div className="study-notebook">
                <div className="study-notebook-tabs" role="tablist" aria-label="Lesson notes">
                  {sorted.map(({ sectionId, section }) => (
                    <button
                      key={sectionId}
                      type="button"
                      role="tab"
                      aria-selected={active.sectionId === sectionId}
                      className={`study-notebook-tab${active.sectionId === sectionId ? ' study-notebook-tab--active' : ''}`}
                      onClick={() => setActiveNoteTab(sectionId)}
                    >
                      {section ? `Lesson ${getLessonNumber(study.sections, section.id)}` : 'Saved Note'}
                    </button>
                  ))}
                </div>
                <article className="study-notebook-page">
                  <p className="study-module-lesson">{active.section ? `Lesson ${getLessonNumber(study.sections, active.section.id)}` : 'Saved Note'}</p>
                  <h3>{active.section?.title ?? active.sectionId}</h3>
                  <p className="study-detail-reference">{active.section ? active.section.reference : 'Lesson reference unavailable'}</p>
                  {(() => {
                    const anchorMap = parseNoteMap(active.note)
                    const hasContent = Object.values(anchorMap).some(v => v?.trim())
                    if (!hasContent) return <p className="study-detail-copy">No notes saved for this lesson yet.</p>
                    return Object.entries(anchorMap).map(([key, html]) => (
                      html?.trim() ? (
                        <div key={key} style={{ marginBottom: '1.25rem' }}>
                          <p className="study-module-focus" style={{ marginBottom: '0.5rem' }}>{ANCHOR_LABELS[key] ?? key}</p>
                          <div className="study-note-rich-content" dangerouslySetInnerHTML={{ __html: html }} />
                        </div>
                      ) : null
                    ))
                  })()}
                  {active.section && <Link to={`/study/${study.slug}/${active.section.id}`} className="btn-secondary">Open Lesson</Link>}
                </article>
              </div>
            )
          })()}
          {message && <p className="study-note-status">{message}</p>}
        </div>
      </section>
    </main>
  )
}

export function StudyAccountPage() {
  const navigate = useNavigate()
  const location = useLocation()

  const [auth, setAuth] = useState<StudyAuthState>({ checked: false, authenticated: false, username: '', enrolledStudySlugs: [], displayName: '', subscribeNewsletter: true })
  const [overview, setOverview] = useState<StudyAccountOverview | null>(null)
  const [loadingOverview, setLoadingOverview] = useState(false)

  const [displayNameInput, setDisplayNameInput] = useState('')
  const [avatarUrlInput, setAvatarUrlInput] = useState('')
  const [profileMessage, setProfileMessage] = useState('')
  const [profileBusy, setProfileBusy] = useState(false)
  const [avatarUploadBusy, setAvatarUploadBusy] = useState(false)
  const [avatarUploadMessage, setAvatarUploadMessage] = useState('')

  const [subscribeNewsletter, setSubscribeNewsletter] = useState(true)
  const [studyRemindersEnabled, setStudyRemindersEnabled] = useState(true)
  const [prefMessage, setPrefMessage] = useState('')
  const [prefBusy, setPrefBusy] = useState(false)
  const [accountModal, setAccountModal] = useState<'none' | 'enrollments' | 'changeEmail' | 'changePassword' | 'profile' | 'preferences' | 'export' | 'choose2fa' | 'setup2fa' | 'setup2fa-email' | 'disable2fa' | 'recoveryCodes'>('none')

  // 2FA state
  const [twoFaQr, setTwoFaQr] = useState('')
  const [twoFaSecret, setTwoFaSecret] = useState('')
  const [twoFaCode, setTwoFaCode] = useState('')
  const [twoFaMessage, setTwoFaMessage] = useState('')
  const [twoFaBusy, setTwoFaBusy] = useState(false)
  const [twoFaRecoveryCodes, setTwoFaRecoveryCodes] = useState<string[]>([])
  const [disablePassword, setDisablePassword] = useState('')

  const [emailCurrentPassword, setEmailCurrentPassword] = useState('')
  const [emailNew, setEmailNew] = useState('')
  const [emailTokenInput, setEmailTokenInput] = useState('')
  const [emailMessage, setEmailMessage] = useState('')
  const [emailBusy, setEmailBusy] = useState(false)

  const [enrollBusySlug, setEnrollBusySlug] = useState('')
  const [enrollMessage, setEnrollMessage] = useState('')

  const [exporting, setExporting] = useState(false)
  const [exportMessage, setExportMessage] = useState('')

  const [pwCurrent, setPwCurrent] = useState('')
  const [pwNew, setPwNew] = useState('')
  const [pwConfirm, setPwConfirm] = useState('')
  const [pwBusy, setPwBusy] = useState(false)
  const [pwMessage, setPwMessage] = useState('')
  const [pwSuccess, setPwSuccess] = useState(false)

  const [signOutBusy, setSignOutBusy] = useState(false)

  const [deleteStep, setDeleteStep] = useState<'idle' | 'warn1' | 'warn2'>('idle')
  const [deleteConfirmInput, setDeleteConfirmInput] = useState('')
  const [deleteBusy, setDeleteBusy] = useState(false)
  const [deleteMessage, setDeleteMessage] = useState('')

  useEffect(() => {
    document.title = 'My Account | Study Hub'
    readJson<StudyAuthStatusResponse>('/api/study-auth/status')
      .then(data => {
        setAuth({
          checked: true,
          authenticated: Boolean(data.authenticated),
          username: data.username ?? '',
          displayName: data.displayName ?? '',
          subscribeNewsletter: data.subscribeNewsletter !== false,
          studyRemindersEnabled: data.studyRemindersEnabled === true,
          avatarUrl: data.avatarUrl ?? '',
          enrolledStudySlugs: normalizeEnrolledStudySlugs(data.enrolledStudySlugs),
          totpEnabled: data.totpEnabled === true,
          twoFaMethod: data.twoFaMethod ?? null,
          totpRecoveryCodesRemaining: data.totpRecoveryCodesRemaining ?? 0,
        })
      })
      .catch(() => setAuth({ checked: true, authenticated: false, username: '', enrolledStudySlugs: [], displayName: '', subscribeNewsletter: true }))
  }, [])

  useEffect(() => {
    if (!auth.authenticated) return
    setLoadingOverview(true)
    readJson<StudyAccountOverview>('/api/study-account/overview')
      .then(data => {
        setOverview(data)
        setDisplayNameInput(data.profile.displayName ?? '')
        setAvatarUrlInput(data.profile.avatarUrl ?? '')
        setSubscribeNewsletter(data.profile.subscribeNewsletter !== false)
        setStudyRemindersEnabled(data.profile.studyRemindersEnabled === true)
      })
      .catch(() => {})
      .finally(() => setLoadingOverview(false))
  }, [auth.authenticated])

  useEffect(() => {
    if (!auth.authenticated) return
    const token = new URLSearchParams(location.search).get('verifyEmailToken')
    if (!token) return
    setEmailTokenInput(token)
    setEmailBusy(true)
    readJson<{ ok: boolean; username: string }>('/api/study-account/verify-email-change', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ token }),
    })
      .then(data => {
        setEmailMessage('Email address verified and updated successfully.')
        setAuth(prev => ({ ...prev, username: data.username }))
        navigate('/study/account', { replace: true })
      })
      .catch(err => setEmailMessage(err instanceof Error ? err.message : 'Unable to verify email token.'))
      .finally(() => setEmailBusy(false))
  }, [auth.authenticated, location.search, navigate])

  async function refreshOverview() {
    const data = await readJson<StudyAccountOverview>('/api/study-account/overview')
    setOverview(data)
    setDisplayNameInput(data.profile.displayName ?? '')
    setAvatarUrlInput(data.profile.avatarUrl ?? '')
    setSubscribeNewsletter(data.profile.subscribeNewsletter !== false)
    setStudyRemindersEnabled(data.profile.studyRemindersEnabled === true)
  }

  async function handleAvatarUpload(file: File) {
    setAvatarUploadBusy(true)
    setAvatarUploadMessage('')
    try {
      if (!file.type.startsWith('image/')) {
        throw new Error('Please upload an image file.')
      }
      const reader = new FileReader()
      const dataUrl = await new Promise<string>((resolve, reject) => {
        reader.onload = () => {
          if (typeof reader.result === 'string') resolve(reader.result)
          else reject(new Error('Unable to read image file.'))
        }
        reader.onerror = () => reject(new Error('Failed to read image file.'))
        reader.readAsDataURL(file)
      })

      const result = await readJson<{ ok: boolean; url: string }>('/api/study-account/avatar-upload', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ filename: file.name, dataUrl }),
      })
      setAvatarUrlInput(result.url)
      setAvatarUploadMessage('Avatar uploaded successfully. Save profile to keep it.')
    } catch (err) {
      setAvatarUploadMessage(err instanceof Error ? err.message : 'Unable to upload avatar.')
    } finally {
      setAvatarUploadBusy(false)
    }
  }

  async function handleProfileSave() {
    setProfileBusy(true)
    setProfileMessage('')
    try {
      const data = await readJson<{ ok: boolean; displayName: string; avatarUrl?: string }>('/api/study-account/profile', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ displayName: displayNameInput, avatarUrl: avatarUrlInput.trim() }),
      })
      setAuth(prev => ({ ...prev, displayName: data.displayName, avatarUrl: data.avatarUrl ?? prev.avatarUrl }))
      if (data.avatarUrl) {
        setAvatarUrlInput(data.avatarUrl)
      }
      setProfileMessage('Profile saved.')
      await refreshOverview()
    } catch (err) {
      setProfileMessage(err instanceof Error ? err.message : 'Unable to save profile.')
    } finally {
      setProfileBusy(false)
    }
  }

  async function handlePreferenceSave() {
    setPrefBusy(true)
    setPrefMessage('')
    try {
      const data = await readJson<{ ok: boolean; subscribeNewsletter: boolean; studyRemindersEnabled: boolean }>('/api/study-account/preferences', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ subscribeNewsletter, studyRemindersEnabled }),
      })
      setAuth(prev => ({ ...prev, subscribeNewsletter: data.subscribeNewsletter, studyRemindersEnabled: data.studyRemindersEnabled }))
      setPrefMessage('Preferences updated.')
      await refreshOverview()
    } catch (err) {
      setPrefMessage(err instanceof Error ? err.message : 'Unable to save preferences.')
    } finally {
      setPrefBusy(false)
    }
  }

  async function handleRequestEmailChange() {
    setEmailBusy(true)
    setEmailMessage('')
    try {
      await readJson<{ ok: boolean }>('/api/study-account/request-email-change', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ newEmail: emailNew, currentPassword: emailCurrentPassword }),
      })
      setEmailCurrentPassword('')
      setEmailMessage('Verification email sent. Open the link in that email to complete the change.')
    } catch (err) {
      setEmailMessage(err instanceof Error ? err.message : 'Unable to request email change.')
    } finally {
      setEmailBusy(false)
    }
  }

  async function handleVerifyTokenInput() {
    setEmailBusy(true)
    setEmailMessage('')
    try {
      const data = await readJson<{ ok: boolean; username: string }>('/api/study-account/verify-email-change', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ token: emailTokenInput }),
      })
      setAuth(prev => ({ ...prev, username: data.username }))
      setEmailTokenInput('')
      setEmailMessage('Email address verified and updated successfully.')
      await refreshOverview()
    } catch (err) {
      setEmailMessage(err instanceof Error ? err.message : 'Unable to verify email token.')
    } finally {
      setEmailBusy(false)
    }
  }

  async function handleEnrollmentToggle(studySlug: string, enrolled: boolean) {
    setEnrollBusySlug(studySlug)
    setEnrollMessage('')
    try {
      const data = await readJson<{ enrolledStudySlugs?: string[]; studyTitle?: string }>(`/api/study-enrollment/${encodeURIComponent(studySlug)}`, {
        method: enrolled ? 'DELETE' : 'POST',
      })
      const slugs = normalizeEnrolledStudySlugs(data.enrolledStudySlugs)
      setAuth(prev => ({ ...prev, enrolledStudySlugs: slugs }))
      setEnrollMessage(enrolled ? `Unenrolled from ${data.studyTitle ?? studySlug}.` : `Enrolled in ${data.studyTitle ?? studySlug}.`)
      await refreshOverview()
    } catch (err) {
      setEnrollMessage(err instanceof Error ? err.message : 'Unable to update enrollment.')
    } finally {
      setEnrollBusySlug('')
    }
  }

  async function handleExport() {
    setExporting(true)
    setExportMessage('')
    try {
      const res = await fetch('/api/study-account/export-notes')
      if (!res.ok) throw new Error('Export failed. Please try again.')
      const blob = await res.blob()
      const url = URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = `my-study-notes-${new Date().toISOString().slice(0, 10)}.docx`
      a.click()
      URL.revokeObjectURL(url)
      setExportMessage('Download started.')
    } catch (err) {
      setExportMessage(err instanceof Error ? err.message : 'Export failed.')
    } finally {
      setExporting(false)
    }
  }

  async function handleChangePassword() {
    setPwMessage('')
    setPwSuccess(false)
    if (!pwCurrent || !pwNew || !pwConfirm) { setPwMessage('Please fill in all password fields.'); return }
    if (pwNew !== pwConfirm) { setPwMessage('New passwords do not match.'); return }
    if (pwNew.length < 8) { setPwMessage('New password must be at least 8 characters.'); return }
    setPwBusy(true)
    try {
      await readJson<{ ok: boolean }>('/api/study-account/change-password', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ currentPassword: pwCurrent, newPassword: pwNew }),
      })
      setPwSuccess(true)
      setPwCurrent(''); setPwNew(''); setPwConfirm('')
    } catch (err) {
      setPwMessage(err instanceof Error ? err.message : 'Password change failed.')
    } finally {
      setPwBusy(false)
    }
  }

  async function handleSignOut() {
    setSignOutBusy(true)
    try {
      await readJson<{ ok: boolean }>('/api/study-auth/logout', { method: 'POST' })
      navigate('/study')
    } catch {
      setSignOutBusy(false)
    }
  }

  async function handleDeleteAccount() {
    setDeleteBusy(true)
    setDeleteMessage('')
    try {
      await readJson<{ ok: boolean }>('/api/study-account', { method: 'DELETE' })
      navigate('/study')
    } catch (err) {
      setDeleteMessage(err instanceof Error ? err.message : 'Unable to delete account. Please try again.')
      setDeleteBusy(false)
    }
  }

  function closeAccountModal() {
    setAccountModal('none')
    setEmailMessage('')
    setPwMessage('')
    setEnrollMessage('')
  }

  useEffect(() => {
    if (accountModal === 'none') return
    function onKeyDown(e: KeyboardEvent) {
      if (e.key === 'Escape') closeAccountModal()
    }
    document.addEventListener('keydown', onKeyDown)
    return () => document.removeEventListener('keydown', onKeyDown)
  }, [accountModal])

  if (!auth.checked) {
    return (
      <main className="thanks-page" aria-label="Loading">
        <div className="thanks-card"><p>Loading...</p></div>
      </main>
    )
  }

  if (!auth.authenticated) {
    return (
      <main className="thanks-page" aria-label="Sign in required">
        <div className="thanks-card">
          <p className="eyebrow">My Account</p>
          <h1>Sign In Required</h1>
          <p>Please sign in to manage your account.</p>
          <Link to="/study/signup" className="btn-primary" style={{ marginTop: '1rem', display: 'inline-block' }}>Sign In</Link>
        </div>
      </main>
    )
  }

  const divider = <hr style={{ margin: '0 0 2rem', border: 'none', borderTop: '1px solid #2a2518' }} />

  return (
    <main className="thanks-page" aria-label="My account">
      <div className="thanks-card" style={{ maxWidth: '760px', textAlign: 'left' }}>
        <p className="eyebrow">Student Account</p>
        <h1>My Account</h1>
        <div style={{ display: 'flex', alignItems: 'center', gap: '1rem', flexWrap: 'wrap', marginBottom: '1rem' }}>
          {auth.avatarUrl ? (
            <img src={auth.avatarUrl} alt="Your avatar" width={64} height={64} style={{ borderRadius: '50%', border: '1px solid #2a2518' }} />
          ) : (
            <div style={{ width: 64, height: 64, borderRadius: '50%', background: '#2a2518', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#f0ead8', fontWeight: 700, fontSize: '1.5rem' }}>
              {auth.displayName?.slice(0, 1).toUpperCase() || auth.username.slice(0, 1).toUpperCase()}
            </div>
          )}
          <div>
            <p style={{ margin: 0, fontSize: '0.95rem' }}>Signed in as</p>
            <p style={{ margin: '0.25rem 0 0', fontWeight: 700 }}>{auth.displayName || auth.username}</p>
            <p style={{ margin: '0.25rem 0 0', fontSize: '0.9rem', color: '#7a7060' }}>{auth.username}</p>
          </div>
        </div>

        {overview?.stats && (
          <>
            <div style={{ display: 'flex', gap: '1rem', flexWrap: 'wrap', marginBottom: '1.5rem' }}>
              <div style={{ flex: '1 1 130px', background: '#1a1a16', borderRadius: '8px', padding: '1rem', border: '1px solid #2a2518' }}>
                <p style={{ fontSize: '1.6rem', fontWeight: 700, margin: 0 }}>{overview.stats.noteCount}</p>
                <p style={{ margin: 0, fontSize: '0.85rem', color: '#7a7060' }}>Notes saved</p>
              </div>
              <div style={{ flex: '1 1 130px', background: '#1a1a16', borderRadius: '8px', padding: '1rem', border: '1px solid #2a2518' }}>
                <p style={{ fontSize: '1.6rem', fontWeight: 700, margin: 0 }}>{overview.stats.currentStreak ?? 0} 🔥</p>
                <p style={{ margin: 0, fontSize: '0.85rem', color: '#7a7060' }}>Day streak</p>
              </div>
              <div style={{ flex: '1 1 130px', background: '#1a1a16', borderRadius: '8px', padding: '1rem', border: '1px solid #2a2518' }}>
                <p style={{ fontSize: '1.6rem', fontWeight: 700, margin: 0 }}>{overview.stats.longestStreak ?? 0}</p>
                <p style={{ margin: 0, fontSize: '0.85rem', color: '#7a7060' }}>Longest streak</p>
              </div>
              <div style={{ flex: '1 1 130px', background: '#1a1a16', borderRadius: '8px', padding: '1rem', border: '1px solid #2a2518' }}>
                <p style={{ fontSize: '1rem', fontWeight: 600, margin: 0 }}>{overview.stats.memberSince && !isNaN(new Date(overview.stats.memberSince).getTime()) ? new Date(overview.stats.memberSince).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) : '—'}</p>
                <p style={{ margin: 0, fontSize: '0.85rem', color: '#7a7060' }}>Member since</p>
              </div>
            </div>
            {overview.studies.filter(s => s.enrolled && s.totalLessons > 0).length > 0 && (
              <div style={{ marginBottom: '1.5rem' }}>
                <p style={{ margin: '0 0 0.75rem', fontSize: '0.85rem', fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.06em', color: '#7a7060' }}>Study Progress</p>
                {overview.studies.filter(s => s.enrolled && s.totalLessons > 0).map(s => {
                  const pct = Math.round((s.completedLessons / s.totalLessons) * 100)
                  return (
                    <div key={s.slug} style={{ marginBottom: '0.85rem' }}>
                      <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: '0.88rem', marginBottom: '0.3rem' }}>
                        <span>{s.title}</span>
                        <span style={{ color: '#7a7060' }}>{s.completedLessons}/{s.totalLessons} lessons · {pct}%</span>
                      </div>
                      <div style={{ height: '6px', background: '#2a2518', borderRadius: '3px', overflow: 'hidden' }}>
                        <div style={{ height: '100%', width: `${pct}%`, background: pct === 100 ? '#4a9a4a' : '#c9a84c', borderRadius: '3px', transition: 'width 0.4s ease' }} />
                      </div>
                    </div>
                  )
                })}
              </div>
            )}
            {divider}
          </>
        )}

        <section style={{ marginBottom: '2rem' }}>
          <h2 style={{ marginTop: 0 }}>Quick Actions</h2>
          <p style={{ fontSize: '0.92rem' }}>Open the settings you need without scrolling through the whole page.</p>
          <div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap', marginTop: '1rem' }}>
            <button type="button" className="btn-primary" onClick={() => setAccountModal('profile')}>Edit Profile</button>
            <button type="button" className="btn-primary" onClick={() => setAccountModal('preferences')}>Preferences</button>
            <button type="button" className="btn-primary" onClick={() => setAccountModal('export')}>Export Notes</button>
            <button type="button" className="btn-primary" onClick={() => setAccountModal('enrollments')}>Manage Enrollments</button>
            <button type="button" className="btn-secondary" onClick={() => setAccountModal('changeEmail')}>Change Email</button>
            <button type="button" className="btn-secondary" onClick={() => setAccountModal('changePassword')}>Change Password</button>
            <button type="button" className={auth.totpEnabled ? 'btn-secondary' : 'btn-primary'} onClick={() => {
              if (auth.totpEnabled) { setAccountModal('disable2fa'); return }
              setAccountModal('choose2fa')
            }} disabled={twoFaBusy}>
              {auth.totpEnabled
                ? `2FA: ${auth.twoFaMethod === 'email' ? 'Email ✓' : 'App ✓'}`
                : '🔐 Enable Two-Factor Auth'}
            </button>
          </div>
          {!auth.totpEnabled && (
            <div style={{ marginTop: '1rem', background: 'rgba(201,168,76,0.07)', border: '1px solid rgba(201,168,76,0.2)', borderRadius: '8px', padding: '0.75rem 1rem', fontSize: '0.85rem', color: '#a89a6a' }}>
              <strong style={{ color: '#c9a84c' }}>Recommended:</strong> Enable two-factor authentication to protect your study notes and account.
            </div>
          )}
          {auth.totpEnabled && auth.totpRecoveryCodesRemaining !== undefined && auth.totpRecoveryCodesRemaining <= 2 && (
            <div style={{ marginTop: '1rem', background: 'rgba(224,92,92,0.07)', border: '1px solid rgba(224,92,92,0.2)', borderRadius: '8px', padding: '0.75rem 1rem', fontSize: '0.85rem', color: '#e07a7a' }}>
              <strong>Warning:</strong> You only have {auth.totpRecoveryCodesRemaining} recovery code{auth.totpRecoveryCodesRemaining === 1 ? '' : 's'} left.{' '}
              <button type="button" style={{ background: 'none', border: 'none', color: '#c9a84c', cursor: 'pointer', textDecoration: 'underline', fontSize: 'inherit' }} onClick={async () => {
                try {
                  const data = await readJson<{ ok: boolean; recoveryCodes: string[] }>('/api/study-auth/totp-regen-recovery', { method: 'POST' })
                  setTwoFaRecoveryCodes(data.recoveryCodes)
                  setAccountModal('recoveryCodes')
                } catch { /* ignore */ }
              }}>Generate new codes →</button>
            </div>
          )}
        </section>

        {accountModal !== 'none' && (
          <div style={{ position: 'fixed', inset: 0, zIndex: 1000, background: 'rgba(5, 5, 5, 0.8)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '1.25rem' }}>
            <div style={{ width: '100%', maxWidth: '720px', maxHeight: 'calc(100vh - 2.5rem)', overflowY: 'auto', background: '#11100d', border: '1px solid #3a3320', borderRadius: '18px', padding: '1.5rem', position: 'relative' }} role="dialog" aria-modal="true" aria-labelledby="account-modal-heading">
              <button type="button" onClick={closeAccountModal} style={{ position: 'absolute', top: '1rem', right: '1rem', background: 'transparent', border: 'none', color: '#f0ead8', fontSize: '1.35rem', cursor: 'pointer' }} aria-label="Close account settings">×</button>
              {accountModal === 'enrollments' && (
                <>
                  <h2 id="account-modal-heading">Manage Enrollments</h2>
                  <p style={{ marginTop: '0.5rem', marginBottom: '1rem', color: '#b9b09b' }}>Enroll or leave studies from one place. Your active study list is shown below.</p>
                  {loadingOverview ? (
                    <p>Loading study access...</p>
                  ) : overview?.studies?.length ? (
                    <div style={{ display: 'grid', gap: '1rem' }}>
                      {overview.studies.map(studyInfo => (
                        <div key={studyInfo.slug} style={{ padding: '1rem', borderRadius: '12px', background: '#14130f', border: '1px solid #2a2518' }}>
                          <div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem', alignItems: 'flex-start' }}>
                            <div>
                              <p style={{ margin: 0, fontSize: '0.9rem', color: '#b09e79' }}>{studyInfo.status === 'active' ? 'Active study' : 'Planned study'}</p>
                              <h3 style={{ margin: '0.35rem 0 0' }}>{studyInfo.title}</h3>
                              <p style={{ margin: '0.4rem 0 0', fontSize: '0.9rem' }}>{studyInfo.completedLessons} of {studyInfo.totalLessons} lessons completed · {studyInfo.noteCount} notes</p>
                            </div>
                            <button
                              type="button"
                              className={studyInfo.enrolled ? 'btn-admin-remove' : 'btn-primary'}
                              disabled={enrollBusySlug === studyInfo.slug}
                              onClick={() => handleEnrollmentToggle(studyInfo.slug, studyInfo.enrolled)}
                            >
                              {enrollBusySlug === studyInfo.slug ? 'Working…' : studyInfo.enrolled ? 'Leave' : 'Enroll'}
                            </button>
                          </div>
                        </div>
                      ))}
                    </div>
                  ) : (
                    <p>No study access information is available right now.</p>
                  )}
                  {enrollMessage && <p className="study-note-status" style={{ marginTop: '1rem' }}>{enrollMessage}</p>}
                </>
              )}
              {accountModal === 'changeEmail' && (
                <>
                  <h2 id="account-modal-heading">Change Email</h2>
                  <p style={{ marginTop: '0.5rem', marginBottom: '1rem', color: '#b9b09b' }}>Update the email address used for sign in and course notifications.</p>
                  <label style={{ display: 'block', marginBottom: '0.5rem' }}>Current email</label>
                  <input type="email" value={auth.username} disabled style={{ width: '100%', padding: '0.75rem', borderRadius: '8px', border: '1px solid #2a2518', background: '#1a1912', color: '#b9b09b', marginBottom: '1rem' }} />
                  <label style={{ display: 'block', marginBottom: '0.5rem' }}>New email</label>
                  <input type="email" value={emailNew} onChange={e => setEmailNew(e.target.value)} placeholder="you@example.com" style={{ width: '100%', padding: '0.75rem', borderRadius: '8px', border: '1px solid #2a2518', background: '#14130f', color: '#f0ead8', marginBottom: '1rem' }} />
                  <label style={{ display: 'block', marginBottom: '0.5rem' }}>Current password</label>
                  <input type="password" value={emailCurrentPassword} onChange={e => setEmailCurrentPassword(e.target.value)} placeholder="Current password" style={{ width: '100%', padding: '0.75rem', borderRadius: '8px', border: '1px solid #2a2518', background: '#14130f', color: '#f0ead8', marginBottom: '1rem' }} />
                  <div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap', marginBottom: '1rem' }}>
                    <button type="button" className="btn-primary" disabled={emailBusy || !emailNew || !emailCurrentPassword} onClick={handleRequestEmailChange}>
                      {emailBusy ? 'Sending…' : 'Send Verification Email'}
                    </button>
                  </div>
                  {emailTokenInput && (
                    <div style={{ marginTop: '1rem' }}>
                      <p style={{ margin: '0 0 0.5rem' }}>Have a verification token?</p>
                      <input type="text" value={emailTokenInput} onChange={e => setEmailTokenInput(e.target.value)} placeholder="Paste token here" style={{ width: '100%', padding: '0.75rem', borderRadius: '8px', border: '1px solid #2a2518', background: '#14130f', color: '#f0ead8', marginBottom: '0.75rem' }} />
                      <button type="button" className="btn-secondary" disabled={emailBusy || !emailTokenInput.trim()} onClick={handleVerifyTokenInput}>Verify Token</button>
                    </div>
                  )}
                  {emailMessage && <p className="study-note-status" style={{ marginTop: '1rem' }}>{emailMessage}</p>}
                </>
              )}
              {accountModal === 'profile' && (
                <>
                  <h2 id="account-modal-heading">Profile Settings</h2>
                  <p style={{ marginTop: '0.5rem', marginBottom: '1rem', color: '#b9b09b' }}>Update your display name and avatar in one place.</p>
                  <label style={{ display: 'block', fontSize: '0.9rem', marginBottom: '0.5rem' }}>Choose an avatar</label>
                  <p style={{ margin: '0 0 0.85rem', color: '#b9b09b' }}>Pick a preset avatar or upload your own image.</p>
                  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(92px, 1fr))', gap: '0.75rem', marginBottom: '1rem' }}>
                    {[
                      { key: 'dog', label: 'Dog', emoji: '🐶' },
                      { key: 'cat', label: 'Cat', emoji: '🐱' },
                      { key: 'rabbit', label: 'Rabbit', emoji: '🐰' },
                      { key: 'fox', label: 'Fox', emoji: '🦊' },
                      { key: 'panda', label: 'Panda', emoji: '🐼' },
                      { key: 'lion', label: 'Lion', emoji: '🦁' },
                    ].map(item => {
                      const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="88" height="88"><rect width="100%" height="100%" rx="18" ry="18" fill="#11100d"/><text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-size="56">${item.emoji}</text></svg>`
                      const url = `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`
                      return (
                        <button key={item.key} type="button" onClick={() => { setAvatarUrlInput(url); setAvatarUploadMessage('Preset avatar selected.') }} style={{ border: avatarUrlInput === url ? '2px solid #e0c070' : '1px solid #2a2518', borderRadius: '14px', padding: 0, background: '#11100d', cursor: 'pointer' }}>
                          <img src={url} alt={item.label} width={88} height={88} style={{ display: 'block', borderRadius: '14px' }} />
                        </button>
                      )
                    })}
                  </div>
                  <div style={{ marginBottom: '1rem' }}>
                    <label style={{ display: 'block', fontSize: '0.9rem', marginBottom: '0.5rem' }}>Upload your own image</label>
                    <input
                      type="file"
                      accept="image/*"
                      onChange={e => {
                        const file = e.target.files?.[0]
                        if (file) {
                          void handleAvatarUpload(file)
                        }
                      }}
                      style={{ color: '#f0ead8' }}
                    />
                    {avatarUploadBusy && <p className="study-note-status" style={{ marginTop: '0.75rem' }}>Uploading avatar…</p>}
                    {avatarUploadMessage && <p className="study-note-status" style={{ marginTop: '0.75rem' }}>{avatarUploadMessage}</p>}
                  </div>
                  {(avatarUrlInput || auth.avatarUrl) && (
                    <div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem', marginBottom: '0.75rem' }}>
                      <img src={avatarUrlInput || auth.avatarUrl || ''} alt="Avatar preview" width={48} height={48} style={{ borderRadius: '50%', border: '1px solid #2a2518', objectFit: 'cover' }} />
                      <p style={{ margin: 0, color: '#b9b09b', fontSize: '0.92rem' }}>Preview of your selected avatar. Save your profile to keep it.</p>
                    </div>
                  )}
                  <label style={{ display: 'block', fontSize: '0.9rem', marginBottom: '0.5rem' }}>Display Name (optional)</label>
                  <input
                    type="text"
                    value={displayNameInput}
                    onChange={e => setDisplayNameInput(e.target.value)}
                    placeholder="How your name appears in emails"
                    style={{ width: '100%', maxWidth: '420px', marginBottom: '0.75rem', padding: '0.5rem', border: '1px solid #3a3320', borderRadius: '4px', background: '#14130f', color: '#f0ead8' }}
                  />
                  <div>
                    <button type="button" className="btn-primary" disabled={profileBusy} onClick={handleProfileSave}>{profileBusy ? 'Saving...' : 'Save Profile'}</button>
                  </div>
                  {profileMessage && <p className="study-note-status" style={{ marginTop: '0.5rem' }}>{profileMessage}</p>}
                </>
              )}
              {accountModal === 'preferences' && (
                <>
                  <h2 id="account-modal-heading">Preferences</h2>
                  <p style={{ marginTop: '0.5rem', marginBottom: '1rem', color: '#b9b09b' }}>Adjust how you receive study reminders and newsletter updates.</p>
                  <div style={{ display: 'grid', gap: '0.75rem', marginBottom: '1rem' }}>
                    <label className="contact-consent" style={{ display: 'flex', alignItems: 'center', gap: '0.75rem' }}>
                      <input type="checkbox" checked={studyRemindersEnabled} onChange={e => setStudyRemindersEnabled(e.target.checked)} />
                      <span>Send email reminders when a new lesson is released</span>
                    </label>
                    <label className="contact-consent" style={{ display: 'flex', alignItems: 'center', gap: '0.75rem' }}>
                      <input type="checkbox" checked={subscribeNewsletter} onChange={e => setSubscribeNewsletter(e.target.checked)} />
                      <span>Subscribe to newsletter updates</span>
                    </label>
                  </div>
                  <button type="button" className="btn-primary" disabled={prefBusy} onClick={handlePreferenceSave}>{prefBusy ? 'Saving...' : 'Save Preferences'}</button>
                  {prefMessage && <p className="study-note-status" style={{ marginTop: '0.75rem' }}>{prefMessage}</p>}
                </>
              )}
              {accountModal === 'export' && (
                <>
                  <h2 id="account-modal-heading">Export Notes</h2>
                  <p style={{ marginTop: '0.5rem', marginBottom: '1rem', color: '#b9b09b' }}>Download all saved notes in a single document.</p>
                  <button type="button" className="btn-primary" disabled={exporting} onClick={handleExport}>
                    {exporting ? 'Preparing...' : 'Download Notes (.docx)'}
                  </button>
                  {exportMessage && <p className="study-note-status" style={{ marginTop: '0.75rem' }}>{exportMessage}</p>}
                </>
              )}
              {accountModal === 'choose2fa' && (
                <>
                  <h2 id="account-modal-heading">Choose Your 2FA Method</h2>
                  <p style={{ marginTop: '0.5rem', marginBottom: '1.5rem', color: '#b9b09b' }}>
                    Pick how you'd like to verify your identity each time you sign in.
                  </p>
                  <div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
                    <button type="button" style={{ textAlign: 'left', background: '#1a1a12', border: '1px solid rgba(201,168,76,0.25)', borderRadius: '10px', padding: '1rem 1.25rem', cursor: 'pointer', color: '#f0e9cc' }} onClick={async () => {
                      setTwoFaBusy(true); setTwoFaMessage('')
                      try {
                        const data = await readJson<{ qrDataUrl: string; secret: string }>('/api/study-auth/totp-setup-init', { method: 'POST' })
                        if (!data.qrDataUrl || !data.secret) throw new Error('Setup response missing QR data.')
                        setTwoFaQr(data.qrDataUrl)
                        setTwoFaSecret(data.secret)
                        setTwoFaCode('')
                        setTwoFaMessage('')
                        setAccountModal('setup2fa')
                      } catch (err) { setTwoFaMessage(err instanceof Error ? err.message : 'Could not start setup. Please try again.') }
                      finally { setTwoFaBusy(false) }
                    }}>
                      <p style={{ fontWeight: 700, margin: '0 0 0.25rem' }}>📱 Authenticator App</p>
                      <p style={{ margin: 0, fontSize: '0.85rem', color: '#8a7f5a' }}>Use Google Authenticator, Authy, 1Password, or any TOTP app. Works offline. More secure.</p>
                    </button>
                    <button type="button" style={{ textAlign: 'left', background: '#1a1a12', border: '1px solid rgba(201,168,76,0.25)', borderRadius: '10px', padding: '1rem 1.25rem', cursor: 'pointer', color: '#f0e9cc' }} onClick={async () => {
                      setTwoFaBusy(true); setTwoFaMessage('')
                      try {
                        await readJson('/api/study-auth/2fa-setup-email', { method: 'POST' })
                        setTwoFaCode(''); setTwoFaMessage('')
                        setAccountModal('setup2fa-email')
                      } catch { setTwoFaMessage('Could not send code. Please try again.') }
                      finally { setTwoFaBusy(false) }
                    }}>
                      <p style={{ fontWeight: 700, margin: '0 0 0.25rem' }}>📧 Email Code</p>
                      <p style={{ margin: 0, fontSize: '0.85rem', color: '#8a7f5a' }}>A one-time code sent to your email each time you sign in. Easier to set up.</p>
                    </button>
                  </div>
                  {twoFaMessage && <p style={{ color: '#e07a7a', marginTop: '0.75rem' }}>{twoFaMessage}</p>}
                </>
              )}

              {accountModal === 'setup2fa-email' && (
                <>
                  <h2 id="account-modal-heading">Verify Your Email for 2FA</h2>
                  <p style={{ marginTop: '0.5rem', marginBottom: '1.25rem', color: '#b9b09b' }}>
                    We sent a 6-digit code to your email. Enter it below to activate email-based two-factor authentication.
                  </p>
                  <label style={{ display: 'block', marginBottom: '0.5rem' }}>Verification Code</label>
                  <input
                    type="text" inputMode="numeric" autoComplete="one-time-code"
                    value={twoFaCode}
                    onChange={e => setTwoFaCode(e.target.value.replace(/\D/g, '').slice(0, 6))}
                    placeholder="000000"
                    autoFocus
                    style={{ width: '100%', padding: '0.75rem', borderRadius: '8px', border: '1px solid #2a2518', background: '#14130f', color: '#f0ead8', marginBottom: '1rem', letterSpacing: '0.3em', fontSize: '1.3rem', textAlign: 'center' }}
                  />
                  {twoFaMessage && <p style={{ color: '#e07a7a', marginBottom: '0.5rem' }}>{twoFaMessage}</p>}
                  <div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap', alignItems: 'center' }}>
                    <button type="button" className="btn-primary" disabled={twoFaBusy || twoFaCode.length < 6} onClick={async () => {
                      setTwoFaBusy(true); setTwoFaMessage('')
                      try {
                        await readJson('/api/study-auth/2fa-setup-email-confirm', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code: twoFaCode }) })
                        setAuth(prev => ({ ...prev, totpEnabled: true, twoFaMethod: 'email', totpRecoveryCodesRemaining: 0 }))
                        closeAccountModal()
                      } catch (err) { setTwoFaMessage(err instanceof Error ? err.message : 'Invalid code.') }
                      finally { setTwoFaBusy(false) }
                    }}>{twoFaBusy ? 'Activating…' : 'Activate Email 2FA'}</button>
                    <button type="button" style={{ background: 'none', border: 'none', color: '#c9a84c', cursor: 'pointer', fontSize: '0.85rem', textDecoration: 'underline' }} onClick={async () => {
                      try { await readJson('/api/study-auth/2fa-setup-email', { method: 'POST' }) } catch { /* ignore */ }
                    }}>Resend code</button>
                  </div>
                </>
              )}

              {accountModal === 'setup2fa' && (
                <>
                  <h2 id="account-modal-heading">Enable Two-Factor Authentication</h2>
                  <p style={{ marginTop: '0.5rem', marginBottom: '1.25rem', color: '#b9b09b' }}>
                    Scan the QR code below with your authenticator app (Google Authenticator, Authy, 1Password, etc.), then enter the 6-digit code to confirm.
                  </p>
                  {twoFaQr ? (
                    <div style={{ textAlign: 'center', marginBottom: '1.25rem' }}>
                      <img
                        src={twoFaQr}
                        alt="2FA QR code"
                        style={{ display: 'block', margin: '0 auto 0.75rem', borderRadius: '8px', background: '#fff', padding: '0.5rem' }}
                        width={180} height={180}
                        onError={e => { (e.target as HTMLImageElement).style.display = 'none' }}
                      />
                      <p style={{ fontSize: '0.8rem', color: '#5a5440', margin: 0 }}>Can't scan? Enter this key manually:</p>
                    </div>
                  ) : (
                    <p style={{ fontSize: '0.85rem', color: '#8a7f5a', marginBottom: '0.5rem' }}>Enter this key manually in your authenticator app:</p>
                  )}
                  {twoFaSecret && (
                    <div style={{ background: '#0a0a08', border: '1px solid rgba(201,168,76,0.2)', borderRadius: '8px', padding: '0.75rem 1rem', marginBottom: '1.25rem', textAlign: 'center', wordBreak: 'break-all' }}>
                      <code style={{ color: '#c9a84c', fontSize: '0.95rem', letterSpacing: '0.1em' }}>{twoFaSecret}</code>
                    </div>
                  )}
                  <label style={{ display: 'block', marginBottom: '0.5rem' }}>Verification Code</label>
                  <input
                    type="text" inputMode="numeric" autoComplete="one-time-code"
                    value={twoFaCode}
                    onChange={e => setTwoFaCode(e.target.value.replace(/\D/g, '').slice(0, 6))}
                    placeholder="000000"
                    style={{ width: '100%', padding: '0.75rem', borderRadius: '8px', border: '1px solid #2a2518', background: '#14130f', color: '#f0ead8', marginBottom: '1rem', letterSpacing: '0.3em', fontSize: '1.3rem', textAlign: 'center' }}
                  />
                  {twoFaMessage && <p style={{ color: '#e07a7a', marginBottom: '0.5rem' }}>{twoFaMessage}</p>}
                  <div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap' }}>
                    <button type="button" className="btn-primary" disabled={twoFaBusy || twoFaCode.length < 6} onClick={async () => {
                      setTwoFaBusy(true); setTwoFaMessage('')
                      try {
                        const data = await readJson<{ ok: boolean; recoveryCodes: string[] }>('/api/study-auth/totp-setup-confirm', {
                          method: 'POST', headers: { 'Content-Type': 'application/json' },
                          body: JSON.stringify({ code: twoFaCode }),
                        })
                        setTwoFaRecoveryCodes(data.recoveryCodes)
                        setAuth(prev => ({ ...prev, totpEnabled: true, totpRecoveryCodesRemaining: data.recoveryCodes.length }))
                        setAccountModal('recoveryCodes')
                      } catch (err) {
                        setTwoFaMessage(err instanceof Error ? err.message : 'Code incorrect. Try again.')
                      } finally { setTwoFaBusy(false) }
                    }}>{twoFaBusy ? 'Verifying…' : 'Activate 2FA'}</button>
                  </div>
                </>
              )}

              {accountModal === 'recoveryCodes' && (
                <>
                  <h2 id="account-modal-heading">Save Your Recovery Codes</h2>
                  <p style={{ marginTop: '0.5rem', marginBottom: '1.25rem', color: '#b9b09b' }}>
                    Store these codes somewhere safe. Each one can be used once if you ever lose access to your authenticator app. <strong style={{ color: '#f0ead8' }}>You won't be able to see these again.</strong>
                  </p>
                  <div style={{ background: '#0a0a08', border: '1px solid rgba(201,168,76,0.2)', borderRadius: '8px', padding: '1rem', marginBottom: '1.25rem', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '0.5rem' }}>
                    {twoFaRecoveryCodes.map(code => (
                      <code key={code} style={{ color: '#c9a84c', fontSize: '0.9rem', letterSpacing: '0.1em' }}>{code}</code>
                    ))}
                  </div>
                  <div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap' }}>
                    <button type="button" className="btn-primary" onClick={() => {
                      navigator.clipboard?.writeText(twoFaRecoveryCodes.join('\n')).catch(() => {})
                    }}>Copy All</button>
                    <button type="button" className="btn-secondary" onClick={closeAccountModal}>Done</button>
                  </div>
                </>
              )}

              {accountModal === 'disable2fa' && (
                <>
                  <h2 id="account-modal-heading">Disable Two-Factor Authentication</h2>
                  <p style={{ marginTop: '0.5rem', marginBottom: '1.25rem', color: '#b9b09b' }}>
                    Enter your password to confirm. This will remove {auth.twoFaMethod === 'email' ? 'email code' : 'authenticator app'} 2FA from your account.
                  </p>
                  <label style={{ display: 'block', marginBottom: '0.5rem' }}>Current Password</label>
                  <input
                    type="password" autoComplete="current-password"
                    value={disablePassword}
                    onChange={e => setDisablePassword(e.target.value)}
                    placeholder="Your password"
                    style={{ width: '100%', padding: '0.75rem', borderRadius: '8px', border: '1px solid #2a2518', background: '#14130f', color: '#f0ead8', marginBottom: '1rem' }}
                  />
                  {twoFaMessage && <p style={{ color: '#e07a7a', marginBottom: '0.5rem' }}>{twoFaMessage}</p>}
                  <div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap' }}>
                    <button type="button" className="btn-admin-remove" disabled={twoFaBusy || !disablePassword} onClick={async () => {
                      setTwoFaBusy(true); setTwoFaMessage('')
                      try {
                        await readJson('/api/study-auth/totp-disable', {
                          method: 'POST', headers: { 'Content-Type': 'application/json' },
                          body: JSON.stringify({ password: disablePassword }),
                        })
                        setAuth(prev => ({ ...prev, totpEnabled: false, totpRecoveryCodesRemaining: 0 }))
                        setDisablePassword('')
                        closeAccountModal()
                      } catch (err) {
                        setTwoFaMessage(err instanceof Error ? err.message : 'Could not disable 2FA.')
                      } finally { setTwoFaBusy(false) }
                    }}>{twoFaBusy ? 'Disabling…' : 'Disable 2FA'}</button>
                    <button type="button" className="btn-secondary" onClick={closeAccountModal}>Cancel</button>
                  </div>
                </>
              )}

              {accountModal === 'changePassword' && (
                <>
                  <h2 id="account-modal-heading">Change Password</h2>
                  <p style={{ marginTop: '0.5rem', marginBottom: '1rem', color: '#b9b09b' }}>Use a strong password to keep your study materials and notes secure.</p>
                  <label style={{ display: 'block', marginBottom: '0.5rem' }}>Current password</label>
                  <input type="password" value={pwCurrent} onChange={e => setPwCurrent(e.target.value)} placeholder="Current password" style={{ width: '100%', padding: '0.75rem', borderRadius: '8px', border: '1px solid #2a2518', background: '#14130f', color: '#f0ead8', marginBottom: '1rem' }} />
                  <label style={{ display: 'block', marginBottom: '0.5rem' }}>New password</label>
                  <input type="password" value={pwNew} onChange={e => setPwNew(e.target.value)} placeholder="New password" style={{ width: '100%', padding: '0.75rem', borderRadius: '8px', border: '1px solid #2a2518', background: '#14130f', color: '#f0ead8', marginBottom: '1rem' }} />
                  <label style={{ display: 'block', marginBottom: '0.5rem' }}>Confirm new password</label>
                  <input type="password" value={pwConfirm} onChange={e => setPwConfirm(e.target.value)} placeholder="Confirm new password" style={{ width: '100%', padding: '0.75rem', borderRadius: '8px', border: '1px solid #2a2518', background: '#14130f', color: '#f0ead8', marginBottom: '1rem' }} />
                  <div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap', marginBottom: '1rem' }}>
                    <button type="button" className="btn-primary" disabled={pwBusy || !pwCurrent || !pwNew || !pwConfirm} onClick={handleChangePassword}>
                      {pwBusy ? 'Saving…' : 'Update Password'}
                    </button>
                  </div>
                  {pwMessage && <p className="study-note-status" style={{ marginTop: '1rem' }}>{pwMessage}</p>}
                  {pwSuccess && <p className="study-note-status" style={{ marginTop: '1rem', color: '#a5d6a7' }}>Password changed successfully.</p>}
                </>
              )}
            </div>
          </div>
        )}

        {divider}

        <section style={{ marginBottom: '2rem' }}>
          <h2 style={{ marginTop: 0 }}>Sign Out</h2>
          <button type="button" className="btn-secondary" disabled={signOutBusy} onClick={handleSignOut}>
            {signOutBusy ? 'Signing out...' : 'Sign Out'}
          </button>
        </section>

        {divider}

        <section>
          <h2 style={{ marginTop: 0, color: '#e57373' }}>Delete Account</h2>
          {deleteStep === 'idle' && (
            <>
              <p style={{ fontSize: '0.9rem' }}>Permanently remove your account and all saved notes. This cannot be undone.</p>
              <button type="button" className="btn-admin-remove" onClick={() => setDeleteStep('warn1')}>Delete My Account</button>
            </>
          )}
          {deleteStep === 'warn1' && (
            <div style={{ background: '#2d2414', border: '1px solid #6b4b1f', borderRadius: '6px', padding: '1rem', marginBottom: '1rem' }}>
              <p style={{ fontWeight: 600 }}>Final warning: export your notes first.</p>
              <div style={{ display: 'flex', gap: '0.6rem', flexWrap: 'wrap' }}>
                <button type="button" className="btn-primary" onClick={handleExport} disabled={exporting}>Export Notes First</button>
                <button type="button" className="btn-admin-remove" onClick={() => setDeleteStep('warn2')}>Continue to Delete</button>
                <button type="button" className="btn-secondary" onClick={() => setDeleteStep('idle')}>Cancel</button>
              </div>
            </div>
          )}
          {deleteStep === 'warn2' && (
            <div style={{ background: '#2b1111', border: '1px solid #8a3b3b', borderRadius: '6px', padding: '1rem' }}>
              <p>Type <strong>DELETE</strong> to confirm permanent deletion:</p>
              <input type="text" value={deleteConfirmInput} onChange={e => setDeleteConfirmInput(e.target.value)} placeholder="DELETE" style={{ marginBottom: '0.8rem', padding: '0.5rem', border: '1px solid #8a3b3b', borderRadius: '4px', background: '#140f0f', color: '#f0ead8' }} />
              {deleteMessage && <p style={{ color: '#ef9a9a', fontSize: '0.875rem' }}>{deleteMessage}</p>}
              <div style={{ display: 'flex', gap: '0.6rem', flexWrap: 'wrap' }}>
                <button type="button" className="btn-admin-remove" disabled={deleteBusy || deleteConfirmInput.trim() !== 'DELETE'} onClick={handleDeleteAccount}>
                  {deleteBusy ? 'Deleting...' : 'Permanently Delete My Account'}
                </button>
                <button type="button" className="btn-secondary" onClick={() => { setDeleteStep('idle'); setDeleteConfirmInput('') }}>Cancel</button>
              </div>
            </div>
          )}
        </section>

        <div style={{ marginTop: '2rem' }}>
          <Link to="/study" className="btn-secondary">Back to Studies</Link>
        </div>
      </div>
    </main>
  )
}

export function StudyQuizPage({ content }: Props) {
  const { studySlug, sectionId } = useParams<{ studySlug: string, sectionId: string }>()
  const navigate = useNavigate()
  const studies = getStudies(content)
  const study = getStudyBySlug(studies, studySlug)
  const section = study ? getSectionById(study.sections, sectionId) : undefined

  const [auth, setAuth] = useState<StudyAuthState>({ checked: false, authenticated: false, username: '', enrolledStudySlugs: [], displayName: '', subscribeNewsletter: true, studyRemindersEnabled: false, avatarUrl: '' })
  const [answers, setAnswers] = useState<string[]>([])
  const [loading, setLoading] = useState(true)
  const [saving, setSaving] = useState(false)
  const [message, setMessage] = useState('')
  const [error, setError] = useState('')
  const [shareToDiscussion, setShareToDiscussion] = useState<Record<number, boolean>>({})
  const [sharedIndexes, setSharedIndexes] = useState<Set<number>>(new Set())

  useEffect(() => {
    let cancelled = false
    async function load() {
      if (!studySlug || !sectionId) return
      setLoading(true)
      setError('')
      try {
        const authData = await readJson<StudyAuthStatusResponse>('/api/study-auth/status')
        if (cancelled) return
        const enrolledStudySlugs = normalizeEnrolledStudySlugs(authData.enrolledStudySlugs)
        setAuth({
          checked: true,
          authenticated: Boolean(authData.authenticated),
          username: authData.username ?? '',
          displayName: authData.displayName ?? '',
          subscribeNewsletter: authData.subscribeNewsletter !== false,
          studyRemindersEnabled: authData.studyRemindersEnabled === true,
          avatarUrl: authData.avatarUrl ?? '',
          enrolledStudySlugs,
        })

        if (!authData.authenticated || !enrolledStudySlugs.includes(studySlug?.trim().toLowerCase())) {
          return
        }

        const data = await readJson<{ studySlug: string; sectionId: string; answers: string[] }>(`/api/study-quiz/${encodeURIComponent(studySlug)}/${encodeURIComponent(sectionId)}`)
        if (cancelled) return
        setAnswers(Array.isArray(data.answers) ? data.answers : [])
      } catch (err) {
        if (cancelled) return
        setError(err instanceof Error ? err.message : 'Unable to load answers.')
      } finally {
        if (cancelled) return
        setLoading(false)
      }
    }
    void load()
    return () => {
      cancelled = true
    }
  }, [studySlug, sectionId])

  async function saveQuiz() {
    if (!studySlug || !sectionId || !study || !section) return
    setSaving(true)
    setMessage('')
    try {
      await readJson<{ ok: boolean; answers: string[] }>(`/api/study-quiz/${encodeURIComponent(studySlug)}/${encodeURIComponent(sectionId)}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ answers }),
      })

      // Post any checked answers to the shared discussion
      const toShare = Object.entries(shareToDiscussion)
        .filter(([, checked]) => checked)
        .map(([idx]) => Number(idx))
        .filter(idx => !sharedIndexes.has(idx) && (answers[idx] ?? '').trim().length >= 2)

      const newlyShared: number[] = []
      for (const idx of toShare) {
        const questionText = section.studyQuestions?.[idx] ? `**${section.studyQuestions[idx]}**\n\n` : ''
        const text = `${questionText}${answers[idx].trim()}`
        try {
          const res = await fetch('/api/study-community/posts', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ studySlug, sectionId, message: text.slice(0, 2000) }),
          })
          if (res.ok) newlyShared.push(idx)
        } catch { /* ignore individual share failures */ }
      }

      if (newlyShared.length > 0) {
        setSharedIndexes(prev => new Set([...prev, ...newlyShared]))
        setShareToDiscussion(prev => {
          const next = { ...prev }
          newlyShared.forEach(idx => { next[idx] = false })
          return next
        })
      }

      setMessage(newlyShared.length > 0 ? `Answers saved and ${newlyShared.length} shared to the discussion.` : 'Answers saved.')
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Unable to save answers.')
    } finally {
      setSaving(false)
    }
  }

  if (!study || !section) {
    return (
      <main className="thanks-page" aria-label="Discussion questions not found">
        <div className="thanks-card">
          <p className="eyebrow">Reflection Questions</p>
          <h1>Discussion questions not found</h1>
          <p>The reflection questions you requested are not available.</p>
          <Link to="/study" className="btn-primary">Back to Studies</Link>
        </div>
      </main>
    )
  }

  const sectionQuestions = section.studyQuestions ?? []
  const canSubmit = sectionQuestions.length > 0
  const isEnrolled = auth.authenticated && normalizeEnrolledStudySlugs(auth.enrolledStudySlugs).includes(study.slug)

  if (!auth.checked) {
    return (
      <main className="thanks-page" aria-label="Loading reflection questions">
        <div className="thanks-card"><p>Loading reflection questions...</p></div>
      </main>
    )
  }

  if (!auth.authenticated) {
    return (
      <main className="thanks-page" aria-label="Sign in required">
        <div className="thanks-card">
          <p className="eyebrow">Reflection Questions</p>
          <h1>Sign In Required</h1>
          <p>You need to sign in before you can view and save your discussion answers.</p>
          <Link to="/study/signup" className="btn-primary">Sign In</Link>
        </div>
      </main>
    )
  }

  if (!isEnrolled) {
    return (
      <main className="thanks-page" aria-label="Enrollment required">
        <div className="thanks-card">
          <p className="eyebrow">Reflection Questions</p>
          <h1>Enroll to Access Reflection Questions</h1>
          <p>Please enroll in {study.title} to open the reflection questions for this lesson.</p>
          <Link to={`/study/${study.slug}`} className="btn-primary">Go to Study</Link>
        </div>
      </main>
    )
  }

  return (
    <main className="study-index-page" aria-label="Discussion questions">
      <section className="section-study-course-hero">
        <div className="section-inner study-course-hero-inner">
          <p className="eyebrow">Reflection Questions</p>
          <h1>{section.title}</h1>
          <p className="study-course-hero-copy">Write out your answers below — they're saved privately. You can also choose to share individual answers to the lesson discussion.</p>
          <div className="study-course-hero-actions">
            <Link to={`/study/${study.slug}/${section.id}`} className="btn-secondary">Back to Lesson</Link>
          </div>
        </div>
      </section>

      <section className="section-study-module" style={{ paddingTop: '2rem' }}>
        <div className="section-inner">
          {loading ? (
            <p>Loading reflection questions...</p>
          ) : error ? (
            <p className="study-note-status">{error}</p>
          ) : !canSubmit ? (
            <article className="study-class-block">
              <h2>No Reflection Questions</h2>
              <p className="study-detail-copy">This lesson does not have reflection questions configured yet.</p>
            </article>
          ) : (
            <form onSubmit={e => { e.preventDefault(); saveQuiz() }}>
              {sectionQuestions.map((question, index) => (
                <div key={index} className="quiz-question-block">
                  <p className="quiz-question-label">{`${index + 1}. ${question}`}</p>
                  <textarea
                    rows={4}
                    className="quiz-question-textarea"
                    value={answers[index] ?? ''}
                    onChange={e => setAnswers(prev => {
                      const next = [...prev]
                      next[index] = e.target.value
                      return next
                    })}
                    placeholder="Write your answer here…"
                  />
                  {(answers[index] ?? '').trim().length >= 2 && (
                    <label className="quiz-share-toggle">
                      <input
                        type="checkbox"
                        checked={shareToDiscussion[index] ?? false}
                        disabled={sharedIndexes.has(index)}
                        onChange={e => setShareToDiscussion(prev => ({ ...prev, [index]: e.target.checked }))}
                      />
                      {sharedIndexes.has(index)
                        ? <span className="quiz-share-label quiz-share-label--done">✓ Shared to discussion</span>
                        : <span className="quiz-share-label">Share this answer to the lesson discussion</span>}
                    </label>
                  )}
                </div>
              ))}
              <div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap', marginTop: '0.5rem' }}>
                <button type="submit" className="btn-primary" disabled={saving}>{saving ? 'Saving…' : 'Save Answers'}</button>
                <button type="button" className="btn-secondary" onClick={() => navigate(`/study/${study.slug}/${section.id}`)}>Back to Lesson</button>
              </div>
              {message && <p className="study-note-status" style={{ marginTop: '1rem' }}>{message}</p>}
            </form>
          )}
        </div>
      </section>
    </main>
  )
}

export function StudyCommunityPage({ content }: Props) {
  const { studySlug } = useParams<{ studySlug: string }>()
  const location = useLocation()
  const studies = getStudies(content)
  const study = getStudyBySlug(studies, studySlug)
  const defaultSectionId = new URLSearchParams(location.search).get('sectionId') ?? ''

  const [auth, setAuth] = useState<StudyAuthState>({ checked: false, authenticated: false, username: '', enrolledStudySlugs: [], displayName: '' })

  useEffect(() => {
    fetch('/api/study-auth/status', { credentials: 'include' })
      .then(r => r.json())
      .then((data: StudyAuthStatusResponse) => {
        setAuth({ checked: true, authenticated: data.authenticated, username: data.username ?? '', enrolledStudySlugs: normalizeEnrolledStudySlugs(data.enrolledStudySlugs), displayName: data.displayName ?? '' })
      })
      .catch(() => setAuth(prev => ({ ...prev, checked: true })))
  }, [])

  if (!study) {
    return (
      <main className="study-index-page" aria-label="Community">
        <section className="section-study-course-hero">
          <div className="section-inner">
            <h1>Study not found</h1>
            <Link to="/study" className="btn-secondary">Back to Studies</Link>
          </div>
        </section>
      </main>
    )
  }

  const isEnrolled = isEnrolledInStudy(auth, study.slug)

  return (
    <main className="study-index-page" aria-label="Study community">
      <section className="section-study-course-hero" style={{ paddingBottom: '2rem' }}>
        <div className="section-inner study-course-hero-inner">
          <p className="eyebrow">{study.title}</p>
          <h1>Study Community</h1>
          <p className="study-course-hero-copy">Talk with other enrolled students. Keep it gracious and on topic.</p>
          <div className="study-course-hero-actions">
            <Link to={`/study/${study.slug}`} className="btn-secondary">Back to Study</Link>
            <Link to={`/contact?source=community&study=${encodeURIComponent(study.title)}`} className="btn-primary">Ask Nate</Link>
          </div>
        </div>
      </section>
      <section className="section-inner" style={{ paddingTop: '2rem', paddingBottom: '4rem', maxWidth: '860px' }}>
        <CommunityBoard study={study} auth={auth} isEnrolled={isEnrolled} sectionFilter={defaultSectionId} />
      </section>
    </main>
  )
}
