systeme.io
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, PageBreak,
HRFlowable, Table, TableStyle, KeepTogether
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import Flowable
W, H = A4
# ── COULEURS ──
NOIR = colors.HexColor('#1A1410')
BRUN = colors.HexColor('#3D2B1F')
TERRE = colors.HexColor('#7A5C4A')
SAUGE = colors.HexColor('#6B8F71')
SAUGE_C = colors.HexColor('#A8C5AC')
SAUGE_P = colors.HexColor('#EBF2EC')
CREME = colors.HexColor('#FBF8F3')
OR = colors.HexColor('#C8A96E')
OR_P = colors.HexColor('#F5EDD8')
BLANC = colors.white
GRIS = colors.HexColor('#F0EDE8')
# ── STYLES ──
def make_styles():
s = {}
s['cover_title'] = ParagraphStyle('cover_title',
fontName='Helvetica-Bold', fontSize=28, leading=34,
textColor=BLANC, alignment=TA_CENTER, spaceAfter=16)
s['cover_sub'] = ParagraphStyle('cover_sub',
fontName='Helvetica', fontSize=13, leading=20,
textColor=colors.HexColor('#D4E8D6'), alignment=TA_CENTER, spaceAfter=8)
s['cover_author'] = ParagraphStyle('cover_author',
fontName='Helvetica-Oblique', fontSize=11, leading=16,
textColor=OR, alignment=TA_CENTER)
s['chapter_num'] = ParagraphStyle('chapter_num',
fontName='Helvetica', fontSize=10, leading=14,
textColor=SAUGE, spaceBefore=6, spaceAfter=4,
letterSpacing=2)
s['chapter_title'] = ParagraphStyle('chapter_title',
fontName='Helvetica-Bold', fontSize=20, leading=26,
textColor=NOIR, spaceBefore=4, spaceAfter=12)
s['chapter_title_white'] = ParagraphStyle('chapter_title_white',
fontName='Helvetica-Bold', fontSize=20, leading=26,
textColor=BLANC, spaceBefore=4, spaceAfter=12)
s['section_title'] = ParagraphStyle('section_title',
fontName='Helvetica-Bold', fontSize=14, leading=20,
textColor=BRUN, spaceBefore=18, spaceAfter=8)
s['body'] = ParagraphStyle('body',
fontName='Helvetica', fontSize=10.5, leading=17,
textColor=TERRE, alignment=TA_JUSTIFY,
spaceBefore=0, spaceAfter=10)
s['body_brun'] = ParagraphStyle('body_brun',
fontName='Helvetica', fontSize=10.5, leading=17,
textColor=BRUN, alignment=TA_JUSTIFY,
spaceBefore=0, spaceAfter=10)
s['bold'] = ParagraphStyle('bold',
fontName='Helvetica-Bold', fontSize=10.5, leading=17,
textColor=NOIR, spaceBefore=0, spaceAfter=6)
s['italic'] = ParagraphStyle('italic',
fontName='Helvetica-Oblique', fontSize=10.5, leading=17,
textColor=TERRE, alignment=TA_JUSTIFY,
spaceBefore=0, spaceAfter=10)
s['quote'] = ParagraphStyle('quote',
fontName='Helvetica-Oblique', fontSize=12, leading=20,
textColor=BRUN, alignment=TA_CENTER,
spaceBefore=16, spaceAfter=16)
s['label'] = ParagraphStyle('label',
fontName='Helvetica-Bold', fontSize=8, leading=12,
textColor=SAUGE, spaceBefore=0, spaceAfter=4,
letterSpacing=1.5)
s['exercise_title'] = ParagraphStyle('exercise_title',
fontName='Helvetica-Bold', fontSize=12, leading=18,
textColor=SAUGE, spaceBefore=4, spaceAfter=6)
s['exercise_body'] = ParagraphStyle('exercise_body',
fontName='Helvetica', fontSize=10, leading=16,
textColor=BRUN, alignment=TA_JUSTIFY,
spaceBefore=0, spaceAfter=8)
s['exercise_q'] = ParagraphStyle('exercise_q',
fontName='Helvetica-Bold', fontSize=10, leading=16,
textColor=BRUN, spaceBefore=8, spaceAfter=4)
s['small'] = ParagraphStyle('small',
fontName='Helvetica', fontSize=9, leading=14,
textColor=TERRE, spaceBefore=0, spaceAfter=6)
s['cta'] = ParagraphStyle('cta',
fontName='Helvetica-Bold', fontSize=12, leading=18,
textColor=BLANC, alignment=TA_CENTER,
spaceBefore=8, spaceAfter=8)
s['cta_sub'] = ParagraphStyle('cta_sub',
fontName='Helvetica', fontSize=10, leading=15,
textColor=SAUGE_C, alignment=TA_CENTER,
spaceBefore=0, spaceAfter=0)
s['bullet_item'] = ParagraphStyle('bullet_item',
fontName='Helvetica', fontSize=10.5, leading=17,
textColor=BRUN, leftIndent=20, spaceBefore=2, spaceAfter=2,
firstLineIndent=-14)
s['toc_item'] = ParagraphStyle('toc_item',
fontName='Helvetica', fontSize=11, leading=20,
textColor=BRUN, spaceBefore=4, spaceAfter=4)
return s
# ── HELPERS ──
def hr(color=SAUGE_C, thickness=0.5, space_before=8, space_after=8):
return [Spacer(1, space_before), HRFlowable(width='100%', thickness=thickness, color=color), Spacer(1, space_after)]
def spacer(h=12):
return Spacer(1, h)
def tag(text, s):
return Paragraph(text.upper(), s['label'])
def section_title(text, s):
return Paragraph(text, s['section_title'])
def body(text, s, style='body'):
return Paragraph(text, s[style])
def bullet(text, s):
return Paragraph(f"• {text}", s['bullet_item'])
def box_sauge(content_list):
"""Encadré fond sauge pâle"""
inner = [[c] for c in content_list]
t = Table([[item] for item in content_list], colWidths=[14.5*cm])
t.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), SAUGE_P),
('ROUNDEDCORNERS', [8]),
('TOPPADDING', (0,0), (-1,0), 16),
('BOTTOMPADDING', (0,-1), (-1,-1), 16),
('LEFTPADDING', (0,0), (-1,-1), 18),
('RIGHTPADDING', (0,0), (-1,-1), 18),
('TOPPADDING', (0,1), (-1,-2), 4),
('BOTTOMPADDING', (0,1), (-1,-2), 4),
]))
return t
def box_or(content_list):
t = Table([[item] for item in content_list], colWidths=[14.5*cm])
t.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), OR_P),
('ROUNDEDCORNERS', [8]),
('TOPPADDING', (0,0), (-1,0), 16),
('BOTTOMPADDING', (0,-1), (-1,-1), 16),
('LEFTPADDING', (0,0), (-1,-1), 18),
('RIGHTPADDING', (0,0), (-1,-1), 18),
('TOPPADDING', (0,1), (-1,-2), 4),
('BOTTOMPADDING', (0,1), (-1,-2), 4),
]))
return t
def box_noir(content_list):
t = Table([[item] for item in content_list], colWidths=[14.5*cm])
t.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), NOIR),
('ROUNDEDCORNERS', [8]),
('TOPPADDING', (0,0), (-1,0), 18),
('BOTTOMPADDING', (0,-1), (-1,-1), 18),
('LEFTPADDING', (0,0), (-1,-1), 20),
('RIGHTPADDING', (0,0), (-1,-1), 20),
('TOPPADDING', (0,1), (-1,-2), 4),
('BOTTOMPADDING', (0,1), (-1,-2), 4),
]))
return t
def exercise_box(title, content_list, s):
items = [Paragraph(f"✦ {title}", s['exercise_title'])] + content_list
t = Table([[item] for item in items], colWidths=[14.5*cm])
t.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), BLANC),
('BOX', (0,0), (-1,-1), 1.5, SAUGE),
('ROUNDEDCORNERS', [8]),
('TOPPADDING', (0,0), (-1,0), 14),
('BOTTOMPADDING', (0,-1), (-1,-1), 14),
('LEFTPADDING', (0,0), (-1,-1), 18),
('RIGHTPADDING', (0,0), (-1,-1), 18),
('TOPPADDING', (0,1), (-1,-2), 3),
('BOTTOMPADDING', (0,1), (-1,-2), 3),
]))
return t
def write_line_box(label, s, lines=3):
"""Lignes à remplir"""
line_content = [Paragraph(label, s['exercise_q'])]
for _ in range(lines):
line_content.append(HRFlowable(width='100%', thickness=0.4, color=SAUGE_C, spaceAfter=10, spaceBefore=6))
t = Table([[item] for item in line_content], colWidths=[14.5*cm])
t.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,-1), GRIS),
('ROUNDEDCORNERS', [6]),
('TOPPADDING', (0,0), (-1,0), 10),
('BOTTOMPADDING', (0,-1), (-1,-1), 12),
('LEFTPADDING', (0,0), (-1,-1), 16),
('RIGHTPADDING', (0,0), (-1,-1), 16),
('TOPPADDING', (0,1), (-1,-2), 2),
('BOTTOMPADDING', (0,1), (-1,-2), 2),
]))
return t
# ══════════════════════════════════════════════════
# GÉNÉRATION DU DOCUMENT
# ══════════════════════════════════════════════════
def build_leadmagnet(filepath):
doc = SimpleDocTemplate(
filepath,
pagesize=A4,
rightMargin=2.5*cm,
leftMargin=2.5*cm,
topMargin=2.5*cm,
bottomMargin=2.5*cm,
title="Les 3 vraies raisons pour lesquelles tu n'as pas réussi à arrêter de fumer",
author="Olivia — La Voie Sans Tabac"
)
s = make_styles()
story = []
# ══ PAGE DE COUVERTURE ══
def cover_bg(canvas, doc):
canvas.saveState()
canvas.setFillColor(NOIR)
canvas.rect(0, 0, W, H, fill=1, stroke=0)
# Cercle décoratif
canvas.setFillColor(colors.HexColor('#2A2010'))
canvas.circle(W*0.8, H*0.75, 180, fill=1, stroke=0)
canvas.setFillColor(colors.HexColor('#222015'))
canvas.circle(W*0.15, H*0.2, 120, fill=1, stroke=0)
# Barre sauge bas
canvas.setFillColor(SAUGE)
canvas.rect(0, 0, W, 0.5*cm, fill=1, stroke=0)
canvas.restoreState()
story.append(Spacer(1, 3.5*cm))
story.append(Paragraph("LA VOIE SANS TABAC", ParagraphStyle('tag_cover',
fontName='Helvetica', fontSize=9, textColor=SAUGE_C,
alignment=TA_CENTER, letterSpacing=3, spaceAfter=24)))
story.append(Paragraph(
"Les 3 vraies raisons\npour lesquelles tu n'as\npas réussi à arrêter",
ParagraphStyle('h1_cover', fontName='Helvetica-Bold', fontSize=30,
leading=38, textColor=BLANC, alignment=TA_CENTER, spaceAfter=24)))
story.append(Paragraph(
"— et ce qui change vraiment la donne",
ParagraphStyle('sub_cover', fontName='Helvetica-Oblique', fontSize=14,
leading=20, textColor=OR, alignment=TA_CENTER, spaceAfter=48)))
story.append(Spacer(1, 1.5*cm))
# Ligne déco
story.append(HRFlowable(width='40%', thickness=0.5, color=SAUGE, hAlign='CENTER'))
story.append(Spacer(1, 24))
story.append(Paragraph(
"Un guide offert par Olivia",
ParagraphStyle('author', fontName='Helvetica', fontSize=11,
textColor=SAUGE_C, alignment=TA_CENTER, spaceAfter=6)))
story.append(Paragraph(
"lavoiesanstabac.fr",
ParagraphStyle('site', fontName='Helvetica', fontSize=10,
textColor=colors.HexColor('#5A7A5E'), alignment=TA_CENTER)))
story.append(PageBreak())
# ══ PAGE 2 : MOT D'OLIVIA ══
story.append(spacer(24))
story.append(tag("Un mot avant de commencer", s))
story.append(Paragraph("Ce guide est pour toi.", s['chapter_title']))
story.append(body(
"Pas pour la fumeuse en général. Pour toi, qui as déjà essayé — une fois, deux fois, peut-être plus. "
"Pour toi qui sais exactement ce que c'est que d'écraser sa dernière cigarette avec conviction, "
"et de la rallumer trois semaines plus tard en se disant encore.", s))
story.append(body(
"Ce n'est pas un manque de volonté. Ce n'est pas une faiblesse de caractère. "
"C'est un manque d'information sur ce qui se passe vraiment — dans ton cerveau, dans ton corps, "
"dans ta vie — quand tu fumes et quand tu essaies d'arrêter.", s))
story.append(body(
"J'ai arrêté de fumer moi-même. Et je n'ai compris ce qui s'était passé que bien plus tard, "
"en accompagnant d'autres femmes. Ce que j'ai compris, je te le partage ici — sans jargon, "
"sans jugement, avec un seul objectif : que tu te voies enfin telle que tu es.", s))
story.append(spacer(8))
story.append(box_sauge([
Paragraph("Ce guide ne te demande pas d'arrêter de fumer.", ParagraphStyle('box_bold',
fontName='Helvetica-Bold', fontSize=11, leading=17, textColor=BRUN)),
Paragraph(
"Il te demande de comprendre. C'est la seule chose dont tu aies besoin maintenant. "
"Tout le reste viendra de là.", ParagraphStyle('box_body',
fontName='Helvetica', fontSize=10.5, leading=17, textColor=TERRE))
]))
story.append(spacer(20))
story.append(Paragraph("Avec toute ma bienveillance,", s['italic']))
story.append(Paragraph("Olivia", s['body_brun']))
story.append(Paragraph("La Voie Sans Tabac", s['small']))
story.append(PageBreak())
# ══ SOMMAIRE ══
story.append(spacer(20))
story.append(tag("Dans ce guide", s))
story.append(Paragraph("Ce que tu vas découvrir", s['chapter_title']))
toc = [
("Raison n°1", "Tu as traité le symptôme, pas la source", "p. 4"),
("Raison n°2", "Tu es partie sans te préparer", "p. 6"),
("Raison n°3", "Tu as essayé de résister au lieu d'avancer", "p. 8"),
("Et maintenant ?", "Le premier pas concret", "p. 10"),
]
for num, titre, page in toc:
row = Table([[
Paragraph(f"{num}", ParagraphStyle('toc_num', fontName='Helvetica-Bold',
fontSize=9, textColor=SAUGE, letterSpacing=1)),
Paragraph(titre, ParagraphStyle('toc_t', fontName='Helvetica', fontSize=11,
leading=16, textColor=BRUN)),
Paragraph(page, ParagraphStyle('toc_p', fontName='Helvetica', fontSize=10,
textColor=TERRE, alignment=TA_CENTER)),
]], colWidths=[2.5*cm, 10*cm, 2*cm])
row.setStyle(TableStyle([
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('BOTTOMPADDING', (0,0), (-1,-1), 12),
('TOPPADDING', (0,0), (-1,-1), 12),
('LINEBELOW', (0,0), (-1,-1), 0.4, SAUGE_C),
('LEFTPADDING', (0,0), (0,-1), 0),
]))
story.append(row)
story.append(PageBreak())
# ══ RAISON 1 ══
story.append(spacer(16))
story.append(tag("Raison n°1", s))
story.append(Paragraph("Tu as traité le symptôme,\npas la source.", s['chapter_title']))
story.append(HRFlowable(width='3cm', thickness=2, color=SAUGE, spaceAfter=20))
story.append(section_title("La cigarette ne t'intéresse pas vraiment", s))
story.append(body(
"Voilà une phrase qui peut sembler étrange. Mais réfléchis : est-ce que tu allumes une cigarette "
"parce que tu trouves que fumer est agréable en soi ? Ou est-ce que tu l'allumes parce que tu es stressée, "
"parce que tu t'ennuies, parce que tu viens de raccrocher le téléphone après une conversation difficile, "
"parce que tu as besoin d'une pause dans ta journée, parce que c'est ce que tu fais depuis 20 ans à ce moment-là ?", s))
story.append(body(
"La cigarette n'est pas le problème. Elle est la réponse à un problème. "
"Et si tu enlèves la réponse sans comprendre le problème, le problème reste — "
"et il cherche une autre réponse.", s))
story.append(spacer(8))
story.append(section_title("Ce que la science comportementale dit", s))
story.append(body(
"Toute habitude fonctionne selon une boucle en trois temps, décrite par le chercheur Charles Duhigg : "
"déclencheur → routine → récompense.", s))
story.append(body(
"Le déclencheur, c'est ce qui active l'envie — une émotion, un contexte, une heure de la journée. "
"La routine, c'est le comportement automatique — allumer une cigarette. "
"La récompense, c'est ce que ça apporte — un apaisement, une pause, un sentiment d'appartenance.", s))
story.append(body(
"Les substituts nicotiniques — patches, gommes, e-cigarette — remplacent la molécule. "
"Mais ils ne touchent pas le déclencheur, et ils ne satisfont pas vraiment la récompense. "
"C'est pourquoi 80 % des tentatives avec substituts seuls échouent dans les 6 premiers mois.", s))
story.append(spacer(8))
story.append(box_or([
Paragraph("La vraie question n'est pas :", ParagraphStyle('box_label',
fontName='Helvetica-Bold', fontSize=10, textColor=BRUN, spaceAfter=6)),
Paragraph(""Comment est-ce que j'arrête de fumer ?"", ParagraphStyle('box_q',
fontName='Helvetica-Oblique', fontSize=12, leading=18, textColor=TERRE, spaceAfter=10)),
Paragraph("C'est :", ParagraphStyle('box_label2',
fontName='Helvetica-Bold', fontSize=10, textColor=BRUN, spaceAfter=6)),
Paragraph(""Qu'est-ce que la cigarette fait pour moi — et comment je vais remplir ce rôle autrement ?"", ParagraphStyle('box_ans',
fontName='Helvetica-BoldOblique', fontSize=12, leading=18, textColor=BRUN)),
]))
story.append(spacer(16))
story.append(exercise_box("Exercice 1 — Mes cigarettes du jour", [
Paragraph(
"Pendant les prochaines 24 heures, observe simplement tes cigarettes. "
"Tu n'as pas à en fumer moins. Tu as juste à noter, pour chacune, une chose : "
"pourquoi tu l'allumes à ce moment précis.", s['exercise_body']),
Paragraph("Pour chaque cigarette, demande-toi :", s['exercise_q']),
Paragraph("• Ce que je ressens juste avant (stress, ennui, automatisme, besoin de pause...)", s['exercise_body']),
Paragraph("• Ce que j'attends d'elle (me calmer, m'occuper les mains, prendre l'air...)", s['exercise_body']),
spacer(8),
Paragraph("Note ici ce que tu remarques :", s['exercise_q']),
HRFlowable(width='100%', thickness=0.4, color=SAUGE_C, spaceAfter=10, spaceBefore=6),
HRFlowable(width='100%', thickness=0.4, color=SAUGE_C, spaceAfter=10, spaceBefore=6),
HRFlowable(width='100%', thickness=0.4, color=SAUGE_C, spaceAfter=10, spaceBefore=6),
Paragraph(
"Pas de jugement. Juste de la curiosité. Tu es en train de devenir experte de toi-même.",
s['italic']),
], s))
story.append(PageBreak())
# ══ RAISON 2 ══
story.append(spacer(16))
story.append(tag("Raison n°2", s))
story.append(Paragraph("Tu es partie sans\nte préparer.", s['chapter_title']))
story.append(HRFlowable(width='3cm', thickness=2, color=SAUGE, spaceAfter=20))
story.append(section_title("Le marathon sans entraînement", s))
story.append(body(
"Imagine que tu décides de courir un marathon. Tu fixes une date, tu t'inscris. "
"Et le jour J, tu te présentes au départ sans avoir jamais couru plus de 5 km. "
"Ce n'est pas un manque de volonté si tu abandonnes au 15ème kilomètre. "
"C'est un manque de préparation.", s))
story.append(body(
"L'arrêt du tabac fonctionne exactement comme ça. La majorité des femmes fixent une date, "
"achètent un paquet de gommes à la nicotine, et s'élancent. "
"Sans avoir compris ce qu'elles vont vivre. Sans avoir construit ce qui va remplacer. "
"Sans avoir anticipé les moments difficiles.", s))
story.append(section_title("Ce que la préparation change — concrètement", s))
story.append(body(
"Une étude publiée dans le British Journal of Health Psychology montre que "
"les personnes qui se préparent cognitivement et émotionnellement à un changement de comportement "
"ont 3 fois plus de chances de réussir sur le long terme que celles qui agissent par impulsion.", s))
story.append(body(
"La préparation ne signifie pas attendre indéfiniment. "
"Elle signifie entrer dans le changement avec les bons outils — "
"connaître ses déclencheurs, avoir construit ses alternatives, "
"savoir comment répondre aux moments difficiles avant qu'ils arrivent.", s))
story.append(spacer(8))
story.append(box_sauge([
Paragraph("La rechute ne se passe pas le jour J.", ParagraphStyle('box_bold',
fontName='Helvetica-Bold', fontSize=11, leading=17, textColor=BRUN, spaceAfter=8)),
Paragraph(
"Elle se passe 3 semaines après, un mercredi soir, quand tu es épuisée, "
"que la journée a été difficile, et que ton cerveau cherche sa solution connue. "
"La préparation, c'est savoir à l'avance quoi faire à ce moment précis.",
ParagraphStyle('box_body2', fontName='Helvetica', fontSize=10.5, leading=17, textColor=TERRE)),
]))
story.append(spacer(16))
story.append(exercise_box("Exercice 2 — Mes moments à risque", [
Paragraph(
"Réfléchis aux moments de ta journée et de ta semaine où la cigarette est la plus difficile "
"à imaginer sans. Ce sont tes moments à risque — et ils méritent une réponse préparée à l'avance.",
s['exercise_body']),
Paragraph("Complète ces phrases :", s['exercise_q']),
Paragraph("• La cigarette dont j'aurais le plus de mal à me passer, c'est celle de :", s['exercise_body']),
HRFlowable(width='100%', thickness=0.4, color=SAUGE_C, spaceAfter=8, spaceBefore=4),
Paragraph("• Quand je suis stressée, je fume parce que ça :", s['exercise_body']),
HRFlowable(width='100%', thickness=0.4, color=SAUGE_C, spaceAfter=8, spaceBefore=4),
Paragraph("• Si je ne pouvais pas fumer dans ce moment, je pourrais à la place :", s['exercise_body']),
HRFlowable(width='100%', thickness=0.4, color=SAUGE_C, spaceAfter=8, spaceBefore=4),
Paragraph(
"Tu viens de commencer à construire ton plan. Sans le savoir, tu te prépares déjà.",
s['italic']),
], s))
story.append(PageBreak())
# ══ RAISON 3 ══
story.append(spacer(16))
story.append(tag("Raison n°3", s))
story.append(Paragraph("Tu as résisté\nau lieu d'avancer.", s['chapter_title']))
story.append(HRFlowable(width='3cm', thickness=2, color=SAUGE, spaceAfter=20))
story.append(section_title("L'énergie de la résistance", s))
story.append(body(
"\"Je n'ai pas fumé aujourd'hui.\" \"J'ai résisté à l'envie.\" \"Je tiens bon.\"", s))
story.append(body(
"Tu reconnais ces phrases ? Elles disent quelque chose d'important : "
"quand on arrête de fumer en mode résistance, toute l'énergie est dirigée contre quelque chose. "
"Et lutter contre quelque chose, sans avancer vers quelque chose d'autre, "
"c'est épuisant — et voué à l'échec.", s))
story.append(body(
"La résistance crée de la privation. Et la privation crée de l'obsession. "
"Plus tu essaies de ne pas penser à la cigarette, plus tu y penses. "
"C'est ce que les psychologues appellent l'effet rebond — ou l'effet 'ne pense pas à un éléphant rose'.", s))
story.append(section_title("La différence entre fuir et avancer", s))
story.append(body(
"Les femmes qui réussissent à arrêter ne parlent pas de ce qu'elles ont abandonné. "
"Elles parlent de ce qu'elles ont découvert. Un souffle retrouvé. Une peau transformée. "
"Un temps qui leur appartient. Une présence à elles-mêmes qu'elles n'avaient pas connue depuis longtemps.", s))
story.append(body(
"La différence n'est pas dans les résultats — elle est dans la direction. "
"Une femme qui arrête de fumer en s'approchant de quelque chose qu'elle désire "
"a beaucoup plus de ressources intérieures qu'une femme qui arrête en s'éloignant de quelque chose qu'elle craint.", s))
story.append(spacer(8))
story.append(box_or([
Paragraph("La question qui change tout :", ParagraphStyle('box_label3',
fontName='Helvetica-Bold', fontSize=10, textColor=BRUN, spaceAfter=8)),
Paragraph(
"Non pas \"qu'est-ce que je perds en arrêtant ?\" mais\n\"qu'est-ce que je veux commencer à vivre ?\"",
ParagraphStyle('box_q2', fontName='Helvetica-BoldOblique', fontSize=12,
leading=19, textColor=BRUN)),
]))
story.append(spacer(16))
story.append(exercise_box("Exercice 3 — Ma vie sans tabac", [
Paragraph(
"Ferme les yeux et imagine-toi dans 3 mois. Tu n'as pas fumé depuis 3 mois. "
"Pas parce que tu résistes — mais parce que tu n'en as plus besoin. "
"Réponds à ces questions avec la première chose qui vient.", s['exercise_body']),
Paragraph("Dans 3 mois sans tabac, je remarque que :", s['exercise_q']),
Paragraph("(Mon corps, mon énergie, ma peau, mon souffle, mon humeur...)", s['small']),
HRFlowable(width='100%', thickness=0.4, color=SAUGE_C, spaceAfter=10, spaceBefore=6),
HRFlowable(width='100%', thickness=0.4, color=SAUGE_C, spaceAfter=10, spaceBefore=6),
Paragraph("Ce que je fais de l'argent retrouvé :", s['exercise_q']),
HRFlowable(width='100%', thickness=0.4, color=SAUGE_C, spaceAfter=10, spaceBefore=6),
Paragraph("La femme que je suis en train de devenir :", s['exercise_q']),
HRFlowable(width='100%', thickness=0.4, color=SAUGE_C, spaceAfter=10, spaceBefore=6),
Paragraph(
"Garde ce que tu as écrit. Relis-le quand tu en auras besoin. "
"C'est vers ça que tu avances.", s['italic']),
], s))
story.append(PageBreak())
# ══ ET MAINTENANT ══
story.append(spacer(16))
story.append(tag("Et maintenant ?", s))
story.append(Paragraph("Le premier pas\nconcret.", s['chapter_title']))
story.append(HRFlowable(width='3cm', thickness=2, color=SAUGE, spaceAfter=20))
story.append(body(
"Tu viens de faire quelque chose que la plupart des femmes ne font jamais avant d'arrêter : "
"tu as regardé honnêtement ce qui se passe.", s))
story.append(body(
"Tu sais maintenant que la cigarette répond à un besoin réel que tu vas devoir satisfaire autrement. "
"Tu sais que la préparation est la clé — pas la volonté. "
"Et tu sais que tu n'arrêtes pas quelque chose, tu commences quelque chose.", s))
story.append(spacer(8))
story.append(section_title("Le prochain niveau", s))
story.append(body(
"Ce guide t'a donné les fondations. "
"Mais comprendre ne suffit pas — il faut construire. "
"Il faut identifier ta dépendance précise, créer tes alternatives personnelles, "
"préparer ton identité de non-fumeuse, et construire ton plan d'arrêt sur mesure.", s))
story.append(body(
"C'est exactement ce que je t'apprends dans Le Déclic — "
"mon guide complet (audio + workbook) spécialement conçu pour les femmes "
"qui veulent arrêter de fumer de l'intérieur, pas juste tenir quelques semaines.", s))
story.append(spacer(12))
story.append(box_noir([
Paragraph("LE DÉCLIC — 7 €", ParagraphStyle('cta_title',
fontName='Helvetica-Bold', fontSize=14, textColor=OR,
alignment=TA_CENTER, letterSpacing=1, spaceAfter=10)),
Paragraph(
"Guide audio (45 min) + Workbook PDF complet pour comprendre ta dépendance réelle, "
"cartographier tes déclencheurs, construire tes alternatives "
"et poser les bases de ton arrêt durable.",
ParagraphStyle('cta_body', fontName='Helvetica', fontSize=10.5, leading=17,
textColor=SAUGE_C, alignment=TA_CENTER, spaceAfter=12)),
Paragraph("→ lavoiesanstabac.fr/declic",
ParagraphStyle('cta_link', fontName='Helvetica-Bold', fontSize=11,
textColor=OR, alignment=TA_CENTER)),
]))
story.append(spacer(24))
story.append(HRFlowable(width='40%', thickness=0.5, color=SAUGE_C, hAlign='CENTER'))
story.append(spacer(16))
story.append(Paragraph(
"\"Arrêter de fumer, c'est commencer à se choisir.\"",
ParagraphStyle('final_quote', fontName='Helvetica-Oblique', fontSize=13,
leading=20, textColor=BRUN, alignment=TA_CENTER, spaceAfter=8)))
story.append(Paragraph("— Olivia, La Voie Sans Tabac",
ParagraphStyle('final_author', fontName='Helvetica', fontSize=10,
textColor=TERRE, alignment=TA_CENTER)))
# ── PAGE HEADERS/FOOTERS ──
def on_page(canvas, doc):
canvas.saveState()
if doc.page == 1:
cover_bg(canvas, doc)
else:
# Fond crème
canvas.setFillColor(CREME)
canvas.rect(0, 0, W, H, fill=1, stroke=0)
# Barre top
canvas.setFillColor(SAUGE)
canvas.rect(0, H - 0.4*cm, W, 0.4*cm, fill=1, stroke=0)
# Footer
canvas.setFillColor(SAUGE_P)
canvas.rect(0, 0, W, 1.2*cm, fill=1, stroke=0)
canvas.setFont('Helvetica', 8)
canvas.setFillColor(TERRE)
canvas.drawString(2.5*cm, 0.45*cm, "La Voie Sans Tabac — Olivia — lavoiesanstabac.fr")
canvas.drawRightString(W - 2.5*cm, 0.45*cm, f"Page {doc.page - 1}")
canvas.restoreState()
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print(f"Lead magnet généré : {filepath}")
build_leadmagnet("/mnt/user-data/outputs/lvst/leadmagnet-gratuit.pdf")