Spaces:
Running
Running
| #!/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() | |