`;
};
// --- PDF UTILITY ---
const downloadPDF = () => {
if (!analysisData.wordCount) {
alert("Please analyze a speech before downloading the report.");
return;
}
const { jsPDF } = window.jspdf;
const pdf = new jsPDF({ orientation: 'p', unit: 'pt', format: 'a4' });
const title = "Speech & Presentation Analysis Report";
const PAGE_WIDTH = pdf.internal.pageSize.getWidth();
const MARGIN = 50;
let y = 0;
// Header
pdf.setFillColor(15, 116, 109); // teal-700
pdf.rect(0, 0, PAGE_WIDTH, 70, 'F');
pdf.setFont('helvetica', 'bold');
pdf.setFontSize(22);
pdf.setTextColor(255, 255, 255);
pdf.text(title, MARGIN, 45);
y = 110;
const addSection = (secTitle, secContent) => {
if (y > pdf.internal.pageSize.getHeight() - 80) { pdf.addPage(); y = MARGIN; }
pdf.setFont('helvetica', 'bold');
pdf.setFontSize(14);
pdf.setTextColor(13, 148, 136); // teal-600
pdf.text(secTitle, MARGIN, y);
y += 20;
pdf.setFont('helvetica', 'normal');
pdf.setFontSize(10);
pdf.setTextColor(51, 65, 85); // slate-700
const lines = pdf.splitTextToSize(secContent, PAGE_WIDTH - MARGIN * 2);
pdf.text(lines, MARGIN, y);
y += lines.length * 12 + 25;
};
const summary = `Word Count: ${analysisData.wordCount}\nEstimated Time: ${analysisData.speakingTimeMinutes}m ${analysisData.speakingTimeSeconds}s (at ${analysisData.wpm} WPM)\nFiller Words Found: ${analysisData.fillerWords.length}`;
addSection("Key Metrics", summary);
if (analysisData.fillerWords.length > 0) {
const fillerCounts = analysisData.fillerWords.reduce((acc, word) => {
const lcWord = word.toLowerCase();
acc[lcWord] = (acc[lcWord] || 0) + 1;
return acc;
}, {});
const fillerList = Object.entries(fillerCounts).map(([word, count]) => `• ${word} (${count})`).join('\n');
addSection("Filler Words Detected", fillerList);
}
if (analysisData.longSentences.length > 0) {
addSection("Long Sentences to Review for Pacing", analysisData.longSentences.join('\n\n'));
}
pdf.addPage();
y = MARGIN;
addSection("Full Speech Script", analysisData.originalText);
pdf.save(`Speech_Analysis_Report.pdf`);
};
// --- EVENT LISTENERS ---
elements.prevBtn.addEventListener('click', () => nextPrev(-1));
elements.nextBtn.addEventListener('click', () => nextPrev(1));
elements.tabs.forEach((tab, i) => {
tab.addEventListener('click', () => {
if (i <= maxUnlockedTab) {
if (i === 1 && !analysisData.wordCount) {
if (!performAnalysis()) return;
}
showTab(i);
}
});
});
elements.downloadPdfBtn.addEventListener('click', downloadPDF);
// Initialize
showTab(currentTab);
});
