import { useEffect, useMemo, useRef, useState } from 'react'
import type { ChangeEvent } from 'react'
import './index.css'
import { createAgentSessionPrompt, createMarkdownPackage, createJsonExport, createPulseJsonl } from './features/export/exporters'
import { loadAppState, replaceAppState, saveAppState, validateAppState } from './store/storage'
import { fetchBackendHealth, fetchRemoteState, pushRemoteState } from './store/remote'
import { FEATURE_COLUMNS, FEATURE_PRIORITIES, FEATURE_STATUSES, PULSE_TYPES, RISK_LEVELS } from './store/types'
import type { AppState, Feature, FeatureColumn, ParkingLotItem, PulseEvent, RiskLevel, TabKey } from './store/types'
import { arrayToLines, formatDateTime, linesToArray, nowIso, slugify } from './utils/format'

const TABS: Array<{ key: TabKey; label: string }> = [
  { key: 'feature-plan', label: 'Feature Plan' },
  { key: 'parking-lot', label: 'Parking Lot' },
  { key: 'pulse-log', label: 'Pulse Log' },
  { key: 'export', label: 'Export' },
]

const PROMPT_TARGETS = ['OpenClaw', 'Claude Code', 'Codex', 'Generic Agent'] as const

const initialFeatureDraft = {
  title: '',
  description: '',
  column: 'now' as FeatureColumn,
  priority: 'must' as (typeof FEATURE_PRIORITIES)[number],
  status: 'idea' as (typeof FEATURE_STATUSES)[number],
  acceptanceCriteria: '',
  scopeNotes: '',
}

const initialParkingDraft = {
  title: '',
  description: '',
  reasonParked: '',
  futurePlacement: '',
  riskLevel: 'medium' as RiskLevel,
}

const initialPulseDraft = {
  featureId: '',
  source: 'manual',
  agentId: 'jimmi',
  pulseType: 'INTENT' as (typeof PULSE_TYPES)[number],
  message: '',
  confidence: '0.9',
  evidenceRefs: '',
  traceId: '',
}

const columnLabels: Record<FeatureColumn, string> = {
  now: 'Now',
  next: 'Next',
  later: 'Later',
  done: 'Done',
}

const downloadText = (filename: string, text: string, contentType = 'text/plain;charset=utf-8') => {
  const blob = new Blob([text], { type: contentType })
  const url = URL.createObjectURL(blob)
  const anchor = document.createElement('a')
  anchor.href = url
  anchor.download = filename
  anchor.click()
  URL.revokeObjectURL(url)
}

function App() {
  const [appState, setAppState] = useState<AppState>(() => loadAppState())
  const [activeTab, setActiveTab] = useState<TabKey>('feature-plan')
  const [statusMessage, setStatusMessage] = useState('Seeded with BuildPulse so you can dogfood it immediately.')
  const [selectedFeatureId, setSelectedFeatureId] = useState<string | null>(null)
  const [selectedParkingId, setSelectedParkingId] = useState<string | null>(null)
  const [selectedPulseId, setSelectedPulseId] = useState<string | null>(null)
  const [featureDraft, setFeatureDraft] = useState(initialFeatureDraft)
  const [parkingDraft, setParkingDraft] = useState(initialParkingDraft)
  const [pulseDraft, setPulseDraft] = useState(initialPulseDraft)
  const [pulseTypeFilter, setPulseTypeFilter] = useState('all')
  const [pulseFeatureFilter, setPulseFeatureFilter] = useState('all')
  const [pulseSourceFilter, setPulseSourceFilter] = useState('all')
  const [promptTarget, setPromptTarget] = useState<(typeof PROMPT_TARGETS)[number]>('OpenClaw')
  const [promptFeatureId, setPromptFeatureId] = useState('')
  const [backendMode, setBackendMode] = useState<'connecting' | 'appwrite' | 'local-cache'>('connecting')
  const [syncStatus, setSyncStatus] = useState<'connecting' | 'synced' | 'pending' | 'syncing' | 'degraded'>('connecting')
  const [lastSyncedAt, setLastSyncedAt] = useState<string | null>(null)
  const [syncAction, setSyncAction] = useState<'idle' | 'refreshing' | 'pushing'>('idle')
  const [selectedFunctionalityTitle, setSelectedFunctionalityTitle] = useState('Project Cockpit')
  const hasHydratedRemote = useRef(false)
  const initialLocalStateRef = useRef(appState)

  useEffect(() => {
    saveAppState(appState)
  }, [appState])

  useEffect(() => {
    let cancelled = false

    const hydrate = async () => {
      try {
        const remoteState = await fetchRemoteState()
        if (cancelled) return

        if (remoteState && validateAppState(remoteState)) {
          setAppState(remoteState)
          saveAppState(remoteState)
          setStatusMessage('Loaded state from Appwrite on the Unraid server.')
        } else {
          await pushRemoteState(initialLocalStateRef.current)
          if (cancelled) return
          setStatusMessage('Seeded Appwrite on Unraid from the local BuildPulse state.')
        }
        setBackendMode('appwrite')
        setSyncStatus('synced')
        setLastSyncedAt(nowIso())
      } catch {
        if (cancelled) return
        setBackendMode('local-cache')
        setSyncStatus('degraded')
        setStatusMessage('Appwrite backend unavailable, so BuildPulse is using the local cache for now.')
      } finally {
        hasHydratedRemote.current = true
      }
    }

    void hydrate()

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

  useEffect(() => {
    if (!hasHydratedRemote.current || backendMode !== 'appwrite') return

    setSyncStatus('pending')
    const timer = window.setTimeout(() => {
      setSyncStatus('syncing')
      void pushRemoteState(appState)
        .then(() => {
          setSyncStatus('synced')
          setLastSyncedAt(nowIso())
        })
        .catch(() => {
          setBackendMode('local-cache')
          setSyncStatus('degraded')
          setStatusMessage('Saved locally. Appwrite sync tripped over itself, so the cache is carrying the load.')
        })
    }, 350)

    return () => window.clearTimeout(timer)
  }, [appState, backendMode])

  const groupedFeatures = useMemo(
    () =>
      FEATURE_COLUMNS.reduce<Record<FeatureColumn, Feature[]>>((acc, column) => {
        acc[column] = appState.features.filter((feature) => feature.column === column)
        return acc
      }, { now: [], next: [], later: [], done: [] }),
    [appState.features],
  )

  const selectedFeature = useMemo(
    () => appState.features.find((feature) => feature.id === selectedFeatureId) ?? null,
    [appState.features, selectedFeatureId],
  )

  const selectedParkingItem = useMemo(
    () => appState.parking_lot.find((item) => item.id === selectedParkingId) ?? null,
    [appState.parking_lot, selectedParkingId],
  )

  const selectedPulse = useMemo(
    () => appState.pulses.find((pulse) => pulse.id === selectedPulseId) ?? null,
    [appState.pulses, selectedPulseId],
  )

  const featurePulseMeta = useMemo(() => {
    const meta = new Map<string, { count: number; latest: PulseEvent | null }>()

    for (const pulse of [...appState.pulses].sort((a, b) => b.timestamp.localeCompare(a.timestamp))) {
      if (!pulse.feature_id) continue

      const current = meta.get(pulse.feature_id)
      if (current) {
        current.count += 1
        continue
      }

      meta.set(pulse.feature_id, { count: 1, latest: pulse })
    }

    return meta
  }, [appState.pulses])

  const selectedFeaturePulses = useMemo(() => {
    if (!selectedFeature) return []

    return [...appState.pulses]
      .filter((pulse) => pulse.feature_id === selectedFeature.id)
      .sort((a, b) => b.timestamp.localeCompare(a.timestamp))
      .slice(0, 4)
  }, [appState.pulses, selectedFeature])

  const filteredPulses = useMemo(() => {
    return [...appState.pulses]
      .filter((pulse) => (pulseTypeFilter === 'all' ? true : pulse.pulse_type === pulseTypeFilter))
      .filter((pulse) => (pulseFeatureFilter === 'all' ? true : pulse.feature_id === pulseFeatureFilter))
      .filter((pulse) => (pulseSourceFilter === 'all' ? true : pulse.source === pulseSourceFilter || pulse.agent_id === pulseSourceFilter))
      .sort((a, b) => b.timestamp.localeCompare(a.timestamp))
  }, [appState.pulses, pulseFeatureFilter, pulseSourceFilter, pulseTypeFilter])

  const uniqueSources = useMemo(
    () => Array.from(new Set(appState.pulses.flatMap((pulse) => [pulse.source, pulse.agent_id]).filter(Boolean))).sort(),
    [appState.pulses],
  )

  const markdownPackage = useMemo(() => createMarkdownPackage(appState), [appState])
  const sessionPrompt = useMemo(
    () => createAgentSessionPrompt(appState, { featureId: promptFeatureId || undefined, target: promptTarget }),
    [appState, promptFeatureId, promptTarget],
  )

  const updateProject = (field: keyof AppState['project'], value: string) => {
    setAppState((current) => ({
      ...current,
      project: {
        ...current.project,
        [field]: value,
        updated_at: nowIso(),
      },
    }))
  }

  const beginFeatureEdit = (feature: Feature) => {
    setSelectedFeatureId(feature.id)
    setFeatureDraft({
      title: feature.title,
      description: feature.description,
      column: feature.column,
      priority: feature.priority,
      status: feature.status,
      acceptanceCriteria: arrayToLines(feature.acceptance_criteria),
      scopeNotes: feature.scope_notes,
    })
  }

  const resetFeatureDraft = () => {
    setSelectedFeatureId(null)
    setFeatureDraft(initialFeatureDraft)
  }

  const saveFeature = () => {
    if (!featureDraft.title.trim()) {
      setStatusMessage('Feature title is required. Tiny cockpit, tiny guardrails.')
      return
    }

    const timestamp = nowIso()
    const acceptanceCriteria = linesToArray(featureDraft.acceptanceCriteria)

    if (selectedFeatureId) {
      setAppState((current) => ({
        ...current,
        features: current.features.map((feature) =>
          feature.id === selectedFeatureId
            ? {
                ...feature,
                title: featureDraft.title.trim(),
                description: featureDraft.description.trim(),
                column: featureDraft.column,
                priority: featureDraft.priority,
                status: featureDraft.status,
                acceptance_criteria: acceptanceCriteria,
                scope_notes: featureDraft.scopeNotes.trim(),
                updated_at: timestamp,
              }
            : feature,
        ),
      }))
      setStatusMessage('Feature updated.')
    } else {
      const title = featureDraft.title.trim()
      const id = `feature_${slugify(title)}_${Date.now().toString(36)}`
      setAppState((current) => ({
        ...current,
        features: [
          {
            id,
            title,
            description: featureDraft.description.trim(),
            column: featureDraft.column,
            priority: featureDraft.priority,
            status: featureDraft.status,
            acceptance_criteria: acceptanceCriteria,
            scope_notes: featureDraft.scopeNotes.trim(),
            created_at: timestamp,
            updated_at: timestamp,
          },
          ...current.features,
        ],
      }))
      setStatusMessage(`Feature “${title}” added.`)
    }

    resetFeatureDraft()
  }

  const deleteFeature = (featureId: string) => {
    setAppState((current) => ({
      ...current,
      features: current.features.filter((feature) => feature.id !== featureId),
    }))
    if (selectedFeatureId === featureId) resetFeatureDraft()
    setStatusMessage('Feature removed. Related pulses stay intact with a graceful missing-feature label.')
  }

  const quickMoveFeature = (featureId: string, column: FeatureColumn) => {
    setAppState((current) => ({
      ...current,
      features: current.features.map((feature) =>
        feature.id === featureId ? { ...feature, column, updated_at: nowIso() } : feature,
      ),
    }))
  }

  const refreshFromBackend = async () => {
    setSyncAction('refreshing')
    setSyncStatus('syncing')

    try {
      const [health, remoteState] = await Promise.all([fetchBackendHealth(), fetchRemoteState()])

      if (!health.ok) throw new Error('Backend health check failed.')

      if (remoteState && validateAppState(remoteState)) {
        setAppState(remoteState)
        saveAppState(remoteState)
        setBackendMode('appwrite')
        setSyncStatus('synced')
        setLastSyncedAt(nowIso())
        setStatusMessage('Reloaded BuildPulse state from Appwrite.')
      } else {
        setBackendMode('appwrite')
        setSyncStatus('synced')
        setStatusMessage('Backend reachable, but there is no valid remote state to reload yet.')
      }
    } catch {
      setBackendMode('local-cache')
      setSyncStatus('degraded')
      setStatusMessage('Refresh failed. Staying on the local cache until Appwrite behaves again.')
    } finally {
      setSyncAction('idle')
    }
  }

  const forceSyncNow = async () => {
    setSyncAction('pushing')
    setSyncStatus('syncing')

    try {
      await pushRemoteState(appState)
      setBackendMode('appwrite')
      setSyncStatus('synced')
      setLastSyncedAt(nowIso())
      setStatusMessage('Forced a clean sync to Appwrite.')
    } catch {
      setBackendMode('local-cache')
      setSyncStatus('degraded')
      setStatusMessage('Forced sync failed. Local cache still has the wheel.')
    } finally {
      setSyncAction('idle')
    }
  }

  const openFeatureHandoff = (featureId: string) => {
    setPromptFeatureId(featureId)
    setPromptTarget('OpenClaw')
    setActiveTab('export')

    const feature = appState.features.find((entry) => entry.id === featureId)
    setStatusMessage(feature ? `Prepared AI handoff for “${feature.title}”.` : 'Prepared AI handoff prompt.')
  }

  const openFeaturePulse = (featureId: string) => {
    const feature = appState.features.find((entry) => entry.id === featureId)
    setSelectedPulseId(null)
    setPulseDraft((current) => ({
      ...initialPulseDraft,
      source: current.source,
      agentId: current.agentId,
      featureId,
      pulseType: 'ACTION',
    }))
    setActiveTab('pulse-log')
    setStatusMessage(feature ? `Pulse composer aimed at “${feature.title}”.` : 'Pulse composer ready.')
  }

  const beginParkingEdit = (item: ParkingLotItem) => {
    setSelectedParkingId(item.id)
    setParkingDraft({
      title: item.title,
      description: item.description,
      reasonParked: item.reason_parked,
      futurePlacement: item.possible_future_placement,
      riskLevel: item.risk_level,
    })
  }

  const resetParkingDraft = () => {
    setSelectedParkingId(null)
    setParkingDraft(initialParkingDraft)
  }

  const saveParkingItem = () => {
    if (!parkingDraft.title.trim()) {
      setStatusMessage('Parking Lot items need a title.')
      return
    }

    const timestamp = nowIso()
    if (selectedParkingId) {
      setAppState((current) => ({
        ...current,
        parking_lot: current.parking_lot.map((item) =>
          item.id === selectedParkingId
            ? {
                ...item,
                title: parkingDraft.title.trim(),
                description: parkingDraft.description.trim(),
                reason_parked: parkingDraft.reasonParked.trim(),
                possible_future_placement: parkingDraft.futurePlacement.trim(),
                risk_level: parkingDraft.riskLevel,
                updated_at: timestamp,
              }
            : item,
        ),
      }))
      setStatusMessage('Parking Lot item updated.')
    } else {
      const title = parkingDraft.title.trim()
      setAppState((current) => ({
        ...current,
        parking_lot: [
          {
            id: `parked_${slugify(title)}_${Date.now().toString(36)}`,
            title,
            description: parkingDraft.description.trim(),
            reason_parked: parkingDraft.reasonParked.trim(),
            possible_future_placement: parkingDraft.futurePlacement.trim(),
            risk_level: parkingDraft.riskLevel,
            created_at: timestamp,
            updated_at: timestamp,
          },
          ...current.parking_lot,
        ],
      }))
      setStatusMessage(`Parked “${title}” safely.`)
    }

    resetParkingDraft()
  }

  const deleteParkingItem = (itemId: string) => {
    setAppState((current) => ({
      ...current,
      parking_lot: current.parking_lot.filter((item) => item.id !== itemId),
    }))
    if (selectedParkingId === itemId) resetParkingDraft()
    setStatusMessage('Parking Lot item removed.')
  }

  const convertParkingItemToFeature = (item: ParkingLotItem) => {
    const timestamp = nowIso()
    setAppState((current) => ({
      ...current,
      features: [
        {
          id: `feature_${slugify(item.title)}_${Date.now().toString(36)}`,
          title: item.title,
          description: item.description,
          column: 'next',
          priority: 'could',
          status: 'idea',
          acceptance_criteria: [],
          scope_notes: `Converted from Parking Lot. Original reason parked: ${item.reason_parked}`,
          created_at: timestamp,
          updated_at: timestamp,
        },
        ...current.features,
      ],
      parking_lot: current.parking_lot.filter((entry) => entry.id !== item.id),
      pulses: [
        {
          id: `pulse_${Date.now().toString(36)}`,
          timestamp,
          project_id: current.project.id,
          source: 'manual',
          agent_id: current.settings.default_agent_id,
          pulse_type: 'PARKED_IDEA',
          message: `Converted parked idea “${item.title}” into a Next feature.`,
          confidence_score: 0.8,
          evidence_refs: ['Converted from Parking Lot'],
        },
        ...current.pulses,
      ],
    }))
    setStatusMessage(`Converted “${item.title}” into a feature.`)
    if (selectedParkingId === item.id) resetParkingDraft()
  }

  const beginPulseEdit = (pulse: PulseEvent) => {
    setSelectedPulseId(pulse.id)
    setPulseDraft({
      featureId: pulse.feature_id ?? '',
      source: pulse.source,
      agentId: pulse.agent_id,
      pulseType: pulse.pulse_type,
      message: pulse.message,
      confidence: String(pulse.confidence_score),
      evidenceRefs: arrayToLines(pulse.evidence_refs),
      traceId: pulse.trace_id ?? '',
    })
  }

  const resetPulseDraft = () => {
    setSelectedPulseId(null)
    setPulseDraft(initialPulseDraft)
  }

  const savePulse = () => {
    if (!pulseDraft.message.trim()) {
      setStatusMessage('Pulse message is required.')
      return
    }

    const timestamp = nowIso()
    const pulse: PulseEvent = {
      id: selectedPulseId ?? `pulse_${Date.now().toString(36)}`,
      timestamp: selectedPulse?.timestamp ?? timestamp,
      project_id: appState.project.id,
      feature_id: pulseDraft.featureId || undefined,
      source: pulseDraft.source.trim() || 'manual',
      agent_id: pulseDraft.agentId.trim() || appState.settings.default_agent_id,
      pulse_type: pulseDraft.pulseType,
      message: pulseDraft.message.trim(),
      confidence_score: Number(pulseDraft.confidence) || 0,
      evidence_refs: linesToArray(pulseDraft.evidenceRefs),
      trace_id: pulseDraft.traceId.trim() || undefined,
    }

    if (selectedPulseId) {
      setAppState((current) => ({
        ...current,
        pulses: current.pulses.map((entry) => (entry.id === selectedPulseId ? pulse : entry)),
      }))
      setStatusMessage('Pulse updated.')
    } else {
      setAppState((current) => ({
        ...current,
        pulses: [pulse, ...current.pulses],
      }))
      setStatusMessage('Pulse added.')
    }

    resetPulseDraft()
  }

  const deletePulse = (pulseId: string) => {
    setAppState((current) => ({
      ...current,
      pulses: current.pulses.filter((pulse) => pulse.id !== pulseId),
    }))
    if (selectedPulseId === pulseId) resetPulseDraft()
    setStatusMessage('Pulse deleted.')
  }

  const copyMarkdown = async (filename: string) => {
    try {
      await navigator.clipboard.writeText(markdownPackage[filename as keyof typeof markdownPackage])
      setStatusMessage(`${filename} copied to clipboard.`)
    } catch {
      setStatusMessage('Clipboard copy failed. Browser said no.')
    }
  }

  const copySessionPrompt = async () => {
    try {
      await navigator.clipboard.writeText(sessionPrompt)
      setStatusMessage('AI session prompt copied to clipboard.')
    } catch {
      setStatusMessage('Clipboard copy failed. Browser said no.')
    }
  }

  const handleImport = async (event: ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0]
    if (!file) return

    try {
      const text = await file.text()
      const parsed = JSON.parse(text)
      if (!validateAppState(parsed)) {
        setStatusMessage('Import failed: invalid BuildPulse schema or unsupported version.')
        return
      }
      setAppState(replaceAppState(parsed))
      setStatusMessage('Import complete. State replaced cleanly.')
    } catch {
      setStatusMessage('Import failed: invalid JSON.')
    } finally {
      event.target.value = ''
    }
  }

  const currentFeatureCount = groupedFeatures.now.length
  const recentPulsePreview = [...appState.pulses].sort((a, b) => b.timestamp.localeCompare(a.timestamp)).slice(0, 3)
  const completedFeatureCount = groupedFeatures.done.length
  const functionalityCards = [
    {
      title: 'Project Cockpit',
      status: 'live',
      description: 'Single-project mission, goal, notes, and focus statistics stay visible before the board tries to swallow the room.',
      signal: appState.project.current_goal ? 'Goal set' : 'Needs current goal',
      metric: appState.project.name,
      action: 'Edit summary',
      tab: 'functionalities' as TabKey,
      operatorNote: 'Use this when the project starts drifting and the cockpit needs a clean north star again.',
      evidence: ['Project summary fields are editable inline.', 'Hero stats reflect live feature, parking, and pulse counts.', 'Current goal is always visible in the page header.'],
      next: 'Add an inline “goal changed” pulse when the current goal is edited.',
    },
    {
      title: 'Feature Plan',
      status: currentFeatureCount ? 'active' : 'ready',
      description: 'Now / Next / Later / Done columns keep work small, shaped, and movable without becoming Jira in a fake moustache.',
      signal: `${appState.features.length} total · ${currentFeatureCount} now · ${completedFeatureCount} done`,
      metric: `${currentFeatureCount} now`,
      action: 'Open board',
      tab: 'feature-plan' as TabKey,
      operatorNote: 'Use this to decide what is actively being built and what should stay out of the way.',
      evidence: ['Four columns: Now, Next, Later, Done.', 'Cards show priority, status, acceptance criteria count, and linked pulse activity.', 'Selected features expose focus notes, criteria, recent pulses, handoff, and pulse actions.'],
      next: 'Add a readiness checklist that highlights missing acceptance criteria before work starts.',
    },
    {
      title: 'Parking Lot',
      status: appState.parking_lot.length ? 'active' : 'ready',
      description: 'Useful distractions get captured, risk-tagged, and converted into features only when they earn their keep.',
      signal: `${appState.parking_lot.length} parked idea${appState.parking_lot.length === 1 ? '' : 's'}`,
      metric: `${appState.parking_lot.length} parked`,
      action: 'Review parked',
      tab: 'parking-lot' as TabKey,
      operatorNote: 'Use this when an idea is useful but too distracting to deserve active build attention yet.',
      evidence: ['Parked ideas carry risk level, reason parked, and possible future placement.', 'A parked idea can be converted into a real feature.', 'Parking keeps future options visible without polluting Now.'],
      next: 'Add a “promote candidate” signal for parked items that keep reappearing in pulses.',
    },
    {
      title: 'Pulse Log',
      status: appState.pulses.length ? 'active' : 'ready',
      description: 'Intent, decisions, blockers, test results, and outcomes form a future-compatible trail for agents and humans.',
      signal: recentPulsePreview[0] ? `Latest: ${recentPulsePreview[0].pulse_type}` : 'No pulses yet',
      metric: `${appState.pulses.length} pulses`,
      action: 'Open log',
      tab: 'pulse-log' as TabKey,
      operatorNote: 'Use this as the honest activity ledger: intent, action, decision, blocker, result.',
      evidence: ['Pulses can link to features.', 'Filters support pulse type, feature, source, and agent.', 'Recent pulse previews surface movement on the Feature Plan.'],
      next: 'Add one-click TEST_RESULT and DECISION templates from the functionality detail panel.',
    },
    {
      title: 'AI Handoff + Export',
      status: 'live',
      description: 'Generate JSON, JSONL, Markdown packages, and focused session prompts so coding agents get context without soup.',
      signal: `${Object.keys(markdownPackage).length} markdown files ready`,
      metric: 'handoff ready',
      action: 'Export context',
      tab: 'export' as TabKey,
      operatorNote: 'Use this when another agent or coding session needs clean context without archaeology.',
      evidence: ['JSON export preserves full app state.', 'JSONL export carries pulse history.', 'Markdown package includes agent-facing project, feature, parking, pulse, and context files.'],
      next: 'Add a “copy focused handoff” button directly on each capability detail.',
    },
    {
      title: 'Appwrite Sync',
      status: backendMode === 'appwrite' && syncStatus === 'synced' ? 'live' : syncStatus === 'degraded' ? 'degraded' : 'syncing',
      description: 'State persists through the Appwrite runtime document, with explicit refresh and force-sync controls for operator recovery.',
      signal: backendMode === 'appwrite' ? `Sync status: ${syncStatus}` : 'Local cache fallback active',
      metric: backendMode === 'appwrite' ? 'Appwrite' : 'cache',
      action: 'Refresh state',
      tab: 'functionalities' as TabKey,
      operatorNote: 'Use this when browser state and backend truth need to be reconciled deliberately.',
      evidence: ['Public health endpoint reports backend=appwrite.', 'Refresh from backend pulls the Appwrite document into local state.', 'Force sync now pushes the current cockpit state back to Appwrite.'],
      next: 'Expose last successful pull/push direction as sync provenance.',
    },
  ]
  const selectedFunctionality = functionalityCards.find((card) => card.title === selectedFunctionalityTitle) ?? functionalityCards[0]
  const backendLabel =
    backendMode === 'appwrite' ? 'Appwrite backend · Unraid server' : backendMode === 'connecting' ? 'Connecting to Appwrite…' : 'Local cache fallback'
  const syncLabel =
    syncStatus === 'synced'
      ? `Synced${lastSyncedAt ? ` ${formatDateTime(lastSyncedAt)}` : ''}`
      : syncStatus === 'pending'
        ? 'Changes queued'
        : syncStatus === 'syncing'
          ? 'Syncing now…'
          : syncStatus === 'degraded'
            ? 'Sync degraded · local cache active'
            : 'Connecting…'

  return (
    <div className="app-shell">
      <header className="hero-card">
        <div>
          <p className="eyebrow">BuildPulse v0.1</p>
          <h1>{appState.project.name}</h1>
          <p className="hero-copy">{appState.project.one_line_pitch}</p>
          <p className="hero-goal">
            <strong>Current goal:</strong> {appState.project.current_goal || 'Set a goal so the cockpit has a heading.'}
          </p>
        </div>
        <div className="hero-stats">
          <div>
            <span>Now</span>
            <strong>{currentFeatureCount}</strong>
          </div>
          <div>
            <span>Parked</span>
            <strong>{appState.parking_lot.length}</strong>
          </div>
          <div>
            <span>Pulses</span>
            <strong>{appState.pulses.length}</strong>
          </div>
        </div>
      </header>

      <section className="status-strip card">
        <div className="status-strip-row">
          <span className={`pill status-${backendMode === 'appwrite' ? 'healthy' : backendMode === 'connecting' ? 'connecting' : 'degraded'}`}>
            {backendLabel}
          </span>
          <span className={`pill status-${syncStatus === 'synced' ? 'healthy' : syncStatus === 'pending' || syncStatus === 'syncing' || syncStatus === 'connecting' ? 'connecting' : 'degraded'}`}>
            {syncLabel}
          </span>
        </div>
        <div className="button-inline-row">
          <button type="button" className="ghost small" disabled={syncAction !== 'idle'} onClick={() => void refreshFromBackend()}>
            {syncAction === 'refreshing' ? 'Refreshing…' : 'Refresh from backend'}
          </button>
          <button type="button" className="ghost small" disabled={syncAction !== 'idle'} onClick={() => void forceSyncNow()}>
            {syncAction === 'pushing' ? 'Syncing…' : 'Force sync now'}
          </button>
        </div>
      </section>

      <section className="project-card card">
        <div className="section-heading compact">
          <div>
            <h2>Project Summary</h2>
            <p>Keep the mission clear without turning this into enterprise theater.</p>
          </div>
        </div>
        <div className="form-grid project-grid">
          <label>
            Project name
            <input value={appState.project.name} onChange={(event) => updateProject('name', event.target.value)} />
          </label>
          <label>
            One-line pitch
            <input
              value={appState.project.one_line_pitch}
              onChange={(event) => updateProject('one_line_pitch', event.target.value)}
            />
          </label>
          <label className="full-span">
            Description
            <textarea
              rows={3}
              value={appState.project.description}
              onChange={(event) => updateProject('description', event.target.value)}
            />
          </label>
          <label className="full-span">
            Current goal
            <input value={appState.project.current_goal} onChange={(event) => updateProject('current_goal', event.target.value)} />
          </label>
          <label className="full-span">
            Notes
            <textarea rows={3} value={appState.project.notes} onChange={(event) => updateProject('notes', event.target.value)} />
          </label>
        </div>
      </section>

      <nav className="tab-bar" aria-label="BuildPulse v0.1 views" role="tablist">
        {TABS.map((tab) => (
          <button
            key={tab.key}
            type="button"
            role="tab"
            aria-selected={tab.key === activeTab}
            className={tab.key === activeTab ? 'tab active' : 'tab'}
            onClick={() => setActiveTab(tab.key)}
          >
            {tab.label}
          </button>
        ))}
      </nav>

      <div className="quick-actions card">
        <button type="button" className="ghost" onClick={() => setActiveTab('functionalities')}>
          Show Functionalities
        </button>
        <button type="button" onClick={() => { setActiveTab('feature-plan'); resetFeatureDraft() }}>
          Add Feature
        </button>
        <button type="button" onClick={() => { setActiveTab('parking-lot'); resetParkingDraft() }}>
          Park Idea
        </button>
        <button type="button" onClick={() => { setActiveTab('pulse-log'); resetPulseDraft() }}>
          Add Pulse
        </button>
        <button type="button" onClick={() => setActiveTab('export')}>
          Export
        </button>
      </div>

      {activeTab === 'functionalities' && (
        <section className="view-stack">
          <div className="section-heading">
            <div>
              <h2>Functionalities</h2>
              <p>The living map of what BuildPulse actually does right now — no brochure fog, no phantom roadmap theatre.</p>
            </div>
            <div className="functionality-summary">
              <span className="pill status-healthy">NPM live</span>
              <span className="pill status-healthy">Appwrite backed</span>
              <span className="pill">Unraid runtime</span>
            </div>
          </div>

          <section className="card functionality-hero">
            <div>
              <p className="eyebrow">Capability map</p>
              <h3>{appState.project.name} is a pulse-compatible feature cockpit.</h3>
              <p>
                It keeps the product thread visible: define the mission, shape features, park distractions, log movement, sync state,
                and hand clean context to AI agents without turning the app into a bloated command bunker.
              </p>
            </div>
            <div className="functionality-scorecard">
              <div>
                <span>Live functions</span>
                <strong>{functionalityCards.filter((card) => card.status === 'live' || card.status === 'active').length}</strong>
              </div>
              <div>
                <span>Operator recovery</span>
                <strong>{backendMode === 'appwrite' ? 'Ready' : 'Cache'}</strong>
              </div>
              <div>
                <span>Context packages</span>
                <strong>{Object.keys(markdownPackage).length}</strong>
              </div>
            </div>
          </section>

          <div className="functionality-grid">
            {functionalityCards.map((card) => (
              <article key={card.title} className={`card functionality-card functionality-${card.status}`}>
                <div className="item-card-header">
                  <div>
                    <p className="eyebrow">{card.status}</p>
                    <h3>{card.title}</h3>
                  </div>
                  <span className="pill">{card.metric}</span>
                </div>
                <p>{card.description}</p>
                <div className="functionality-signal">
                  <span>{card.signal}</span>
                  <div className="button-inline-row">
                    <button type="button" className="ghost small" onClick={() => setSelectedFunctionalityTitle(card.title)}>
                      Inspect
                    </button>
                    <button
                      type="button"
                      className="ghost small"
                      onClick={() => {
                        if (card.title === 'Appwrite Sync') {
                          void refreshFromBackend()
                        } else {
                          setActiveTab(card.tab)
                        }
                      }}
                    >
                      {card.action}
                    </button>
                  </div>
                </div>
              </article>
            ))}
          </div>

          <section className="card functionality-detail">
            <div className="section-heading compact">
              <div>
                <p className="eyebrow">Selected functionality</p>
                <h3>{selectedFunctionality.title}</h3>
                <p>{selectedFunctionality.operatorNote}</p>
              </div>
              <span className={`pill functionality-${selectedFunctionality.status}`}>{selectedFunctionality.status}</span>
            </div>
            <div className="functionality-detail-grid">
              <article>
                <h4>Proof it exists</h4>
                <ul>
                  {selectedFunctionality.evidence.map((item) => (
                    <li key={item}>{item}</li>
                  ))}
                </ul>
              </article>
              <article>
                <h4>Current signal</h4>
                <p>{selectedFunctionality.signal}</p>
                <h4>Next useful improvement</h4>
                <p>{selectedFunctionality.next}</p>
              </article>
            </div>
          </section>

          <section className="card functionality-roadmap">
            <div className="section-heading compact">
              <div>
                <h3>What this is deliberately not yet</h3>
                <p>Guardrails matter. The small cockpit wins because it refuses to cosplay as a whole enterprise suite.</p>
              </div>
            </div>
            <div className="roadmap-grid">
              <div>
                <strong>Not Jira</strong>
                <p>No issue jungle, sprint ceremony, or fake certainty factory.</p>
              </div>
              <div>
                <strong>Not an autonomous agent framework</strong>
                <p>Agent ingestion can come later; manual pulse truth comes first.</p>
              </div>
              <div>
                <strong>Not multi-project yet</strong>
                <p>Single-project discipline keeps v0.1 sharp enough to dogfood.</p>
              </div>
            </div>
          </section>
        </section>
      )}

      {activeTab === 'feature-plan' && (
        <section className="view-stack">
          <div className="section-heading">
            <div>
              <h2>Feature Plan</h2>
              <p>Lead with focus, not overview. This is the calm “what now?” screen.</p>
            </div>
          </div>

          {selectedFeature && (
            <section className="card quick-actions">
              <div>
                <strong>{selectedFeature.title}</strong>
                <p>Selected and ready. Shape it here, then kick a clean brief to your agent.</p>
              </div>
              <div className="button-inline-row">
                <button type="button" className="ghost" onClick={() => openFeaturePulse(selectedFeature.id)}>
                  Log Feature Pulse
                </button>
                <button type="button" onClick={() => openFeatureHandoff(selectedFeature.id)}>
                  Prepare AI Handoff
                </button>
              </div>
            </section>
          )}

          {selectedFeature && (
            <section className="card focus-card">
              <div className="section-heading compact">
                <div>
                  <p className="eyebrow">Night Shift Focus</p>
                  <h3>{selectedFeature.title}</h3>
                  <p>The current build thread, stripped of excuses and fog.</p>
                </div>
                <div className="focus-badges">
                  <span className={`pill ${selectedFeature.priority}`}>{selectedFeature.priority}</span>
                  <span className="pill">{selectedFeature.status}</span>
                  <span className="pill">{columnLabels[selectedFeature.column]}</span>
                </div>
              </div>
              <div className="focus-grid">
                <article className="focus-panel">
                  <h4>Acceptance Criteria</h4>
                  {selectedFeature.acceptance_criteria.length ? (
                    <ul>
                      {selectedFeature.acceptance_criteria.map((criterion) => (
                        <li key={criterion}>{criterion}</li>
                      ))}
                    </ul>
                  ) : (
                    <p>No criteria yet. A dangerous little vacuum.</p>
                  )}
                </article>
                <article className="focus-panel">
                  <h4>Scope Notes</h4>
                  <p>{selectedFeature.scope_notes || 'No scope notes yet. Add the edges before the feature sprawls.'}</p>
                  <h4>Recent Pulse</h4>
                  {selectedFeaturePulses.length ? (
                    <div className="list-stack compact-stack">
                      {selectedFeaturePulses.map((pulse) => (
                        <div key={pulse.id} className="mini-pulse">
                          <strong>{pulse.pulse_type}</strong>
                          <span>{formatDateTime(pulse.timestamp)}</span>
                          <p>{pulse.message}</p>
                        </div>
                      ))}
                    </div>
                  ) : (
                    <p>No feature-linked pulses yet. Log intent before the night gets blurry.</p>
                  )}
                </article>
              </div>
            </section>
          )}

          <div className="board-grid">
            {FEATURE_COLUMNS.map((column) => (
              <article key={column} className="column card">
                <div className="column-header">
                  <div>
                    <h3>{columnLabels[column]}</h3>
                    <p>{groupedFeatures[column].length} feature{groupedFeatures[column].length === 1 ? '' : 's'}</p>
                  </div>
                </div>
                <div className="column-body">
                  {groupedFeatures[column].length ? (
                    groupedFeatures[column].map((feature) => {
                      const pulseMeta = featurePulseMeta.get(feature.id)

                      return (
                        <button key={feature.id} type="button" className="item-card feature-card" onClick={() => beginFeatureEdit(feature)}>
                          <div className="item-card-header">
                            <strong>{feature.title}</strong>
                            <span className={`pill ${feature.priority}`}>{feature.priority}</span>
                          </div>
                          <p>{feature.description || 'No description yet.'}</p>
                          <div className="feature-signal-row">
                            <span>{feature.acceptance_criteria.length} criteria</span>
                            {pulseMeta ? (
                              <span className="feature-signal">
                                {pulseMeta.count} pulse{pulseMeta.count === 1 ? '' : 's'} · last {pulseMeta.latest?.pulse_type ?? 'event'}
                              </span>
                            ) : (
                              <span className="feature-signal quiet">No linked pulses yet</span>
                            )}
                          </div>
                          <div className="meta-row">
                            <span className="pill">{feature.status}</span>
                            <label>
                              <span className="sr-only">Move feature</span>
                              <select
                                value={feature.column}
                                onChange={(event) => {
                                  event.stopPropagation()
                                  quickMoveFeature(feature.id, event.target.value as FeatureColumn)
                                }}
                              >
                                {FEATURE_COLUMNS.map((entry) => (
                                  <option key={entry} value={entry}>
                                    {columnLabels[entry]}
                                  </option>
                                ))}
                              </select>
                            </label>
                          </div>
                        </button>
                      )
                    })
                  ) : (
                    <div className="empty-state">No features here yet.</div>
                  )}
                </div>
              </article>
            ))}
          </div>

          <div className="editor-grid">
            <section className="card editor-card">
              <div className="section-heading compact">
                <div>
                  <h3>{selectedFeature ? 'Edit Feature' : 'Add Feature'}</h3>
                  <p>Keep it small, clear, and testable.</p>
                </div>
              </div>
              <div className="form-grid">
                <label>
                  Title
                  <input value={featureDraft.title} onChange={(event) => setFeatureDraft((current) => ({ ...current, title: event.target.value }))} />
                </label>
                <label>
                  Column
                  <select value={featureDraft.column} onChange={(event) => setFeatureDraft((current) => ({ ...current, column: event.target.value as FeatureColumn }))}>
                    {FEATURE_COLUMNS.map((column) => (
                      <option key={column} value={column}>
                        {columnLabels[column]}
                      </option>
                    ))}
                  </select>
                </label>
                <label>
                  Priority
                  <select value={featureDraft.priority} onChange={(event) => setFeatureDraft((current) => ({ ...current, priority: event.target.value as (typeof FEATURE_PRIORITIES)[number] }))}>
                    {FEATURE_PRIORITIES.map((priority) => (
                      <option key={priority} value={priority}>
                        {priority}
                      </option>
                    ))}
                  </select>
                </label>
                <label>
                  Status
                  <select value={featureDraft.status} onChange={(event) => setFeatureDraft((current) => ({ ...current, status: event.target.value as (typeof FEATURE_STATUSES)[number] }))}>
                    {FEATURE_STATUSES.map((status) => (
                      <option key={status} value={status}>
                        {status}
                      </option>
                    ))}
                  </select>
                </label>
                <label className="full-span">
                  Description
                  <textarea rows={3} value={featureDraft.description} onChange={(event) => setFeatureDraft((current) => ({ ...current, description: event.target.value }))} />
                </label>
                <label className="full-span">
                  Acceptance criteria (one per line)
                  <textarea rows={5} value={featureDraft.acceptanceCriteria} onChange={(event) => setFeatureDraft((current) => ({ ...current, acceptanceCriteria: event.target.value }))} />
                </label>
                <label className="full-span">
                  Scope notes
                  <textarea rows={3} value={featureDraft.scopeNotes} onChange={(event) => setFeatureDraft((current) => ({ ...current, scopeNotes: event.target.value }))} />
                </label>
              </div>
              <div className="button-row">
                <button type="button" onClick={saveFeature}>{selectedFeature ? 'Save Changes' : 'Add Feature'}</button>
                <button type="button" className="ghost" onClick={resetFeatureDraft}>Clear</button>
                {selectedFeature && (
                  <>
                    <button type="button" className="ghost" onClick={() => openFeaturePulse(selectedFeature.id)}>
                      Log Feature Pulse
                    </button>
                    <button type="button" className="ghost" onClick={() => openFeatureHandoff(selectedFeature.id)}>
                      Prepare AI Handoff
                    </button>
                    <button type="button" className="danger" onClick={() => deleteFeature(selectedFeature.id)}>
                      Delete Feature
                    </button>
                  </>
                )}
              </div>
            </section>

            <section className="card preview-card">
              <div className="section-heading compact">
                <div>
                  <h3>Recent Pulse</h3>
                  <p>Just enough movement to stay grounded.</p>
                </div>
              </div>
              {recentPulsePreview.length ? (
                <div className="list-stack">
                  {recentPulsePreview.map((pulse) => (
                    <div key={pulse.id} className="mini-pulse">
                      <strong>{pulse.pulse_type}</strong>
                      <span>{formatDateTime(pulse.timestamp)}</span>
                      <p>{pulse.message}</p>
                    </div>
                  ))}
                </div>
              ) : (
                <div className="empty-state">No pulses yet. Add an INTENT or DECISION to start the log.</div>
              )}
            </section>
          </div>
        </section>
      )}

      {activeTab === 'parking-lot' && (
        <section className="view-stack">
          <div className="section-heading">
            <div>
              <h2>Parking Lot</h2>
              <p>This is where useful distractions go so they do not hijack the build.</p>
            </div>
          </div>
          <div className="editor-grid">
            <section className="card editor-card">
              <div className="section-heading compact">
                <div>
                  <h3>{selectedParkingItem ? 'Edit Parked Idea' : 'Park a New Idea'}</h3>
                  <p>Capture it cleanly, then get back to the real work.</p>
                </div>
              </div>
              <div className="form-grid">
                <label>
                  Title
                  <input value={parkingDraft.title} onChange={(event) => setParkingDraft((current) => ({ ...current, title: event.target.value }))} />
                </label>
                <label>
                  Risk level
                  <select value={parkingDraft.riskLevel} onChange={(event) => setParkingDraft((current) => ({ ...current, riskLevel: event.target.value as RiskLevel }))}>
                    {RISK_LEVELS.map((level) => (
                      <option key={level} value={level}>
                        {level}
                      </option>
                    ))}
                  </select>
                </label>
                <label className="full-span">
                  Description
                  <textarea rows={3} value={parkingDraft.description} onChange={(event) => setParkingDraft((current) => ({ ...current, description: event.target.value }))} />
                </label>
                <label className="full-span">
                  Reason parked
                  <textarea rows={3} value={parkingDraft.reasonParked} onChange={(event) => setParkingDraft((current) => ({ ...current, reasonParked: event.target.value }))} />
                </label>
                <label className="full-span">
                  Possible future placement
                  <input value={parkingDraft.futurePlacement} onChange={(event) => setParkingDraft((current) => ({ ...current, futurePlacement: event.target.value }))} />
                </label>
              </div>
              <div className="button-row">
                <button type="button" onClick={saveParkingItem}>{selectedParkingItem ? 'Save Changes' : 'Park Idea'}</button>
                <button type="button" className="ghost" onClick={resetParkingDraft}>Clear</button>
                {selectedParkingItem && (
                  <>
                    <button type="button" className="ghost" onClick={() => convertParkingItemToFeature(selectedParkingItem)}>
                      Convert to Feature
                    </button>
                    <button type="button" className="danger" onClick={() => deleteParkingItem(selectedParkingItem.id)}>
                      Delete
                    </button>
                  </>
                )}
              </div>
            </section>

            <section className="card list-card">
              <div className="section-heading compact">
                <div>
                  <h3>Parked Ideas</h3>
                  <p>Visible enough to trust, quiet enough not to derail you.</p>
                </div>
              </div>
              <div className="list-stack">
                {appState.parking_lot.length ? (
                  appState.parking_lot.map((item) => (
                    <button key={item.id} type="button" className="item-card parking-card" onClick={() => beginParkingEdit(item)}>
                      <div className="item-card-header">
                        <strong>{item.title}</strong>
                        <span className={`pill risk-${item.risk_level}`}>{item.risk_level}</span>
                      </div>
                      <p>{item.description || 'No description yet.'}</p>
                      <small>{item.reason_parked || 'No reason parked yet.'}</small>
                    </button>
                  ))
                ) : (
                  <div className="empty-state">No parked ideas yet. That probably means you haven’t had a normal distracted brain day yet.</div>
                )}
              </div>
            </section>
          </div>
        </section>
      )}

      {activeTab === 'pulse-log' && (
        <section className="view-stack">
          <div className="section-heading">
            <div>
              <h2>Pulse Log</h2>
              <p>Manual now, future-compatible later. Keep the history honest.</p>
            </div>
          </div>
          <div className="editor-grid">
            <section className="card editor-card">
              <div className="section-heading compact">
                <div>
                  <h3>{selectedPulse ? 'Edit Pulse' : 'Add Pulse'}</h3>
                  <p>Log what happened, not a fantasy backlog status.</p>
                </div>
              </div>
              <div className="form-grid">
                <label>
                  Pulse type
                  <select value={pulseDraft.pulseType} onChange={(event) => setPulseDraft((current) => ({ ...current, pulseType: event.target.value as (typeof PULSE_TYPES)[number] }))}>
                    {PULSE_TYPES.map((pulseType) => (
                      <option key={pulseType} value={pulseType}>
                        {pulseType}
                      </option>
                    ))}
                  </select>
                </label>
                <label>
                  Feature link
                  <select value={pulseDraft.featureId} onChange={(event) => setPulseDraft((current) => ({ ...current, featureId: event.target.value }))}>
                    <option value="">No linked feature</option>
                    {appState.features.map((feature) => (
                      <option key={feature.id} value={feature.id}>
                        {feature.title}
                      </option>
                    ))}
                  </select>
                </label>
                <label>
                  Source
                  <input value={pulseDraft.source} onChange={(event) => setPulseDraft((current) => ({ ...current, source: event.target.value }))} />
                </label>
                <label>
                  Agent ID
                  <input value={pulseDraft.agentId} onChange={(event) => setPulseDraft((current) => ({ ...current, agentId: event.target.value }))} />
                </label>
                <label>
                  Confidence
                  <input value={pulseDraft.confidence} onChange={(event) => setPulseDraft((current) => ({ ...current, confidence: event.target.value }))} />
                </label>
                <label>
                  Trace ID
                  <input value={pulseDraft.traceId} onChange={(event) => setPulseDraft((current) => ({ ...current, traceId: event.target.value }))} />
                </label>
                <label className="full-span">
                  Message
                  <textarea rows={4} value={pulseDraft.message} onChange={(event) => setPulseDraft((current) => ({ ...current, message: event.target.value }))} />
                </label>
                <label className="full-span">
                  Evidence refs (one per line)
                  <textarea rows={4} value={pulseDraft.evidenceRefs} onChange={(event) => setPulseDraft((current) => ({ ...current, evidenceRefs: event.target.value }))} />
                </label>
              </div>
              <div className="button-row">
                <button type="button" onClick={savePulse}>{selectedPulse ? 'Save Changes' : 'Add Pulse'}</button>
                <button type="button" className="ghost" onClick={resetPulseDraft}>Clear</button>
                {selectedPulse && (
                  <button type="button" className="danger" onClick={() => deletePulse(selectedPulse.id)}>
                    Delete Pulse
                  </button>
                )}
              </div>
            </section>

            <section className="card list-card">
              <div className="section-heading compact filters-heading">
                <div>
                  <h3>Pulse Timeline</h3>
                  <p>Newest first, with just enough filtering to stay useful.</p>
                </div>
                <div className="filter-row">
                  <select value={pulseTypeFilter} onChange={(event) => setPulseTypeFilter(event.target.value)}>
                    <option value="all">All types</option>
                    {PULSE_TYPES.map((pulseType) => (
                      <option key={pulseType} value={pulseType}>
                        {pulseType}
                      </option>
                    ))}
                  </select>
                  <select value={pulseFeatureFilter} onChange={(event) => setPulseFeatureFilter(event.target.value)}>
                    <option value="all">All features</option>
                    {appState.features.map((feature) => (
                      <option key={feature.id} value={feature.id}>
                        {feature.title}
                      </option>
                    ))}
                  </select>
                  <select value={pulseSourceFilter} onChange={(event) => setPulseSourceFilter(event.target.value)}>
                    <option value="all">All sources</option>
                    {uniqueSources.map((source) => (
                      <option key={source} value={source}>
                        {source}
                      </option>
                    ))}
                  </select>
                </div>
              </div>
              <div className="list-stack">
                {filteredPulses.length ? (
                  filteredPulses.map((pulse) => {
                    const linkedFeature = appState.features.find((feature) => feature.id === pulse.feature_id)
                    return (
                      <button key={pulse.id} type="button" className="item-card pulse-card" onClick={() => beginPulseEdit(pulse)}>
                        <div className="item-card-header">
                          <strong>{pulse.pulse_type}</strong>
                          <span>{formatDateTime(pulse.timestamp)}</span>
                        </div>
                        <p>{pulse.message}</p>
                        <small>
                          {linkedFeature?.title ?? (pulse.feature_id ? `${pulse.feature_id} (missing feature)` : 'No linked feature')} · {pulse.source} / {pulse.agent_id}
                        </small>
                      </button>
                    )
                  })
                ) : (
                  <div className="empty-state">No pulses match the current filters.</div>
                )}
              </div>
            </section>
          </div>
        </section>
      )}

      {activeTab === 'export' && (
        <section className="view-stack">
          <div className="section-heading">
            <div>
              <h2>Export</h2>
              <p>Ship clean context packages, not rambling AI bait.</p>
            </div>
          </div>
          <div className="editor-grid">
            <section className="card editor-card">
              <div className="section-heading compact">
                <div>
                  <h3>Data Exports</h3>
                  <p>Backups and handoffs first. Fancy multi-file packaging can wait.</p>
                </div>
              </div>
              <div className="button-stack">
                <button type="button" onClick={() => downloadText('buildpulse-export.json', createJsonExport(appState), 'application/json;charset=utf-8')}>
                  Download Full JSON
                </button>
                <button type="button" onClick={() => downloadText('pulses.jsonl', createPulseJsonl(appState), 'application/x-ndjson;charset=utf-8')}>
                  Download Pulse JSONL
                </button>
                <label className="import-label">
                  Import JSON
                  <input type="file" accept="application/json" onChange={handleImport} />
                </label>
              </div>
            </section>

            <div className="list-stack">
              <section className="card list-card">
                <div className="section-heading compact">
                  <div>
                    <h3>AI Session Prompt</h3>
                    <p>Pick a focus feature and hand a sharp brief to your coding agent instead of pasting the whole kitchen sink.</p>
                  </div>
                </div>
                <div className="filter-row">
                  <label>
                    Target
                    <select value={promptTarget} onChange={(event) => setPromptTarget(event.target.value as (typeof PROMPT_TARGETS)[number])}>
                      {PROMPT_TARGETS.map((target) => (
                        <option key={target} value={target}>
                          {target}
                        </option>
                      ))}
                    </select>
                  </label>
                  <label>
                    Focus Feature
                    <select value={promptFeatureId} onChange={(event) => setPromptFeatureId(event.target.value)}>
                      <option value="">Auto-pick first Now feature</option>
                      {appState.features.map((feature) => (
                        <option key={feature.id} value={feature.id}>
                          {feature.title} · {columnLabels[feature.column]}
                        </option>
                      ))}
                    </select>
                  </label>
                </div>
                <div className="button-inline-row">
                  <button type="button" onClick={copySessionPrompt}>
                    Copy Prompt
                  </button>
                  <button type="button" className="ghost" onClick={() => downloadText('AI_SESSION_PROMPT.md', sessionPrompt)}>
                    Download Prompt
                  </button>
                </div>
                <div className="markdown-card">
                  <div className="item-card-header">
                    <strong>AI_SESSION_PROMPT.md</strong>
                  </div>
                  <pre>{sessionPrompt}</pre>
                </div>
              </section>

              <section className="card list-card">
                <div className="section-heading compact">
                  <div>
                    <h3>Markdown Package</h3>
                    <p>`CLAUDE_CONTEXT.md` is the decision-boundary file. Keep it sharp.</p>
                  </div>
                </div>
                <div className="list-stack markdown-list">
                  {Object.entries(markdownPackage).map(([filename, content]) => (
                    <div key={filename} className="markdown-card">
                      <div className="item-card-header">
                        <strong>{filename}</strong>
                        <div className="button-inline-row">
                          <button type="button" className="ghost small" onClick={() => copyMarkdown(filename)}>
                            Copy
                          </button>
                          <button type="button" className="ghost small" onClick={() => downloadText(filename, content)}>
                            Download
                          </button>
                        </div>
                      </div>
                      <pre>{content}</pre>
                    </div>
                  ))}
                </div>
              </section>
            </div>
          </div>
        </section>
      )}

      <footer className="status-bar">
        <span>{statusMessage}</span>
        <span>{backendLabel} · {syncLabel} · schema {appState.schema_version}</span>
      </footer>
    </div>
  )
}

export default App
