Files
foil-cap-theories/generate_presentation.js
m.elgin d3b67b5271 update
2026-06-30 17:03:39 +03:00

431 lines
23 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const path = require('path');
const pptxgen = require('pptxgenjs');
const base = __dirname;
const outPath = path.join(base, 'prezentaciya-vampiricheskoe-tenevoe-pravitelstvo.pptx');
const assets = {
agent: path.join(base, 'assets', 'generated', 'ai-01-snv12-agent.png'),
medieval: path.join(base, 'assets', 'generated', 'ai-02-medieval-spread-map.png'),
classes: path.join(base, 'assets', 'generated', 'ai-03-vampire-classes.png'),
failed: path.join(base, 'assets', 'generated', 'ai-04-failed-infection.png'),
economy: path.join(base, 'assets', 'generated', 'ai-05-blood-economy.png'),
artificial: path.join(base, 'assets', 'generated', 'ai-06-live-vs-artificial-blood.png'),
market: path.join(base, 'assets', 'generated', 'ai-07-hidden-donor-market.png'),
zones: path.join(base, 'assets', 'generated', 'ai-08-feeding-zones-map.png'),
signTeeth: path.join(base, 'assets', 'generated', 'ai-sign-01-teeth-canines.png'),
signEyeNeutral: path.join(base, 'assets', 'generated', 'ai-sign-02-eye-neutral.png'),
signEyeHunger: path.join(base, 'assets', 'generated', 'ai-sign-03-eye-hunger.png'),
signSkin: path.join(base, 'assets', 'generated', 'ai-sign-04-skin-aging.png'),
signHand: path.join(base, 'assets', 'generated', 'ai-sign-05-hand-motorics.png'),
signBehavior: path.join(base, 'assets', 'generated', 'ai-sign-06-behavioral-portrait.png')
};
const pptx = new pptxgen();
pptx.layout = 'LAYOUT_WIDE';
pptx.author = 'Hermes Agent';
pptx.company = 'Nous Research';
pptx.subject = 'Строгая псевдонаучная модель гемозависимой элиты';
pptx.title = 'Пищевая цепочка: от тебя до теневого правительства';
pptx.lang = 'ru-RU';
pptx.theme = {
headFontFace: 'Aptos Display',
bodyFontFace: 'Aptos',
lang: 'ru-RU'
};
const C = {
bg: 'F7F9FC',
white: 'FFFFFF',
ink: '1F2937',
muted: '667085',
line: 'CAD5E2',
blue: '245B8F',
blueSoft: 'EAF2FB',
red: 'B42318',
redSoft: 'FDECEC',
graySoft: 'EEF2F6',
dark: '102A43'
};
function footer(slide, n, dark = false) {
slide.addText(String(n).padStart(2, '0'), {
x: 12.48,
y: 7.02,
w: 0.36,
h: 0.18,
fontSize: 10,
color: dark ? 'D0DAE6' : C.muted,
align: 'right',
margin: 0
});
}
function put(slide, text, x, y, w, h, opts = {}) {
slide.addText(text, {
x, y, w, h,
fontFace: opts.fontFace ?? 'Aptos',
fontSize: opts.fontSize ?? 14,
color: opts.color ?? C.ink,
bold: opts.bold ?? false,
italic: opts.italic ?? false,
align: opts.align ?? 'left',
valign: opts.valign ?? 'mid',
margin: opts.margin ?? 0.02,
breakLine: opts.breakLine ?? true
});
}
function card(slide, x, y, w, h, title, body, opts = {}) {
slide.addShape(pptx.ShapeType.roundRect, {
x, y, w, h,
rectRadius: 0.05,
fill: { color: opts.fill ?? C.white },
line: { color: opts.line ?? C.line, pt: opts.pt ?? 1.1 }
});
if (title) {
put(slide, title, x + 0.18, y + 0.16, w - 0.36, 0.28, {
fontSize: opts.titleSize ?? 16,
bold: true,
color: opts.titleColor ?? C.ink
});
}
if (body) {
put(slide, body, x + 0.18, y + (title ? 0.52 : 0.18), w - 0.36, h - (title ? 0.68 : 0.28), {
fontSize: opts.bodySize ?? 13.5,
color: opts.bodyColor ?? C.ink,
valign: opts.bodyValign ?? 'top',
margin: 0.04
});
}
}
function pill(slide, x, y, w, h, text, opts = {}) {
slide.addShape(pptx.ShapeType.roundRect, {
x, y, w, h,
rectRadius: 0.08,
fill: { color: opts.fill ?? C.graySoft },
line: { color: opts.line ?? C.graySoft, pt: 1 }
});
put(slide, text, x + 0.08, y + 0.05, w - 0.16, h - 0.1, {
fontSize: opts.fontSize ?? 12.5,
color: opts.color ?? C.ink,
bold: opts.bold ?? false,
align: opts.align ?? 'center'
});
}
function titleSlideBase(slide, title, subtitle) {
slide.background = { color: C.bg };
put(slide, title, 0.9, 0.78, 6.1, 1.25, { fontSize: 28, bold: true, color: C.dark, margin: 0 });
put(slide, subtitle, 0.92, 2.18, 6.3, 0.55, { fontSize: 16, color: C.muted, margin: 0 });
}
function textSlideBase(slide, title, kicker = 'Псевдонаучная реконструкция') {
slide.background = { color: C.bg };
put(slide, title, 0.7, 0.52, 8.4, 0.42, { fontSize: 26, bold: true, color: C.dark, margin: 0 });
put(slide, kicker, 10.05, 0.58, 2.55, 0.2, { fontSize: 10.5, color: C.blue, italic: true, align: 'right', margin: 0 });
}
function fullImage(slide, imagePath) {
slide.background = { color: C.white };
slide.addImage({ path: imagePath, x: 0, y: 0, w: 13.333, h: 7.5 });
}
// 1. title
{
const s = pptx.addSlide();
titleSlideBase(s,
'Пищевая цепочка:\nот тебя до теневого правительства',
'Модель гемозависимой элиты'
);
card(s, 0.92, 3.0, 5.25, 2.25, 'Исходная гипотеза',
'Теневое правительство — не только сеть власти, но и каста с контролем отбора, хранения и распределения крови.',
{ fill: C.white, line: C.line, bodySize: 15, bodyValign: 'mid' }
);
card(s, 7.1, 1.2, 5.2, 4.95, 'Минимальная схема', '', { fill: C.white, line: C.line });
pill(s, 7.6, 2.0, 1.1, 0.5, 'человек', { fill: C.blueSoft, line: C.blue, color: C.blue, bold: true });
put(s, '→', 8.85, 2.08, 0.3, 0.2, { fontSize: 24, color: C.muted, align: 'center' });
pill(s, 9.25, 2.0, 1.2, 0.5, 'отбор', { fill: C.graySoft, line: C.line, color: C.ink, bold: true });
put(s, '→', 10.55, 2.08, 0.3, 0.2, { fontSize: 24, color: C.muted, align: 'center' });
pill(s, 10.95, 2.0, 1.1, 0.5, 'кровь', { fill: C.redSoft, line: C.red, color: C.red, bold: true });
put(s, '→', 8.85, 3.48, 0.3, 0.2, { fontSize: 24, color: C.muted, align: 'center' });
pill(s, 9.25, 3.4, 2.05, 0.56, 'верхушка элиты', { fill: C.dark, line: C.dark, color: C.white, bold: true });
put(s, 'долгожительство\nселекция\nскрытая логистика', 7.58, 4.28, 4.1, 0.95, {
fontSize: 16,
color: C.muted,
align: 'center'
});
put(s, 'Псевдонаучная реконструкция', 0.95, 6.55, 6.8, 0.22, {
fontSize: 12.5,
color: C.muted,
italic: true,
margin: 0
});
footer(s, 1);
}
// 2. hypothesis
{
const s = pptx.addSlide();
textSlideBase(s, 'Исходная гипотеза');
card(s, 0.88, 1.45, 12.0, 1.2,
'Тезис',
'Элита не только управляет обществом, но и питается им.',
{ fill: C.white, line: C.blue, titleColor: C.blue, bodySize: 17, bodyValign: 'mid' }
);
card(s, 0.88, 3.0, 2.75, 2.05, '1. Биология', 'Вампиризм = вирусная адаптация.', { fill: C.redSoft, line: C.red });
card(s, 3.85, 3.0, 2.75, 2.05, '2. Долголетие', 'Возраст даёт власть и время.', { fill: C.blueSoft, line: C.blue });
card(s, 6.82, 3.0, 2.75, 2.05, '3. Кровь', 'Кровь = еда, валюта, селекция.', { fill: C.white, line: C.line });
card(s, 9.79, 3.0, 3.09, 2.05, '4. Институты', 'Система власти маскирует кормовую сеть.', { fill: C.white, line: C.line });
pill(s, 1.7, 5.72, 9.9, 0.62, 'Ключевая формула: власть = контроль кормовой инфраструктуры', { fill: C.dark, line: C.dark, color: C.white, fontSize: 20, bold: true });
footer(s, 2);
}
// 3. biological agent
{
const s = pptx.addSlide();
fullImage(s, assets.agent);
put(s, 'Биологический агент: вирус, молекула и механизм действия', 0.62, 0.23, 11.98, 0.42, {
fontSize: 24, bold: true, color: C.dark, align: 'center'
});
put(s, '1. Вирион SNV-12', 1.28, 1.3, 2.45, 0.26, { fontSize: 14, bold: true, color: C.red, align: 'center' });
put(s, '2. Гемофильный регуляторный комплекс', 5.0, 1.3, 2.75, 0.26, { fontSize: 13.6, bold: true, color: C.red, align: 'center' });
put(s, 'HEP + MitoX + Reg\nперестройка обмена', 7.7, 2.46, 1.68, 0.78, { fontSize: 11, color: C.ink, align: 'center' });
put(s, 'связывание → вход → РНК → транспорт', 4.58, 5.9, 3.24, 0.34, { fontSize: 11.2, color: C.blue, align: 'center', bold: true });
put(s, '3. Клеточные мишени и системные эффекты', 9.08, 1.3, 3.9, 0.26, { fontSize: 13.2, bold: true, color: C.red, align: 'center' });
put(s, 'ROS↑,\nпотенциал↓', 8.42, 3.18, 1.35, 0.38, { fontSize: 10.5, color: C.red, align: 'center' });
put(s, 'сдвиг\nметаболизма гема', 9.88, 3.18, 1.62, 0.38, { fontSize: 10.5, color: C.red, align: 'center' });
put(s, 'ускорение\nрепарации тканей', 11.52, 3.18, 1.2, 0.38, { fontSize: 10.1, color: C.red, align: 'center' });
put(s, 'сумеречное зрение\nи фоточувствительность', 8.42, 5.15, 1.34, 0.42, { fontSize: 9.8, color: C.blue, align: 'center' });
put(s, 'лактатный сдвиг\nи экономия энергии', 11.52, 5.15, 1.16, 0.42, { fontSize: 9.8, color: C.blue, align: 'center' });
put(s, 'Донорская кровь: сигналы → гем → гормоны → адаптация', 8.18, 6.05, 4.1, 0.28, {
fontSize: 10.2, color: C.blue, align: 'center', bold: true
});
put(s, 'Вампиризм = перенастройка обмена, регенерации и светочувствительности.', 10.63, 6.75, 2.2, 0.48, {
fontSize: 10.2, color: C.muted, align: 'center'
});
footer(s, 3);
}
// 4. medieval spread map
{
const s = pptx.addSlide();
fullImage(s, assets.medieval);
put(s, 'Средневековье создаёт идеальную среду', 0.22, 0.28, 4.12, 0.34, { fontSize: 21, bold: true, color: C.dark, align: 'center' });
put(s, 'XIIXIV века: торговля, миграции, войны и эпидемии', 0.22, 0.62, 4.12, 0.22, { fontSize: 11.2, color: C.muted, align: 'center' });
put(s, 'Торговля, войны и миграции создают коридоры распространения SNV-12.', 11.28, 5.55, 1.82, 1.34, {
fontSize: 10.4, color: C.ink, align: 'center', valign: 'mid'
});
footer(s, 4);
}
// 5. physiological changes
{
const s = pptx.addSlide();
textSlideBase(s, 'Как вирус меняет организм');
card(s, 0.88, 1.4, 3.88, 1.4, 'Кровяная среда', 'Норма: транспорт O₂.\nЗаражение: спрос на гем.\nАдаптация: кровь = сигнал.', { fill: C.white, line: C.red });
card(s, 4.95, 1.4, 3.88, 1.4, 'Обмен веществ', 'Норма: базовый цикл.\nЗаражение: стресс.\nАдаптация: экономный режим.', { fill: C.white, line: C.blue });
card(s, 9.02, 1.4, 3.43, 1.4, 'Нервная система', 'Норма: баланс.\nЗаражение: перегрузка.\nАдаптация: фокус на добыче.', { fill: C.white, line: C.line });
card(s, 0.88, 3.15, 3.88, 1.4, 'Зрение и свет', 'Норма: дневное зрение.\nЗаражение: фотостресс.\nАдаптация: сумеречный режим.', { fill: C.white, line: C.blue });
card(s, 4.95, 3.15, 3.88, 1.4, 'Регенерация', 'Норма: обычное заживление.\nЗаражение: воспаление.\nАдаптация: быстрая репарация.', { fill: C.white, line: C.red });
card(s, 9.02, 3.15, 3.43, 1.4, 'Старение', 'Норма: обычный цикл.\nЗаражение: нагрузка.\nАдаптация: медленное старение.', { fill: C.white, line: C.line });
card(s, 0.88, 5.08, 11.98, 1.08, 'Итог', 'Отсюда: кровь, свет, регенерация, долголетие.', { fill: C.dark, line: C.dark, titleColor: C.white, bodyColor: 'EAF2FB', bodySize: 15, bodyValign: 'mid' });
footer(s, 5);
}
// 6. dependency on blood
{
const s = pptx.addSlide();
textSlideBase(s, 'Почему возникает зависимость от крови');
pill(s, 0.92, 2.1, 2.25, 0.9, '1. Вирус требует\nживые сигнальные молекулы', { fill: C.redSoft, line: C.red, color: C.red, bold: true, fontSize: 15 });
put(s, '→', 3.3, 2.34, 0.4, 0.2, { fontSize: 28, color: C.muted, align: 'center' });
pill(s, 3.82, 2.1, 2.25, 0.9, '2. Донорская кровь несёт\nсигналы и маркеры', { fill: C.blueSoft, line: C.blue, color: C.blue, bold: true, fontSize: 14.2 });
put(s, '→', 6.22, 2.34, 0.4, 0.2, { fontSize: 28, color: C.muted, align: 'center' });
pill(s, 6.72, 2.1, 2.25, 0.9, '3. Суррогат даёт\nтранспорт, но не сигналы', { fill: C.graySoft, line: C.line, color: C.ink, bold: true, fontSize: 14.2 });
put(s, '→', 9.12, 2.34, 0.4, 0.2, { fontSize: 28, color: C.muted, align: 'center' });
pill(s, 9.62, 2.1, 2.75, 0.9, '4. Голод = дефицит\nсигнальных компонентов', { fill: C.dark, line: C.dark, color: C.white, bold: true, fontSize: 14.2 });
card(s, 1.15, 4.0, 3.45, 1.25, 'Живая кровь', 'Сигналы, вариативность, метаболизм.', { fill: C.white, line: C.red });
card(s, 5.0, 4.0, 3.45, 1.25, 'Искусственная кровь', 'Транспорт есть. Сигналов почти нет.', { fill: C.white, line: C.blue });
card(s, 8.85, 4.0, 3.45, 1.25, 'Следствие', 'Селекция, ритуалы, рынок доноров.', { fill: C.white, line: C.line });
footer(s, 6);
}
// 7. classes
{
const s = pptx.addSlide();
fullImage(s, assets.classes);
put(s, 'Классы вампирической адаптации', 0.88, 0.3, 11.6, 0.36, { fontSize: 22, bold: true, color: C.dark, align: 'center' });
put(s, 'Выше класс — выше контроль, доступ и влияние.', 0.3, 6.9, 12.7, 0.24, { fontSize: 11.5, color: C.muted, align: 'center' });
footer(s, 7);
}
// 8. failed infection
{
const s = pptx.addSlide();
fullImage(s, assets.failed);
put(s, 'Неудачное заражение: каскад несовместимости', 1.1, 0.28, 11.1, 0.36, { fontSize: 22, bold: true, color: C.dark, align: 'center' });
put(s, 'нейровегетативный\nсбой', 3.6, 1.78, 1.44, 0.44, { fontSize: 11.2, color: C.blue, align: 'center' });
put(s, 'кардиореспираторный\nстресс', 3.57, 2.92, 1.5, 0.44, { fontSize: 11.2, color: C.blue, align: 'center' });
put(s, 'абдоминальный\nсосудистый криз', 3.58, 4.12, 1.48, 0.44, { fontSize: 11.0, color: C.blue, align: 'center' });
put(s, 'периферический\nспазм', 3.58, 5.33, 1.48, 0.4, { fontSize: 11.0, color: C.blue, align: 'center' });
put(s, 'терминальное\nистощение', 3.58, 6.42, 1.48, 0.4, { fontSize: 11.0, color: C.blue, align: 'center' });
put(s, 'генетическая и иммунная\nнесовместимость', 7.62, 1.7, 4.66, 0.42, { fontSize: 12.2, color: C.red, align: 'center', bold: true });
put(s, 'сосудистый перегрев\nи гиперметаболизм', 7.62, 3.0, 4.66, 0.42, { fontSize: 12.2, color: C.red, align: 'center', bold: true });
put(s, 'массовый гемолиз\nи высвобождение гема', 7.62, 4.25, 4.66, 0.42, { fontSize: 12.2, color: C.red, align: 'center', bold: true });
put(s, 'воспалительный каскад\nи токсическая перегрузка', 7.62, 5.46, 4.66, 0.42, { fontSize: 12.2, color: C.red, align: 'center', bold: true });
put(s, 'системный коллапс\nбез устойчивой адаптации', 7.62, 6.65, 4.66, 0.42, { fontSize: 12.2, color: C.red, align: 'center', bold: true });
footer(s, 8);
}
// 9. recognition slide built in ppt
{
const s = pptx.addSlide();
textSlideBase(s, 'Как распознать вампира');
const items = [
{ x: 0.72, y: 1.22, img: assets.signTeeth, title: 'Клыки', body: 'удлинение без деформации' },
{ x: 4.38, y: 1.22, img: assets.signEyeNeutral, title: 'Глаз: сытая фаза', body: 'зрачок почти нормален' },
{ x: 8.04, y: 1.22, img: assets.signEyeHunger, title: 'Глаз: голод', body: 'зрачок расширен и темнее' },
{ x: 0.72, y: 4.02, img: assets.signSkin, title: 'Кожа и возраст', body: 'ровная кожа, слабый возрастной шум' },
{ x: 4.38, y: 4.02, img: assets.signHand, title: 'Кисть и моторика', body: 'точность, вены, холодная пластика' },
{ x: 8.04, y: 4.02, img: assets.signBehavior, title: 'Поведение', body: 'кровь, документы, закрытые круги' }
];
items.forEach((item) => {
card(s, item.x, item.y, 3.05, 2.48, '', '', { fill: C.white, line: C.line, pt: 1.15 });
s.addImage({ path: item.img, x: item.x + 0.12, y: item.y + 0.12, w: 2.81, h: 1.72 });
put(s, item.title, item.x + 0.14, item.y + 1.88, 2.76, 0.18, {
fontSize: 11.8,
bold: true,
color: C.dark,
align: 'center',
margin: 0
});
put(s, item.body, item.x + 0.18, item.y + 2.08, 2.68, 0.22, {
fontSize: 9.6,
color: C.muted,
align: 'center',
margin: 0
});
});
pill(s, 1.58, 6.9, 10.15, 0.34, 'Смотреть нужно на комбинацию признаков.', { fill: C.dark, line: C.dark, color: C.white, fontSize: 12.4, bold: true });
footer(s, 9);
}
// 10. blood economy
{
const s = pptx.addSlide();
fullImage(s, assets.economy);
put(s, 'Экономика качественной крови', 0.42, 0.32, 12.48, 0.34, { fontSize: 22, bold: true, color: C.dark, align: 'center' });
put(s, 'Массовая кровь — периферии.\nПиковая и династическая — элите.', 0.45, 6.3, 4.3, 0.8, { fontSize: 11.3, color: C.muted, align: 'center' });
put(s, 'Чем древнее адаптант,\nтем уже доступ.', 5.05, 6.3, 4.3, 0.8, { fontSize: 11.3, color: C.muted, align: 'center' });
footer(s, 10);
}
// 11. live vs artificial blood
{
const s = pptx.addSlide();
fullImage(s, assets.artificial);
put(s, 'Почему искусственная кровь не подходит', 1.78, 0.2, 9.8, 0.34, { fontSize: 22, bold: true, color: C.dark, align: 'center' });
put(s, 'вариативность\nсигналов', 0.24, 3.15, 2.05, 0.38, { fontSize: 10.8, color: C.red, align: 'center' });
put(s, 'активная\nнейрохимия', 0.24, 4.16, 2.05, 0.38, { fontSize: 10.8, color: C.red, align: 'center' });
put(s, 'иммунный\nотклик', 0.24, 5.18, 2.05, 0.38, { fontSize: 10.8, color: C.red, align: 'center' });
put(s, 'эффект\nнасыщения', 0.24, 6.2, 2.05, 0.38, { fontSize: 10.8, color: C.red, align: 'center' });
put(s, 'сигналы\nсглажены', 11.0, 3.15, 2.05, 0.38, { fontSize: 10.8, color: C.blue, align: 'center' });
put(s, 'подпись\nстёрта', 11.0, 4.16, 2.05, 0.38, { fontSize: 10.8, color: C.blue, align: 'center' });
put(s, 'ответ\nнизкий', 11.0, 5.18, 2.05, 0.38, { fontSize: 10.8, color: C.blue, align: 'center' });
put(s, 'сытости\nнет', 11.0, 6.2, 2.05, 0.38, { fontSize: 10.8, color: C.blue, align: 'center' });
put(s, 'Живая кровь: сигналы, метаболизм, насыщение.', 0.2, 6.7, 5.7, 0.48, {
fontSize: 11.4, color: C.red, align: 'center', bold: true
});
put(s, 'Суррогат: транспорт без насыщения.', 7.48, 6.7, 5.7, 0.48, {
fontSize: 11.4, color: C.blue, align: 'center', bold: true
});
footer(s, 11);
}
// 12. hidden donor market
{
const s = pptx.addSlide();
fullImage(s, assets.market);
put(s, 'Тайный рынок доноров', 0.28, 0.18, 12.75, 0.36, { fontSize: 22, bold: true, color: C.dark, align: 'center' });
put(s, 'Поток: источник → отбор → биобанк → доставка.\nКлючевые узкие места: объём, холод, безопасность.', 9.52, 5.85, 3.1, 1.0, {
fontSize: 10.8, color: C.ink, align: 'left', valign: 'top'
});
footer(s, 12);
}
// 13. feeding zones map
{
const s = pptx.addSlide();
fullImage(s, assets.zones);
put(s, 'Геополитика кормовых зон', 1.02, 0.18, 10.6, 0.34, { fontSize: 22, bold: true, color: C.dark, align: 'center' });
put(s, 'Не страны, а контуры снабжения:\nрезервуары, коридоры, убежища, эксперименты.', 11.18, 5.2, 1.74, 1.2, {
fontSize: 10.2, color: C.ink, align: 'center'
});
footer(s, 13);
}
// 14. consequences matrix
{
const s = pptx.addSlide();
textSlideBase(s, 'Следствия: почему вампиры именно такие');
card(s, 0.92, 1.5, 5.8, 0.62, 'Биомеханизм', '', { fill: C.dark, line: C.dark, titleColor: C.white });
card(s, 6.82, 1.5, 5.58, 0.62, 'Наблюдаемое следствие', '', { fill: C.red, line: C.red, titleColor: C.white });
const left = [
'дефицит сигнальных молекул',
'изменённые фоторецепторные пути',
'усиленная регенеративная сигнализация',
'перестройка клеточного цикла',
'хронический голодный стресс',
'высокая цена качественной крови'
];
const right = [
'питание кровью',
'чувствительность к солнцу',
'быстрое восстановление после травм',
'медленное старение',
'ритуалы и иерархия доступа',
'элитные сети и рынок доноров'
];
for (let i = 0; i < left.length; i += 1) {
const y = 2.35 + i * 0.7;
card(s, 0.92, y, 5.8, 0.56, '', left[i], { fill: C.white, line: C.line, bodySize: 13.3, bodyValign: 'mid' });
card(s, 6.82, y, 5.58, 0.56, '', right[i], { fill: C.white, line: C.line, bodySize: 13.3, bodyValign: 'mid' });
}
footer(s, 14);
}
// 15. conclusion
{
const s = pptx.addSlide();
s.background = { color: C.dark };
put(s, 'Вывод', 0.95, 0.92, 2.5, 0.42, { fontSize: 28, bold: true, color: C.white, margin: 0 });
put(s,
'Если теория верна, власть — это доступ к качественной крови.',
0.95, 2.0, 7.35, 1.55,
{ fontSize: 23, color: 'EAF2FB', margin: 0.02, valign: 'mid' }
);
card(s, 9.0, 1.7, 3.15, 3.4, 'Ключевые формулы', '• вампиризм = зависимость + инфраструктура\n\n• власть = доступ к крови\n\n• миф скрывает систему снабжения', {
fill: '16324F',
line: '7FA6C9',
titleColor: C.white,
bodyColor: 'EAF2FB',
bodySize: 15,
bodyValign: 'mid'
});
put(s, 'Псевдонаучная реконструкция', 0.98, 6.48, 6.9, 0.2, { fontSize: 12.5, color: 'B8C7D9', italic: true, margin: 0 });
footer(s, 15, true);
}
async function main() {
await pptx.writeFile({ fileName: outPath });
}
main().catch((err) => {
console.error(err.stack || err.message || String(err));
process.exit(1);
});