$ cat node-template.py
S
Slide Generator
// Generates a single presentation slide from text content and an instruction. Connect multiple Slide Generator outputs to a Presentation Composer to build a full presentation.
Process
Document
template.py
1import os2import sys3import json4import re5import base646import mimetypes7import traceback8from gais import Gais910SYSTEM_PROMPT = '''You are a presentation slide designer. Your task is to generate exactly ONE Reveal.js slide as an HTML <section> element.1112RULES:131. Output ONLY a single <section>...</section> element. No <!DOCTYPE>, no <html>, no <head>, no wrapper.142. Use <h2> for the slide title (not <h1>).153. Use semantic HTML: <ul>/<ol> for lists, <p> for text, <table> for data, <blockquote> for quotes.164. Use class="fragment" on elements that should appear one-by-one during the presentation.175. Use <aside class="notes">...</aside> for speaker notes (always include brief notes).186. Do NOT set data-background-color on <section>. The presentation theme controls all colors — never override it.197. Keep content concise — slides should be scannable, not walls of text.208. Do NOT include any CSS <style> blocks or <script> tags.219. Do NOT set color, background-color, or any color-related inline styles. Let the Reveal.js theme handle all colors.2210. Only use inline styles for LAYOUT purposes (display:flex, display:grid, gap, font-size). Never for colors or backgrounds.2311. Use plain HTML that Reveal.js themes will style automatically.2412. THEME × TEMPLATE COUPLING: each slide layout template in this system is theme-specific. marina-* templates (marina-intro, marina-content, marina-metrics, marina-timeline, marina-comparison, marina-outro) require the 'marina' Reveal theme and use Marina-only classes (.title-slide, .closing-slide, data-header-title, .card-grid, .tag.commercial, etc.). emblema-* templates (emblema-cover, emblema-agenda, emblema-section, …, emblema-closing) require the 'emblema' theme and use Emblema-only classes (.slide-cover, .slide-section, .slide-pad, .slide-bullets, etc.). NEVER emit a marina-* slide structure when the deck theme is emblema (the cover and closing collapse to unstyled white pages because emblema CSS does not define .title-slide / .closing-slide). NEVER emit an emblema-* slide structure when the deck theme is marina. If you are asked to produce a cover or closing for an emblema deck, use emblema-cover and emblema-closing — not marina-intro / marina-outro.2526IMAGE PLACEHOLDERS:27When a slide layout requires images, use picsum.photos for royalty-free placeholder images:28- Landscape: <img src="https://picsum.photos/seed/{topic}/600/400" alt="description">29- Portrait: <img src="https://picsum.photos/seed/{topic}/400/600" alt="description">30- Square: <img src="https://picsum.photos/seed/{topic}/400/400" alt="description">31Replace {topic} with a short keyword related to the slide content (e.g. "analytics", "team", "growth").32Always include a descriptive alt attribute. Set width via style if needed for layout.3334LAYOUT PATTERNS you can use:35- Title slide: <h2> + <p> subtitle36- Bullet points: <h2> + <ul> with <li class="fragment">37- Two columns: <div style="display:flex;gap:2em"> with two <div> children38- Data table: <h2> + <table>39- Quote: <blockquote> + attribution40- Image + text: <h2> + <div style="display:flex;gap:2em"> with <img> and text side by side4142Always output valid HTML. The content should be based ONLY on the provided source material — do not invent facts or data.'''4344# Layout instructions for each slide template45TEMPLATE_INSTRUCTIONS = {46 # ─── Marina Militare layouts ───47 "marina-intro": "[THEME GATE: this template is valid ONLY when the active deck theme is 'marina'. If the active theme is 'emblema', DO NOT emit this structure — switch to the 'emblema-cover' template instead, which is the Emblema brand cover. The Marina .title-slide class is unstyled in the Emblema theme and would render as a blank white slide.] "48 "Create a Marina Militare INTRO/COVER slide. The <section> MUST start with class='title-slide' — WITHOUT THIS CLASS, the Marina Militare crest will NOT render and the Graduate uppercase title font will NOT apply. The slide will collapse to a plain navy background with default text. Use this EXACT structure:\n"49 "<section class='title-slide'>\n"50 " <h1>OPERATION OR BRIEFING TITLE</h1>\n"51 " <p class='subtitle'>Subtitle line — short, two lines maximum</p>\n"52 " <p class='meta'>Mission ID | Unit | Date | Classification</p>\n"53 " <aside class='notes'>Cover slide — set the audience and the mission.</aside>\n"54 "</section>\n"55 "The Marina Militare crest is injected by the theme via a CSS pseudo-element above the title — do NOT add an <img> for the logo. The <h1> renders in uppercase Graduate font and tolerates a <br> mid-line for a two-line title. Keep the subtitle to one or two lines using <p class='subtitle'>. Use <p class='meta'> for the small operational metadata (mission ID, unit, date, classification). Keep all class names EXACTLY as shown — class='title-slide' on the section is LOAD-BEARING.",5657 "marina-content": "Create a Marina Militare CONTENT slide. "58 "CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source → Italian heading). Extract the heading from the actual source content — do NOT invent generic English dashboard phrases. BANNED headings that you MUST NOT use as <h2>: 'Overview', 'Summary', 'Key Points', 'Main Content', 'Content Summary', 'Information', 'Details'. These are hallucinations from other templates and look unprofessional. Good examples for an Italian Navy briefing: 'Identificazione Missione', 'Assetto della Piattaforma', 'Quadro Operativo Generale'. "59 "The <section> MUST have a data-header-title='SHORT TITLE' attribute — WITHOUT THIS ATTRIBUTE, the top header bar with the Marina Militare logo and uppercase title will NOT render. The slide will look unbranded. Use this EXACT structure:\n"60 "<section data-header-title='SHORT SLIDE TITLE'>\n"61 " <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n"62 " <p class='section-label'>Optional small label / subtitle</p>\n"63 " <div class='card-grid cols-3'>\n"64 " <div class='card'><div class='label'>LABEL</div><div class='value gold'>VALUE</div><div class='detail'>Detail</div></div>\n"65 " <!-- ...more cards... -->\n"66 " </div>\n"67 " <aside class='notes'>Speaker notes.</aside>\n"68 "</section>\n"69 "The data-header-title attribute on <section> drives the fixed header bar — the theme injects the Marina Militare logo on the left and this title text in uppercase on the right. The <h2> is the slide body heading. For data points, you MUST PREFER <div class='card-grid cols-2|cols-3|cols-4'> with <div class='card'> children over plain <ul> bullet lists — the cards are the marina theme's signature visual element and plain bullets look unbranded. Each card contains <div class='label'> (uppercase blue), <div class='value'> (large, MUST add a color modifier class: .gold for highlights, .cyan for cool readings, .red for alerts, .green for OK status), and optional <div class='detail'>. "70 "CRITICAL CARD STATE COUPLING RULE: the color modifier on <div class='value'> MUST be mirrored by a matching class on the parent <div class='card'>: "71 "<div class='value red'> (alert/threat/critical) → parent MUST be <div class='card alert'> (red border + red glow + red-tinted background + red label); "72 "<div class='value gold'> (the single most important metric) → parent MUST be <div class='card highlight'> (gold border + gold label); "73 "<div class='value cyan'> or <div class='value green'> → parent stays as plain <div class='card'> (no parent modifier). "74 "Do NOT emit <div class='card'><div class='value red'>...</div></div> — a red value inside a blue card looks inconsistent and unprofessional. Always pair .value.red with .card.alert and .value.gold with .card.highlight. "75 "Do NOT add background-color or color inline styles — the theme owns them. Anti-pattern to AVOID: producing <ul><li>...</li></ul> for what should be a card grid.",7677 "marina-metrics": "Create a Marina Militare METRICS / CAPABILITY DASHBOARD slide. "78 "CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's metric set, written in the SAME LANGUAGE as the source document. Extract the heading from the actual source content — do NOT invent generic English dashboard phrases. BANNED headings that you MUST NOT use as <h2>: 'Capability Snapshot', 'Key Metrics', 'Performance Overview', 'KPI Dashboard', 'Metrics Dashboard', 'Operational Metrics', 'Overview', 'Summary', 'Snapshot', 'Performance Dashboard'. These are hallucinations from other dashboard templates and look unprofessional in a naval briefing. Good examples for an Italian Navy briefing: 'ITS Margottini — Snapshot T+12 h', 'Assetto Piattaforma al T+24 h', 'Meteo e Condizioni del Mare', 'Readiness e Asset Operativi'. "79 "The <section> MUST have data-header-title='SHORT TITLE' AND the body MUST contain a <div class='card-grid cols-N'> with at least 3 <div class='card'> children — WITHOUT THE CARD GRID, this layout has no visual and degrades to plain text. Each card's <div class='value'> MUST have a color modifier class (.gold, .cyan, .red, or .green) — without it, values render in plain white and lose all semantic meaning. Use this EXACT structure:\n"80 "<section data-header-title='SHORT SLIDE TITLE'>\n"81 " <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n"82 " <p class='section-label'>Optional small label (e.g. timestamp or unit)</p>\n"83 " <div class='card-grid cols-3'>\n"84 " <div class='card'>\n"85 " <div class='label'>METRIC LABEL</div>\n"86 " <div class='value cyan'>VALUE</div>\n"87 " <div class='detail'>Brief detail</div>\n"88 " </div>\n"89 " <!-- Repeat for 3-6 metric cards -->\n"90 " </div>\n"91 " <div class='metrics-callout highlight'> <!-- OPTIONAL: include only if the source content has operational interpretation of the metrics -->\n"92 " <div class='label'>IMPATTO OPERATIVO</div>\n"93 " <p>Short editorial paragraph interpreting the metrics. Use <strong>bold</strong> on the most important phrases to highlight them in gold.</p>\n"94 " </div>\n"95 " <aside class='notes'>Speaker notes.</aside>\n"96 "</section>\n"97 "Produce 3-6 capability cards in a grid row (cols-2 / cols-3 / cols-4 depending on count). Each card MUST contain: <div class='label'> (uppercase blue), <div class='value COLOR'> with one of {gold|cyan|red|green} (gold for highlights, cyan for cool/neutral readings, red for alerts/threats, green for OK/operational), and <div class='detail'> for a short subtitle. Vary the colors based on the meaning of each value — do NOT make every card the same color. "98 "CRITICAL CARD STATE COUPLING RULE: the color modifier on <div class='value'> MUST be mirrored by a matching class on the parent <div class='card'>: "99 "<div class='value red'> (alert/threat/critical) → parent MUST be <div class='card alert'> (red border + red glow + red-tinted background + red label); "100 "<div class='value gold'> (the single most important metric) → parent MUST be <div class='card highlight'> (gold border + gold label); "101 "<div class='value cyan'> or <div class='value green'> → parent stays as plain <div class='card'> (no parent modifier). "102 "Do NOT emit <div class='card'><div class='value red'>...</div></div> — a red value floating inside a blue card looks broken and unprofessional. Always pair .value.red with .card.alert and .value.gold with .card.highlight. "103 "Extract real numbers from the source content. Optional class='fragment' on each card for staggered reveal. "104 "The <div class='metrics-callout highlight'> below the card grid is OPTIONAL — include it ONLY when the source content contains a short editorial interpretation of the metrics (e.g. 'IMPATTO OPERATIVO', 'VALUTAZIONE', 'SIGNIFICATO OPERATIVO'). It has a <div class='label'> header (uppercase, short) and a single <p> body with 1-3 sentences; use <strong> on key phrases to highlight them in gold. The .highlight variant has a gold left border and gold label; omit .highlight for a blue-accent variant. When there is no editorial interpretation to show, OMIT the whole .metrics-callout block. "105 "Anti-pattern to AVOID: producing plain text rows or <ul><li>Metric: value</li></ul> instead of the card grid.",106107 "marina-timeline": "Create a Marina Militare VERTICAL TIMELINE slide. "108 "CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing what this specific timeline covers, written in the SAME LANGUAGE as the source document. Extract the heading from the actual source content — do NOT invent generic English phrases. BANNED headings that you MUST NOT use as <h2>: 'Timeline Overview', 'Chronology', 'Events', 'Timeline', 'Event Timeline', 'Operational Timeline', 'Timeline Summary', 'Schedule'. These are hallucinations from generic templates. Good examples for an Italian Navy briefing: 'Cronologia Operativa — 13 Aprile 2026', 'Sequenza Eventi T-004', 'Fasi della Missione MV-2026-0413', 'Log Operativo'. "109 "The <section> MUST have data-header-title='SHORT TITLE' AND the body MUST contain a <div class='timeline'> with <div class='event'> children — WITHOUT THIS STRUCTURE, the vertical rail and circular markers will NOT render and the slide will degrade to plain text. Do NOT produce <ul><li>HH:MM Event</li></ul> for chronological content — always use the .timeline/.event structure. Use this EXACT structure:\n"110 "<section data-header-title='SHORT SLIDE TITLE'>\n"111 " <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n"112 " <div class='timeline-layout'>\n"113 " <div class='timeline'>\n"114 " <div class='event'><span class='time'>HH:MM</span> Event description</div>\n"115 " <div class='event alert'><span class='time'>HH:MM</span> Critical event (red marker)</div>\n"116 " <div class='event gold'><span class='time'>HH:MM</span> Milestone event (gold marker)</div>\n"117 " <!-- Repeat for 4-8 events -->\n"118 " </div>\n"119 " <div class='timeline-aside'> <!-- OPTIONAL: include only if the source content has a natural sidebar (next-actions, summary, related contacts, etc.) -->\n"120 " <div class='card highlight'>\n"121 " <div class='label'>PROSSIME AZIONI</div>\n"122 " <ul><li>Action one</li><li>Action two</li></ul>\n"123 " </div>\n"124 " <div class='card'>\n"125 " <div class='label'>RIEPILOGO FINALE</div>\n"126 " <ul><li>Summary point one</li><li>Summary point two</li></ul>\n"127 " </div>\n"128 " </div>\n"129 " </div>\n"130 " <aside class='notes'>Speaker notes.</aside>\n"131 "</section>\n"132 "Vertical timeline with circular markers along a left rail. Each event is <div class='event'> with a leading <span class='time'> for the timestamp and the description text after the closing </span>. Add class='event alert' for critical events (red marker with glow halo) and class='event gold' for milestones (gold marker). Extract real timestamps and event descriptions from the source content (4-8 events ideal). "133 "The <div class='timeline-aside'> right column is OPTIONAL — include it ONLY when the source content naturally has sidebar information (next-actions, summary of contacts, related entities, follow-up items). Each aside card has a <div class='label'> header and a short <ul> or <p> body. Use class='card highlight' for the primary aside card (gold accent) and plain class='card' for secondary cards. When there is no sidebar content, OMIT the whole .timeline-layout wrapper and .timeline-aside — use just a bare <div class='timeline'>. "134 "Anti-pattern to AVOID: <ul><li>10:00 - Event</li><li>11:00 - Event</li></ul> — this completely bypasses the timeline visual.",135136 "marina-comparison": "Create a Marina Militare COMPARISON / TRACKING TABLE slide. "137 "CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing what this specific table shows, written in the SAME LANGUAGE as the source document. Extract the heading from the actual source content — do NOT invent generic English phrases. BANNED headings that you MUST NOT use as <h2>: 'Comparison Table', 'Data Table', 'Summary Table', 'Overview Table', 'Tracking Table', 'Comparison', 'Summary', 'Overview', 'Data'. These are hallucinations from generic templates. Good examples for an Italian Navy briefing: 'Tabella Tracce — T+12 h', 'Contatti Attivi nello Stretto', 'Confronto Assetti Alleati', 'Situazione Tattica Corrente'. "138 "The <section> MUST have data-header-title='SHORT TITLE' AND the body MUST contain a real <table> with <thead> and <tbody> — WITHOUT THE TABLE, this layout has no visual and degrades to plain text columns. Do NOT produce two-column <div> layouts or bullet lists for tabular content. Use this EXACT structure:\n"139 "<section data-header-title='SHORT SLIDE TITLE'>\n"140 " <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n"141 " <p class='section-label'>Optional context line (row count, source, etc.)</p>\n"142 " <table>\n"143 " <thead><tr><th>Col 1</th><th>Col 2</th><th>Col 3</th><th>Status</th></tr></thead>\n"144 " <tbody>\n"145 " <tr><td>Row 1</td><td>Value</td><td>Value</td><td><span class='tag commercial'>Commercial</span></td></tr>\n"146 " <!-- Repeat for 4-10 rows -->\n"147 " </tbody>\n"148 " </table>\n"149 " <aside class='notes'>Speaker notes.</aside>\n"150 "</section>\n"151 "Wide HTML table with a navy header (gold accent column labels) and bordered rows. For status pills inside cells, use <span class='tag X'>...</span> where X is one of: commercial (blue), allied (green), friendly (cyan), fishing (olive), high-threat (red), humanitarian (gold). For inline status indicators, use <span class='status-dot Y'></span> where Y is one of: green, gold, red, blue. To highlight a critical row, add class='alert' to the <tr> (red row background). Extract real comparison/tracking data from the source content (4-10 rows ideal). Anti-pattern to AVOID: producing <div> column layouts or <ul> lists instead of a real <table>.",152153 "marina-outro": "[THEME GATE: this template is valid ONLY when the active deck theme is 'marina'. If the active theme is 'emblema', DO NOT emit this structure — switch to the 'emblema-closing' template instead, which is the Emblema brand closing slide. The Marina .closing-slide class is unstyled in the Emblema theme and would render as a blank white slide.] "154 "Create a Marina Militare CLOSING slide. The <section> MUST start with class='closing-slide' — WITHOUT THIS CLASS, the Marina Militare crest will NOT render and the slide will collapse to a plain navy background with default text. Use this EXACT structure:\n"155 "<section class='closing-slide'>\n"156 " <h1>Grazie</h1>\n"157 " <p class='hashtag'>#NoiSiamoLaMarina</p>\n"158 " <aside class='notes'>Closing slide.</aside>\n"159 "</section>\n"160 "The Marina Militare crest is injected by the theme via a CSS pseudo-element above the headline — do NOT add an <img> for the logo. The <h1> renders in Montserrat bold (use 'Grazie' / 'Grazie dell'attenzione' / 'Domande?' for Italian briefings, 'Thank You' for English). The <p class='hashtag'> renders in normal weight below — keep it relevant to the unit/operation (e.g. #NoiSiamoLaMarina, #MarinaMilitare). Keep all class names EXACTLY as shown — class='closing-slide' on the section is LOAD-BEARING.",161162 # ─── Emblema layouts ───163 "emblema-cover": "Create an Emblema COVER slide. The <section> MUST contain a <div class='slide-cover'> with two child columns; WITHOUT THIS WRAPPER the title will not render against the brand split-panel layout (white left, full-bleed teal right). CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h1> values: 'Welcome', 'Title Slide', 'Cover', 'Introduction', 'Presentation'. Good examples: 'Building thoughtful AI products.', 'Operazione Mediterraneo Sicuro 2026'. Use this EXACT structure:\n<section>\n <div class='slide-cover'>\n <div class='left'>\n <div class='brand'><span class='eyebrow'>SHORT EYEBROW (2-4 words, uppercase)</span></div>\n <div>\n <h1>Headline derived<br>from source content.</h1>\n <p class='subtitle'>One- or two-line subtitle pulled from the source.</p>\n </div>\n <p class='meta'>AUTHOR · DATE · VERSION</p>\n </div>\n <div class='right'></div>\n </div>\n <aside class='notes'>One-line speaker note.</aside>\n</section>\nThe <div class='right'> is intentionally empty -- the theme renders the teal panel + decorative gradients via CSS. The <h1> may use a <br> to break across lines. The eyebrow is the small uppercase label above the title, the subtitle is one or two lines of secondary copy, and the meta line carries author / date / version separated by middots. Do NOT add background-color or color inline styles -- the theme owns them.",164 "emblema-agenda": "Create an Emblema AGENDA slide. The body MUST contain a <div class='slide-pad slide-agenda'> with an <ol> of agenda items; WITHOUT THE .slide-agenda CLASS the numbered counters and 2-column grid will not render and the items will fall back to default <ol> bullets. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Agenda', 'Outline', 'Overview', 'Topics', 'Schedule', 'Today'. Good examples: 'What we'll cover today.', 'Programma del briefing.'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-agenda'>\n <div>\n <span class='eyebrow'>Agenda</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <ol>\n <li><span class='topic'>Topic name</span><span class='duration'>X min</span></li>\n <!-- 4-8 items total -->\n </ol>\n </div>\n <div class='brand-mark'>Brand</div>\n <div class='page-num'>NN / NN</div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nEach <li> MUST contain a <span class='topic'> for the topic and <span class='duration'> for the duration -- these are CSS-targeted for two-column alignment. The leading numbered counter (01, 02, ...) is auto-generated by CSS counter, do NOT add it as text. Use 4-8 items; fewer collapses the layout, more wraps awkwardly. Anti-pattern to AVOID: <ul> bullets or plain <p> lines without <span> wrappers.",165 "emblema-section": "Create an Emblema SECTION DIVIDER slide. The body MUST contain a <div class='slide-section'> with a <div class='num'> and a <div class='meta'>; WITHOUT THIS STRUCTURE the big section number, teal background, and 2-column layout will not render. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Section Two', 'Part One', 'Section Divider', 'Next Section', 'Chapter', 'Overview'. Good examples: 'The opportunity in front of us.', 'I numeri dietro la storia.'. Use this EXACT structure:\n<section>\n <div class='slide-section'>\n <div class='num'>NN</div>\n <div class='meta'>\n <span class='label'>Section N or Capitolo N</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <p>One- or two-sentence framing pulled from the source content.</p>\n </div>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nThe <div class='num'> renders as a 280px Plex Sans Light digit pair (use '01', '02', etc.). The <span class='label'> is the small uppercase label above the section title. The <p> body is restrained to 1-3 sentences -- this is a divider, not a content slide. Anti-pattern to AVOID: cramming bullet lists or KPI cards into a section divider.",166 "emblema-statement": "Create an Emblema STATEMENT / PULL QUOTE slide. The body MUST contain a <div class='slide-statement'> with a <p class='quote'> that highlights one phrase via <em>; WITHOUT THE <em> the teal accent on the key phrase will not appear and the slide loses its rhetorical hook. CRITICAL HEADING RULE: The pull quote MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. The <em> wraps the SINGLE most important phrase in the quote (2-6 words). Use this EXACT structure:\n<section>\n <div class='slide-statement'>\n <div>\n <p class='quote'>The quote text with one <em>key phrase</em> highlighted in teal.</p>\n <p class='attribution'>— Source or speaker, ROLE</p>\n </div>\n </div>\n <div class='corner-index'>SECTION <span class='num'>NN</span> · SLIDE_NUM</div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nDo NOT use <h1> or <h2> on this layout -- the quote IS the headline and is styled via .slide-statement .quote (64px Plex Light). Use exactly ONE <em> in the quote (zero loses the accent, multiple looks busy). The <p class='attribution'> is uppercase tracked-out text below the quote. Anti-pattern to AVOID: <blockquote> or <h2> instead of <p class='quote'>.",167 "emblema-two-col": "Create an Emblema TWO-COLUMN slide. The body MUST contain a <div class='slide-grid-2 slide-two-col'> with exactly two child <div>s; WITHOUT BOTH CLASSES the 50/50 grid and centered alignment will not render. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Two Columns', 'Comparison', 'Side by Side', 'Overview', 'Summary'. Good examples: 'Knowledge work is drowning.', 'Domanda e offerta.'. Use this EXACT structure:\n<section>\n <div class='slide-grid-2 slide-two-col'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <p>Body paragraph 1 from source.</p>\n <p class='muted' style='font-size:16px'>Source or footnote.</p>\n </div>\n <div class='visual'>\n <!-- Either an <img> or a decorative SVG. Theme styles .visual as an et-50 panel. -->\n </div>\n </div>\n <div class='brand-mark'>Brand</div>\n <div class='page-num'>NN / NN</div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nLeft column is text; right column has class='visual' which the theme styles as a soft teal-tinted panel for an SVG/image. If no visual is available, leave the .visual div empty -- do NOT replace it with a body paragraph. Anti-pattern to AVOID: 50/50 with TWO text columns (use emblema-bullets or emblema-compare instead).",168 "emblema-bullets": "Create an Emblema BULLET TAKEAWAYS slide. The body MUST contain a <div class='slide-pad slide-bullets'> with a <ul> of 3-4 <li> items; EACH <li> MUST contain a <span class='marker'>NN</span> and a <div> wrapping <h4>+<p>; WITHOUT THE .marker SPAN the numbered teal-tint circles will not render and bullets will fall back to plain dots. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Key Takeaways', 'Bullet Points', 'Summary', 'Main Points', 'Highlights', 'Overview'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-bullets'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <ul>\n <li>\n <span class='marker'>01</span>\n <div>\n <h4>Bullet headline.</h4>\n <p>1-2 sentence body for this bullet.</p>\n </div>\n </li>\n <!-- 3-4 bullets total -->\n </ul>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nUse 3 or 4 bullets in a 2-column grid. Marker numbers MUST use leading zeros: 01, 02, 03, 04. Anti-pattern to AVOID: plain <ul><li>text</li></ul> without the marker/div structure -- the theme requires the wrapper to render the numbered circles.",169 "emblema-image": "Create an Emblema FULL-BLEED IMAGE slide. The body MUST contain a <div class='slide-image'> with a <div class='overlay'> child for the text; WITHOUT THIS STRUCTURE the bottom dark-gradient overlay and white text positioning will not render. The .slide-image background is a teal gradient by default; an <img> tag may be appended INSIDE .slide-image to override. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Image', 'Photo', 'Visual', 'Picture', 'Background'. Use this EXACT structure:\n<section>\n <div class='slide-image'>\n <!-- Optional: <img src='...' alt='...' style='position:absolute;inset:0;width:100%;height:100%;object-fit:cover;'> -->\n <div class='overlay'>\n <span class='eyebrow eyebrow--inverse'>SHORT LOCATION OR LABEL</span>\n <h2>Image headline pulled from source.</h2>\n <p>Caption or context, 1-2 sentences.</p>\n </div>\n </div>\n <div class='page-num' style='color: rgba(255,255,255,0.7);'>NN / NN</div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nThe .eyebrow MUST also have eyebrow--inverse so the small uppercase label renders in light teal against the dark background. Page number is forced to translucent white via inline style (the only inline color allowed on this layout, and only because the chrome lives outside the gradient). Anti-pattern to AVOID: omitting the .overlay wrapper -- the text falls through onto a transparent background.",170 "emblema-magazine": "Create an Emblema MAGAZINE SPREAD slide. The body MUST contain a <div class='slide-mag'> with a <div class='photo-col'> on the left and <div class='text-col'> on the right; WITHOUT BOTH CHILDREN the asymmetric photo-left / text-right grid will not render. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Magazine', 'Spread', 'Story', 'Customer Story', 'Case Study'. Good examples: 'From four spreadsheets to one workflow.', 'Da quattro fogli a un flusso.'. Use this EXACT structure:\n<section>\n <div class='slide-mag'>\n <div class='photo-col'>\n <div class='photo photo--var2'><span class='photo-tag'>Photo · MM.YYYY</span></div>\n </div>\n <div class='text-col'>\n <span class='eyebrow'>Customer story · Subject</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <p class='body'>Long-form body paragraph -- 3-5 sentences pulled from the source.</p>\n <div class='meta'>\n <span><strong>Photographed at</strong> — Place</span>\n <span><strong>Words by</strong> — Author</span>\n <span><strong>Month YYYY</strong></span>\n </div>\n </div>\n </div>\n <div class='page-num'>NN / NN</div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nPick ONE of .photo--var1 through .photo--var8 to set the gradient placeholder colour. To use a real image, replace the .photo div with an <img> covering the photo-col area. The .meta uses <strong> labels for byline-style metadata. Anti-pattern to AVOID: <table> or <ul> instead of the .meta <span> structure.",171 "emblema-two-img": "Create an Emblema TWO IMAGES slide. The body MUST contain a <div class='slide-pad slide-two-img'> with a <div class='grid'> of exactly two <div class='item'> children; WITHOUT THE .grid AND .item CLASSES the side-by-side layout and per-item caption styling will not render. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Two Images', 'Photos', 'Pictures', 'Gallery', 'Examples'. Good examples: 'Two teams, two transformations.', 'Field studies — Spring 2026'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-two-img'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <div class='grid'>\n <div class='item'>\n <div class='photo photo--var1'><span class='photo-tag'>Tag 1</span></div>\n <h4>Item 1 title</h4>\n <p>One- or two-sentence description.</p>\n <div class='cap'>— Credit, Date</div>\n </div>\n <div class='item'>\n <div class='photo photo--var6'><span class='photo-tag'>Tag 2</span></div>\n <h4>Item 2 title</h4>\n <p>One- or two-sentence description.</p>\n <div class='cap'>— Credit, Date</div>\n </div>\n </div>\n </div>\n <div class='page-num'>NN / NN</div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nExactly TWO .item children -- adding a third breaks the equal-width grid. Each .item has photo + h4 + p + .cap. Anti-pattern to AVOID: omitting the .photo wrapper around an <img> (the .photo class is what gives images their teal-tint placeholder fallback).",172 "emblema-grid-img": "Create an Emblema 2x2 IMAGE GRID slide. The body MUST contain a <div class='slide-grid-img'> with a <div class='header'> and a <div class='grid'> of exactly four <div class='photo'> children; WITHOUT THIS STRUCTURE the full-bleed teal background, white header, and 2x2 image grid will not render. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Image Grid', 'Gallery', 'Photos', '2x2', 'Examples'. Use this EXACT structure:\n<section>\n <div class='slide-grid-img'>\n <div class='header'>\n <span class='eyebrow eyebrow--inverse'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <p>One- or two-sentence framing.</p>\n </div>\n <div class='grid'>\n <div class='photo photo--var4'><span class='photo-tag'>Caption 1</span></div>\n <div class='photo photo--var5'><span class='photo-tag'>Caption 2</span></div>\n <div class='photo photo--var7'><span class='photo-tag'>Caption 3</span></div>\n <div class='photo photo--var8'><span class='photo-tag'>Caption 4</span></div>\n </div>\n </div>\n <div class='page-num' style='color: rgba(255,255,255,0.7);'>NN / NN</div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nUse eyebrow--inverse for light teal text against the dark background. Pick distinct .photo--varN values for visual variety. Exactly 4 photos. Anti-pattern to AVOID: 3 or 5 photos -- breaks the 2x2 grid.",173 "emblema-hero-centered": "Create an Emblema CENTERED HERO slide. The body MUST contain a <div class='slide-hero-centered'> with a <div class='header'>, a <div class='photo'>, and a <p class='caption'>; WITHOUT THIS STRUCTURE the centered alignment, hero photo sizing, and italic caption styling will not render. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Hero', 'Image', 'Photo', 'Featured Image'. Good examples: 'The room where the first prototype shipped.', 'La sala riunioni del comando.'. Use this EXACT structure:\n<section>\n <div class='slide-hero-centered'>\n <div class='header'>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n </div>\n <div class='photo photo--var2'><span class='photo-tag'>Photo · MM.YYYY</span></div>\n <p class='caption'>Italic caption text. <em>Photographed by NAME · Month YYYY</em></p>\n </div>\n <div class='brand-mark'>Brand</div>\n <div class='page-num'>NN / NN</div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nThe .photo grows to fill the available vertical space between header and caption. To use a real <img>, place it INSIDE the .photo div with object-fit:cover. Anti-pattern to AVOID: large <img> without the .photo wrapper -- inherits composer's max-width:100% rule and shrinks awkwardly.",174 "emblema-hero-card": "Create an Emblema HERO + FLOATING CARD slide. The body MUST contain a <div class='slide-hero-card'> with a full-bleed <div class='photo'> and a floating <div class='card'>; WITHOUT BOTH CHILDREN the hero image background and white card with shadow will not render. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Spotlight', 'Featured', 'Card', 'Highlight'. Good examples: 'Inside the launch of our largest deployment yet.', 'Dietro le quinte della missione X.'. Use this EXACT structure:\n<section>\n <div class='slide-hero-card'>\n <div class='photo photo--var5'><span class='photo-tag'>SHORT TAG</span></div>\n <div class='card'>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <p>1-3 sentence body pulled from source.</p>\n <div class='meta'>Subject · Place · Month YYYY</div>\n </div>\n </div>\n <div class='page-num' style='color: rgba(255,255,255,0.7);'>NN / NN</div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nThe .card floats absolute bottom-left over the hero photo with a drop-shadow. The .meta is a tracked-out uppercase metadata line at the card's bottom. Anti-pattern to AVOID: putting all content inside .photo -- the card layer is what creates the magazine-style legibility against the photo.",175 "emblema-collage": "Create an Emblema IMAGE COLLAGE slide. The body MUST contain a <div class='slide-collage'> with a <div class='text-col'> and a <div class='stack'> of exactly THREE <div class='photo'> children; WITHOUT THE .stack AND THREE PHOTOS the rotated layered photo collage will not render (each photo has a nth-child rule that positions it). CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Collage', 'Gallery', 'Photos', 'Year in Review'. Use this EXACT structure:\n<section>\n <div class='slide-collage'>\n <div class='text-col'>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <p>One paragraph framing the collage.</p>\n <p class='caption'>Optional caption identifying the photos clockwise.</p>\n </div>\n <div class='stack'>\n <div class='photo photo--var1'><span class='photo-tag'>01</span></div>\n <div class='photo photo--var3'><span class='photo-tag'>02</span></div>\n <div class='photo photo--var5'><span class='photo-tag'>03</span></div>\n </div>\n </div>\n <div class='brand-mark'>Brand</div>\n <div class='page-num'>NN / NN</div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nExactly THREE .photo children -- the CSS targets :nth-child(1), :nth-child(2), :nth-child(3) for rotation/positioning. Anti-pattern to AVOID: 2 or 4 photos -- breaks the layered effect.",176 "emblema-stat": "Create an Emblema BIG STAT slide. The body MUST contain a <div class='slide-stat'> with a <div class='number'> and a <div class='copy'>; WITHOUT THIS STRUCTURE the 280px teal stat number and side-by-side copy will not render. CRITICAL HEADING RULE: The <h3> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h3> values: 'Big Number', 'Stat', 'Metric', 'Key Number'. The <h3> is the supporting headline -- the BIG NUMBER itself goes in <div class='number'> NOT in a heading. Use this EXACT structure:\n<section>\n <div class='slide-stat'>\n <div class='number'>NN<span class='unit'>%</span></div>\n <div class='copy'>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h3>One-sentence interpretation derived from the source.</h3>\n <p>1-2 sentence body explaining the number.</p>\n </div>\n </div>\n <div class='brand-mark'>Brand</div>\n <div class='page-num'>NN / NN</div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nThe <div class='number'> takes the bare numeric (no euro/dollar sign in front -- prefix those into the <span class='unit'> if needed; e.g. '<span class=\"unit\">€</span>1.2M'). The <span class='unit'> renders at half size in lighter teal. Use a single number per slide -- for multiples use emblema-kpis. Anti-pattern to AVOID: <h2>NN%</h2> -- defeats the purpose of the layout.",177 "emblema-kpis": "Create an Emblema KPI GRID slide. The body MUST contain a <div class='slide-pad slide-kpis'> with a <div class='grid'> of BETWEEN 3 AND 9 <div class='kpi'> children — prefer multiples of 3 (3, 6, or 9); WITHOUT THE .kpi WRAPPER each metric loses its top teal accent, soft background, and large-number styling. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'KPIs', 'Key Metrics', 'Numbers', 'Performance', 'Dashboard', 'Overview', 'Stats'. Good examples: 'Three numbers we're proud of.', 'Tre KPI del Q1 2026'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-kpis'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <div class='grid'>\n <div class='kpi'>\n <div class='num'>NN<span class='delta'>↑ X</span></div>\n <h4>KPI title</h4>\n <p>One-line context derived from source.</p>\n </div>\n <!-- 3 to 9 KPIs, prefer multiples of 3 -->\n </div>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nUse 3, 6, or 9 KPIs based on content density: 3 (single row) for headline metrics, 6 (2 rows) for paired-metric dashboards, 9 (3 rows) for full quarterly scorecards. CSS uses grid-template-columns: repeat(3, 1fr) — counts that aren't multiples of 3 leave a partial last row. The <span class='delta'> is OPTIONAL and renders in green by default; for a NEGATIVE delta change the arrow to ↓. Anti-pattern to AVOID: more than 9 KPIs (likely belong in emblema-table or emblema-chart instead — the kpi card design loses impact at higher counts). Counts that aren't multiples of 3 (4, 5, 7, 8) are acceptable but visually weaker than a clean 3/6/9 grid.",178 "emblema-compare": "Create an Emblema BEFORE/AFTER COMPARISON slide. The body MUST contain a <div class='slide-pad slide-compare'> with a <div class='grid'> containing a .col, a .arrow span, and a .col.col--after; WITHOUT THE 1fr-80px-1fr GRID and the .col--after class on the right column, the highlighted 'after' state will not render and the arrow will not be centered. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Comparison', 'Before/After', 'Then/Now', 'Old vs New'. Good examples: 'How a quarterly review changes after Emblema.', 'Da manuale ad automatico.'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-compare'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <div class='grid'>\n <div class='col'>\n <h4>BEFORE / OLD STATE</h4>\n <ul>\n <li>Pain point 1</li>\n <li>Pain point 2</li>\n <li>Pain point 3</li>\n </ul>\n </div>\n <div class='arrow'>→</div>\n <div class='col col--after'>\n <h4>AFTER / NEW STATE</h4>\n <ul>\n <li>Resolution 1</li>\n <li>Resolution 2</li>\n <li>Resolution 3</li>\n </ul>\n </div>\n </div>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nCRITICAL: the AFTER column MUST have BOTH .col AND .col--after classes -- without .col--after it loses the teal-tint background and teal border that signal 'this is the improved state'. Match item count between columns (3-5 items each). Anti-pattern to AVOID: <table> with 2 columns, or putting both lists in a single .col div.",179 "emblema-chart": "Create an Emblema CHART slide. The body MUST contain a <div class='slide-pad slide-chart'> with a <div class='chart-wrap'> wrapping the visualization, plus a <div class='legend'>; WITHOUT THE .chart-wrap container the chart panel border and padding will not render. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Chart', 'Graph', 'Data', 'Trend'. Good examples: 'Revenue lift across the cohort.', 'Andamento clienti 2024-2026'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-chart'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <div class='chart-wrap'>\n <!-- An inline <svg viewBox='0 0 W H'> for bar/line/area chart, OR a placeholder. -->\n <svg viewBox='0 0 800 320' style='width:100%;height:auto'>\n <!-- bars/lines using <rect>, <line>, <path>; reuse var(--et-500) color -->\n </svg>\n </div>\n <div class='legend'>\n <span><i style='background:var(--et-500)'></i>Series 1</span>\n <span><i style='background:var(--et-300)'></i>Series 2</span>\n </div>\n <p class='muted' style='font-size:14px;margin-top:1em'>Source — reference</p>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nThe <i> in legend items is intentionally empty -- CSS sizes it as a 12px swatch. Inline style `background:var(--et-500)` is the ONLY allowed inline color (legend swatches need it because there is no enumerable class for arbitrary swatch colors). Anti-pattern to AVOID: <table> instead of an SVG chart -- use emblema-table for data tables.",180 "emblema-table": "Create an Emblema DATA TABLE slide. The body MUST contain a <div class='slide-pad slide-table'> with a real <table> containing <thead>, <tbody>, and optionally <tfoot>; WITHOUT A REAL <table> the column-aligned numerics and uppercase tracked-out header styling will not render. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Data Table', 'Table', 'Numbers', 'Financials', 'Metrics'. Good examples: 'Q1 2026 financial summary.', 'Bilancio operativo del primo trimestre.'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-table'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <table>\n <thead><tr><th>Metric</th><th class='num'>Period A</th><th class='num'>Period B</th><th class='num'>Delta</th></tr></thead>\n <tbody>\n <tr><td class='label'>Row name</td><td class='num'>1,234</td><td class='num'>2,345</td><td class='num up'>+90%</td></tr>\n <!-- 4-8 rows -->\n </tbody>\n <tfoot><tr><td>Total</td><td class='num'>X</td><td class='num'>Y</td><td class='num up'>Z</td></tr></tfoot>\n </table>\n <p class='src'>Source — reference</p>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nNumeric columns MUST have class='num' on every <th> and <td> -- this right-aligns and applies tabular-nums. For deltas, use class='up' (green), class='down' (red), or class='flat' (grey) on the <td>. The class='label' on the first body cell makes the row label semibold. Anti-pattern to AVOID: <div> grids with manual alignment -- use a real table.",181 "emblema-matrix": "Create an Emblema COMPARISON MATRIX slide. The body MUST contain a <div class='slide-pad slide-matrix'> with a <table> whose <thead> has EXACTLY ONE <th class='featured'>; WITHOUT .featured on one column the 'OUR PICK' badge and teal column highlight will not render. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Comparison', 'Matrix', 'Options', 'Compare'. Good examples: 'Why Emblema vs the build/buy alternatives.', 'Confronto con le alternative di mercato.'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-matrix'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <table>\n <thead><tr><th>Feature</th><th>Option A</th><th class='featured'>Emblema</th><th>Option C</th></tr></thead>\n <tbody>\n <tr><td>Capability label</td><td><span class='no'>×</span></td><td class='featured'><span class='yes'>✓</span></td><td><span class='partial'>partial</span></td></tr>\n <!-- 4-8 rows -->\n </tbody>\n </table>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nEXACTLY ONE <th class='featured'> -- having two means the 'OUR PICK' badge appears twice and the visual hierarchy collapses. Each row's cell under the featured column ALSO needs class='featured' so it inherits the teal-tint background. Cell content uses <span class='yes'>✓</span>, <span class='no'>×</span>, or <span class='partial'>partial</span>. Anti-pattern to AVOID: emoji ✓/✗ instead of the styled span variants -- emoji bypasses the theme color logic.",182 "emblema-spec": "Create an Emblema SPEC SHEET slide. The body MUST contain a <div class='slide-pad slide-spec'> with a <div class='spec-grid'> of 2 or 4 <div class='spec-section'> children, each with an <h4> and a <dl>; WITHOUT THIS STRUCTURE the 2-column spec layout, dashed dividers, and uppercase teal section headers will not render. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Specifications', 'Specs', 'Details', 'Properties', 'Information'. Good examples: 'Platform technical specifications.', 'Specifiche piattaforma ITS Margottini.'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-spec'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <div class='spec-grid'>\n <div class='spec-section'>\n <h4>Section Name<span class='num'>01</span></h4>\n <dl>\n <div><dt>Key</dt><dd>Value <span class='badge'>BADGE</span></dd></div>\n <div><dt>Key</dt><dd>Value</dd></div>\n <!-- 3-6 entries per section -->\n </dl>\n </div>\n <!-- 2 or 4 .spec-section blocks -->\n </div>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nThe <dl> uses a non-standard <div> wrapper around each <dt>/<dd> pair -- this is REQUIRED because the CSS uses .slide-spec dl > div for grid alignment. The <span class='badge'> is OPTIONAL inline highlight inside a <dd>. Anti-pattern to AVOID: flat <dl><dt><dd></dl> without div wrappers (loses the per-row alignment) or <table> (visual is wrong for spec sheets).",183 "emblema-status": "Create an Emblema PROJECT STATUS slide. The body MUST contain a <div class='slide-pad slide-status'> with a <table> whose status cells contain <span class='dot dot--COLOR'> elements; WITHOUT THE .dot--COLOR CLASSES the green/amber/red/gray RAG indicators will not render and the table looks like generic data. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Status', 'RAG', 'Project Status', 'Portfolio', 'Health'. Good examples: 'Q1 portfolio — status at week 11.', 'Stato del portafoglio progetti.'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-status'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <table>\n <thead><tr><th>Project</th><th class='owner'>Owner</th><th class='note'>Note</th><th class='status'>Status</th></tr></thead>\n <tbody>\n <tr><td>Project A</td><td class='owner'>Owner</td><td class='note'>Short note.</td><td class='status'><span class='dot dot--green'></span></td></tr>\n <tr><td>Project B</td><td class='owner'>Owner</td><td class='note'>Short note.</td><td class='status'><span class='dot dot--amber'></span></td></tr>\n <tr><td>Project C</td><td class='owner'>Owner</td><td class='note'>Short note.</td><td class='status'><span class='dot dot--red'></span></td></tr>\n <!-- 4-8 rows -->\n </tbody>\n </table>\n <div class='legend'>\n <span><span class='dot dot--green'></span>On track</span>\n <span><span class='dot dot--amber'></span>At risk</span>\n <span><span class='dot dot--red'></span>Off track</span>\n <span><span class='dot dot--gray'></span>Not started</span>\n </div>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nSTATUS COUPLING RULE: dot--green = on track, dot--amber = at risk, dot--red = off track, dot--gray = not started. Use the dot color that matches the SEMANTICS of each project's status -- do NOT assign colors arbitrarily. Anti-pattern to AVOID: emoji 🟢🟡🔴 instead of styled spans (no theme control over color), or omitting the dot wrapper inside the .status td.",184 "emblema-process": "Create an Emblema PROCESS / STEPS slide. The body MUST contain a <div class='slide-pad slide-process'> with a <div class='steps'> of BETWEEN 4 AND 8 <div class='step'> children — prefer multiples of 4 (4 or 8); WITHOUT THE .step WRAPPER each card loses its left teal border and uppercase step label. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Process', 'Steps', 'Workflow', 'How it works', 'Methodology'. Good examples: 'How an Emblema rollout flows.', 'Le quattro fasi del nostro metodo.'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-process'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <div class='steps'>\n <div class='step'>\n <div class='icon'><svg viewBox='0 0 22 22'><!-- 22x22 icon --></svg></div>\n <span class='num'>STEP 01</span>\n <h4>Step title</h4>\n <p>1-2 sentences describing the step.</p>\n </div>\n <!-- 4 to 8 .step children, prefer multiples of 4 -->\n </div>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nUse 4 (single row) or 8 (two rows) based on process complexity. CSS uses grid-template-columns: repeat(4, 1fr) — counts other than 4 or 8 (5, 6, 7) produce a partial last row that's acceptable but visually unbalanced. Use leading zeros on the step numbers (01, 02, ..., 0N). The <div class='icon'> can be empty if no icon is available -- it still renders as a teal-tinted square placeholder. Anti-pattern to AVOID: fewer than 4 steps (use emblema-statement or emblema-bullets for short sequences). Counts other than 4 or 8 are acceptable when content has that many genuine steps, but 4 and 8 are visually cleanest.",185 "emblema-timeline": "Create an Emblema HORIZONTAL TIMELINE slide. The body MUST contain a <div class='slide-pad slide-timeline'> with a <div class='track'> wrapping a <div class='line'> and a <div class='points'> of EXACTLY FIVE <div class='point'> children; STATE COUPLING RULE: at most ONE <div class='point now'> (the present moment), all earlier points use <div class='point done'>, all later points use plain <div class='point'>. Without these state classes the dots are blank circles. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Timeline', 'Schedule', 'Roadmap', 'Milestones', 'Plan'. Good examples: 'A year of Emblema, milestone by milestone.', 'I cinque snodi del 2025.'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-timeline'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <div class='track'>\n <div class='line'></div>\n <div class='points'>\n <div class='point done'><div class='dot'></div><span class='date'>Q1 2025</span><h4>Milestone</h4><p>1-line description.</p></div>\n <div class='point done'><div class='dot'></div><span class='date'>Q2 2025</span><h4>Milestone</h4><p>1-line description.</p></div>\n <div class='point now'><div class='dot'></div><span class='date'>NOW</span><h4>Current focus</h4><p>1-line description.</p></div>\n <div class='point'><div class='dot'></div><span class='date'>Q4 2025</span><h4>Upcoming</h4><p>1-line description.</p></div>\n <div class='point'><div class='dot'></div><span class='date'>Q1 2026</span><h4>Upcoming</h4><p>1-line description.</p></div>\n </div>\n </div>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nEXACTLY 5 .point children -- the CSS uses grid-template-columns: repeat(5, 1fr). At most one .now; .done points must come before .now in DOM order; plain .point come after. The <div class='line'> is intentionally empty (CSS-styled track). Anti-pattern to AVOID: vertical <ul><li> timeline (use a different layout for vertical chronology) or 4/6 points (breaks the grid).",186 "emblema-roadmap": "Create an Emblema ROADMAP slide. The body MUST contain a <div class='slide-pad slide-roadmap'> with a <div class='phases'> of EXACTLY THREE <div class='phase'> children: 'Now' (default), 'Next' (.phase--next), and 'Later' (.phase--later); WITHOUT THE .phase--next AND .phase--later modifiers the three phases all render with the same teal header and the time hierarchy is lost. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Roadmap', 'Plan', 'Phases', 'Schedule', 'Timeline'. Good examples: 'What ships next, and what comes after.', 'Roadmap del prodotto 2026.'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-roadmap'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <div class='phases'>\n <div class='phase'><header><h4>Now</h4><span class='when'>Q1 2026</span></header><ul><li>Item 1</li><li>Item 2</li><li>Item 3</li></ul></div>\n <div class='phase phase--next'><header><h4>Next</h4><span class='when'>Q2 2026</span></header><ul><li>Item 1</li><li>Item 2</li></ul></div>\n <div class='phase phase--later'><header><h4>Later</h4><span class='when'>H2 2026</span></header><ul><li>Item 1</li><li>Item 2</li></ul></div>\n </div>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nPHASE COUPLING RULE: first .phase = default (teal header), second = .phase.phase--next (teal-mid header), third = .phase.phase--later (gray header). The DOM order encodes the time order. Each .phase has a <header> with <h4> + <span class='when'> followed by a <ul>. Anti-pattern to AVOID: 4 phases (breaks the 3-col grid) or omitting the modifier classes (all phases look identical).",187 "emblema-team": "Create an Emblema TEAM GRID slide. The body MUST contain a <div class='slide-pad slide-team'> with a <div class='grid'> of EXACTLY FOUR <div class='person'> children, each with .avatar + h4 + .role + p.bio; WITHOUT THE .person AND .avatar CLASSES the square avatar tiles and team-card layout will not render. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Team', 'Our Team', 'Founders', 'People', 'Who We Are'. Good examples: 'Four people, fifteen years of compounding craft.', 'Il team che fa funzionare tutto.'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-team'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <div class='grid'>\n <div class='person'>\n <div class='avatar'>FN</div> <!-- Two-letter initials, OR replace with <img src='...' alt='...'> -->\n <h4>Full Name</h4>\n <p class='role'>Role · Department</p>\n <p class='bio'>1-2 sentence bio derived from source content.</p>\n </div>\n <!-- Exactly 4 .person children -->\n </div>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nEXACTLY 4 people -- the CSS uses repeat(4, 1fr). The .avatar div renders as a teal-tinted square; if no real photo, place 2-letter initials inside; if a photo is available, use <img> with width/height filling the .avatar. Anti-pattern to AVOID: <ul> of names (loses the grid + avatar) or 5+ people (rows wrap awkwardly).",188 "emblema-testimonial": "Create an Emblema TESTIMONIAL slide. The body MUST contain a <div class='slide-testimonial'> with a <div class='photo'> on the left and a <div> wrapping <p class='quote'> + <p class='who'> + <p class='who-meta'> on the right; WITHOUT THE .quote CLASS the leading large opening-quote pseudo-element will not render. CRITICAL HEADING RULE: The pull quote MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. The quote is the headline, NOT a separate <h2>. Use this EXACT structure:\n<section>\n <div class='slide-testimonial'>\n <div class='photo'>FN</div> <!-- Initials, OR replace with <img> -->\n <div>\n <p class='quote'>The full quote text from the source.</p>\n <p class='who'>Speaker Name</p>\n <p class='who-meta'>Role · Company · Subject</p>\n </div>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nDo NOT use <blockquote> or <h2> for the quote -- the <p class='quote'> is what triggers the styled opening-quote pseudo-element and 36px Plex Light styling. The .photo renders as a circular gradient by default; replace with an <img> for a real headshot. Anti-pattern to AVOID: <em>quote</em> wrappers (italics fight the existing styling) or splitting attribution across multiple unstyled <p>.",189 "emblema-logos": "Create an Emblema LOGO CLOUD slide. The body MUST contain a <div class='slide-pad slide-logos'> with a <div class='grid'> of <div class='cell'> children (5 columns); WITHOUT THE .cell WRAPPER the 16:9 logo cells with hairline borders will not render. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Logos', 'Customers', 'Partners', 'Clients', 'Brands'. Good examples: 'Teams that quietly run on Emblema.', 'I clienti che ci hanno scelto nel 2025.'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-logos'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <div class='grid'>\n <div class='cell'>BRAND</div>\n <!-- 10 or 15 cells (5 per row, 2-3 rows) -->\n </div>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nEach .cell contains a brand wordmark as plain text (Plex Sans 600), or replace with an <img>. Use a multiple of 5 cells (10 or 15) for clean rows. Anti-pattern to AVOID: <ul><li>brand</li></ul> (loses the cell border + 16:9 aspect ratio).",190 "emblema-ui": "Create an Emblema UI SHOWCASE slide. The body MUST contain a <div class='slide-ui'> with a <div class='left'> for copy and a <div class='browser'> for the screenshot mockup; WITHOUT THE .browser WRAPPER the chrome bar with traffic-light dots and URL bar will not render. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'UI', 'Product', 'Screenshot', 'App', 'Interface'. Good examples: 'Inside the workspace -- one panel, one source of truth.', 'Una sola interfaccia per tutto il flusso operativo.'. Use this EXACT structure:\n<section>\n <div class='slide-ui'>\n <div class='left'>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <ul>\n <li>Feature point 1</li>\n <li>Feature point 2</li>\n <li>Feature point 3</li>\n <li>Feature point 4</li>\n </ul>\n </div>\n <div class='browser'>\n <div class='chrome'>\n <span></span><span></span><span></span>\n <div class='url'>app.emblema.ai/workspaces</div>\n </div>\n <div class='body'>\n <!-- Optional: <img> for a real screenshot. Otherwise placeholder rows: -->\n <div class='ui-row'></div>\n <div class='ui-row short'></div>\n <div class='ui-card'><h5>Card label</h5><p>Card body.</p></div>\n </div>\n </div>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nThe three empty <span> elements in .chrome are the traffic-light dots (CSS sizes them). The .url div is the address bar. Inside .body, use empty <div class='ui-row'> for placeholder lines or insert a real <img> screenshot. Anti-pattern to AVOID: full-bleed <img> outside the .browser wrapper (loses the framing chrome).",191 "emblema-features": "Create an Emblema FEATURE GRID slide. The body MUST contain a <div class='slide-pad slide-features'> with a <div class='grid'> of BETWEEN 6 AND 12 <div class='card'> children — prefer multiples of 3 (6, 9, or 12) so the 3-col grid wraps cleanly, each with .icon + h4 + p; WITHOUT THE .card AND .icon WRAPPERS the cards lose their hairline borders and teal-tint icon tiles. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Features', 'Capabilities', 'What we do', 'Highlights', 'Functionality'. Good examples: 'Six things Emblema does that others don't.', 'Sei capacita' che ci distinguono.'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-features'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <div class='grid'>\n <div class='card'>\n <div class='icon'><svg viewBox='0 0 22 22'><!-- 22x22 icon --></svg></div>\n <h4>Feature title</h4>\n <p>1-2 sentences derived from source.</p>\n </div>\n <!-- 6 to 12 .card children, prefer multiples of 3 -->\n </div>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nUse 6, 9, or 12 cards based on content density: 6 (3x2) for sparse content, 9 (3x3) for medium-dense feature lists, 12 (3x4) for very dense lists. CSS uses grid-template-columns: repeat(3, 1fr) — counts that aren't multiples of 3 (7, 8, 10, 11) leave a partial last row that's acceptable but visually weaker. The .icon div is a teal-tinted square; the inline SVG is OPTIONAL (an empty .icon still renders as the swatch). Anti-pattern to AVOID: fewer than 6 cards (under-fills the layout, leaves the slide looking sparse). Counts that aren't multiples of 3 are acceptable when content genuinely has that many discrete points, but multiples of 3 always look cleaner.",192 "emblema-pricing": "Create an Emblema PRICING TIERS slide. The body MUST contain a <div class='slide-pad slide-pricing'> with a <div class='grid'> of EXACTLY THREE <div class='tier'> children, with EXACTLY ONE marked .tier--featured (the recommended tier); WITHOUT .tier--featured on one card, the lifted shadow + teal CTA + 'Most popular' badge will not render. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Pricing', 'Plans', 'Tiers', 'Subscriptions', 'Cost'. Good examples: 'Pricing for teams of every size.', 'I tre piani di Emblema.'. Use this EXACT structure:\n<section>\n <div class='slide-pad slide-pricing'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <hr class='divider'>\n </div>\n <div class='grid'>\n <div class='tier'>\n <h4>Tier name</h4>\n <div class='price'>€X<span class='per'>/mo</span></div>\n <p class='desc'>Short description of who it's for.</p>\n <ul class='feats'><li>Feature 1</li><li>Feature 2</li></ul>\n <a class='cta'>Choose plan</a>\n </div>\n <div class='tier tier--featured'>\n <span class='badge'>Most popular</span>\n <h4>Tier name</h4>\n <div class='price'>€Y<span class='per'>/mo</span></div>\n <p class='desc'>Description.</p>\n <ul class='feats'><li>Feature 1</li><li>Feature 2</li><li>Feature 3</li></ul>\n <a class='cta'>Choose plan</a>\n </div>\n <div class='tier'>\n <!-- Same structure as tier 1 -->\n </div>\n </div>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nTIER COUPLING RULE: EXACTLY ONE .tier--featured (typically the middle one). The .badge span ONLY appears inside .tier--featured. Each tier has h4 (label) + .price (with .per for the period suffix) + .desc + ul.feats + a.cta. Anti-pattern to AVOID: zero or two .tier--featured (visual hierarchy collapses) or 4 tiers (breaks the 3-col grid).",193 "emblema-question": "Create an Emblema BIG QUESTION slide. The body MUST contain a <div class='slide-question'> with a <p class='q'> for the question; the CSS pseudo-element appends a TEAL '?' automatically -- do NOT include the question mark in the text. CRITICAL HEADING RULE: The question text MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. Use this EXACT structure:\n<section>\n <div class='slide-question'>\n <p class='q'>What if the smallest team did the most thoughtful work</p>\n <p class='hint'>Optional one-line hint or framing for the audience.</p>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nThe <p class='q'> renders at 96px Plex Light. The CSS adds a teal '?' via ::after -- so the text inside <p class='q'> must NOT end with a question mark (otherwise you get two: '??'). The <p class='hint'> is OPTIONAL and renders smaller and tracked-out below. Anti-pattern to AVOID: <h1> or <h2> for the question text -- loses the styled '?' pseudo-element.",194 "emblema-definition": "Create an Emblema DEFINITION slide. The body MUST contain a <div class='slide-definition'> with a <div class='term'> on the left (with optional <span class='ipa'>) and a body block on the right with .pos + .meaning + .example; WITHOUT THE .term AND .meaning CLASSES the dictionary-style typography and teal vertical rule will not render. CRITICAL HEADING RULE: The term MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. Use this EXACT structure:\n<section>\n <div class='slide-definition'>\n <div class='term'>\n Word or phrase\n <span class='ipa'>/æIpa\u02c8notæSiΗn/</span>\n </div>\n <div>\n <p class='pos'>Part of Speech</p>\n <p class='meaning'>Plain-language definition derived from source.</p>\n <p class='example'>An italic example sentence using the term.</p>\n </div>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nThe <div class='term'> sits left of a teal vertical rule (CSS-applied). The <span class='ipa'> is OPTIONAL pronunciation; omit if the source doesn't include it. The .pos is the small uppercase part-of-speech label. Anti-pattern to AVOID: <dl><dt><dd> (semantically tempting but the styling is wrong) or wrapping everything in a single <p>.",195 "emblema-code": "Create an Emblema CODE slide. The body MUST contain a <div class='slide-code'> with a <div> for copy on the left and a <pre> on the right; WITHOUT <pre> THE DARK SYNTAX BACKGROUND AND IBM PLEX MONO STYLING will not render -- the theme styles `.slide-code pre` specifically. CRITICAL HEADING RULE: The <h2> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h2> values: 'Code', 'Snippet', 'Example', 'Programming'. Use this EXACT structure:\n<section>\n <div class='slide-code'>\n <div>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h2>HEADING_DERIVED_FROM_SOURCE_CONTENT</h2>\n <p>1-2 sentence framing of what the code does.</p>\n </div>\n <pre>\n<span class='c'># Comment</span>\n<span class='k'>def</span> <span class='f'>function_name</span>(<span class='n'>arg</span>):\n <span class='k'>return</span> <span class='s'>'string'</span>\n </pre>\n </div>\n <aside class='notes'>Speaker notes.</aside>\n</section>\nUse the theme's syntax-color spans inside <pre>: .k = keyword (cyan), .s = string (yellow), .c = comment (grey italic), .f = function name (teal), .n = identifier (white). The <pre>::before pseudo-element shows a 'python' label in the top-right corner -- this is hardcoded in the theme; if you need a different language, the label still says 'python' (limitation of the theme; do not try to override). Indent code with spaces, not tabs. Anti-pattern to AVOID: emitting `<script>` (composer strips it) or styling code with inline color (bypasses the theme).",196 "emblema-closing": "Create an Emblema CLOSING slide. The body MUST contain a <div class='slide-closing'> with a <div class='left'> and a <div class='right'>; WITHOUT BOTH the teal split layout, gradient right panel, and contact-pair layout will not render. CRITICAL HEADING RULE: The <h1> MUST be 3-8 words describing THIS specific slide's content, written in the SAME LANGUAGE as the source document (Italian source -> Italian heading, English source -> English heading). Extract the heading from the actual source content -- do NOT invent generic phrases. BANNED <h1> values: 'Thank you', 'Questions?', 'The end' (use them ONLY if they're the literal close in the source language and tone). Good examples: 'Let's build something thoughtful together.', 'Costruiamo qualcosa di importante.'. Use this EXACT structure:\n<section>\n <div class='slide-closing'>\n <div class='left'>\n <span class='eyebrow'>SHORT EYEBROW</span>\n <h1>Closing headline derived from source.</h1>\n <dl class='contacts'>\n <div><dt>Email</dt><dd>hello@example.com</dd></div>\n <div><dt>Web</dt><dd>example.com</dd></div>\n <div><dt>Phone</dt><dd>+39 02 1234 5678</dd></div>\n <div><dt>Address</dt><dd>City, Country</dd></div>\n </dl>\n </div>\n <div class='right'></div>\n </div>\n <aside class='notes'>Closing slide.</aside>\n</section>\nThe <div class='right'> is intentionally empty -- the theme renders the radial gradient via CSS. The <dl class='contacts'> uses the same div-per-pair wrapper as the spec sheet. Up to 4 contact pairs (CSS uses 2x2 grid). Anti-pattern to AVOID: putting contact info inline as <p> rows -- breaks the styled key:value alignment.",197}198199200def build_layout_instruction(template_name):201 """Build additional system prompt instruction for the selected layout template."""202 if not template_name or template_name == "auto":203 return ""204 instruction = TEMPLATE_INSTRUCTIONS.get(template_name, "")205 if instruction:206 result = f"\n\nIMPORTANT LAYOUT INSTRUCTION: The user selected the '{template_name}' layout. {instruction}\nFollow this layout pattern precisely while adapting the content."207 if template_name.startswith("marina-") or template_name.startswith("emblema-"):208 result += "\n\nANIMATION: Do NOT add class='fragment' to any element. The entire slide MUST appear at once — no staggered reveal. Arrow keys move between slides, not between items within a slide."209 return result210 return f"\n\nThe user selected the '{template_name}' layout. Use this layout pattern."211212213def extract_section(html: str) -> str:214 # Extract the <section>...</section> from LLM output, handling markdown fences.215216 # Strip markdown code fences if present217 html = re.sub(r"^```(?:html)?\s*", "", html, flags=re.MULTILINE)218 html = re.sub(r"```\s*$", "", html, flags=re.MULTILINE)219 html = html.strip()220221 # Extract <section>...</section> if wrapped in other content222 match = re.search(r"(<section[\s\S]*</section>)", html, re.IGNORECASE)223 if match:224 return match.group(1)225226 # If no <section> found, wrap the content in one227 return f"<section>\n{html}\n</section>"228229230def main():231 try:232 execution_input = json.loads(sys.stdin.read())233 inputs = execution_input.get("inputs", {})234235 content = inputs.get("content")236 instruction = inputs.get("instruction")237 image_filename = inputs.get("image", "")238 template_name = inputs.get("template_name", "auto")239 llm_model = inputs.get("llmModel")240241 if not content:242 raise ValueError("Required input 'content' not provided")243 if not instruction:244 raise ValueError("Required input 'instruction' not provided")245 if not llm_model:246 raise ValueError("Required input 'llmModel' not provided")247248 # Read image and convert to base64 data URI if provided249 image_data_uri = ""250 if image_filename:251 image_path = f"/data/input/{image_filename}"252 if os.path.isfile(image_path):253 mime = mimetypes.guess_type(image_filename)[0] or "image/png"254 with open(image_path, "rb") as f:255 b64 = base64.b64encode(f.read()).decode("ascii")256 image_data_uri = f"data:{mime};base64,{b64}"257 print(f"Image loaded: {image_filename} ({len(b64)} base64 chars)", file=sys.stderr)258259 print(f"Generating slide with model: {llm_model}", file=sys.stderr)260 print(f"Content length: {len(content)} chars", file=sys.stderr)261 print(f"Instruction: {instruction[:100]}...", file=sys.stderr)262 print(f"Layout template: {template_name}", file=sys.stderr)263264 # Build system prompt with optional layout instruction265 system_prompt = SYSTEM_PROMPT + build_layout_instruction(template_name)266267 # If image provided, add instruction to use {{IMAGE}} placeholder268 if image_data_uri:269 system_prompt += (270 "\n\nIMAGE INPUT: The user has provided an image. "271 "Use {{IMAGE}} as the exact src attribute value for the <img> tag. "272 "CRITICAL: Always wrap the <img> inside a <div style='flex:1;min-width:0'> when using flex layout. "273 "Never place <img> as a direct flex child — it will overflow. "274 "Example: <div style='flex:1;min-width:0'><img src='{{IMAGE}}' alt='description' style='width:100%;border-radius:8px'></div>. "275 "Do NOT use picsum.photos — use {{IMAGE}} instead."276 )277278 user_message = (279 f"<instruction>{instruction}</instruction>\n\n"280 f"<source_content>\n{content}\n</source_content>"281 )282283 messages = [284 {"role": "system", "content": system_prompt},285 {"role": "user", "content": user_message},286 ]287288 raw_output = Gais.llm.chat(messages, model=llm_model, temperature=0.3).text289 slide_html = extract_section(raw_output)290291 # Post-process: ensure flex children have min-width:0 to prevent overflow.292 # LLMs output flex:1 without min-width:0, causing text to expand and hide images.293 def _fix_flex_styles(html):294 result = []295 i = 0296 tag = 'style="'297 while i < len(html):298 pos = html.find(tag, i)299 if pos == -1:300 # Also try single quotes301 pos2 = html.find("style='", i)302 if pos2 == -1:303 result.append(html[i:])304 break305 pos = pos2306 tag = "style='"307 q = "'"308 else:309 q = '"'310 result.append(html[i:pos])311 # Find end of style attribute312 start = pos + len('style=') + 1313 end = html.find(q, start)314 if end == -1:315 result.append(html[pos:])316 break317 style_val = html[start:end]318 # Fix: add min-width:0 if has flex:1 but not min-width319 if 'flex:' in style_val and '1' in style_val.split('flex:')[-1][:3] and 'min-width' not in style_val:320 style_val = style_val.rstrip(';') + ';min-width:0;overflow:hidden'321 result.append(f'style={q}{style_val}{q}')322 i = end + 1323 tag = 'style="'324 return ''.join(result)325326 slide_html = _fix_flex_styles(slide_html)327328 # Replace {{IMAGE}} placeholder with actual base64 data URI329 if image_data_uri and "{{IMAGE}}" in slide_html:330 slide_html = slide_html.replace("{{IMAGE}}", image_data_uri)331 print("Replaced {{IMAGE}} placeholder with base64 data URI", file=sys.stderr)332333 print(f"Generated slide: {len(slide_html)} chars", file=sys.stderr)334335 output = {"slide_html": slide_html}336 print(json.dumps(output))337338 except Exception as e:339 error_output = {340 "error": str(e),341 "errorType": type(e).__name__,342 "traceback": traceback.format_exc(),343 }344 print(json.dumps(error_output), file=sys.stderr)345 sys.exit(1)346347348if __name__ == "__main__":349 main()$ git log --oneline
v1.5.0
HEAD
2026-05-07v1.3.12026-04-23
v1.1.02026-04-07
v1.0.02026-03-29