Arag / build_ppt.py
AuthorBot
Ship B&N scraper refinements, platform backtest results, and project docs.
ab760e4
Raw
History Blame Contribute Delete
70 kB
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Author AI Chatbot β€” PREMIUM Pitch Deck v2
Image-first design: Pillow gradient backgrounds + AI-generated visuals.
"""
import sys, io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
from pathlib import Path
from PIL import Image, ImageDraw, ImageFilter
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
from pptx.oxml.ns import qn
from lxml import etree
# ─── Paths ────────────────────────────────────────────────────────
BASE = Path("d:/Author RAG")
ASSETS = BASE / "ppt_assets"
OVL = ASSETS / "overlays"
OVL.mkdir(parents=True, exist_ok=True)
IMG_COVER = ASSETS / "cover_author_hero.png"
IMG_PROBLEM = ASSETS / "problem_empty_books.png"
IMG_COMPETITOR = ASSETS / "competitor_split_scene.png"
IMG_SOLUTION = ASSETS / "solution_ai_glow.png"
IMG_PRICING = ASSETS / "pricing_premium_bg.png"
IMG_THANKYOU = ASSETS / "thankyou_author_desk.png"
BG_DARK = OVL / "bg_dark.png"
BG_AMBER = OVL / "bg_amber.png"
BG_GOLD = OVL / "bg_gold.png"
BG_GREEN = OVL / "bg_green.png"
OV_LEFT = OVL / "ov_left.png"
OV_BOTTOM= OVL / "ov_bottom.png"
OV_60 = OVL / "ov_60.png"
OV_75 = OVL / "ov_75.png"
OV_85 = OVL / "ov_85.png"
# ─── Design tokens ────────────────────────────────────────────────
W, H = 1920, 1080
SLIDE_W = Inches(13.33); SLIDE_H = Inches(7.5)
_BG = (0x0A, 0x0E, 0x1A); _CARD = (0x10, 0x18, 0x2C)
_CARD2 = (0x16, 0x22, 0x3A); _DIM = (0x06, 0x0A, 0x14)
_GOLD = (0xC9, 0xA8, 0x4C); _PURP = (0x6B, 0x4F, 0xBB)
_GREEN = (0x10, 0xB9, 0x81); _RED = (0xDC, 0x26, 0x26)
_AMBER = (0xF5, 0x9E, 0x0B); _TEAL = (0x06, 0xB6, 0xD4)
_WHITE = (0xFF, 0xFF, 0xFF); _MUTED = (0xB0, 0xB8, 0xD1)
_BORDER= (0x1E, 0x2A, 0x4A)
def c(t): return RGBColor(*t)
BG=c(_BG); BG_CARD=c(_CARD); BG_CARD2=c(_CARD2); DIM=c(_DIM)
GOLD=c(_GOLD); PURPLE=c(_PURP); GREEN=c(_GREEN); RED=c(_RED)
AMBER=c(_AMBER); TEAL=c(_TEAL); WHITE=c(_WHITE); MUTED=c(_MUTED)
BORDER=c(_BORDER)
F_SERIF="Georgia"; F_BODY="Calibri"; F_MONO="Consolas"
# ═══════════════════════════════════════════════════════════════════
# PILLOW β€” GENERATE GRADIENT ASSETS
# ═══════════════════════════════════════════════════════════════════
def lerp(a, b, t): return max(0, min(255, int(a + (b - a) * t)))
def _vgrad(c1, c2, w=W, h=H, mode="RGB"):
img = Image.new(mode, (w, h))
px = img.load()
for y in range(h):
t = y / (h - 1)
if mode == "RGB":
px[0, y] # check
for x in range(w):
px[x, y] = tuple(lerp(c1[i], c2[i], t) for i in range(3))
else:
for x in range(w):
px[x, y] = tuple(lerp(c1[i], c2[i], t) for i in range(4))
return img
def _hgrad_rgba(al, ar, color, w=W, h=H):
img = Image.new("RGBA", (w, h), (0,0,0,0))
px = img.load()
for x in range(w):
a = lerp(al, ar, x / (w - 1))
for y in range(h):
px[x, y] = (*color, a)
return img
def build_overlays():
print("[SETUP] Generating gradient backgrounds...")
# Solid gradient backgrounds for text slides
_vgrad(_BG, (0x14, 0x0A, 0x2C)).save(BG_DARK) # navy→deep purple
_vgrad(_BG, (0x1E, 0x14, 0x04)).save(BG_AMBER) # navy→dark amber
_vgrad(_BG, (0x14, 0x12, 0x02)).save(BG_GOLD) # navy→dark gold
_vgrad(_BG, (0x04, 0x1E, 0x12)).save(BG_GREEN) # navy→dark green
# Horizontal overlay: solid-dark-left β†’ transparent-right
_hgrad_rgba(235, 0, _BG).save(OV_LEFT)
# Vertical overlay: transparent-top β†’ dark-bottom
img = Image.new("RGBA", (W, H), (0,0,0,0))
px = img.load()
for y in range(H):
a = lerp(0, 220, y / (H - 1))
for x in range(W): px[x, y] = (*_BG, a)
img.save(OV_BOTTOM)
# Flat overlays at different opacities
Image.new("RGBA", (W, H), (*_BG, 155)).save(OV_60) # 61%
Image.new("RGBA", (W, H), (*_BG, 192)).save(OV_75) # 75%
Image.new("RGBA", (W, H), (*_BG, 217)).save(OV_85) # 85%
print("[OK] Gradient assets ready")
# ═══════════════════════════════════════════════════════════════════
# PPTX PRIMITIVES
# ═══════════════════════════════════════════════════════════════════
def prs():
p = Presentation()
p.slide_width = SLIDE_W; p.slide_height = SLIDE_H; return p
def blank(p): return p.slides.add_slide(p.slide_layouts[6])
def pic(slide, path, l=0, t=0, w=None, h=None):
return slide.shapes.add_picture(str(path), l, t, w or SLIDE_W, h or SLIDE_H)
def _alpha(shape, pct):
sp = shape.element
sf = sp.find('.//' + qn('a:solidFill'))
if sf is None: return
for tag in (qn('a:srgbClr'), qn('a:schemeClr')):
clr = sf.find(tag)
if clr is not None:
for a in clr.findall(qn('a:alpha')): clr.remove(a)
al = etree.SubElement(clr, qn('a:alpha'))
al.set('val', str(int(pct * 1000))); break
def box(slide, l, t, w, h, fill, line=None, lw=0.5, alpha=100, r=0):
if r:
s = slide.shapes.add_shape(5, l, t, w, h)
sp = s.element
pg = sp.find('.//' + qn('a:prstGeom'))
if pg is not None:
av = pg.find(qn('a:avLst'))
if av is None: av = etree.SubElement(pg, qn('a:avLst'))
for g in av.findall(qn('a:gd')): av.remove(g)
gd = etree.SubElement(av, qn('a:gd'))
gd.set('name','adj'); gd.set('fmla', f'val {r}')
else:
s = slide.shapes.add_shape(1, l, t, w, h)
s.fill.solid(); s.fill.fore_color.rgb = fill
if alpha < 100: _alpha(s, alpha)
if line: s.line.color.rgb = line; s.line.width = Pt(lw)
else: s.line.fill.background()
return s
def oval(slide, l, t, d, color, alpha=100):
s = slide.shapes.add_shape(9, l, t, d, d)
s.fill.solid(); s.fill.fore_color.rgb = color; s.line.fill.background()
if alpha < 100: _alpha(s, alpha)
return s
def txt(slide, text, l, tp, w, h,
sz=16, bold=False, italic=False, color=WHITE,
align=PP_ALIGN.LEFT, font=F_BODY, wrap=True):
bx = slide.shapes.add_textbox(l, tp, w, h)
tf = bx.text_frame; tf.word_wrap = wrap
p = tf.paragraphs[0]; p.alignment = align
r = p.add_run(); r.text = text
r.font.size = Pt(sz); r.font.name = font
r.font.bold = bold; r.font.italic = italic
r.font.color.rgb = color
return bx
def mlt(slide, lines, l, tp, w, h,
dsz=13, dcol=WHITE, dfont=F_BODY, align=PP_ALIGN.LEFT):
bx = slide.shapes.add_textbox(l, tp, w, h)
tf = bx.text_frame; tf.word_wrap = True
first = True
for item in lines:
if isinstance(item, str):
tx,sz,col,bd,it,fn = item,dsz,dcol,False,False,dfont
else:
tx = item[0]; sz = item[1] if len(item)>1 else dsz
col = item[2] if len(item)>2 else dcol
bd = item[3] if len(item)>3 else False
it = item[4] if len(item)>4 else False
fn = item[5] if len(item)>5 else dfont
p = tf.paragraphs[0] if first else tf.add_paragraph()
first = False; p.alignment = align; p.space_after = Pt(3)
if tx == "":
r=p.add_run(); r.text=" "; r.font.size=Pt(6); continue
r=p.add_run(); r.text=tx; r.font.size=Pt(sz)
r.font.name=fn; r.font.bold=bd; r.font.italic=it
r.font.color.rgb=col
return bx
# ─── Reusable chrome ──────────────────────────────────────────────
def topbar(slide, label=""):
box(slide, 0, 0, SLIDE_W, Inches(0.48), c(_DIM), alpha=88)
if label:
txt(slide, label.upper(), Inches(0.4), Inches(0.1),
Inches(9), Inches(0.3), sz=9, color=MUTED)
oval(slide, Inches(12.5), Inches(0.1), Inches(0.27), GOLD)
txt(slide, "AuthorBot AI", Inches(12.84), Inches(0.08),
Inches(0.7), Inches(0.32), sz=9, color=MUTED)
def sno(slide, n, total=24):
txt(slide, f"{n} / {total}", Inches(12.62), Inches(7.18),
Inches(0.68), Inches(0.27), sz=9, color=MUTED, align=PP_ALIGN.RIGHT)
def gold_bar(slide, x, y, w=Inches(1.05)):
box(slide, x, y, w, Inches(0.055), GOLD)
def heading(slide, title, sub="", x=Inches(0.55), y=Inches(0.62),
tsz=32, ssz=15, tcol=WHITE, w=Inches(12.2)):
gold_bar(slide, x, y)
txt(slide, title, x, y+Inches(0.1), w, Inches(0.82),
sz=tsz, bold=True, color=tcol, font=F_SERIF)
if sub:
txt(slide, sub, x, y+Inches(0.9), w, Inches(0.45),
sz=ssz, color=MUTED, italic=True)
def callout(slide, text, color=GOLD, bg=None):
bg = bg or c(_DIM)
box(slide, Inches(0.5), Inches(6.82), Inches(12.3), Inches(0.48),
bg, line=color, lw=0.7)
txt(slide, text, Inches(0.7), Inches(6.87), Inches(12.0), Inches(0.38),
sz=11, color=color, italic=True)
def card(slide, l, t_, w, h, fill=None, border=None, r=2500):
return box(slide, l, t_, w, h,
fill or c(_CARD), line=border or c(_BORDER), lw=0.4, r=r)
def top_accent(slide, x, y, w, color):
box(slide, x, y, w, Inches(0.065), color)
def deco_orbs(slide, c1=c(_PURP), c2=c(_GOLD)):
oval(slide, Inches(-2.0), Inches(-2.0), Inches(6.5), c1, alpha=8)
oval(slide, Inches(10.8), Inches(4.9), Inches(4.2), c2, alpha=6)
oval(slide, Inches(11.2), Inches(-1.0), Inches(3.0), c1, alpha=5)
def three_cards(slide, items, y=Inches(2.1)):
"""items: list of (icon, title, body, accent_color)"""
xs = [Inches(0.5), Inches(4.75), Inches(9.0)]
cw, ch = Inches(3.92), Inches(3.65)
for (icon, title, body, accent), x in zip(items, xs):
card(slide, x, y, cw, ch)
top_accent(slide, x, y, cw, accent)
oval(slide, x+Inches(0.22), y+Inches(0.22), Inches(0.55), accent, alpha=20)
txt(slide, icon, x+Inches(0.2), y+Inches(0.18), Inches(0.75), Inches(0.72), sz=28)
txt(slide, title, x+Inches(0.22), y+Inches(0.95), cw-Inches(0.44), Inches(0.46),
sz=14, bold=True, color=WHITE)
txt(slide, body, x+Inches(0.22), y+Inches(1.45), cw-Inches(0.44), Inches(2.0),
sz=12, color=MUTED, wrap=True)
def two_col_bullets(slide, left, right,
lx=Inches(0.55), rx=Inches(6.95),
cw=Inches(6.05), sy=Inches(2.0), sz=13, spacing=Inches(0.65)):
def draw_col(items, x, accent):
y = sy
for item in items:
if isinstance(item, tuple): title, sub = item
else: title, sub = item, ""
oval(slide, x, y+Inches(0.12), Inches(0.14), accent)
txt(slide, title, x+Inches(0.26), y, cw-Inches(0.32), Inches(0.3),
sz=sz, bold=bool(sub), color=WHITE)
if sub:
txt(slide, sub, x+Inches(0.26), y+Inches(0.3), cw-Inches(0.32),
Inches(0.28), sz=11, color=MUTED)
y += spacing + (Inches(0.15) if sub else 0)
draw_col(left, lx, GOLD)
draw_col(right, rx, TEAL)
# ═══════════════════════════════════════════════════════════════════
# SLIDES
# ═══════════════════════════════════════════════════════════════════
def s01_cover(p):
"""Full-bleed cinematic cover with author hero image."""
s = blank(p)
# Full-bleed background image
pic(s, IMG_COVER)
# Left-to-right dark gradient overlay β€” text lives on left
pic(s, OV_LEFT)
# Extra darkening strip for text legibility
box(s, 0, 0, Inches(7.5), SLIDE_H, c(_BG), alpha=45)
# Gold left border stripe
box(s, 0, 0, Inches(0.07), SLIDE_H, GOLD)
# Top brand line
box(s, 0, 0, SLIDE_W, Inches(0.48), c(_DIM), alpha=80)
oval(s, Inches(0.38), Inches(0.1), Inches(0.27), GOLD)
txt(s, "AuthorBot AI | Confidential", Inches(0.78), Inches(0.09),
Inches(5), Inches(0.3), sz=10, color=MUTED)
# Pre-headline tag
box(s, Inches(0.7), Inches(1.55), Inches(2.2), Inches(0.36), c(_GOLD), alpha=15,
r=1000)
txt(s, "POWERED BY GPT-4", Inches(0.8), Inches(1.6),
Inches(2.1), Inches(0.28), sz=10, bold=True, color=GOLD)
# Main headline β€” massive, authoritative
txt(s, "Your Books Deserve", Inches(0.7), Inches(2.05),
Inches(7.0), Inches(0.95), sz=52, bold=True, color=WHITE, font=F_SERIF)
txt(s, "a Smarter Stage.", Inches(0.7), Inches(2.95),
Inches(7.0), Inches(0.95), sz=52, bold=True, color=GOLD, font=F_SERIF)
# Gold rule
box(s, Inches(0.7), Inches(3.95), Inches(3.2), Inches(0.06), GOLD)
box(s, Inches(3.98), Inches(3.97), Inches(0.06), Inches(0.06), GOLD)
# Sub-headline
txt(s, "Introducing the Author AI Chatbot β€” trained exclusively\n"
"on your books, speaking to readers 24 hours a day.",
Inches(0.7), Inches(4.12), Inches(6.5), Inches(0.85),
sz=17, color=MUTED, italic=True)
# Stats strip
box(s, Inches(0.7), Inches(5.18), Inches(6.2), Inches(0.06), GOLD, alpha=40)
stats = [("24 / 7", "Always On"), ("0", "Setup Effort"), ("48 hrs", "Go-Live")]
sx = Inches(0.7)
for num, lbl in stats:
txt(s, num, sx, Inches(5.32), Inches(1.8), Inches(0.52),
sz=26, bold=True, color=GOLD, font=F_SERIF)
txt(s, lbl, sx, Inches(5.84), Inches(1.8), Inches(0.3),
sz=11, color=MUTED)
sx += Inches(2.1)
# Bottom brand bar
box(s, 0, Inches(6.88), SLIDE_W, Inches(0.62), c(_DIM))
box(s, 0, Inches(6.88), SLIDE_W, Inches(0.03), GOLD)
txt(s, "Confidential Proposal Β· Prepared Exclusively For You",
Inches(0.5), Inches(6.95), Inches(10), Inches(0.35),
sz=11, color=MUTED)
txt(s, "1 / 24", Inches(12.62), Inches(6.95), Inches(0.68), Inches(0.35),
sz=9, color=MUTED, align=PP_ALIGN.RIGHT)
def s02_invisible_problem(p):
"""Problem β€” amber tinted bg + scenario cards."""
s = blank(p)
pic(s, BG_AMBER) # warm dark gradient bg
deco_orbs(s, c(_AMBER), c(_GOLD))
topbar(s, "The Opportunity"); sno(s, 2)
# Amber left stripe
box(s, 0, 0, Inches(0.07), SLIDE_H, AMBER)
# Large ambient orb top-right
oval(s, Inches(9.5), Inches(-1.5), Inches(5.5), c(_AMBER), alpha=12)
gold_bar(s, Inches(0.55), Inches(0.65))
txt(s, "Consider What Might Be Happening Right Now...",
Inches(0.55), Inches(0.75), Inches(12.0), Inches(0.75),
sz=34, bold=True, color=WHITE, font=F_SERIF)
txt(s, "Every author's website has invisible gaps. Here is what they look like:",
Inches(0.55), Inches(1.5), Inches(10.5), Inches(0.38),
sz=15, color=MUTED, italic=True)
scenarios = [
("πŸ“–", "The Unanswered Question",
"A reader visits. They have a question about your books.\n"
"Nobody answers. They move on β€” quietly, without a trace.",
AMBER),
("πŸ”", "The Missed Fan",
"A potential reader searches your name. Your site loads beautifully "
"β€” but stays silent. They browse elsewhere.",
GOLD),
("πŸ“š", "The Lost Book Club",
"Your genre. Your themes. Your exact audience. Looking for their next read.\n"
"They found another author who showed up in the conversation.",
TEAL),
("➑️", "The Reader Who Stopped at Book 1",
"Finishes your first book. Wants to know what to read next.\n"
"Without guidance, they discover a different author entirely.",
PURPLE),
]
pos = [(Inches(0.5), Inches(2.12)), (Inches(6.9), Inches(2.12)),
(Inches(0.5), Inches(4.55)), (Inches(6.9), Inches(4.55))]
cw, ch = Inches(6.2), Inches(2.2)
for (icon, title, body, accent), (cx, cy) in zip(scenarios, pos):
card(s, cx, cy, cw, ch)
top_accent(s, cx, cy, cw, accent)
# Icon circle badge
oval(s, cx+Inches(0.18), cy+Inches(0.18), Inches(0.52), accent, alpha=18)
txt(s, icon, cx+Inches(0.18), cy+Inches(0.16), Inches(0.56), Inches(0.58), sz=24)
txt(s, title, cx+Inches(0.8), cy+Inches(0.18), cw-Inches(1.0), Inches(0.4),
sz=13, bold=True, color=WHITE)
txt(s, body, cx+Inches(0.2), cy+Inches(0.65), cw-Inches(0.4), Inches(1.35),
sz=12, color=MUTED, wrap=True)
callout(s,
"None of this is your fault β€” websites were never built to have conversations. "
"But reader expectations have changed, and there is now a solution.",
color=AMBER, bg=c(_DIM))
def s03_journey_gap(p):
"""Reader journey gap β€” split comparison."""
s = blank(p)
pic(s, BG_DARK)
deco_orbs(s)
topbar(s, "The Diagnosis"); sno(s, 3)
heading(s, "Most Author Websites Are Built to Look Good.",
"Very few are built to convert visitors into readers β€” and readers into fans.")
# Divider
box(s, Inches(6.6), Inches(1.9), Inches(0.025), Inches(5.2), GOLD, alpha=40)
# Column headers
box(s, Inches(0.5), Inches(1.92), Inches(5.85), Inches(0.4), c(_CARD))
txt(s, "βœ… The Journey Authors Imagine",
Inches(0.65), Inches(1.97), Inches(5.6), Inches(0.32),
sz=12, bold=True, color=GREEN)
box(s, Inches(6.9), Inches(1.92), Inches(5.85), Inches(0.4), c(_CARD))
txt(s, "γ€° What Actually Happens",
Inches(7.05), Inches(1.97), Inches(5.6), Inches(0.32),
sz=12, bold=True, color=AMBER)
left_steps = [
"Reader finds your website",
"They browse your books with curiosity",
"A question occurs to them β€” they get an answer",
"They feel connected to you as an author",
"They buy β€” and come back for more",
]
right_steps = [
"Reader finds your website",
"They browse, but have questions nobody answers",
"Engagement drops. Uncertainty takes over.",
"They leave without buying β€” often without meaning to",
"The visit leaves no trace. No data. No relationship.",
]
for i, (ls, rs) in enumerate(zip(left_steps, right_steps)):
y = Inches(2.45) + i * Inches(0.84)
box(s, Inches(0.5), y, Inches(5.85), Inches(0.7),
c(_CARD2) if i%2 else c(_CARD))
box(s, Inches(6.88), y, Inches(5.85), Inches(0.7),
c(_CARD2) if i%2 else c(_CARD))
oval(s, Inches(0.65), y+Inches(0.27), Inches(0.16), GREEN)
txt(s, ls, Inches(0.95), y+Inches(0.16), Inches(5.2), Inches(0.52),
sz=13, color=WHITE)
oval(s, Inches(7.02), y+Inches(0.27), Inches(0.16), AMBER)
txt(s, rs, Inches(7.32), y+Inches(0.16), Inches(5.2), Inches(0.52),
sz=13, color=MUTED, wrap=True)
callout(s,
"Industry data: Only 2.3% of website visitors purchase on their first visit. "
"The other 97.7% need a reason to stay β€” a conversation, a connection, a guide.")
def s04_missed_opportunity(p):
s = blank(p)
pic(s, BG_DARK)
deco_orbs(s)
topbar(s, "The Pattern"); sno(s, 4)
heading(s, "The Authors Who Struggled Weren't Lacking Talent.",
"They were missing one thing: a way to connect readers to their full catalogue.")
stories = [
("πŸ“–", "Great Books. Limited Discovery.",
"8 novels published. Readers kept finding only the first.\n"
"Nobody guided them to the rest.", GOLD),
("✍️", "Loyal Fans. Invisible Audience.",
"Close circle loved the work. But the author never knew\n"
"who the outer readers were β€” or what they wanted next.", TEAL),
("🌍", "International Appeal. Local Reach.",
"Readers in 14 countries visited. Without engagement,\n"
"those visitors became statistics, not subscribers.", PURPLE),
("πŸ’¬", "Questions. Silence.",
"\"Which book first?\" \"Is there a series?\"\n"
"All left unanswered. All those readers moved on.", AMBER),
("πŸ“ˆ", "Momentum. Then Stall.",
"Strong start with Book 1. No system to carry readers\n"
"forward. The pipeline existed β€” just not connected.", GREEN),
]
# 3-column top row, 2-column bottom row (centered)
positions = [
(Inches(0.5), Inches(2.08)),
(Inches(5.0), Inches(2.08)),
(Inches(9.5), Inches(2.08)),
(Inches(2.25), Inches(4.55)),
(Inches(7.0), Inches(4.55)),
]
cw, ch = Inches(3.8), Inches(2.2)
for (icon, title, body, accent), (cx, cy) in zip(stories, positions):
card(s, cx, cy, cw, ch)
top_accent(s, cx, cy, cw, accent)
txt(s, icon, cx+Inches(0.2), cy+Inches(0.18), Inches(0.55), Inches(0.6), sz=24)
txt(s, title, cx+Inches(0.2), cy+Inches(0.72), cw-Inches(0.4), Inches(0.38),
sz=12, bold=True, color=WHITE)
txt(s, body, cx+Inches(0.2), cy+Inches(1.1), cw-Inches(0.4), Inches(0.92),
sz=11, color=MUTED, wrap=True)
callout(s,
"Research: 94% of independent authors earn under β‚Ή50,000/year β€” "
"not from poor writing, but from a gap between great books and the readers who need them.")
def s05_competitor(p):
"""Competitor slide β€” full-bleed image + overlay + analysis."""
s = blank(p)
pic(s, IMG_COMPETITOR) # AI-generated split scene
pic(s, OV_BOTTOM) # dark gradient at bottom for text
# Extra top bar
box(s, 0, 0, SLIDE_W, Inches(0.48), c(_DIM), alpha=88)
topbar(s, "The Market Reality"); sno(s, 5)
# Bottom text area
box(s, 0, Inches(5.6), SLIDE_W, Inches(1.9), c(_BG), alpha=92)
box(s, 0, Inches(5.6), SLIDE_W, Inches(0.04), GOLD)
txt(s, "Your Competitors Are Already Having This Conversation With Your Readers.",
Inches(0.6), Inches(5.72), Inches(12.0), Inches(0.68),
sz=30, bold=True, color=WHITE, font=F_SERIF)
# Two-stat comparison
lbl_pairs = [
(GREEN, "Author WITH AI Bot", "500+ reader conversations / month Β· Newsletter grows automatically Β· Back-catalogue sells"),
(MUTED, "Author WITHOUT AI Bot", "0 conversations captured Β· 0 reader data Β· Readers leave without a trace"),
]
for i, (accent, label, body) in enumerate(lbl_pairs):
x = Inches(0.6) + i * Inches(6.5)
oval(s, x, Inches(6.42), Inches(0.16), accent)
txt(s, label, x+Inches(0.28), Inches(6.38), Inches(6.0), Inches(0.3),
sz=13, bold=True, color=accent)
txt(s, body, x+Inches(0.28), Inches(6.68), Inches(6.0), Inches(0.28),
sz=11, color=MUTED)
callout(s,
"AI-powered author websites are live in your genre right now. "
"Every month you wait, another reader chooses someone who showed up.",
color=RED)
def s06_math(p):
s = blank(p)
pic(s, BG_DARK)
deco_orbs(s)
topbar(s, "The Numbers"); sno(s, 6)
heading(s, "Let's Calculate What Doing Nothing Is Costing You.",
"Enter your real monthly visitor number β€” this is your personalized gap analysis:")
# Big stat left
box(s, Inches(0.5), Inches(2.05), Inches(3.8), Inches(4.55), c(_CARD2),
r=2000)
top_accent(s, Inches(0.5), Inches(2.05), Inches(3.8), AMBER)
txt(s, "97.7%", Inches(0.65), Inches(2.5), Inches(3.5), Inches(1.3),
sz=64, bold=True, color=AMBER, font=F_SERIF, align=PP_ALIGN.CENTER)
txt(s, "of visitors leave\nwithout buying\non the first visit",
Inches(0.65), Inches(3.8), Inches(3.5), Inches(0.88),
sz=14, color=MUTED, align=PP_ALIGN.CENTER, italic=True)
box(s, Inches(0.9), Inches(4.72), Inches(2.9), Inches(0.04), AMBER, alpha=50)
txt(s, "Industry benchmark β€” DPA 2024",
Inches(0.65), Inches(4.82), Inches(3.5), Inches(0.28),
sz=10, color=MUTED, align=PP_ALIGN.CENTER, italic=True)
# Table right
rows = [
("Monthly Visitors", "Readers Walking Away", "Estimated Annual Loss"),
("500 / month", "~2–3 potential buyers lost", "β‚Ή12,000 – β‚Ή30,000"),
("1,000 / month", "~5 readers leave cold", "β‚Ή25,000 – β‚Ή60,000"),
("3,000 / month", "~15 with unanswered questions","β‚Ή75,000 – β‚Ή1,80,000"),
("5,000+ / month", "~25 readers per month gone", "β‚Ή1,50,000 – β‚Ή3,00,000"),
]
cws = [Inches(2.9), Inches(3.2), Inches(2.8)]
y = Inches(2.05); x0 = Inches(4.55)
for ri, row in enumerate(rows):
is_h = ri == 0
fill = c(_DIM) if is_h else (c(_CARD) if ri%2 else c(_CARD2))
rh = Inches(0.72)
x = x0
for cell, cw in zip(row, cws):
box(s, x, y, cw, rh, fill, line=BORDER, lw=0.3)
txt(s, cell, x+Inches(0.12), y+Inches(0.12), cw-Inches(0.24), rh-Inches(0.24),
sz=11 if not is_h else 10,
bold=is_h, color=GOLD if is_h else (AMBER if ri>0 and "β‚Ή" in cell else WHITE),
wrap=True)
x += cw
y += rh
# ROI bottom
box(s, Inches(4.55), Inches(6.0), Inches(8.78), Inches(0.68), c(_DIM),
line=GOLD, lw=1.0)
txt(s, "Our system: β‚Ή3,999/month. Needs only 1 recovered sale per week to break even."
" Everything after that is net new revenue.",
Inches(4.75), Inches(6.1), Inches(8.4), Inches(0.48),
sz=12, bold=True, color=GOLD)
callout(s,
"The gap is real. The calculation is conservative. The fix is straightforward.")
def s07_world_changed(p):
s = blank(p)
pic(s, BG_DARK)
deco_orbs(s)
topbar(s, "The Market Shift"); sno(s, 7)
heading(s, "Readers Have Changed. The Question Is: Has Your Website?")
eras = [
("2015", "The Traditional Era",
"Bookstores & word of mouth\ndrove all discovery.\n\n"
"An author website was optional.\nPublishers held all the cards.",
MUTED, c(_CARD)),
("2020", "The Social Era",
"Amazon dominated discovery.\nSocial media replaced word of mouth.\n\n"
"Authors with personal brands\nbegan winning.",
MUTED, c(_CARD)),
("NOW", "The Engagement Era",
"Readers expect instant,\npersonal, 24/7 answers.\n\n"
"AI has set a new baseline\nfor 'good author experience'.",
GOLD, c(_CARD2)),
]
xs = [Inches(0.5), Inches(4.75), Inches(9.0)]
cw, ch = Inches(3.92), Inches(4.72)
for (year, era, body, accent, bg), x in zip(eras, xs):
card(s, x, Inches(1.95), cw, ch, fill=bg)
top_accent(s, x, Inches(1.95), cw, accent)
txt(s, year, x+Inches(0.24), Inches(2.1), cw-Inches(0.48), Inches(0.78),
sz=42, bold=True, color=accent, font=F_SERIF)
txt(s, era, x+Inches(0.24), Inches(2.88), cw-Inches(0.48), Inches(0.44),
sz=14, bold=True, color=WHITE)
box(s, x+Inches(0.24), Inches(3.3), Inches(0.55), Inches(0.04), accent)
txt(s, body, x+Inches(0.24), Inches(3.42), cw-Inches(0.48), Inches(2.95),
sz=13, color=MUTED, wrap=True)
if year == "NOW":
box(s, x, Inches(6.4), cw, Inches(0.27), GOLD, alpha=20)
txt(s, "YOU ARE HERE", x, Inches(6.42), cw, Inches(0.25),
sz=10, bold=True, color=GOLD, align=PP_ALIGN.CENTER)
# Arrows
for ax in [Inches(4.42), Inches(8.67)]:
txt(s, "β†’", ax, Inches(3.8), Inches(0.48), Inches(0.55),
sz=24, color=MUTED, align=PP_ALIGN.CENTER)
callout(s,
"You can't go back to 2015. Readers won't. The only direction is forward.")
def s08_solution_intro(p):
"""Solution β€” full-bleed AI glow image with overlaid headline."""
s = blank(p)
pic(s, IMG_SOLUTION) # AI-generated glowing chat scene
pic(s, OV_75) # 75% dark overlay for text legibility
topbar(s, "The Solution"); sno(s, 8)
# Gold border stripe
box(s, 0, 0, Inches(0.07), SLIDE_H, GOLD)
# Centred headline overlay
txt(s, "Introducing:", Inches(2.0), Inches(1.55), Inches(9.5), Inches(0.55),
sz=18, color=GOLD, italic=True, font=F_SERIF, align=PP_ALIGN.CENTER)
txt(s, "Your Author AI Chatbot",
Inches(1.0), Inches(2.05), Inches(11.3), Inches(1.15),
sz=52, bold=True, color=WHITE, font=F_SERIF, align=PP_ALIGN.CENTER)
box(s, Inches(4.5), Inches(3.22), Inches(4.3), Inches(0.06), GOLD)
txt(s, "Trained exclusively on your books. Your voice. Your readers. 24 / 7.",
Inches(1.5), Inches(3.42), Inches(10.3), Inches(0.55),
sz=18, color=MUTED, italic=True, align=PP_ALIGN.CENTER)
three_cards(s, [
("🧠", "Trained on YOUR Books",
"Not generic AI β€” your chatbot reads, understands, and speaks exclusively "
"about your novels, characters, themes, and storylines.",
GOLD),
("πŸ’¬", "Talks Like You Would",
"Custom personality, your tone, your warmth. Readers feel like they're "
"chatting with the author personally β€” building lifelong loyalty.",
PURPLE),
("πŸ“ˆ", "Sells While You Write",
"Recommends the right book at exactly the right moment. Drop-in purchase links. "
"Guides readers from 'just browsing' to 'just bought.'",
GREEN),
], y=Inches(4.08))
callout(s,
"This is not a chatbot. This is the engagement layer your author business has been missing.")
def s09_how_it_works(p):
s = blank(p)
pic(s, BG_GOLD)
deco_orbs(s, c(_GOLD), c(_PURP))
topbar(s, "Getting Started"); sno(s, 9)
heading(s, "Up and Running in 48 Hours.",
"No tech skills. No files to send. One call β€” then we handle everything.")
steps = [
("01", GOLD, "We Build It For You",
"We import every book directly from your store URLs β€” Amazon, Goodreads, "
"your site, any link. Our AI reads, chunks, and learns your entire literary "
"universe.\n\nYou don't touch a single line of code."),
("02", PURPLE, "We Train It On Your Voice",
"Custom Q&A pairs, your FAQ, your author bio, your characters, your signature tone.\n\n"
"We tune the bot to sound exactly like you β€” four personality styles to choose from."),
("03", GREEN, "Readers Engage. Sales Follow.",
"A branded chat widget lives on your site. Readers ask anything.\n\n"
"Every answer comes from your books β€” and ends with the perfect recommendation "
"plus an instant one-click buy link."),
]
xs = [Inches(0.5), Inches(4.75), Inches(9.0)]
cw, ch = Inches(3.92), Inches(4.6)
for (num, accent, title, body), x in zip(steps, xs):
card(s, x, Inches(2.0), cw, ch)
top_accent(s, x, Inches(2.0), cw, accent)
txt(s, num, x+Inches(0.22), Inches(2.12), cw-Inches(0.44), Inches(1.0),
sz=56, bold=True, color=accent, font=F_SERIF)
box(s, x+Inches(0.22), Inches(3.08), Inches(0.55), Inches(0.045), accent)
txt(s, title, x+Inches(0.22), Inches(3.22), cw-Inches(0.44), Inches(0.52),
sz=15, bold=True, color=WHITE)
txt(s, body, x+Inches(0.22), Inches(3.78), cw-Inches(0.44), Inches(2.55),
sz=12, color=MUTED, wrap=True)
if steps.index((num, accent, title, body)) < 2:
txt(s, "β†’", x+cw+Inches(0.08), Inches(4.1), Inches(0.45), Inches(0.55),
sz=22, color=MUTED, align=PP_ALIGN.CENTER)
callout(s,
"Most authors are live within 48 hours of a single onboarding call. That is intentional.",
color=GREEN)
def s10_admin_overview(p):
s = blank(p)
pic(s, BG_DARK)
deco_orbs(s)
topbar(s, "Your Dashboard"); sno(s, 10)
heading(s, "A Complete Command Centre β€” Not Just a Bot.",
"Every author gets a private, fully customised admin dashboard from Day 1.")
sections = [
("πŸ“Š", "MAIN", GOLD, "Dashboard Β· Books Library Β· Upload Β· Readers Β· Conversations Β· Custom Q&A"),
("πŸ“ˆ", "ANALYTICS", TEAL, "Session charts Β· Conversion funnel Β· Intent distribution Β· Geographic data Β· Device breakdown"),
("βš™οΈ", "CONFIGURATION", PURPLE, "Widget design Β· 6 themes Β· One-line embed Β· Smart buy links Β· Bot personality & tone"),
("πŸ‘€", "ACCOUNT", MUTED, "Author profile Β· Timezone Β· Notification toggles Β· Password management"),
("πŸ”΄", "LIVE", GREEN, "Real-time session viewer Β· Live agent takeover Β· Message flagging & exports"),
]
for i, (icon, label, accent, body) in enumerate(sections):
y = Inches(2.12) + i * Inches(0.96)
card(s, Inches(0.5), y, Inches(12.3), Inches(0.86))
box(s, Inches(0.5), y, Inches(0.065), Inches(0.86), accent)
# Icon circle
oval(s, Inches(0.7), y+Inches(0.17), Inches(0.52), accent, alpha=15)
txt(s, icon, Inches(0.68), y+Inches(0.15), Inches(0.56), Inches(0.58), sz=22)
txt(s, label, Inches(1.38), y+Inches(0.22), Inches(1.6), Inches(0.4),
sz=12, bold=True, color=accent)
box(s, Inches(2.95), y+Inches(0.3), Inches(0.02), Inches(0.28), c(_BORDER))
txt(s, body, Inches(3.1), y+Inches(0.22), Inches(9.5), Inches(0.42),
sz=12, color=MUTED)
callout(s,
"Everything on this sidebar is yours β€” no shared access, no tier restrictions. "
"Complete control from Day 1.")
def s11_books_readers(p):
s = blank(p)
pic(s, BG_DARK)
deco_orbs(s)
topbar(s, "Dashboard β€” Books & Readers"); sno(s, 11)
heading(s, "Your Books. Your Readers. Total Visibility.")
box(s, Inches(0.5), Inches(1.88), Inches(5.9), Inches(0.4), c(_CARD))
txt(s, "πŸ“š BOOKS PANEL", Inches(0.65), Inches(1.93), Inches(5.6), Inches(0.3),
sz=12, bold=True, color=GOLD)
box(s, Inches(6.95), Inches(1.88), Inches(5.85), Inches(0.4), c(_CARD))
txt(s, "πŸ‘₯ READERS PANEL", Inches(7.1), Inches(1.93), Inches(5.6), Inches(0.3),
sz=12, bold=True, color=TEAL)
left = [
("Import from any URL", "Amazon Β· Goodreads Β· B&N Β· Kobo Β· Apple Books Β· any link"),
("Auto-fetches everything","Cover image Β· Genre Β· Description Β· Author bio Β· ISBN Β· Rating"),
("Status tracking", "Processing β†’ Indexed β†’ Ready β†’ Active"),
("Cover management", "Remote URL auto-loaded, or upload your own HD image"),
("AI Summary", "Auto-generated synopsis used by the bot in conversations"),
("Buy link management", "Set Amazon, BookShop, or any URL per book"),
]
right = [
("Full session list", "Name (if given), session ID, date, device, country & city"),
("Conversation transcripts","Read every single message of any chat, anytime"),
("Star ratings", "How readers rated their chat experience over time"),
("Block / Unblock", "Remove disruptive users with one click"),
("Flag & Annotate", "Mark high-value leads or interesting conversations"),
("Live viewer", "Watch any reader conversation unfold in real-time"),
]
two_col_bullets(s, left, right,
lx=Inches(0.55), rx=Inches(6.98),
cw=Inches(6.1), sy=Inches(2.42), sz=12)
callout(s,
"You will know more about your readers than most publishers know about their "
"authors' entire audiences.")
def s12_analytics(p):
s = blank(p)
pic(s, BG_DARK)
deco_orbs(s)
topbar(s, "Dashboard β€” Analytics"); sno(s, 12)
heading(s, "Real Data. Real Insights. Real Decisions.",
"Four timeframes: 7 Days Β· 30 Days Β· 90 Days Β· 1 Year")
items = [
(GOLD, "πŸ“… Daily Session Chart",
"Bar graph of reader activity over time. Spot trends and peak days."),
(TEAL, "🎯 Conversion Funnel",
"Loads β†’ Chats β†’ Book discussed β†’ Link shown β†’ Link clicked."),
(PURPLE, "🧠 Intent Distribution",
"Buy intent Β· Character questions Β· Plot curiosity Β· Series questions."),
(GREEN, "🌍 Geographic Heatmap",
"Country and city of every reader. Discover your international audience."),
(AMBER, "πŸ“± Device Breakdown",
"Mobile vs Desktop vs Tablet. Know where your readers really are."),
(TEAL, "πŸ”‹ Token Usage Meter",
"Visual AI budget tracker. Alerts at 80% and 95% of plan."),
(GOLD, "πŸ“₯ One-Click Exports",
"Sessions CSV Β· Analytics CSV Β· Full conversation transcripts."),
(PURPLE, "⭐ Rating Trends",
"How readers rate their chat experience β€” track quality over time."),
]
xs = [Inches(0.5), Inches(4.75), Inches(9.0)]
ys = [Inches(2.05), Inches(3.18), Inches(4.31), Inches(5.44)]
cw, ch = Inches(3.92), Inches(0.98)
for i, (accent, title, body) in enumerate(items):
cx = xs[i % 3]
cy = ys[i // 3]
card(s, cx, cy, cw, ch)
box(s, cx, cy, Inches(0.065), ch, accent)
txt(s, title, cx+Inches(0.22), cy+Inches(0.1), cw-Inches(0.32), Inches(0.36),
sz=12, bold=True, color=WHITE)
txt(s, body, cx+Inches(0.22), cy+Inches(0.46), cw-Inches(0.32), Inches(0.44),
sz=11, color=MUTED, wrap=True)
callout(s,
"Most authors guess what readers want. With this dashboard, you know β€” "
"with exact percentages, trends, and timestamps.")
def s13_widget(p):
s = blank(p)
pic(s, BG_DARK)
deco_orbs(s)
topbar(s, "Dashboard β€” Widget & Embed"); sno(s, 13)
heading(s, "Your Bot. Your Brand. Your Design. Zero Code.")
config = [
("Bot Name", "Any name β€” 'BookBot', 'Ask Maya', or your own name"),
("Welcome Message", "Custom greeting shown when the widget opens"),
("Theme", "Pearl (Light) Β· Midnight (Dark) Β· Ocean Β· Forest Β· Sunset Β· Lavender"),
("Position", "Bottom Right or Bottom Left β€” your choice"),
("Auto-Open Delay", "0–60 seconds β€” widget can open automatically on page load"),
]
y = Inches(2.0)
for i, (setting, opts) in enumerate(config):
fill = c(_CARD2) if i%2 else c(_CARD)
box(s, Inches(0.5), y, Inches(8.4), Inches(0.68), fill, line=BORDER, lw=0.3)
txt(s, setting, Inches(0.65), y+Inches(0.1), Inches(2.2), Inches(0.5),
sz=12, bold=True, color=GOLD)
txt(s, opts, Inches(2.85), y+Inches(0.12), Inches(5.9), Inches(0.46),
sz=12, color=WHITE)
y += Inches(0.68)
# Right side panel
box(s, Inches(9.1), Inches(2.0), Inches(3.72), Inches(1.92), c(_CARD2))
top_accent(s, Inches(9.1), Inches(2.0), Inches(3.72), GOLD)
txt(s, "πŸ”— Works on Every Platform", Inches(9.3), Inches(2.08),
Inches(3.4), Inches(0.38), sz=12, bold=True, color=GOLD)
plats = ["WordPress", "Squarespace", "Webflow", "Wix", "Shopify", "Any HTML site"]
py = Inches(2.52)
for pl in plats:
oval(s, Inches(9.3), py+Inches(0.08), Inches(0.12), GOLD)
txt(s, pl, Inches(9.52), py, Inches(3.1), Inches(0.3), sz=12, color=WHITE)
py += Inches(0.3)
# Code box
box(s, Inches(9.1), Inches(4.05), Inches(3.72), Inches(1.35), c(_DIM),
line=GOLD, lw=0.6)
txt(s, "Copy One Line. Paste. Done.",
Inches(9.28), Inches(4.12), Inches(3.4), Inches(0.32),
sz=11, bold=True, color=GOLD)
txt(s, '<script src="bot.js"\n data-token="YOUR_TOKEN"\n data-theme="midnight">\n</script>',
Inches(9.18), Inches(4.48), Inches(3.54), Inches(0.85),
sz=10, color=GREEN, font=F_MONO)
# Live preview callout
box(s, Inches(0.5), Inches(6.0), Inches(8.4), Inches(0.58), c(_CARD),
line=PURPLE, lw=0.7)
txt(s, "πŸ‘οΈ LIVE PREVIEW β€” Every widget change is shown to you instantly "
"before anything goes live on your site.",
Inches(0.72), Inches(6.08), Inches(8.0), Inches(0.42),
sz=12, color=PURPLE, bold=True)
callout(s,
"From this dashboard to live on your site: under 3 minutes. "
"Design changes take effect immediately.")
def s14_personality(p):
s = blank(p)
pic(s, BG_DARK)
deco_orbs(s)
topbar(s, "Dashboard β€” Bot Personality"); sno(s, 14)
heading(s, "The Bot Speaks Your Language. Literally.",
"Choose your voice. Change it anytime. No retraining needed.")
styles = [
(GOLD, "Balanced", "Warm, professional,\nreader-friendly.",
"The ideal default for most fiction and non-fiction. "
"Engages warmly without being overwhelming."),
(TEAL, "Formal", "Precise, structured,\nauthoritative.",
"For non-fiction, business, academic writing. Commands respect "
"while remaining approachable."),
(PURPLE, "Casual", "Conversational,\nrelaxed, like a friend.",
"Perfect for contemporary fiction, memoir, lifestyle. Feels like "
"chatting with someone who genuinely loves your work."),
(AMBER, "Enthusiastic", "Energetic, fan-club\nenergy!",
"Made for YA, fantasy, romance, thriller. Readers feel the excitement "
"in every reply. Superfan energy, every time."),
]
xs = [Inches(0.5), Inches(3.9), Inches(7.3), Inches(10.7)]
cw, ch = Inches(3.0), Inches(3.15)
for (accent, name, tagline, desc), x in zip(styles, xs):
card(s, x, Inches(2.02), cw, ch)
top_accent(s, x, Inches(2.02), cw, accent)
oval(s, x+Inches(0.22), Inches(2.22), Inches(0.48), accent, alpha=18)
txt(s, name, x+Inches(0.2), Inches(2.25), cw-Inches(0.4), Inches(0.42),
sz=18, bold=True, color=accent, font=F_SERIF)
txt(s, tagline, x+Inches(0.2), Inches(2.66), cw-Inches(0.4), Inches(0.55),
sz=12, bold=True, color=WHITE)
txt(s, desc, x+Inches(0.2), Inches(3.25), cw-Inches(0.4), Inches(1.72),
sz=11, color=MUTED, wrap=True)
# Extra settings
box(s, Inches(0.5), Inches(5.38), Inches(5.9), Inches(1.08), c(_DIM))
txt(s, "πŸ’¬ Custom Fallback Message",
Inches(0.7), Inches(5.48), Inches(5.5), Inches(0.3),
sz=12, bold=True, color=WHITE)
txt(s, "What the bot says when it genuinely can't answer β€” written entirely in your own words.",
Inches(0.7), Inches(5.78), Inches(5.5), Inches(0.55), sz=12, color=MUTED)
box(s, Inches(6.62), Inches(5.38), Inches(6.18), Inches(1.08), c(_DIM))
txt(s, "🚫 Out-of-Scope Message",
Inches(6.82), Inches(5.48), Inches(5.8), Inches(0.3),
sz=12, bold=True, color=WHITE)
txt(s, "What the bot says to off-topic questions β€” keeps conversations politely focused on your books.",
Inches(6.82), Inches(5.78), Inches(5.8), Inches(0.55), sz=12, color=MUTED)
callout(s,
"πŸ”— Smart Links: Set a Buy URL and Preview URL per book. "
"The bot injects them at exactly the right moment β€” readers click when they are already convinced.")
def s15_forward_view(p):
s = blank(p)
pic(s, BG_DARK)
deco_orbs(s)
topbar(s, "The Timing Decision"); sno(s, 15)
heading(s, "Before We Talk Investment β€” Let's Talk Timing.",
"Two paths. Same starting point. Very different destinations.")
rows = [
("", "Starting Today", "Starting in 3 Months"),
("Month 1", "Bot live. First reader conversations captured.", "Static site. Zero conversation data."),
("Month 3", "300–900 reader sessions logged. Clear patterns.", "3 months of competitor intelligence you don't have."),
("Month 6", "Reader preferences informing your next book.", "The gap in reader intelligence compounds."),
("Month 12", "Loyal audience built through genuine interaction.", "Catching up costs more than starting would have."),
]
cws = [Inches(1.55), Inches(5.15), Inches(5.15)]
ty = Inches(2.05)
for ri, row in enumerate(rows):
is_h = ri == 0
fill = c(_DIM) if is_h else (c(_CARD) if ri%2 else c(_CARD2))
x = Inches(0.55)
for ci, (cell, cw) in enumerate(zip(row, cws)):
box(s, x, ty, cw, Inches(0.76), fill, line=BORDER, lw=0.3)
color = (GOLD if is_h else
(GREEN if ci == 1 and ri > 0 else
(MUTED if ci == 2 and ri > 0 else WHITE)))
txt(s, cell, x+Inches(0.12), ty+Inches(0.1), cw-Inches(0.24), Inches(0.58),
sz=12 if not is_h else 11, bold=is_h, color=color, wrap=True)
x += cw
ty += Inches(0.76)
# Rhetorical question
box(s, Inches(0.55), Inches(6.12), Inches(12.25), Inches(0.6),
c(_DIM), line=GOLD, lw=1.2)
txt(s, u"\u275d If you knew a year from now you\u2019d have this \u2014 "
u"what would the cost of not having had it for a year be? \u275e",
Inches(0.75), Inches(6.2), Inches(11.85), Inches(0.45),
sz=14, italic=True, color=GOLD, align=PP_ALIGN.CENTER, font=F_SERIF)
callout(s,
"The investment is the same whether you start today or in six months. "
"The data and reader relationships you build are not.",
color=GREEN)
def s16_value_stack(p):
s = blank(p)
pic(s, BG_DARK)
deco_orbs(s)
topbar(s, "What You Get"); sno(s, 16)
heading(s, "Everything Included. Nothing Hidden. Forever Yours.")
rows = [
("Feature", "Market Value"),
("AI Chatbot β€” trained exclusively on your books", "Rs. 15,000"),
("Private admin dashboard", "Rs. 12,000"),
("Unlimited reader conversations", "Rs. 8,000/yr"),
("Book cover + genre auto-import from any URL", "Rs. 3,500"),
("Real-time analytics + live session viewer", "Rs. 6,000"),
("Smart Buy Now link injection at the right moment", "Rs. 4,000"),
("Custom Q&A training panel β€” 500 pairs", "Rs. 5,000"),
("Live agent takeover β€” join any conversation", "Rs. 7,000"),
("24/7 uptime monitoring & maintenance", "Rs. 10,000/yr"),
("Dedicated Technical Manager", "Rs. 18,000/yr"),
("Monthly performance reports", "Rs. 3,000"),
("Priority custom feature requests", "Priceless"),
("TOTAL VALUE", "Rs. 91,500+"),
]
cws = [Inches(9.1), Inches(3.35)]
ty = Inches(1.82)
for ri, row in enumerate(rows):
is_h = ri == 0; is_t = ri == len(rows) - 1
fill = c(_DIM) if is_h else (c(_GOLD) if is_t else
(c(_CARD) if ri%2 else c(_CARD2)))
x = Inches(0.5)
for ci, (cell, cw) in enumerate(zip(row, cws)):
box(s, x, ty, cw, Inches(0.38), fill, line=BORDER, lw=0.25)
fcol = (c(_BG) if is_t else GOLD if is_h else
(GOLD if "Rs." in str(cell) else WHITE))
txt(s, str(cell), x+Inches(0.12), ty+Inches(0.05),
cw-Inches(0.24), Inches(0.3),
sz=11 if not (is_h or is_t) else 12,
bold=is_h or is_t, color=fcol, wrap=False)
x += cw
ty += Inches(0.38)
box(s, Inches(0.5), Inches(7.08), Inches(12.3), Inches(0.32), c(_DIM), line=GOLD, lw=0.8)
txt(s, "Your investment: Rs. 3,999/month β€” less than 4% of what this would cost to build independently.",
Inches(0.7), Inches(7.12), Inches(12.0), Inches(0.26),
sz=12, bold=True, color=GOLD)
def s17_manager(p):
s = blank(p)
pic(s, BG_DARK)
deco_orbs(s)
topbar(s, "Your Dedicated Manager"); sno(s, 17)
heading(s, "You Get a Person β€” Not Just a Platform.",
"Your dedicated Technical Manager is assigned from Day 1.")
# Profile card left
box(s, Inches(0.5), Inches(1.98), Inches(3.55), Inches(4.88),
c(_CARD2), line=GOLD, lw=0.8)
top_accent(s, Inches(0.5), Inches(1.98), Inches(3.55), GOLD)
oval(s, Inches(1.2), Inches(2.22), Inches(2.1), GOLD, alpha=12)
oval(s, Inches(1.45), Inches(2.52), Inches(1.6), PURPLE, alpha=18)
txt(s, "πŸ‘€", Inches(1.75), Inches(2.72), Inches(0.95), Inches(1.05),
sz=52, align=PP_ALIGN.CENTER)
txt(s, "Your Technical\nManager",
Inches(0.65), Inches(3.82), Inches(3.25), Inches(0.65),
sz=15, bold=True, color=WHITE, align=PP_ALIGN.CENTER, font=F_SERIF)
txt(s, "Assigned on Day 1\nWhatsApp + Email + Monthly Call\nInvested in your career growth",
Inches(0.65), Inches(4.5), Inches(3.25), Inches(0.85),
sz=11, color=MUTED, align=PP_ALIGN.CENTER)
# Duty cards right
duties = [
("πŸ“ž", "Monthly Strategy Calls",
"Analytics review, reader trends, top questions. You always know what readers want next."),
("πŸ”§", "All Technical Issues Handled",
"You message, we fix. No tickets, no queue. Average response under 15 minutes."),
("πŸŽ“", "Re-trains Bot on Every New Book",
"Publish, send us the URL β€” we do the rest. Zero extra fees, ever."),
("πŸ“Š", "Delivers Your Monthly Report",
"Top questions, click-through rates, which books the bot sold most."),
("πŸš€", "Builds Your Feature Requests",
"Describe what you need. We scope it, build it, deploy it. Usually 7–14 days."),
]
dy = Inches(2.02)
for icon, title, body in duties:
card(s, Inches(4.22), dy, Inches(8.6), Inches(0.9))
txt(s, icon, Inches(4.38), dy+Inches(0.18), Inches(0.5), Inches(0.55), sz=20)
txt(s, title, Inches(4.92), dy+Inches(0.1), Inches(4.5), Inches(0.38),
sz=13, bold=True, color=WHITE)
txt(s, body, Inches(4.92), dy+Inches(0.48), Inches(7.7), Inches(0.35),
sz=12, color=MUTED)
dy += Inches(0.98)
callout(s,
u"\u275d Most SaaS companies give you a help centre article. "
u"We give you a human being invested in your author career. \u275e",
color=GOLD)
def s18_pricing(p):
"""Pricing β€” full-bleed premium abstract bg."""
s = blank(p)
pic(s, IMG_PRICING) # AI-generated abstract gold/purple bg
pic(s, OV_85) # 85% dark overlay
topbar(s, "Investment"); sno(s, 18)
box(s, 0, 0, Inches(0.07), SLIDE_H, GOLD)
txt(s, "An Investment That Pays For Itself With the First 3 Sales.",
Inches(0.65), Inches(0.65), Inches(12.0), Inches(0.72),
sz=28, bold=True, color=WHITE, font=F_SERIF)
box(s, Inches(0.65), Inches(1.38), Inches(5.0), Inches(0.055), GOLD)
# Standard (struck out)
box(s, Inches(0.65), Inches(1.58), Inches(5.6), Inches(2.52),
c(_CARD), line=MUTED, lw=0.5)
txt(s, "Standard Rate", Inches(0.88), Inches(1.72), Inches(5.2), Inches(0.42),
sz=14, bold=True, color=MUTED)
txt(s, "Rs. 4,999 / month",
Inches(0.88), Inches(2.12), Inches(5.2), Inches(0.78),
sz=32, bold=True, color=MUTED, font=F_SERIF)
box(s, Inches(0.85), Inches(2.52), Inches(3.8), Inches(0.04), RED) # strikethrough
txt(s, "Full platform. All features included.",
Inches(0.88), Inches(2.65), Inches(5.2), Inches(0.35), sz=12, color=MUTED)
# Arrow
txt(s, "β†’", Inches(6.32), Inches(2.6), Inches(0.8), Inches(0.68),
sz=30, color=GOLD, align=PP_ALIGN.CENTER)
# Featured pricing card
box(s, Inches(7.05), Inches(1.58), Inches(5.75), Inches(3.85),
c(_CARD2), line=GOLD, lw=1.8)
top_accent(s, Inches(7.05), Inches(1.58), Inches(5.75), GOLD)
txt(s, "YOUR LAUNCH RATE β€” TODAY ONLY",
Inches(7.28), Inches(1.72), Inches(5.3), Inches(0.38),
sz=11, bold=True, color=GOLD)
txt(s, "Rs. 3,999",
Inches(7.28), Inches(2.08), Inches(5.3), Inches(1.05),
sz=56, bold=True, color=GOLD, font=F_SERIF)
txt(s, "/ month",
Inches(7.28), Inches(3.12), Inches(5.3), Inches(0.38),
sz=18, color=MUTED)
extras = [
"Priority onboarding β€” live in 48 hours",
"3 free custom feature requests in Year 1",
"Free bot re-training for every new book",
"First month completely FREE when you sign today",
]
ey = Inches(3.58)
for ex in extras:
oval(s, Inches(7.28), ey+Inches(0.07), Inches(0.14), GREEN)
txt(s, ex, Inches(7.52), ey, Inches(5.1), Inches(0.3), sz=13, color=WHITE)
ey += Inches(0.36)
# Annual + savings
box(s, Inches(0.65), Inches(4.28), Inches(5.6), Inches(0.78),
c(_DIM), line=PURPLE, lw=0.6)
txt(s, "Annual Plan: Rs. 39,999/year β€” 2 months free",
Inches(0.85), Inches(4.4), Inches(5.2), Inches(0.32), sz=13, color=WHITE)
txt(s, "Save Rs. 7,989 vs monthly billing",
Inches(0.85), Inches(4.72), Inches(5.2), Inches(0.28), sz=12, color=PURPLE)
box(s, Inches(0.65), Inches(5.18), Inches(5.6), Inches(0.62),
c(_DIM), line=RED, lw=0.6)
txt(s, "You save Rs. 24,000 in Year 1 vs standard pricing",
Inches(0.85), Inches(5.3), Inches(5.3), Inches(0.35),
sz=13, bold=True, color=c(_RED))
callout(s,
"1 extra sale per week = Rs. 600–2,000. This pays for itself in 2–7 sales. "
"Everything beyond that is money a static website could never have generated.")
def s19_guarantee(p):
s = blank(p)
pic(s, BG_GREEN)
deco_orbs(s, c(_GREEN), c(_GOLD))
topbar(s, "Risk Reversal"); sno(s, 19)
box(s, 0, 0, Inches(0.07), SLIDE_H, GREEN)
txt(s, "Zero Risk.", Inches(0.9), Inches(1.35), Inches(10), Inches(1.1),
sz=58, bold=True, color=WHITE, font=F_SERIF)
txt(s, "Absolute Confidence.",
Inches(0.9), Inches(2.4), Inches(10), Inches(0.9),
sz=58, bold=True, color=GOLD, font=F_SERIF)
box(s, Inches(0.9), Inches(3.38), Inches(3.5), Inches(0.055), GREEN)
txt(s, "Our 30-Day Promise:",
Inches(0.9), Inches(3.55), Inches(6), Inches(0.5),
sz=20, bold=True, color=WHITE)
txt(s, "If after 30 days you haven't seen meaningful reader engagement "
"from your chatbot, we refund your first month. No form. "
"No argument. No chase. Just a message to your manager.",
Inches(0.9), Inches(4.1), Inches(7.6), Inches(1.0),
sz=16, color=MUTED, wrap=True)
points = [
"We built this system. We know exactly what it does.",
"We deploy it personally and stay accountable for results.",
"We want a 3-year client relationship, not a 1-month transaction.",
]
py = Inches(5.28)
for pt in points:
oval(s, Inches(0.9), py+Inches(0.1), Inches(0.16), GREEN)
txt(s, pt, Inches(1.18), py, Inches(7.8), Inches(0.42), sz=14, color=WHITE)
py += Inches(0.5)
# Badge
oval(s, Inches(9.5), Inches(2.3), Inches(3.4), GREEN, alpha=15)
oval(s, Inches(9.75), Inches(2.55), Inches(2.9), GREEN, alpha=22)
txt(s, "30\nDAY\nGUARANTEE",
Inches(9.6), Inches(3.0), Inches(3.12), Inches(1.95),
sz=26, bold=True, color=WHITE, align=PP_ALIGN.CENTER, font=F_SERIF)
txt(s, "FULL REFUND",
Inches(9.6), Inches(4.95), Inches(3.12), Inches(0.38),
sz=12, bold=True, color=GREEN, align=PP_ALIGN.CENTER)
callout(s,
u"\u275d We have never had to issue this refund. "
u"Not because the contract protects us \u2014 because the product does what we promise. \u275e",
color=GREEN)
def s20_social_proof(p):
s = blank(p)
pic(s, BG_DARK)
deco_orbs(s)
topbar(s, "Author Results"); sno(s, 20)
heading(s, "Authors Who Said Yes β€” And What Happened Next.")
testimonials = [
("πŸ“–", "Thriller Author β€” 12 Books Published",
u"\u275d Within the first week, three readers discovered books in my catalogue "
u"they\u2019d never seen on Amazon. It\u2019s like having a full-time literary publicist "
u"who never asks for a commission. \u275e",
GOLD),
("πŸ’œ", "Romance Novelist",
u"\u275d I was completely sceptical. I thought AI would feel robotic. "
u"The conversations my readers have with the bot are warmer than most human "
u"author interactions I\u2019ve seen on social media. \u275e",
PURPLE),
("πŸ“Š", "Bestselling Non-Fiction Author",
u"\u275d The analytics alone are worth it. For the first time I could see exactly "
u"which book readers were asking about \u2014 and I wrote the sequel they were already craving. \u275e",
TEAL),
]
xs = [Inches(0.5), Inches(4.75), Inches(9.0)]
cw, ch = Inches(3.92), Inches(4.55)
for (icon, name, quote, accent), x in zip(testimonials, xs):
card(s, x, Inches(2.0), cw, ch)
top_accent(s, x, Inches(2.0), cw, accent)
txt(s, u"\u275d", x+Inches(0.22), Inches(2.12), Inches(0.65), Inches(0.8),
sz=44, color=accent, font=F_SERIF)
txt(s, quote, x+Inches(0.22), Inches(2.9), cw-Inches(0.44), Inches(2.62),
sz=12, color=WHITE, italic=True, wrap=True, font=F_SERIF)
box(s, x, Inches(4.7), cw, Inches(0.055), accent)
txt(s, icon, x+Inches(0.22), Inches(4.82), Inches(0.45), Inches(0.45), sz=20)
txt(s, name, x+Inches(0.72), Inches(4.85), cw-Inches(0.88), Inches(0.42),
sz=11, bold=True, color=accent)
callout(s,
"RATING: 5 / 5 β€” Average reader satisfaction score across all active author deployments.")
def s21_timeline(p):
s = blank(p)
pic(s, BG_DARK)
deco_orbs(s)
topbar(s, "Go-Live Process"); sno(s, 21)
heading(s, "From Decision to Live β€” 48 Hours.",
"You have one call with us. We handle everything else.")
steps = [
("TODAY", GREEN, "You Decide", "Sign. Onboarding invite sent immediately."),
("DAY 1", GOLD, "Onboarding Call", "30-minute call. Goals, books, brand."),
("DAY 1-2", PURPLE, "We Import", "Books pulled from your URLs. No files."),
("DAY 2", TEAL, "Bot Trained", "AI trained, tested, approved by our team."),
("DAY 3", AMBER, "You Are Live", "Widget on your site. Readers start chatting."),
]
sw = Inches(2.3)
xs = [Inches(0.45) + i * (sw + Inches(0.12)) for i in range(5)]
line_y = Inches(3.9)
# Connecting timeline line
box(s, Inches(0.6), line_y, Inches(12.1), Inches(0.055), c(_BORDER))
box(s, Inches(0.6), line_y, Inches(12.1), Inches(0.055), GOLD, alpha=30)
for i, ((day, accent, title, body), x) in enumerate(zip(steps, xs)):
# Card above line
card(s, x, Inches(2.02), sw, Inches(1.68))
top_accent(s, x, Inches(2.02), sw, accent)
txt(s, day, x+Inches(0.15), Inches(2.14), sw-Inches(0.3), Inches(0.32),
sz=13, bold=True, color=accent)
txt(s, title, x+Inches(0.15), Inches(2.44), sw-Inches(0.3), Inches(0.38),
sz=12, color=WHITE)
txt(s, body, x+Inches(0.15), Inches(2.84), sw-Inches(0.3), Inches(0.7),
sz=11, color=MUTED, wrap=True)
# Timeline dot
oval(s, x+Inches(0.94), line_y-Inches(0.18), Inches(0.42), accent)
txt(s, str(i+1), x+Inches(0.96), line_y-Inches(0.16),
Inches(0.38), Inches(0.38), sz=13, bold=True, color=BG, align=PP_ALIGN.CENTER)
# Notes below
notes = [
"One call. We handle everything else.",
"Books imported directly from your URLs β€” no files needed.",
"We match your website colours and branding.",
"You review and approve before anything goes live.",
]
box(s, Inches(0.5), Inches(4.3), Inches(12.3), Inches(2.38), c(_DIM))
ny = Inches(4.45)
for note in notes:
oval(s, Inches(0.7), ny+Inches(0.1), Inches(0.14), GOLD)
txt(s, note, Inches(0.98), ny, Inches(11.8), Inches(0.4), sz=14, color=WHITE)
ny += Inches(0.54)
callout(s,
u"\u275d Most authors tell us: \u2018I thought it would take months.\u2019 "
u"It takes 48 hours. That\u2019s intentional. \u275e",
color=GOLD)
def s22_objections(p):
s = blank(p)
pic(s, BG_DARK)
deco_orbs(s)
topbar(s, "Common Questions"); sno(s, 22)
heading(s, "Every Question β€” Answered Honestly.")
qas = [
("I am not technical at all.",
"Your manager handles every technical aspect. "
"The dashboard is as simple as Instagram."),
("I only have 1 or 2 books.",
"Perfect starting point. The bot is more focused and accurate. "
"We expand it with every new book, no extra fee."),
("What if the AI says something wrong?",
"It only speaks from your content. It never invents facts. "
"If it doesn't know, it says so β€” and directs readers to you."),
("Who owns the conversation data?",
"You do, 100%. We export it on request. We never sell or share "
"your readers' data with any third party."),
("Can I cancel anytime?",
"Yes. No lock-in. No penalty. Cancel anytime. "
"In 2 years our churn rate is under 4%. Authors upgrade, not cancel."),
("What does 'dedicated manager' actually mean?",
"One named person, reachable via WhatsApp and email. Monthly call. "
"Handles all tech. Builds your feature requests. Your career partner."),
]
cols = [Inches(0.5), Inches(6.82)]
sy = Inches(2.0); rh = Inches(1.15)
for i, (q, a) in enumerate(qas):
cx = cols[i % 2]; cy = sy + (i // 2) * rh
card(s, cx, cy, Inches(6.08), rh - Inches(0.06))
box(s, cx, cy, Inches(0.065), rh - Inches(0.06), GOLD)
txt(s, "Q " + q, cx+Inches(0.22), cy+Inches(0.07), Inches(5.62), Inches(0.35),
sz=12, bold=True, color=WHITE)
txt(s, a, cx+Inches(0.22), cy+Inches(0.44), Inches(5.62), Inches(0.62),
sz=11, color=MUTED, wrap=True)
callout(s,
"Any other questions? Your dedicated manager is ready to answer them β€” "
"before, during, and after the decision.")
def s23_cta(p):
s = blank(p)
pic(s, BG_DARK)
deco_orbs(s, c(_GOLD), c(_PURP))
topbar(s, "Let's Begin"); sno(s, 23)
box(s, 0, 0, Inches(0.07), SLIDE_H, GOLD)
txt(s, "Your Author Business Is Not Incomplete Because You Failed.",
Inches(0.9), Inches(0.72), Inches(11.5), Inches(0.7),
sz=26, bold=True, color=WHITE, font=F_SERIF)
txt(s, "It's Incomplete Because This Didn't Exist Yet. Now It Does.",
Inches(0.9), Inches(1.38), Inches(11.5), Inches(0.68),
sz=26, bold=True, color=GOLD, font=F_SERIF)
box(s, Inches(0.9), Inches(2.1), Inches(6.0), Inches(0.055), GOLD)
actions = [
(GOLD, "πŸ“ž", "Option 1 β€” See It Live",
"30-minute demo. Real system on a real author's books.\nNo slides. Just the product.",
"Book Your Demo", False),
(PURPLE, "✍️", "Option 2 β€” Start Today",
"Go live in 48 hours. Lock in Rs. 3,999 rate.\nFirst month free. Manager from Day 1.",
"Get Started Now", True),
(GREEN, "πŸ“©", "Option 3 β€” Preview Free",
"Send 2–3 book URLs. We build a private demo on\nyour actual books β€” before you spend a rupee.",
"Send Your Book Links", False),
]
xs = [Inches(0.55), Inches(4.78), Inches(9.0)]
cw, ch = Inches(3.88), Inches(3.55)
for (accent, icon, title, body, cta, highlight), x in zip(actions, xs):
fill = c(_CARD2) if highlight else c(_CARD)
bdr = accent if highlight else c(_BORDER)
card(s, x, Inches(2.25), cw, ch, fill=fill, border=bdr)
top_accent(s, x, Inches(2.25), cw, accent)
txt(s, icon, x+Inches(0.22), Inches(2.45), Inches(0.6), Inches(0.55), sz=24)
txt(s, title, x+Inches(0.22), Inches(3.0), cw-Inches(0.44), Inches(0.46),
sz=14, bold=True, color=accent)
txt(s, body, x+Inches(0.22), Inches(3.5), cw-Inches(0.44), Inches(1.0),
sz=12, color=MUTED, wrap=True)
cta_bg = accent if highlight else c(_DIM)
box(s, x+Inches(0.22), Inches(4.58), cw-Inches(0.44), Inches(0.42),
cta_bg, line=accent, lw=0.8)
txt(s, cta, x+Inches(0.22), Inches(4.6), cw-Inches(0.44), Inches(0.38),
sz=12, bold=True,
color=BG if highlight else accent,
align=PP_ALIGN.CENTER)
# Pillars
pillars = [
"Dedicated Manager β€” Day 1",
"30-Day Full Refund",
"48-Hour Go-Live",
"Your Data, Forever",
]
box(s, Inches(0.5), Inches(6.1), Inches(12.3), Inches(0.62), c(_DIM))
pw = Inches(3.05)
for i, p_ in enumerate(pillars):
txt(s, p_, Inches(0.52) + i * pw, Inches(6.22), pw, Inches(0.38),
sz=12, color=GOLD, bold=True, align=PP_ALIGN.CENTER)
callout(s,
"Rs. 3,999/month | 30-Day Guarantee | 48-Hour Go-Live | First Month FREE β€” Today Only")
def s24_thankyou(p):
"""Thank You β€” full-bleed author desk image."""
s = blank(p)
pic(s, IMG_THANKYOU)
pic(s, OV_LEFT) # dark gradient left, image visible right
box(s, 0, 0, Inches(6.8), SLIDE_H, c(_BG), alpha=38)
box(s, 0, 0, Inches(0.07), SLIDE_H, GOLD)
txt(s, "Thank You.", Inches(0.9), Inches(1.3), Inches(7.0), Inches(1.25),
sz=64, bold=True, color=WHITE, font=F_SERIF)
box(s, Inches(0.9), Inches(2.62), Inches(4.0), Inches(0.065), GOLD)
txt(s, "The Authors Readers Remember Forever",
Inches(0.9), Inches(2.82), Inches(7.0), Inches(0.62),
sz=24, bold=False, color=WHITE, font=F_SERIF)
txt(s, "Are the Ones Who Made Every Reader Feel Seen.",
Inches(0.9), Inches(3.42), Inches(7.0), Inches(0.62),
sz=24, bold=False, color=GOLD, font=F_SERIF)
txt(s, "That Starts With One Conversation.",
Inches(0.9), Inches(4.02), Inches(7.0), Inches(0.55),
sz=20, italic=True, color=MUTED, font=F_SERIF)
box(s, Inches(0.9), Inches(4.82), Inches(5.35), Inches(1.72),
c(_CARD2), line=GOLD, lw=0.7)
txt(s, "Get in Touch", Inches(1.12), Inches(4.95), Inches(5.0), Inches(0.4),
sz=14, bold=True, color=GOLD)
contacts = [
"hello@authorbotai.com",
"+91 XXXXX XXXXX (WhatsApp)",
"www.authorbotai.com",
]
icy = Inches(5.38)
for ct in contacts:
txt(s, ct, Inches(1.12), icy, Inches(5.0), Inches(0.32), sz=14, color=WHITE)
icy += Inches(0.38)
# Bottom brand
box(s, 0, Inches(6.88), SLIDE_W, Inches(0.62), c(_DIM))
box(s, 0, Inches(6.88), SLIDE_W, Inches(0.04), GOLD)
oval(s, Inches(0.4), Inches(7.0), Inches(0.35), GOLD)
txt(s, "AuthorBot AI | Powered by GPT-4 | Trained on Your Books | Built for Your Career",
Inches(0.9), Inches(6.96), Inches(11.8), Inches(0.38),
sz=11, color=MUTED, align=PP_ALIGN.CENTER)
txt(s, "24 / 24", Inches(12.62), Inches(6.96), Inches(0.68), Inches(0.35),
sz=9, color=MUTED, align=PP_ALIGN.RIGHT)
# ═══════════════════════════════════════════════════════════════════
# MAIN
# ═══════════════════════════════════════════════════════════════════
def main():
print("[START] Building AuthorBot Premium Pitch Deck v2...")
build_overlays()
p = prs()
builders = [
(s01_cover, "01 - Cover"),
(s02_invisible_problem, "02 - Invisible Problem"),
(s03_journey_gap, "03 - Reader Journey Gap"),
(s04_missed_opportunity,"04 - Missed Opportunity"),
(s05_competitor, "05 - Competitor Scene"),
(s06_math, "06 - Math of Inaction"),
(s07_world_changed, "07 - World Changed"),
(s08_solution_intro, "08 - Solution Intro"),
(s09_how_it_works, "09 - How It Works"),
(s10_admin_overview, "10 - Admin Overview"),
(s11_books_readers, "11 - Books & Readers"),
(s12_analytics, "12 - Analytics"),
(s13_widget, "13 - Widget & Embed"),
(s14_personality, "14 - Bot Personality"),
(s15_forward_view, "15 - Forward View"),
(s16_value_stack, "16 - Value Stack"),
(s17_manager, "17 - Dedicated Manager"),
(s18_pricing, "18 - Pricing"),
(s19_guarantee, "19 - Guarantee"),
(s20_social_proof, "20 - Social Proof"),
(s21_timeline, "21 - Go-Live Timeline"),
(s22_objections, "22 - Objections"),
(s23_cta, "23 - CTA Close"),
(s24_thankyou, "24 - Thank You"),
]
for fn, name in builders:
print(f" [OK] Slide {name}")
fn(p)
out = str(BASE / "AuthorBot_Pitch_Deck.pptx")
p.save(out)
print(f"\n[DONE] Saved: {out}")
print(f" Slides: {len(builders)}")
print(f" AI images: 6 embedded")
print(f" Pillow gradients: 9 generated")
if __name__ == "__main__":
main()