claude-presentation-master 7.2.1 → 7.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -354,6 +354,8 @@ interface ContentAnalysis$1 {
354
354
  detectedType: PresentationType$1;
355
355
  /** Main title */
356
356
  title: string;
357
+ /** Subtitle (line after title) */
358
+ subtitle?: string;
357
359
  /** Content sections */
358
360
  sections: ContentSection$1[];
359
361
  /** SCQA structure extracted */
@@ -950,6 +952,7 @@ interface ContentSection {
950
952
  interface ContentAnalysis {
951
953
  detectedType: PresentationType;
952
954
  title: string;
955
+ subtitle: string;
953
956
  sections: ContentSection[];
954
957
  keyMessages: string[];
955
958
  dataPoints: Array<{
@@ -990,7 +993,12 @@ declare class ContentAnalyzer {
990
993
  */
991
994
  private parseContent;
992
995
  /**
993
- * Extract the main title from content
996
+ * Extract the main title AND subtitle from content
997
+ * Subtitle is the line immediately after the H1 title (if not another header)
998
+ */
999
+ private extractTitleAndSubtitle;
1000
+ /**
1001
+ * Extract the main title from content (legacy wrapper)
994
1002
  */
995
1003
  private extractTitle;
996
1004
  /**
@@ -1215,6 +1223,11 @@ declare class ContentPatternClassifier {
1215
1223
  } | null;
1216
1224
  /**
1217
1225
  * Extract timeline/process steps from content
1226
+ * Handles multiple formats:
1227
+ * - "Step 1: Do something" → label: "Step 1", description: "Do something"
1228
+ * - "1. First item" → label: "1", description: "First item"
1229
+ * - "Title - Description text" → label: "Title", description: "Description text"
1230
+ * - "Plain text" → label: "1", description: "Plain text"
1218
1231
  */
1219
1232
  extractSteps(section: ContentSection$1): Array<{
1220
1233
  label: string;
package/dist/index.d.ts CHANGED
@@ -354,6 +354,8 @@ interface ContentAnalysis$1 {
354
354
  detectedType: PresentationType$1;
355
355
  /** Main title */
356
356
  title: string;
357
+ /** Subtitle (line after title) */
358
+ subtitle?: string;
357
359
  /** Content sections */
358
360
  sections: ContentSection$1[];
359
361
  /** SCQA structure extracted */
@@ -950,6 +952,7 @@ interface ContentSection {
950
952
  interface ContentAnalysis {
951
953
  detectedType: PresentationType;
952
954
  title: string;
955
+ subtitle: string;
953
956
  sections: ContentSection[];
954
957
  keyMessages: string[];
955
958
  dataPoints: Array<{
@@ -990,7 +993,12 @@ declare class ContentAnalyzer {
990
993
  */
991
994
  private parseContent;
992
995
  /**
993
- * Extract the main title from content
996
+ * Extract the main title AND subtitle from content
997
+ * Subtitle is the line immediately after the H1 title (if not another header)
998
+ */
999
+ private extractTitleAndSubtitle;
1000
+ /**
1001
+ * Extract the main title from content (legacy wrapper)
994
1002
  */
995
1003
  private extractTitle;
996
1004
  /**
@@ -1215,6 +1223,11 @@ declare class ContentPatternClassifier {
1215
1223
  } | null;
1216
1224
  /**
1217
1225
  * Extract timeline/process steps from content
1226
+ * Handles multiple formats:
1227
+ * - "Step 1: Do something" → label: "Step 1", description: "Do something"
1228
+ * - "1. First item" → label: "1", description: "First item"
1229
+ * - "Title - Description text" → label: "Title", description: "Description text"
1230
+ * - "Plain text" → label: "1", description: "Plain text"
1218
1231
  */
1219
1232
  extractSteps(section: ContentSection$1): Array<{
1220
1233
  label: string;
package/dist/index.js CHANGED
@@ -961,7 +961,8 @@ var ContentAnalyzer = class {
961
961
  async analyze(content, contentType) {
962
962
  await this.initialize();
963
963
  const text = this.parseContent(content, contentType);
964
- const title = this.extractTitle(text);
964
+ const { title, subtitle } = this.extractTitleAndSubtitle(text);
965
+ logger.step(`Title: "${title}", Subtitle: "${subtitle || "(none)"}"`);
965
966
  const detectedType = this.detectPresentationType(text);
966
967
  logger.step(`Detected type: ${detectedType}`);
967
968
  const sections = this.extractSections(text);
@@ -974,9 +975,13 @@ var ContentAnalyzer = class {
974
975
  const titles = sections.map((s) => s.header).filter((h) => h.length > 0);
975
976
  const starMoments = this.extractStarMoments(text);
976
977
  const estimatedSlideCount = Math.max(5, sections.length + 3);
978
+ const whatIsContent = scqa.situation ? [scqa.situation] : [];
979
+ const whatCouldBeContent = scqa.answer ? [scqa.answer] : keyMessages.slice(0, 2);
977
980
  return {
978
981
  detectedType,
979
982
  title,
983
+ subtitle,
984
+ // NEW: Use explicit subtitle from content
980
985
  sections,
981
986
  keyMessages,
982
987
  dataPoints,
@@ -987,8 +992,10 @@ var ContentAnalyzer = class {
987
992
  answer: scqa.answer || ""
988
993
  },
989
994
  sparkline: {
990
- whatIs: sparkline.callToAction ? [sparkline.callToAction] : [],
991
- whatCouldBe: keyMessages,
995
+ whatIs: whatIsContent,
996
+ // FIX: Use situation, not CTA
997
+ whatCouldBe: whatCouldBeContent,
998
+ // FIX: Use answer/vision, not random messages
992
999
  callToAdventure: sparkline.callToAction || ""
993
1000
  },
994
1001
  titles,
@@ -1016,18 +1023,46 @@ var ContentAnalyzer = class {
1016
1023
  return text;
1017
1024
  }
1018
1025
  /**
1019
- * Extract the main title from content
1026
+ * Extract the main title AND subtitle from content
1027
+ * Subtitle is the line immediately after the H1 title (if not another header)
1020
1028
  */
1021
- extractTitle(text) {
1022
- const h1Match = text.match(/^#\s+(.+)$/m);
1023
- if (h1Match && h1Match[1]) {
1024
- return h1Match[1].replace(/\*\*/g, "").trim();
1029
+ extractTitleAndSubtitle(text) {
1030
+ const lines = text.split("\n");
1031
+ let title = "Presentation";
1032
+ let subtitle = "";
1033
+ let foundTitle = false;
1034
+ let titleLineIndex = -1;
1035
+ for (let i = 0; i < lines.length; i++) {
1036
+ const rawLine = lines[i];
1037
+ if (!rawLine) continue;
1038
+ const line = rawLine.trim();
1039
+ const h1Match = line.match(/^#\s+(.+)$/);
1040
+ if (h1Match && h1Match[1] && !foundTitle) {
1041
+ title = h1Match[1].replace(/\*\*/g, "").trim();
1042
+ foundTitle = true;
1043
+ titleLineIndex = i;
1044
+ continue;
1045
+ }
1046
+ if (foundTitle && i > titleLineIndex && line.length > 0) {
1047
+ if (line.startsWith("#")) break;
1048
+ if (line.startsWith("-") || line.startsWith("*") || /^\d+\./.test(line)) break;
1049
+ subtitle = line.replace(/\*\*/g, "").trim().slice(0, 100);
1050
+ break;
1051
+ }
1025
1052
  }
1026
- const lines = text.split("\n").filter((l) => l.trim().length > 0);
1027
- if (lines.length > 0 && lines[0]) {
1028
- return lines[0].replace(/^#+\s*/, "").replace(/\*\*/g, "").trim().slice(0, 80);
1053
+ if (!foundTitle) {
1054
+ const firstLine = lines.find((l) => l.trim().length > 0);
1055
+ if (firstLine) {
1056
+ title = firstLine.replace(/^#+\s*/, "").replace(/\*\*/g, "").trim().slice(0, 80);
1057
+ }
1029
1058
  }
1030
- return "Presentation";
1059
+ return { title, subtitle };
1060
+ }
1061
+ /**
1062
+ * Extract the main title from content (legacy wrapper)
1063
+ */
1064
+ extractTitle(text) {
1065
+ return this.extractTitleAndSubtitle(text).title;
1031
1066
  }
1032
1067
  /**
1033
1068
  * Detect presentation type from content signals
@@ -1650,6 +1685,11 @@ var ContentPatternClassifier = class {
1650
1685
  }
1651
1686
  /**
1652
1687
  * Extract timeline/process steps from content
1688
+ * Handles multiple formats:
1689
+ * - "Step 1: Do something" → label: "Step 1", description: "Do something"
1690
+ * - "1. First item" → label: "1", description: "First item"
1691
+ * - "Title - Description text" → label: "Title", description: "Description text"
1692
+ * - "Plain text" → label: "1", description: "Plain text"
1653
1693
  */
1654
1694
  extractSteps(section) {
1655
1695
  const steps = [];
@@ -1660,12 +1700,28 @@ var ContentPatternClassifier = class {
1660
1700
  label: stepMatch[1].trim(),
1661
1701
  description: stepMatch[2].trim()
1662
1702
  });
1663
- } else {
1703
+ continue;
1704
+ }
1705
+ const dashMatch = bullet.match(/^([^-]+)\s+-\s+(.+)$/);
1706
+ if (dashMatch && dashMatch[1] && dashMatch[2]) {
1664
1707
  steps.push({
1665
- label: `${steps.length + 1}`,
1666
- description: bullet
1708
+ label: dashMatch[1].trim(),
1709
+ description: dashMatch[2].trim()
1667
1710
  });
1711
+ continue;
1668
1712
  }
1713
+ const colonMatch = bullet.match(/^([^:]+):\s*(.+)$/);
1714
+ if (colonMatch && colonMatch[1] && colonMatch[2] && colonMatch[1].length < 40) {
1715
+ steps.push({
1716
+ label: colonMatch[1].trim(),
1717
+ description: colonMatch[2].trim()
1718
+ });
1719
+ continue;
1720
+ }
1721
+ steps.push({
1722
+ label: `${steps.length + 1}`,
1723
+ description: bullet
1724
+ });
1669
1725
  }
1670
1726
  return steps;
1671
1727
  }
@@ -1830,9 +1886,10 @@ var SlideFactory = class {
1830
1886
  const data = {
1831
1887
  title: this.truncateText(analysis.title, this.config.rules.wordsPerSlide.max)
1832
1888
  };
1833
- if (analysis.keyMessages[0]) {
1889
+ const subtitleSource = analysis.subtitle || analysis.keyMessages[0] || "";
1890
+ if (subtitleSource) {
1834
1891
  data.subtitle = this.truncateText(
1835
- analysis.keyMessages[0],
1892
+ subtitleSource,
1836
1893
  this.config.defaults.subtitle.maxWords
1837
1894
  // FROM KB
1838
1895
  );
@@ -1876,7 +1933,9 @@ var SlideFactory = class {
1876
1933
  addSCQASlides(slides, analysis) {
1877
1934
  const scqa = analysis.scqa;
1878
1935
  const titles = this.config.scqaTitles;
1879
- if (scqa?.situation && !this.usedContent.has("scqa-situation")) {
1936
+ const minBodyLength = 20;
1937
+ const situationBody = scqa?.situation ? this.truncateText(scqa.situation, this.config.rules.wordsPerSlide.max) : "";
1938
+ if (situationBody.length >= minBodyLength && !this.usedContent.has("scqa-situation")) {
1880
1939
  this.usedContent.add("scqa-situation");
1881
1940
  slides.push({
1882
1941
  index: slides.length,
@@ -1884,12 +1943,13 @@ var SlideFactory = class {
1884
1943
  data: {
1885
1944
  title: titles.situation,
1886
1945
  // FROM KB - not hardcoded 'Current Situation'
1887
- body: this.truncateText(scqa.situation, this.config.rules.wordsPerSlide.max)
1946
+ body: situationBody
1888
1947
  },
1889
1948
  classes: ["situation-slide"]
1890
1949
  });
1891
1950
  }
1892
- if (scqa?.complication && !this.usedContent.has("scqa-complication")) {
1951
+ const complicationBody = scqa?.complication ? this.truncateText(scqa.complication, this.config.rules.wordsPerSlide.max) : "";
1952
+ if (complicationBody.length >= minBodyLength && !this.usedContent.has("scqa-complication")) {
1893
1953
  this.usedContent.add("scqa-complication");
1894
1954
  slides.push({
1895
1955
  index: slides.length,
@@ -1897,12 +1957,13 @@ var SlideFactory = class {
1897
1957
  data: {
1898
1958
  title: titles.complication,
1899
1959
  // FROM KB - not hardcoded 'The Challenge'
1900
- body: this.truncateText(scqa.complication, this.config.rules.wordsPerSlide.max)
1960
+ body: complicationBody
1901
1961
  },
1902
1962
  classes: ["complication-slide"]
1903
1963
  });
1904
1964
  }
1905
- if (scqa?.question && !this.usedContent.has("scqa-question")) {
1965
+ const questionBody = scqa?.question ? this.truncateText(scqa.question, this.config.rules.wordsPerSlide.max) : "";
1966
+ if (questionBody.length >= minBodyLength && !this.usedContent.has("scqa-question")) {
1906
1967
  this.usedContent.add("scqa-question");
1907
1968
  slides.push({
1908
1969
  index: slides.length,
@@ -1910,7 +1971,7 @@ var SlideFactory = class {
1910
1971
  data: {
1911
1972
  title: titles.question,
1912
1973
  // FROM KB - not hardcoded 'The Question'
1913
- body: this.truncateText(scqa.question, this.config.rules.wordsPerSlide.max)
1974
+ body: questionBody
1914
1975
  },
1915
1976
  classes: ["question-slide"]
1916
1977
  });
@@ -1920,7 +1981,8 @@ var SlideFactory = class {
1920
1981
  const spark = analysis.sparkline;
1921
1982
  const titles = this.config.sparklineTitles;
1922
1983
  const whatIsFirst = spark?.whatIs?.[0];
1923
- if (whatIsFirst && !this.usedContent.has("spark-what-is")) {
1984
+ const whatIsBody = whatIsFirst ? this.truncateText(whatIsFirst, this.config.rules.wordsPerSlide.max) : "";
1985
+ if (whatIsBody.length >= 20 && !this.usedContent.has("spark-what-is")) {
1924
1986
  this.usedContent.add("spark-what-is");
1925
1987
  slides.push({
1926
1988
  index: slides.length,
@@ -1928,13 +1990,14 @@ var SlideFactory = class {
1928
1990
  data: {
1929
1991
  title: titles.whatIs,
1930
1992
  // FROM KB - not hardcoded 'Where We Are Today'
1931
- body: this.truncateText(whatIsFirst, this.config.rules.wordsPerSlide.max)
1993
+ body: whatIsBody
1932
1994
  },
1933
1995
  classes: ["what-is-slide"]
1934
1996
  });
1935
1997
  }
1936
1998
  const whatCouldBeFirst = spark?.whatCouldBe?.[0];
1937
- if (whatCouldBeFirst && !this.usedContent.has("spark-could-be")) {
1999
+ const whatCouldBeBody = whatCouldBeFirst ? this.truncateText(whatCouldBeFirst, this.config.rules.wordsPerSlide.max) : "";
2000
+ if (whatCouldBeBody.length >= 20 && !this.usedContent.has("spark-could-be")) {
1938
2001
  this.usedContent.add("spark-could-be");
1939
2002
  slides.push({
1940
2003
  index: slides.length,
@@ -1942,7 +2005,7 @@ var SlideFactory = class {
1942
2005
  data: {
1943
2006
  title: titles.whatCouldBe,
1944
2007
  // FROM KB - not hardcoded 'What Could Be'
1945
- body: this.truncateText(whatCouldBeFirst, this.config.rules.wordsPerSlide.max)
2008
+ body: whatCouldBeBody
1946
2009
  },
1947
2010
  classes: ["what-could-be-slide"]
1948
2011
  });
@@ -2151,16 +2214,18 @@ var SlideFactory = class {
2151
2214
  };
2152
2215
  }
2153
2216
  createSingleStatementSlide(index, section) {
2217
+ const bodyContent = section.content || section.bullets.join(" ") || "";
2218
+ const truncatedBody = this.truncateText(bodyContent, this.config.rules.wordsPerSlide.max);
2219
+ if (truncatedBody.length < 15 && section.bullets.length > 0) {
2220
+ return this.createBulletSlide(index, section);
2221
+ }
2154
2222
  return {
2155
2223
  index,
2156
2224
  type: "single-statement",
2157
2225
  data: {
2158
2226
  title: this.createTitle(section.header, section),
2159
- body: this.truncateText(
2160
- section.content || section.bullets[0] || "",
2161
- this.config.rules.wordsPerSlide.max
2162
- // FROM KB
2163
- )
2227
+ body: truncatedBody || section.header
2228
+ // Fallback to header if no body
2164
2229
  },
2165
2230
  classes: ["single-statement-slide"]
2166
2231
  };
@@ -2534,6 +2599,9 @@ var TemplateEngine = class {
2534
2599
  this.handlebars.registerHelper("animDelay", function(index, baseMs = 100) {
2535
2600
  return `animation-delay: ${index * baseMs}ms`;
2536
2601
  });
2602
+ this.handlebars.registerHelper("add", function(a, b) {
2603
+ return a + b;
2604
+ });
2537
2605
  this.handlebars.registerHelper("safeHTML", function(text) {
2538
2606
  return new import_handlebars.default.SafeString(text);
2539
2607
  });
@@ -2641,7 +2709,12 @@ var TemplateEngine = class {
2641
2709
  this.templates.set("single-statement", this.handlebars.compile(`
2642
2710
  <section class="{{classes}}" data-slide-index="{{slideIndex}}" style="{{styles}}">
2643
2711
  <div class="slide-content statement-content">
2712
+ {{#if body}}
2713
+ <h2 class="title animate-fadeIn">{{title}}</h2>
2714
+ <p class="statement animate-fadeIn delay-200">{{markdown body}}</p>
2715
+ {{else}}
2644
2716
  <p class="statement animate-fadeIn">{{title}}</p>
2717
+ {{/if}}
2645
2718
  </div>
2646
2719
  {{> speakerNotes}}
2647
2720
  </section>
@@ -2707,14 +2780,30 @@ var TemplateEngine = class {
2707
2780
  <h2 class="title animate-fadeIn">{{title}}</h2>
2708
2781
  <div class="columns two-columns">
2709
2782
  <div class="column column-left animate-slideRight">
2710
- {{#if body}}
2711
- <p class="body">{{markdown body}}</p>
2783
+ {{#if leftColumn.title}}<h3>{{leftColumn.title}}</h3>{{/if}}
2784
+ {{#if leftColumn.body}}
2785
+ <p class="body">{{markdown leftColumn.body}}</p>
2712
2786
  {{/if}}
2713
- {{#if hasBullets}}
2714
- {{> bulletList}}
2787
+ {{#if leftColumn.bullets}}
2788
+ <ul class="bullets stagger-children">
2789
+ {{#each leftColumn.bullets}}
2790
+ <li class="bullet animate-fadeIn" style="{{animDelay @index 150}}">{{markdown this}}</li>
2791
+ {{/each}}
2792
+ </ul>
2715
2793
  {{/if}}
2716
2794
  </div>
2717
2795
  <div class="column column-right animate-slideLeft delay-200">
2796
+ {{#if rightColumn.title}}<h3>{{rightColumn.title}}</h3>{{/if}}
2797
+ {{#if rightColumn.body}}
2798
+ <p class="body">{{markdown rightColumn.body}}</p>
2799
+ {{/if}}
2800
+ {{#if rightColumn.bullets}}
2801
+ <ul class="bullets stagger-children">
2802
+ {{#each rightColumn.bullets}}
2803
+ <li class="bullet animate-fadeIn" style="{{animDelay @index 150}}">{{markdown this}}</li>
2804
+ {{/each}}
2805
+ </ul>
2806
+ {{/if}}
2718
2807
  {{#if hasImage}}
2719
2808
  {{> imageWithCaption images.[0]}}
2720
2809
  {{else if metrics}}
@@ -2735,11 +2824,13 @@ var TemplateEngine = class {
2735
2824
  {{#each columns}}
2736
2825
  <div class="column animate-fadeIn" style="{{animDelay @index 200}}">
2737
2826
  {{#if title}}<h3 class="column-title">{{title}}</h3>{{/if}}
2827
+ {{#if content}}<p class="column-body">{{markdown content}}</p>{{/if}}
2738
2828
  {{#if body}}<p class="column-body">{{markdown body}}</p>{{/if}}
2739
2829
  {{#if icon}}<div class="column-icon">{{icon}}</div>{{/if}}
2740
2830
  </div>
2741
2831
  {{/each}}
2742
2832
  </div>
2833
+ {{> source}}
2743
2834
  </div>
2744
2835
  {{> speakerNotes}}
2745
2836
  </section>
@@ -2748,25 +2839,24 @@ var TemplateEngine = class {
2748
2839
  <section class="{{classes}}" data-slide-index="{{slideIndex}}" style="{{styles}}">
2749
2840
  <div class="slide-content">
2750
2841
  <h2 class="title animate-fadeIn">{{title}}</h2>
2751
- <div class="comparison-container">
2752
- <div class="comparison-left animate-slideRight">
2753
- <h3>{{leftTitle}}</h3>
2754
- <ul>
2755
- {{#each leftItems}}
2756
- <li>{{this}}</li>
2757
- {{/each}}
2758
- </ul>
2759
- </div>
2760
- <div class="comparison-divider"></div>
2761
- <div class="comparison-right animate-slideLeft delay-200">
2762
- <h3>{{rightTitle}}</h3>
2842
+ <div class="comparison-container columns two-columns">
2843
+ {{#each columns}}
2844
+ <div class="column comparison-{{#if @first}}left animate-slideRight{{else}}right animate-slideLeft delay-200{{/if}}">
2845
+ <h3 class="column-title">{{title}}</h3>
2846
+ {{#if content}}
2847
+ <p class="column-content">{{markdown content}}</p>
2848
+ {{/if}}
2849
+ {{#if bullets}}
2763
2850
  <ul>
2764
- {{#each rightItems}}
2851
+ {{#each bullets}}
2765
2852
  <li>{{this}}</li>
2766
2853
  {{/each}}
2767
2854
  </ul>
2855
+ {{/if}}
2768
2856
  </div>
2857
+ {{/each}}
2769
2858
  </div>
2859
+ {{> source}}
2770
2860
  </div>
2771
2861
  {{> speakerNotes}}
2772
2862
  </section>
@@ -2830,18 +2920,18 @@ var TemplateEngine = class {
2830
2920
  <section class="{{classes}}" data-slide-index="{{slideIndex}}" style="{{styles}}">
2831
2921
  <div class="slide-content">
2832
2922
  <h2 class="title animate-fadeIn">{{title}}</h2>
2833
- <div class="timeline stagger-children">
2834
- {{#each events}}
2835
- <div class="timeline-item animate-fadeIn" style="{{animDelay @index 200}}">
2836
- <div class="timeline-marker"></div>
2923
+ <div class="timeline steps stagger-children">
2924
+ {{#each steps}}
2925
+ <div class="step timeline-item animate-fadeIn" style="{{animDelay @index 200}}">
2926
+ <div class="step-number">{{add @index 1}}</div>
2837
2927
  <div class="timeline-content">
2838
- <div class="timeline-date">{{date}}</div>
2839
- <div class="timeline-title">{{title}}</div>
2840
- {{#if description}}<div class="timeline-desc">{{description}}</div>{{/if}}
2928
+ <div class="step-title">{{label}}</div>
2929
+ {{#if description}}<div class="step-desc">{{description}}</div>{{/if}}
2841
2930
  </div>
2842
2931
  </div>
2843
2932
  {{/each}}
2844
2933
  </div>
2934
+ {{> source}}
2845
2935
  </div>
2846
2936
  {{> speakerNotes}}
2847
2937
  </section>
@@ -5379,29 +5469,70 @@ ${slides}
5379
5469
  }
5380
5470
 
5381
5471
  /* Comparison slides: Split visual */
5382
- .reveal .slide-comparison .columns {
5472
+ .reveal .slide-comparison .columns,
5473
+ .reveal .slide-comparison .comparison-container {
5383
5474
  gap: 60px;
5384
5475
  }
5385
- .reveal .slide-comparison .column:first-child {
5476
+ .reveal .slide-comparison .column:first-child,
5477
+ .reveal .slide-comparison .comparison-left {
5386
5478
  border-right: 2px solid ${this.lightenColor(secondary, 70)};
5387
5479
  padding-right: 30px;
5388
5480
  }
5481
+ .reveal .column-title {
5482
+ font-size: 1.2em;
5483
+ font-weight: 600;
5484
+ margin-bottom: 0.5em;
5485
+ color: var(--color-accent);
5486
+ }
5487
+ .reveal .column-content,
5488
+ .reveal .column-body {
5489
+ line-height: 1.6;
5490
+ }
5389
5491
 
5390
5492
  /* Timeline/Process: Visual flow */
5391
5493
  .reveal .slide-timeline .steps,
5392
- .reveal .slide-process .steps {
5494
+ .reveal .slide-timeline .timeline,
5495
+ .reveal .slide-process .steps,
5496
+ .reveal .slide-process .process-steps {
5393
5497
  display: flex;
5394
5498
  gap: 20px;
5499
+ flex-wrap: wrap;
5500
+ justify-content: center;
5395
5501
  }
5396
5502
  .reveal .slide-timeline .step,
5397
- .reveal .slide-process .step {
5503
+ .reveal .slide-timeline .timeline-item,
5504
+ .reveal .slide-process .step,
5505
+ .reveal .slide-process .process-step {
5398
5506
  flex: 1;
5507
+ min-width: 150px;
5508
+ max-width: 250px;
5399
5509
  padding: 20px;
5400
5510
  background: ${isDark ? this.lightenColor(background, 10) : this.lightenColor(secondary, 92)};
5401
5511
  border-radius: 8px;
5402
5512
  border-top: 4px solid var(--color-accent);
5403
5513
  ${isDark ? `color: ${text};` : ""}
5404
5514
  }
5515
+ .reveal .step-number {
5516
+ font-size: 1.5em;
5517
+ font-weight: 700;
5518
+ color: var(--color-accent);
5519
+ margin-bottom: 0.5em;
5520
+ }
5521
+ .reveal .step-title {
5522
+ font-size: 1.1em;
5523
+ font-weight: 600;
5524
+ margin-bottom: 0.5em;
5525
+ }
5526
+ .reveal .step-desc {
5527
+ font-size: 0.9em;
5528
+ color: var(--color-text-light);
5529
+ }
5530
+ .reveal .step-arrow {
5531
+ display: flex;
5532
+ align-items: center;
5533
+ font-size: 1.5em;
5534
+ color: var(--color-accent);
5535
+ }
5405
5536
 
5406
5537
  /* Progress bar enhancement */
5407
5538
  .reveal .progress {
package/dist/index.mjs CHANGED
@@ -889,7 +889,8 @@ var ContentAnalyzer = class {
889
889
  async analyze(content, contentType) {
890
890
  await this.initialize();
891
891
  const text = this.parseContent(content, contentType);
892
- const title = this.extractTitle(text);
892
+ const { title, subtitle } = this.extractTitleAndSubtitle(text);
893
+ logger.step(`Title: "${title}", Subtitle: "${subtitle || "(none)"}"`);
893
894
  const detectedType = this.detectPresentationType(text);
894
895
  logger.step(`Detected type: ${detectedType}`);
895
896
  const sections = this.extractSections(text);
@@ -902,9 +903,13 @@ var ContentAnalyzer = class {
902
903
  const titles = sections.map((s) => s.header).filter((h) => h.length > 0);
903
904
  const starMoments = this.extractStarMoments(text);
904
905
  const estimatedSlideCount = Math.max(5, sections.length + 3);
906
+ const whatIsContent = scqa.situation ? [scqa.situation] : [];
907
+ const whatCouldBeContent = scqa.answer ? [scqa.answer] : keyMessages.slice(0, 2);
905
908
  return {
906
909
  detectedType,
907
910
  title,
911
+ subtitle,
912
+ // NEW: Use explicit subtitle from content
908
913
  sections,
909
914
  keyMessages,
910
915
  dataPoints,
@@ -915,8 +920,10 @@ var ContentAnalyzer = class {
915
920
  answer: scqa.answer || ""
916
921
  },
917
922
  sparkline: {
918
- whatIs: sparkline.callToAction ? [sparkline.callToAction] : [],
919
- whatCouldBe: keyMessages,
923
+ whatIs: whatIsContent,
924
+ // FIX: Use situation, not CTA
925
+ whatCouldBe: whatCouldBeContent,
926
+ // FIX: Use answer/vision, not random messages
920
927
  callToAdventure: sparkline.callToAction || ""
921
928
  },
922
929
  titles,
@@ -944,18 +951,46 @@ var ContentAnalyzer = class {
944
951
  return text;
945
952
  }
946
953
  /**
947
- * Extract the main title from content
954
+ * Extract the main title AND subtitle from content
955
+ * Subtitle is the line immediately after the H1 title (if not another header)
948
956
  */
949
- extractTitle(text) {
950
- const h1Match = text.match(/^#\s+(.+)$/m);
951
- if (h1Match && h1Match[1]) {
952
- return h1Match[1].replace(/\*\*/g, "").trim();
957
+ extractTitleAndSubtitle(text) {
958
+ const lines = text.split("\n");
959
+ let title = "Presentation";
960
+ let subtitle = "";
961
+ let foundTitle = false;
962
+ let titleLineIndex = -1;
963
+ for (let i = 0; i < lines.length; i++) {
964
+ const rawLine = lines[i];
965
+ if (!rawLine) continue;
966
+ const line = rawLine.trim();
967
+ const h1Match = line.match(/^#\s+(.+)$/);
968
+ if (h1Match && h1Match[1] && !foundTitle) {
969
+ title = h1Match[1].replace(/\*\*/g, "").trim();
970
+ foundTitle = true;
971
+ titleLineIndex = i;
972
+ continue;
973
+ }
974
+ if (foundTitle && i > titleLineIndex && line.length > 0) {
975
+ if (line.startsWith("#")) break;
976
+ if (line.startsWith("-") || line.startsWith("*") || /^\d+\./.test(line)) break;
977
+ subtitle = line.replace(/\*\*/g, "").trim().slice(0, 100);
978
+ break;
979
+ }
953
980
  }
954
- const lines = text.split("\n").filter((l) => l.trim().length > 0);
955
- if (lines.length > 0 && lines[0]) {
956
- return lines[0].replace(/^#+\s*/, "").replace(/\*\*/g, "").trim().slice(0, 80);
981
+ if (!foundTitle) {
982
+ const firstLine = lines.find((l) => l.trim().length > 0);
983
+ if (firstLine) {
984
+ title = firstLine.replace(/^#+\s*/, "").replace(/\*\*/g, "").trim().slice(0, 80);
985
+ }
957
986
  }
958
- return "Presentation";
987
+ return { title, subtitle };
988
+ }
989
+ /**
990
+ * Extract the main title from content (legacy wrapper)
991
+ */
992
+ extractTitle(text) {
993
+ return this.extractTitleAndSubtitle(text).title;
959
994
  }
960
995
  /**
961
996
  * Detect presentation type from content signals
@@ -1578,6 +1613,11 @@ var ContentPatternClassifier = class {
1578
1613
  }
1579
1614
  /**
1580
1615
  * Extract timeline/process steps from content
1616
+ * Handles multiple formats:
1617
+ * - "Step 1: Do something" → label: "Step 1", description: "Do something"
1618
+ * - "1. First item" → label: "1", description: "First item"
1619
+ * - "Title - Description text" → label: "Title", description: "Description text"
1620
+ * - "Plain text" → label: "1", description: "Plain text"
1581
1621
  */
1582
1622
  extractSteps(section) {
1583
1623
  const steps = [];
@@ -1588,12 +1628,28 @@ var ContentPatternClassifier = class {
1588
1628
  label: stepMatch[1].trim(),
1589
1629
  description: stepMatch[2].trim()
1590
1630
  });
1591
- } else {
1631
+ continue;
1632
+ }
1633
+ const dashMatch = bullet.match(/^([^-]+)\s+-\s+(.+)$/);
1634
+ if (dashMatch && dashMatch[1] && dashMatch[2]) {
1592
1635
  steps.push({
1593
- label: `${steps.length + 1}`,
1594
- description: bullet
1636
+ label: dashMatch[1].trim(),
1637
+ description: dashMatch[2].trim()
1595
1638
  });
1639
+ continue;
1596
1640
  }
1641
+ const colonMatch = bullet.match(/^([^:]+):\s*(.+)$/);
1642
+ if (colonMatch && colonMatch[1] && colonMatch[2] && colonMatch[1].length < 40) {
1643
+ steps.push({
1644
+ label: colonMatch[1].trim(),
1645
+ description: colonMatch[2].trim()
1646
+ });
1647
+ continue;
1648
+ }
1649
+ steps.push({
1650
+ label: `${steps.length + 1}`,
1651
+ description: bullet
1652
+ });
1597
1653
  }
1598
1654
  return steps;
1599
1655
  }
@@ -1758,9 +1814,10 @@ var SlideFactory = class {
1758
1814
  const data = {
1759
1815
  title: this.truncateText(analysis.title, this.config.rules.wordsPerSlide.max)
1760
1816
  };
1761
- if (analysis.keyMessages[0]) {
1817
+ const subtitleSource = analysis.subtitle || analysis.keyMessages[0] || "";
1818
+ if (subtitleSource) {
1762
1819
  data.subtitle = this.truncateText(
1763
- analysis.keyMessages[0],
1820
+ subtitleSource,
1764
1821
  this.config.defaults.subtitle.maxWords
1765
1822
  // FROM KB
1766
1823
  );
@@ -1804,7 +1861,9 @@ var SlideFactory = class {
1804
1861
  addSCQASlides(slides, analysis) {
1805
1862
  const scqa = analysis.scqa;
1806
1863
  const titles = this.config.scqaTitles;
1807
- if (scqa?.situation && !this.usedContent.has("scqa-situation")) {
1864
+ const minBodyLength = 20;
1865
+ const situationBody = scqa?.situation ? this.truncateText(scqa.situation, this.config.rules.wordsPerSlide.max) : "";
1866
+ if (situationBody.length >= minBodyLength && !this.usedContent.has("scqa-situation")) {
1808
1867
  this.usedContent.add("scqa-situation");
1809
1868
  slides.push({
1810
1869
  index: slides.length,
@@ -1812,12 +1871,13 @@ var SlideFactory = class {
1812
1871
  data: {
1813
1872
  title: titles.situation,
1814
1873
  // FROM KB - not hardcoded 'Current Situation'
1815
- body: this.truncateText(scqa.situation, this.config.rules.wordsPerSlide.max)
1874
+ body: situationBody
1816
1875
  },
1817
1876
  classes: ["situation-slide"]
1818
1877
  });
1819
1878
  }
1820
- if (scqa?.complication && !this.usedContent.has("scqa-complication")) {
1879
+ const complicationBody = scqa?.complication ? this.truncateText(scqa.complication, this.config.rules.wordsPerSlide.max) : "";
1880
+ if (complicationBody.length >= minBodyLength && !this.usedContent.has("scqa-complication")) {
1821
1881
  this.usedContent.add("scqa-complication");
1822
1882
  slides.push({
1823
1883
  index: slides.length,
@@ -1825,12 +1885,13 @@ var SlideFactory = class {
1825
1885
  data: {
1826
1886
  title: titles.complication,
1827
1887
  // FROM KB - not hardcoded 'The Challenge'
1828
- body: this.truncateText(scqa.complication, this.config.rules.wordsPerSlide.max)
1888
+ body: complicationBody
1829
1889
  },
1830
1890
  classes: ["complication-slide"]
1831
1891
  });
1832
1892
  }
1833
- if (scqa?.question && !this.usedContent.has("scqa-question")) {
1893
+ const questionBody = scqa?.question ? this.truncateText(scqa.question, this.config.rules.wordsPerSlide.max) : "";
1894
+ if (questionBody.length >= minBodyLength && !this.usedContent.has("scqa-question")) {
1834
1895
  this.usedContent.add("scqa-question");
1835
1896
  slides.push({
1836
1897
  index: slides.length,
@@ -1838,7 +1899,7 @@ var SlideFactory = class {
1838
1899
  data: {
1839
1900
  title: titles.question,
1840
1901
  // FROM KB - not hardcoded 'The Question'
1841
- body: this.truncateText(scqa.question, this.config.rules.wordsPerSlide.max)
1902
+ body: questionBody
1842
1903
  },
1843
1904
  classes: ["question-slide"]
1844
1905
  });
@@ -1848,7 +1909,8 @@ var SlideFactory = class {
1848
1909
  const spark = analysis.sparkline;
1849
1910
  const titles = this.config.sparklineTitles;
1850
1911
  const whatIsFirst = spark?.whatIs?.[0];
1851
- if (whatIsFirst && !this.usedContent.has("spark-what-is")) {
1912
+ const whatIsBody = whatIsFirst ? this.truncateText(whatIsFirst, this.config.rules.wordsPerSlide.max) : "";
1913
+ if (whatIsBody.length >= 20 && !this.usedContent.has("spark-what-is")) {
1852
1914
  this.usedContent.add("spark-what-is");
1853
1915
  slides.push({
1854
1916
  index: slides.length,
@@ -1856,13 +1918,14 @@ var SlideFactory = class {
1856
1918
  data: {
1857
1919
  title: titles.whatIs,
1858
1920
  // FROM KB - not hardcoded 'Where We Are Today'
1859
- body: this.truncateText(whatIsFirst, this.config.rules.wordsPerSlide.max)
1921
+ body: whatIsBody
1860
1922
  },
1861
1923
  classes: ["what-is-slide"]
1862
1924
  });
1863
1925
  }
1864
1926
  const whatCouldBeFirst = spark?.whatCouldBe?.[0];
1865
- if (whatCouldBeFirst && !this.usedContent.has("spark-could-be")) {
1927
+ const whatCouldBeBody = whatCouldBeFirst ? this.truncateText(whatCouldBeFirst, this.config.rules.wordsPerSlide.max) : "";
1928
+ if (whatCouldBeBody.length >= 20 && !this.usedContent.has("spark-could-be")) {
1866
1929
  this.usedContent.add("spark-could-be");
1867
1930
  slides.push({
1868
1931
  index: slides.length,
@@ -1870,7 +1933,7 @@ var SlideFactory = class {
1870
1933
  data: {
1871
1934
  title: titles.whatCouldBe,
1872
1935
  // FROM KB - not hardcoded 'What Could Be'
1873
- body: this.truncateText(whatCouldBeFirst, this.config.rules.wordsPerSlide.max)
1936
+ body: whatCouldBeBody
1874
1937
  },
1875
1938
  classes: ["what-could-be-slide"]
1876
1939
  });
@@ -2079,16 +2142,18 @@ var SlideFactory = class {
2079
2142
  };
2080
2143
  }
2081
2144
  createSingleStatementSlide(index, section) {
2145
+ const bodyContent = section.content || section.bullets.join(" ") || "";
2146
+ const truncatedBody = this.truncateText(bodyContent, this.config.rules.wordsPerSlide.max);
2147
+ if (truncatedBody.length < 15 && section.bullets.length > 0) {
2148
+ return this.createBulletSlide(index, section);
2149
+ }
2082
2150
  return {
2083
2151
  index,
2084
2152
  type: "single-statement",
2085
2153
  data: {
2086
2154
  title: this.createTitle(section.header, section),
2087
- body: this.truncateText(
2088
- section.content || section.bullets[0] || "",
2089
- this.config.rules.wordsPerSlide.max
2090
- // FROM KB
2091
- )
2155
+ body: truncatedBody || section.header
2156
+ // Fallback to header if no body
2092
2157
  },
2093
2158
  classes: ["single-statement-slide"]
2094
2159
  };
@@ -2462,6 +2527,9 @@ var TemplateEngine = class {
2462
2527
  this.handlebars.registerHelper("animDelay", function(index, baseMs = 100) {
2463
2528
  return `animation-delay: ${index * baseMs}ms`;
2464
2529
  });
2530
+ this.handlebars.registerHelper("add", function(a, b) {
2531
+ return a + b;
2532
+ });
2465
2533
  this.handlebars.registerHelper("safeHTML", function(text) {
2466
2534
  return new Handlebars.SafeString(text);
2467
2535
  });
@@ -2569,7 +2637,12 @@ var TemplateEngine = class {
2569
2637
  this.templates.set("single-statement", this.handlebars.compile(`
2570
2638
  <section class="{{classes}}" data-slide-index="{{slideIndex}}" style="{{styles}}">
2571
2639
  <div class="slide-content statement-content">
2640
+ {{#if body}}
2641
+ <h2 class="title animate-fadeIn">{{title}}</h2>
2642
+ <p class="statement animate-fadeIn delay-200">{{markdown body}}</p>
2643
+ {{else}}
2572
2644
  <p class="statement animate-fadeIn">{{title}}</p>
2645
+ {{/if}}
2573
2646
  </div>
2574
2647
  {{> speakerNotes}}
2575
2648
  </section>
@@ -2635,14 +2708,30 @@ var TemplateEngine = class {
2635
2708
  <h2 class="title animate-fadeIn">{{title}}</h2>
2636
2709
  <div class="columns two-columns">
2637
2710
  <div class="column column-left animate-slideRight">
2638
- {{#if body}}
2639
- <p class="body">{{markdown body}}</p>
2711
+ {{#if leftColumn.title}}<h3>{{leftColumn.title}}</h3>{{/if}}
2712
+ {{#if leftColumn.body}}
2713
+ <p class="body">{{markdown leftColumn.body}}</p>
2640
2714
  {{/if}}
2641
- {{#if hasBullets}}
2642
- {{> bulletList}}
2715
+ {{#if leftColumn.bullets}}
2716
+ <ul class="bullets stagger-children">
2717
+ {{#each leftColumn.bullets}}
2718
+ <li class="bullet animate-fadeIn" style="{{animDelay @index 150}}">{{markdown this}}</li>
2719
+ {{/each}}
2720
+ </ul>
2643
2721
  {{/if}}
2644
2722
  </div>
2645
2723
  <div class="column column-right animate-slideLeft delay-200">
2724
+ {{#if rightColumn.title}}<h3>{{rightColumn.title}}</h3>{{/if}}
2725
+ {{#if rightColumn.body}}
2726
+ <p class="body">{{markdown rightColumn.body}}</p>
2727
+ {{/if}}
2728
+ {{#if rightColumn.bullets}}
2729
+ <ul class="bullets stagger-children">
2730
+ {{#each rightColumn.bullets}}
2731
+ <li class="bullet animate-fadeIn" style="{{animDelay @index 150}}">{{markdown this}}</li>
2732
+ {{/each}}
2733
+ </ul>
2734
+ {{/if}}
2646
2735
  {{#if hasImage}}
2647
2736
  {{> imageWithCaption images.[0]}}
2648
2737
  {{else if metrics}}
@@ -2663,11 +2752,13 @@ var TemplateEngine = class {
2663
2752
  {{#each columns}}
2664
2753
  <div class="column animate-fadeIn" style="{{animDelay @index 200}}">
2665
2754
  {{#if title}}<h3 class="column-title">{{title}}</h3>{{/if}}
2755
+ {{#if content}}<p class="column-body">{{markdown content}}</p>{{/if}}
2666
2756
  {{#if body}}<p class="column-body">{{markdown body}}</p>{{/if}}
2667
2757
  {{#if icon}}<div class="column-icon">{{icon}}</div>{{/if}}
2668
2758
  </div>
2669
2759
  {{/each}}
2670
2760
  </div>
2761
+ {{> source}}
2671
2762
  </div>
2672
2763
  {{> speakerNotes}}
2673
2764
  </section>
@@ -2676,25 +2767,24 @@ var TemplateEngine = class {
2676
2767
  <section class="{{classes}}" data-slide-index="{{slideIndex}}" style="{{styles}}">
2677
2768
  <div class="slide-content">
2678
2769
  <h2 class="title animate-fadeIn">{{title}}</h2>
2679
- <div class="comparison-container">
2680
- <div class="comparison-left animate-slideRight">
2681
- <h3>{{leftTitle}}</h3>
2682
- <ul>
2683
- {{#each leftItems}}
2684
- <li>{{this}}</li>
2685
- {{/each}}
2686
- </ul>
2687
- </div>
2688
- <div class="comparison-divider"></div>
2689
- <div class="comparison-right animate-slideLeft delay-200">
2690
- <h3>{{rightTitle}}</h3>
2770
+ <div class="comparison-container columns two-columns">
2771
+ {{#each columns}}
2772
+ <div class="column comparison-{{#if @first}}left animate-slideRight{{else}}right animate-slideLeft delay-200{{/if}}">
2773
+ <h3 class="column-title">{{title}}</h3>
2774
+ {{#if content}}
2775
+ <p class="column-content">{{markdown content}}</p>
2776
+ {{/if}}
2777
+ {{#if bullets}}
2691
2778
  <ul>
2692
- {{#each rightItems}}
2779
+ {{#each bullets}}
2693
2780
  <li>{{this}}</li>
2694
2781
  {{/each}}
2695
2782
  </ul>
2783
+ {{/if}}
2696
2784
  </div>
2785
+ {{/each}}
2697
2786
  </div>
2787
+ {{> source}}
2698
2788
  </div>
2699
2789
  {{> speakerNotes}}
2700
2790
  </section>
@@ -2758,18 +2848,18 @@ var TemplateEngine = class {
2758
2848
  <section class="{{classes}}" data-slide-index="{{slideIndex}}" style="{{styles}}">
2759
2849
  <div class="slide-content">
2760
2850
  <h2 class="title animate-fadeIn">{{title}}</h2>
2761
- <div class="timeline stagger-children">
2762
- {{#each events}}
2763
- <div class="timeline-item animate-fadeIn" style="{{animDelay @index 200}}">
2764
- <div class="timeline-marker"></div>
2851
+ <div class="timeline steps stagger-children">
2852
+ {{#each steps}}
2853
+ <div class="step timeline-item animate-fadeIn" style="{{animDelay @index 200}}">
2854
+ <div class="step-number">{{add @index 1}}</div>
2765
2855
  <div class="timeline-content">
2766
- <div class="timeline-date">{{date}}</div>
2767
- <div class="timeline-title">{{title}}</div>
2768
- {{#if description}}<div class="timeline-desc">{{description}}</div>{{/if}}
2856
+ <div class="step-title">{{label}}</div>
2857
+ {{#if description}}<div class="step-desc">{{description}}</div>{{/if}}
2769
2858
  </div>
2770
2859
  </div>
2771
2860
  {{/each}}
2772
2861
  </div>
2862
+ {{> source}}
2773
2863
  </div>
2774
2864
  {{> speakerNotes}}
2775
2865
  </section>
@@ -5307,29 +5397,70 @@ ${slides}
5307
5397
  }
5308
5398
 
5309
5399
  /* Comparison slides: Split visual */
5310
- .reveal .slide-comparison .columns {
5400
+ .reveal .slide-comparison .columns,
5401
+ .reveal .slide-comparison .comparison-container {
5311
5402
  gap: 60px;
5312
5403
  }
5313
- .reveal .slide-comparison .column:first-child {
5404
+ .reveal .slide-comparison .column:first-child,
5405
+ .reveal .slide-comparison .comparison-left {
5314
5406
  border-right: 2px solid ${this.lightenColor(secondary, 70)};
5315
5407
  padding-right: 30px;
5316
5408
  }
5409
+ .reveal .column-title {
5410
+ font-size: 1.2em;
5411
+ font-weight: 600;
5412
+ margin-bottom: 0.5em;
5413
+ color: var(--color-accent);
5414
+ }
5415
+ .reveal .column-content,
5416
+ .reveal .column-body {
5417
+ line-height: 1.6;
5418
+ }
5317
5419
 
5318
5420
  /* Timeline/Process: Visual flow */
5319
5421
  .reveal .slide-timeline .steps,
5320
- .reveal .slide-process .steps {
5422
+ .reveal .slide-timeline .timeline,
5423
+ .reveal .slide-process .steps,
5424
+ .reveal .slide-process .process-steps {
5321
5425
  display: flex;
5322
5426
  gap: 20px;
5427
+ flex-wrap: wrap;
5428
+ justify-content: center;
5323
5429
  }
5324
5430
  .reveal .slide-timeline .step,
5325
- .reveal .slide-process .step {
5431
+ .reveal .slide-timeline .timeline-item,
5432
+ .reveal .slide-process .step,
5433
+ .reveal .slide-process .process-step {
5326
5434
  flex: 1;
5435
+ min-width: 150px;
5436
+ max-width: 250px;
5327
5437
  padding: 20px;
5328
5438
  background: ${isDark ? this.lightenColor(background, 10) : this.lightenColor(secondary, 92)};
5329
5439
  border-radius: 8px;
5330
5440
  border-top: 4px solid var(--color-accent);
5331
5441
  ${isDark ? `color: ${text};` : ""}
5332
5442
  }
5443
+ .reveal .step-number {
5444
+ font-size: 1.5em;
5445
+ font-weight: 700;
5446
+ color: var(--color-accent);
5447
+ margin-bottom: 0.5em;
5448
+ }
5449
+ .reveal .step-title {
5450
+ font-size: 1.1em;
5451
+ font-weight: 600;
5452
+ margin-bottom: 0.5em;
5453
+ }
5454
+ .reveal .step-desc {
5455
+ font-size: 0.9em;
5456
+ color: var(--color-text-light);
5457
+ }
5458
+ .reveal .step-arrow {
5459
+ display: flex;
5460
+ align-items: center;
5461
+ font-size: 1.5em;
5462
+ color: var(--color-accent);
5463
+ }
5333
5464
 
5334
5465
  /* Progress bar enhancement */
5335
5466
  .reveal .progress {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-presentation-master",
3
- "version": "7.2.1",
3
+ "version": "7.4.0",
4
4
  "description": "Generate world-class presentations using expert methodologies from Duarte, Reynolds, Gallo, and Anderson. Enforces rigorous quality standards through real visual validation.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",