#!/usr/bin/env python3
"""
CDP Executive On-Camera Video Production Guide
Tailored for CDP (Carbon Disclosure Project) — Global Environmental Disclosure Platform
Restructuring moment: splitting into CDP (commercial, Permira-backed) + CDP Foundation (nonprofit)
CEO: Sherry Madera (commercial) | Foundation CEO: Beth Thoren (designate)
Key themes: Earth-positive economics, disclosure -> action, simplicity, 25yr milestone, Permira partnership
"""

from reportlab.lib.pagesizes import letter
from reportlab.lib.colors import HexColor, Color, white
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    PageBreak, Flowable, KeepTogether
)
from reportlab.platypus.doctemplate import PageTemplate
from reportlab.platypus.frames import Frame
from reportlab.lib.units import inch
import io

OUTPUT = '/home/node/workspace/cdp_video_guide.pdf'

W, H = letter
LM = RM = 0.75 * inch
TM = 0.65 * inch
BM = 0.6 * inch

# ── CDP COLORS (drawn from cdp.net brand palette) ───────────────────────────
C_BG          = HexColor('#F7F8F5')   # near-white with green tint
C_DARK        = HexColor('#1A2118')   # deep forest
C_ACCENT      = HexColor('#3D7A4F')   # CDP green
C_ACCENT2     = HexColor('#2C5A38')   # deeper green
C_ACCENT_LITE = HexColor('#7AB88A')   # light green
C_RULE        = HexColor('#C8D9C8')   # muted green rule
C_SECTION     = HexColor('#1A2118')
C_MID         = HexColor('#4A5A48')
C_LIGHT       = HexColor('#8A9A88')
C_BOX_BG      = HexColor('#EDF3EE')   # very light green
C_BOX_BRD     = HexColor('#3D7A4F')
C_COVER_BG    = HexColor('#0E1C12')   # very deep forest green
C_COVER_TXT   = HexColor('#F2F7F2')
C_COVER_GOLD  = HexColor('#A8C878')   # warm light green (accent on dark bg)

# ── PAGE BACKGROUNDS ─────────────────────────────────────────────────────────
def cover_bg(canvas, doc):
    canvas.saveState()
    canvas.setFillColor(C_COVER_BG)
    canvas.rect(0, 0, W, H, fill=1, stroke=0)
    # Top green bar
    canvas.setFillColor(C_ACCENT)
    canvas.rect(0, H - 5, W, 5, fill=1, stroke=0)
    canvas.rect(0, 0, W, 4, fill=1, stroke=0)
    # Subtle side lines
    canvas.setFillColor(Color(0.24, 0.48, 0.31, 0.25))
    canvas.rect(LM - 0.15*inch, BM, 1.5, H - TM - BM, fill=1, stroke=0)
    canvas.rect(W - RM + 0.1*inch, BM, 1.5, H - TM - BM, fill=1, stroke=0)
    canvas.restoreState()

def content_bg(canvas, doc):
    canvas.saveState()
    canvas.setFillColor(C_BG)
    canvas.rect(0, 0, W, H, fill=1, stroke=0)
    # Top green rule
    canvas.setFillColor(C_ACCENT)
    canvas.rect(LM, H - TM + 10, W - LM - RM, 1.5, fill=1, stroke=0)
    canvas.rect(LM, BM - 14, W - LM - RM, 1.5, fill=1, stroke=0)
    # Footer
    canvas.setFont('Helvetica', 7.5)
    canvas.setFillColor(C_LIGHT)
    canvas.drawCentredString(W/2, BM - 24, 'CDP  //  EXECUTIVE VIDEO PRODUCTION GUIDE  //  CONFIDENTIAL')
    canvas.drawRightString(W - RM, BM - 24, f'{doc.page}')
    canvas.restoreState()

# ── CUSTOM FLOWABLES ─────────────────────────────────────────────────────────
class GreenRule(Flowable):
    def __init__(self, width, thickness=1.0, alpha=1.0):
        Flowable.__init__(self)
        self.width = width
        self.thickness = thickness
        self.alpha = alpha
        self.height = thickness + 2

    def draw(self):
        self.canv.setFillColor(Color(0.24, 0.48, 0.31, self.alpha))
        self.canv.rect(0, 0, self.width, self.thickness, fill=1, stroke=0)

class SectionDivider(Flowable):
    def __init__(self, width):
        Flowable.__init__(self)
        self.width = width
        self.height = 14

    def draw(self):
        c = self.canv
        y = 6
        c.setFillColor(C_ACCENT)
        c.circle(6, y, 3, fill=1, stroke=0)
        c.circle(self.width - 6, y, 3, fill=1, stroke=0)
        c.setFillColor(C_RULE)
        c.rect(14, y - 0.5, self.width - 28, 1, fill=1, stroke=0)

# ── STYLES ───────────────────────────────────────────────────────────────────
def make_styles():
    s = {}

    s['cover_title'] = ParagraphStyle('cover_title',
        fontName='Helvetica-Bold', fontSize=30,
        textColor=C_COVER_TXT, leading=36,
        alignment=TA_CENTER, spaceAfter=6)

    s['cover_org'] = ParagraphStyle('cover_org',
        fontName='Helvetica-Bold', fontSize=11,
        textColor=C_COVER_GOLD, leading=16,
        alignment=TA_CENTER, spaceBefore=4, spaceAfter=2,
        characterSpacing=2)

    s['cover_sub'] = ParagraphStyle('cover_sub',
        fontName='Helvetica', fontSize=12,
        textColor=C_COVER_GOLD, leading=18,
        alignment=TA_CENTER, spaceAfter=4)

    s['cover_detail'] = ParagraphStyle('cover_detail',
        fontName='Helvetica', fontSize=8.5,
        textColor=HexColor('#607860'), leading=13,
        alignment=TA_CENTER)

    s['section_label'] = ParagraphStyle('section_label',
        fontName='Helvetica-Bold', fontSize=8,
        textColor=C_ACCENT2, leading=12,
        spaceBefore=18, spaceAfter=2,
        characterSpacing=1.5)

    s['section_title'] = ParagraphStyle('section_title',
        fontName='Helvetica-Bold', fontSize=17,
        textColor=C_SECTION, leading=21,
        spaceBefore=2, spaceAfter=8)

    s['body'] = ParagraphStyle('body',
        fontName='Helvetica', fontSize=10,
        textColor=C_MID, leading=15,
        spaceBefore=3, spaceAfter=6,
        alignment=TA_LEFT)

    s['bullet'] = ParagraphStyle('bullet',
        fontName='Helvetica', fontSize=10,
        textColor=C_MID, leading=15,
        spaceBefore=2, spaceAfter=2,
        leftIndent=16)

    s['sub_head'] = ParagraphStyle('sub_head',
        fontName='Helvetica-Bold', fontSize=11,
        textColor=C_DARK, leading=15,
        spaceBefore=10, spaceAfter=4)

    s['callout'] = ParagraphStyle('callout',
        fontName='Helvetica-BoldOblique', fontSize=10.5,
        textColor=C_ACCENT2, leading=16,
        spaceBefore=4, spaceAfter=4,
        alignment=TA_CENTER)

    s['tip_head'] = ParagraphStyle('tip_head',
        fontName='Helvetica-Bold', fontSize=9.5,
        textColor=C_DARK, leading=13)

    s['tip_body'] = ParagraphStyle('tip_body',
        fontName='Helvetica', fontSize=9,
        textColor=C_MID, leading=13)

    return s

# ── HELPERS ──────────────────────────────────────────────────────────────────
def section_header(label, title, styles):
    return [
        Spacer(1, 0.15*inch),
        Paragraph(label.upper(), styles['section_label']),
        Paragraph(title, styles['section_title']),
        GreenRule(W - LM - RM, thickness=1.5),
        Spacer(1, 0.12*inch),
    ]

def P(text, style):
    """Wrap text in a Paragraph so reportlab word-wraps it inside table cells."""
    return Paragraph(str(text), style)

def tip_box(head, body_text, styles, aw):
    data = [[
        Paragraph(head, styles['tip_head']),
        Paragraph(body_text, styles['tip_body']),
    ]]
    t = Table(data, colWidths=[1.4*inch, aw - 1.4*inch])
    t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), C_BOX_BG),
        ('BOX', (0,0), (-1,-1), 0.5, C_BOX_BRD),
        ('LINEAFTER', (0,0), (0,-1), 0.5, C_BOX_BRD),
        ('TOPPADDING', (0,0), (-1,-1), 7),
        ('BOTTOMPADDING', (0,0), (-1,-1), 7),
        ('LEFTPADDING', (0,0), (-1,-1), 10),
        ('RIGHTPADDING', (0,0), (-1,-1), 10),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    return t

def prompt_cards(prompts, styles, aw):
    """Full-width prompt cards — guaranteed no overflow."""
    q_style = ParagraphStyle('q',
        fontName='Helvetica-Bold', fontSize=9.5,
        textColor=C_DARK, leading=14, spaceAfter=3)
    sub_style = ParagraphStyle('sub',
        fontName='Helvetica', fontSize=8.5,
        textColor=C_MID, leading=12)
    num_style = ParagraphStyle('num',
        fontName='Helvetica-Bold', fontSize=8.5,
        textColor=white, alignment=TA_CENTER)

    num_col = 24
    # card_width must fit within aw with zero outer padding
    card_width = aw
    num_cell_col = num_col + 8   # num badge + small right gap
    text_cell_col = card_width - num_cell_col
    # text_col = text_cell_col minus inner cell L+R padding (10+10=20)
    text_col = text_cell_col - 22

    result = []
    for i, (q, sub) in enumerate(prompts):
        num_cell = Table(
            [[Paragraph(str(i+1), num_style)]],
            colWidths=[num_col], rowHeights=[num_col])
        num_cell.setStyle(TableStyle([
            ('BACKGROUND', (0,0), (-1,-1), C_ACCENT),
            ('TOPPADDING', (0,0), (-1,-1), 4),
            ('BOTTOMPADDING', (0,0), (-1,-1), 4),
            ('LEFTPADDING', (0,0), (-1,-1), 0),
            ('RIGHTPADDING', (0,0), (-1,-1), 0),
            ('ALIGN', (0,0), (-1,-1), 'CENTER'),
            ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ]))

        text_block = Table(
            [[Paragraph(q, q_style)],
             [Paragraph(sub, sub_style)]],
            colWidths=[text_col])
        text_block.setStyle(TableStyle([
            ('TOPPADDING', (0,0), (-1,-1), 0),
            ('BOTTOMPADDING', (0,0), (-1,-1), 0),
            ('LEFTPADDING', (0,0), (-1,-1), 0),
            ('RIGHTPADDING', (0,0), (-1,-1), 0),
            ('VALIGN', (0,0), (-1,-1), 'TOP'),
        ]))

        card = Table(
            [[num_cell, text_block]],
            colWidths=[num_cell_col, text_cell_col])
        card.setStyle(TableStyle([
            ('BACKGROUND', (0,0), (-1,-1), C_BOX_BG),
            ('BOX', (0,0), (-1,-1), 0.5, C_BOX_BRD),
            ('LINEAFTER', (0,0), (0,-1), 3, C_ACCENT),
            ('TOPPADDING', (0,0), (-1,-1), 7),
            ('BOTTOMPADDING', (0,0), (-1,-1), 7),
            ('LEFTPADDING', (0,0), (0,-1), 6),
            ('RIGHTPADDING', (0,0), (0,-1), 4),
            ('LEFTPADDING', (1,0), (1,-1), 10),
            ('RIGHTPADDING', (1,0), (1,-1), 10),
            ('VALIGN', (0,0), (-1,-1), 'TOP'),
        ]))

        result.append(KeepTogether([card, Spacer(1, 6)]))

    return result

# ── BUILD STORY ──────────────────────────────────────────────────────────────
def make_story(styles, aw):
    story = []

    # ── COVER ────────────────────────────────────────────────────────────────
    story.append(Spacer(1, 1.6*inch))
    story.append(GreenRule(aw, thickness=2))
    story.append(Spacer(1, 0.22*inch))

    story.append(Paragraph('EXECUTIVE ON-CAMERA', styles['cover_org']))
    story.append(Paragraph('Video Production Guide', styles['cover_title']))
    story.append(Spacer(1, 0.15*inch))
    story.append(GreenRule(aw, thickness=2))
    story.append(Spacer(1, 0.3*inch))

    story.append(Paragraph('Prepared for CDP', styles['cover_sub']))
    story.append(Paragraph(
        'Straight-to-Camera  //  Leadership Series  //  2-Hour Shoot',
        styles['cover_sub']))

    story.append(Spacer(1, 2.0*inch))
    story.append(GreenRule(aw, thickness=0.5, alpha=0.35))
    story.append(Spacer(1, 0.18*inch))
    story.append(Paragraph(
        'CDP  //  TURNING TRANSPARENCY TO ACTION\n'
        'CONFIDENTIAL  //  DO NOT DISTRIBUTE',
        styles['cover_detail']))

    story.append(PageBreak())

    # ── SECTION 1: ABOUT CDP + CONTEXT ──────────────────────────────────────
    story += section_header('Section 01', 'About CDP & Shoot Context', styles)

    story.append(Paragraph(
        'CDP is the global system for environmental disclosure — the world\'s most '
        'comprehensive platform for climate and nature data, representing over 22,000 '
        'disclosing organizations, 1,100+ cities and regions, and US$110 trillion in '
        'institutional assets. For 25 years, CDP has turned environmental transparency '
        'into actionable intelligence for companies, investors, and governments.',
        styles['body']))

    story.append(Paragraph(
        'This shoot captures CDP leadership at a pivotal inflection point: the '
        'organization is splitting into two distinct but unified entities — '
        'CDP, a Permira-backed commercial data platform, and CDP Foundation, '
        'a nonprofit focused on science-led disclosure. Both leaders are delivering '
        'a message of momentum, clarity of purpose, and commitment to impact.',
        styles['body']))

    story.append(Spacer(1, 0.1*inch))

    lbl = ParagraphStyle('tbl_lbl', fontName='Helvetica-Bold', fontSize=9,
                         textColor=C_ACCENT2, leading=13)
    val = ParagraphStyle('tbl_val', fontName='Helvetica', fontSize=9,
                         textColor=C_MID, leading=13)
    lbl_w = 1.3 * inch
    val_w = aw - lbl_w

    context_data = [
        [P('FORMAT', lbl),     P('Straight-to-camera, single camera, talking head', val)],
        [P('DURATION', lbl),   P('2-hour session per executive', val)],
        [P('SUBJECTS', lbl),   P('Senior CDP leadership (CEO and/or direct reports)', val)],
        [P('PURPOSE', lbl),    P('Annual priorities, organizational evolution, Earth-positive vision', val)],
        [P('TONE', lbl),       P('Authoritative, human, urgent — not corporate or rehearsed', val)],
        [P('KEY MOMENT', lbl), P("CDP's 25th year + historic restructuring into two entities", val)],
    ]
    ct = Table(context_data, colWidths=[lbl_w, val_w])
    ct.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (0,-1), C_BOX_BG),
        ('BACKGROUND', (1,0), (1,-1), white),
        ('GRID', (0,0), (-1,-1), 0.5, C_RULE),
        ('TOPPADDING', (0,0), (-1,-1), 7),
        ('BOTTOMPADDING', (0,0), (-1,-1), 7),
        ('LEFTPADDING', (0,0), (-1,-1), 10),
        ('RIGHTPADDING', (0,0), (-1,-1), 10),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    story.append(ct)
    story.append(Spacer(1, 0.2*inch))
    story.append(SectionDivider(aw))

    # ── SECTION 2: PRODUCTION APPROACH ──────────────────────────────────────
    story += section_header('Section 02', 'Production Approach', styles)

    story.append(Paragraph(
        'CDP\'s brand communicates precision, credibility, and global authority. '
        'The production approach should reflect that — clean, confident, and '
        'purposeful. Nothing staged or over-produced. These are leaders with '
        'genuine conviction; the camera\'s job is to get out of the way.',
        styles['body']))

    story.append(Paragraph('Camera & Frame', styles['sub_head']))
    for b in [
        'Single camera, locked off on tripod. Eye-level — CDP leadership speaks as peers, not from above.',
        '85mm or 100mm prime lens. Shallow depth of field. Clean, uncluttered background.',
        'If shooting at CDP offices: a window with natural light, a bookshelf with the green CDP visual language, or a plain wall all work well.',
        'Interviewer sits directly behind or adjacent to the lens — eyeline stays near-camera throughout.',
        'Avoid handheld unless deliberately used for B-roll. The talking-head should feel grounded.',
    ]:
        story.append(Paragraph(f'- {b}', styles['bullet']))

    story.append(Paragraph('Lighting', styles['sub_head']))
    for b in [
        'Soft, directional key light at 45 degrees — warm but not golden. CDP\'s visual world is clean and verdant.',
        'Keep it simple: key + fill + optional separation light. Avoid over-lighting. Authenticity > glamour.',
        'Natural light from a north-facing window is ideal if available. Supplement with LED panels to match.',
        'Avoid overhead practicals (fluorescents kill skin tone and confidence on screen).',
    ]:
        story.append(Paragraph(f'- {b}', styles['bullet']))

    story.append(Paragraph('Audio', styles['sub_head']))
    for b in [
        'Lavalier mic, hidden under clothing. CDP leaders will likely wear professional attire — plan for mic concealment.',
        'Record room tone at the top of every session.',
        'Kill all HVAC, phones, and building noise before rolling.',
        'Boom as backup. If the subject leans or gestures widely, a boom may be more reliable.',
    ]:
        story.append(Paragraph(f'- {b}', styles['bullet']))

    story.append(Spacer(1, 0.2*inch))
    story.append(SectionDivider(aw))

    # ── SECTION 3: SESSION STRUCTURE ────────────────────────────────────────
    story += section_header('Section 03', 'Session Structure (2-Hour Shoot)', styles)

    story.append(Paragraph(
        'CDP leadership operates at pace. The session structure should be tight, '
        'well-paced, and respectful of their time — while still leaving room for '
        'the unscripted moments that make executive video worth watching.',
        styles['body']))

    hdr  = ParagraphStyle('tl_hdr',  fontName='Helvetica-Bold', fontSize=8.5, textColor=white,    leading=12)
    tcol = ParagraphStyle('tl_time', fontName='Helvetica-Bold', fontSize=8.5, textColor=C_ACCENT2, leading=12)
    acol = ParagraphStyle('tl_act',  fontName='Helvetica-Bold', fontSize=8.5, textColor=C_DARK,   leading=12)
    ncol = ParagraphStyle('tl_note', fontName='Helvetica',      fontSize=8.5, textColor=C_MID,    leading=12)

    c1, c2, c3 = 1.1*inch, 1.5*inch, aw - 2.6*inch
    tl = [
        [P('TIME', hdr), P('ACTIVITY', hdr), P('NOTES', hdr)],
        [P('0:00 - 0:20', tcol), P('Setup & Mic / Wardrobe', acol),        P('Confirm mic, lighting match, brief monitor review with subject. Chat casually — do not discuss questions.', ncol)],
        [P('0:20 - 0:30', tcol), P('Warm-Up / Off-Camera', acol),          P("Ask about their week, CDP's history, what's happening in the market. Get them talking naturally before the lens is live.", ncol)],
        [P('0:30 - 0:50', tcol), P('Block 1: Mission & Evolution', acol),  P('CDP\'s 25-year story, the restructuring, what it means. Historical and emotional — the "why we exist" territory.', ncol)],
        [P('0:50 - 1:00', tcol), P('Break + Block 1 Pickups', acol),       P('Water, touch-up. Review and reshoot any stumbles from Block 1 while memory is fresh.', ncol)],
        [P('1:00 - 1:25', tcol), P('Block 2: Priorities & Benchmarks', acol), P('The core content. Annual goals, Earth-positive economics agenda, technology investment, Permira partnership.', ncol)],
        [P('1:25 - 1:35', tcol), P('Block 3: Data, Markets & Impact', acol), P('The external audience: companies, investors, policymakers. What CDP delivers for them and why it matters now.', ncol)],
        [P('1:35 - 1:50', tcol), P('Pickups & Second Takes', acol),         P('Reshoot any incomplete answers. Also: prompt for shorter, punchier versions of strong answers.', ncol)],
        [P('1:50 - 2:00', tcol), P('Closing Statements', acol),             P('Direct-to-camera closes. These anchor the edit. Keep them brief, forward-looking, and warm.', ncol)],
    ]
    tt = Table(tl, colWidths=[c1, c2, c3])
    tt.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), C_ACCENT2),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [white, C_BOX_BG]),
        ('GRID', (0,0), (-1,-1), 0.5, C_RULE),
        ('TOPPADDING', (0,0), (-1,-1), 7),
        ('BOTTOMPADDING', (0,0), (-1,-1), 7),
        ('LEFTPADDING', (0,0), (-1,-1), 8),
        ('RIGHTPADDING', (0,0), (-1,-1), 8),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ]))
    story.append(tt)
    story.append(Spacer(1, 0.2*inch))
    story.append(SectionDivider(aw))

    # ── SECTION 4: SUBJECT PREPARATION ──────────────────────────────────────
    story += section_header('Section 04', 'Preparing Your Subjects', styles)

    story.append(Paragraph(
        'CDP leaders are data-literate, globally oriented, and deeply knowledgeable '
        'about their subject matter. They will not need to be briefed on content — '
        'they live it. The preparation work here is about presence, delivery, and '
        'helping them translate boardroom fluency into camera fluency.',
        styles['body']))

    story.append(Paragraph('Recommended Approach: Talking Points (Not Script)', styles['sub_head']))
    story.append(Paragraph(
        'Send 5-7 bullet-point themes the morning of the shoot. No sentences. '
        'CDP executives will internalize quickly and deliver authentically — '
        'they communicate for a living. The producer reads one prompt at a time. '
        'Subject answers directly to camera. Result: editorial-ready soundbites '
        'that do not sound rehearsed.',
        styles['body']))

    story.append(Paragraph('Fallback: Q&A Format', styles['sub_head']))
    story.append(Paragraph(
        'If a subject prefers structure, the interviewer (off-camera) reads prompts '
        'one at a time. Subject is coached to start every answer with a complete '
        'thought — not a reference to the question. This creates standalone editable '
        'segments that do not require the question in the final cut.',
        styles['body']))

    story.append(Paragraph('Day-Of Notes', styles['sub_head']))
    for b in [
        '"Forget this is being recorded. Imagine you\'re briefing your most important investor. Talk to them."',
        'First take is a warm-up. Always go again, even if it seemed perfect.',
        'If they use jargon (TCFD, TNFD, CSRD) — do not interrupt. They know their audience. Flag for post.',
        'Watch for "presentation mode" — the tone shift when they think they\'re "on." Bring them back down with a casual question between takes.',
        'CDP leadership is global — allow for natural pauses. Do not rush.',
    ]:
        story.append(Paragraph(f'- {b}', styles['bullet']))

    story.append(Spacer(1, 0.2*inch))
    story.append(SectionDivider(aw))
    story.append(PageBreak())

    # ── SECTION 5: PROMPT LIBRARY ────────────────────────────────────────────
    story += section_header('Section 05', 'CDP Executive Prompt Library', styles)

    story.append(Paragraph(
        'All prompts are tailored to CDP\'s mission, current priorities, and '
        'the moment the organization is in. Coach subjects to answer in complete '
        'thoughts — no "yeah" or "great question." Every answer should be able '
        'to stand alone as a 30-90 second clip.',
        styles['body']))
    story.append(Spacer(1, 0.1*inch))

    # ─ BLOCK A: MISSION, HISTORY & THE RESTRUCTURING ────────────────────────
    story.append(Paragraph('Block 1 — Mission, 25 Years & The Next Chapter', styles['sub_head']))
    story.append(GreenRule(aw, thickness=0.75, alpha=0.5))
    story.append(Spacer(1, 0.1*inch))

    story += prompt_cards([
        ('Tell us what CDP is and why it exists.',
         'Coach: Simple, human, from conviction. Avoid jargon. Imagine someone who has never heard of CDP.'),
        ('CDP has been doing this for 25 years. What has actually changed in how the world treats environmental data?',
         'Coach: Then vs. now. The moment when disclosure went from "weird" to essential. Concrete shift.'),
        ('CDP is now becoming two organizations. How do you explain that decision and what it means?',
         'Coach: The foundation and the commercial entity. Why this structure, why now, and why it\'s an evolution not a break.'),
        ('Permira is coming in as a strategic partner. What does that investment make possible?',
         'Coach: Technology, scale, speed. What couldn\'t you do before that you can do now?'),
        ('What does it mean to be a purpose-driven organization that also operates commercially at scale?',
         'Coach: The tension between mission and market. How CDP holds both. Be honest about the challenge.'),
        ('What would you say to the people inside CDP right now about where this organization is going?',
         'Coach: Speak directly to the team. Acknowledging the turbulence of the past year (layoffs, restructuring) is appropriate and human.'),
    ], styles, aw)

    story.append(Spacer(1, 0.2*inch))

    # ─ BLOCK B: PRIORITIES, BENCHMARKS & EARTH-POSITIVE ECONOMICS ───────────
    story.append(Paragraph('Block 2 — Priorities, Benchmarks & Earth-Positive Economics', styles['sub_head']))
    story.append(GreenRule(aw, thickness=0.75, alpha=0.5))
    story.append(Spacer(1, 0.1*inch))

    story += prompt_cards([
        ('What are CDP\'s top priorities for the year ahead?',
         'Coach: Name them directly. Simplicity of disclosure, technology investment, Earth-positive economics agenda. Be specific.'),
        ('You\'ve said disclosure is just the first step. What does the step after that look like?',
         'Coach: Turning data into decisions, action, financial strategy. The "disclosure to action" shift.'),
        ('What is Earth-positive economics, and why does it matter now?',
         'Coach: Moving beyond correlation — proving cause and effect between environmental performance and economic value. Plain language.'),
        ('What will tell you, in 12 months, that this year was a success?',
         'Coach: Specific, measurable if possible. What does a good year for CDP actually look like from the outside?'),
        ('You\'ve invested heavily in simplifying disclosure for 2026. What specifically has changed, and why did it matter?',
         'Coach: The questionnaire improvements, portal upgrades, framework alignment. Why complexity was a barrier to impact.'),
        ('CDP covers climate, water, and forests. Are these getting equal attention, or is one pulling ahead?',
         'Coach: Honest assessment. The nature data agenda is expanding — what does balance look like across the three pillars?'),
    ], styles, aw)

    story.append(Spacer(1, 0.2*inch))

    # ─ BLOCK C: MARKETS, CUSTOMERS & GLOBAL REACH ───────────────────────────
    story.append(Paragraph('Block 3 — Markets, Customers & Global Reach', styles['sub_head']))
    story.append(GreenRule(aw, thickness=0.75, alpha=0.5))
    story.append(Spacer(1, 0.1*inch))

    story += prompt_cards([
        ('Why should a company disclose through CDP in 2026?',
         'Coach: The ABC argument — access to capital, business efficiency, compliance. Make the financial case, not just the moral one.'),
        ('What does CDP offer investors that they cannot get anywhere else?',
         'Coach: $110 trillion in assets uses this data. What is the specific insight that makes CDP indispensable to that community?'),
        ('You operate globally across very different regulatory environments. How do you maintain relevance across all of them?',
         'Coach: CSRD in Europe, SEC rollbacks in the US, growth in Asia. How CDP navigates a fragmented regulatory landscape.'),
        ('The number of disclosing companies has been under pressure. How do you rebuild momentum?',
         'Coach: Honest and forward-looking. Simplification, market trust, the value of the CDP score.'),
        ('What role does CDP play in supply chains specifically?',
         'Coach: The $165B in identified opportunities. How CDP connects buyers and suppliers around environmental risk.'),
        ('What does a company that truly "gets it" look like — one that uses CDP the way it was intended?',
         'Coach: A concrete example (name or archetype). What does exceptional disclosure behavior actually produce for a business?'),
    ], styles, aw)

    story.append(Spacer(1, 0.2*inch))

    # ─ BLOCK D: CULTURE, CLOSING ────────────────────────────────────────────
    story.append(Paragraph('Block 4 — Team, Culture & Closing Statements', styles['sub_head']))
    story.append(GreenRule(aw, thickness=0.75, alpha=0.5))
    story.append(Spacer(1, 0.1*inch))

    story += prompt_cards([
        ('What does the team at CDP need to hear from you right now?',
         'Coach: Post-restructuring, post-layoffs. Real, direct, warm. Not a pep talk — an honest moment of leadership.'),
        ('What kind of people thrive at CDP? What does the culture actually feel like from the inside?',
         'Coach: Specific behaviors and values, not mission-statement language. What makes someone a good fit here?'),
        ('Is there anything you want to say to the companies and organizations that disclose with you?',
         'Coach: Gratitude and a challenge. What do you need from them in this moment?'),
        ('What gives you genuine confidence that environmental transparency is still advancing, even in a skeptical environment?',
         'Coach: The market signal they trust most. Where are they seeing real movement when the headlines are noisy?'),
        ('What is the single most important thing CDP does, in one sentence?',
         'Coach: This is the pull quote. The editorial anchor. Take multiple takes. It should be effortless and exact.'),
        ('What are you most looking forward to in the year ahead?',
         'Coach: Closing energy. Human and forward-looking. Let them end on something real, not rehearsed.'),
    ], styles, aw)

    story.append(Spacer(1, 0.25*inch))
    story.append(SectionDivider(aw))

    # ── SECTION 6: PRODUCER NOTES ────────────────────────────────────────────
    story += section_header('Section 06', 'Producer Direction Notes', styles)

    tips = [
        ('CDP language is dense.',
         'Terms like TCFD, TNFD, CSRD, Scope 3, and SBTi are second nature to CDP leadership. '
         'Do not ask them to simplify mid-take — flag acronym-heavy answers for post and decide in edit '
         'whether to add a lower third or request a cleaner re-take.'),
        ('Use silence.',
         'After each answer, wait 3 full seconds before moving on. CDP leaders are thoughtful — '
         'the best lines often come after the first answer settles. Do not rush.'),
        ('"Say that again, but start with..."',
         'The most useful redirect in executive video. Gets a clean soundbite without the subject '
         'feeling they failed. Use constantly, especially on compound answers.'),
        ('Watch for the pivot to policy.',
         'CDP executives naturally move toward regulatory and policy language when they want to '
         'sound authoritative. Redirect: "What does that mean for the business sitting in front of you?"'),
        ('Energy check at the hour mark.',
         'Around 60 minutes in, energy can drop. Stop. Get the subject moving — stand up, walk around, '
         'get water. Block 2 content is too important to shoot on low energy.'),
        ('The restructuring is sensitive.',
         'The split into two entities and the Permira investment are significant news. '
         'Subjects may be measured in their language. Create space for more candid answers '
         'by going off-camera first: "Tell me informally what this means to you." Then ask on-camera.'),
    ]

    for head, body in tips:
        story.append(KeepTogether([
            tip_box(head, body, styles, aw),
            Spacer(1, 6),
        ]))

    story.append(Spacer(1, 0.2*inch))
    story.append(SectionDivider(aw))

    # ── SECTION 7: POST-PRODUCTION ───────────────────────────────────────────
    story += section_header('Section 07', 'Post-Production Notes', styles)

    story.append(Paragraph(
        'CDP\'s audience — companies, investors, policymakers — is sophisticated and '
        'time-poor. The edit should be tight, purposeful, and visually consistent '
        'with CDP\'s existing brand language.',
        styles['body']))

    for b in [
        'Color grade: clean and verdant. Green tones, natural skin, good contrast. Avoid oversaturation.',
        'Lower thirds: name, title, CDP — match the CDP brand typographic system. Clean and minimal.',
        'Segment structure: each block should cut independently as a 60-120 second topic piece.',
        'Full-length version for internal/stakeholder use. Short cuts (30-60 sec) for social and campaigns.',
        'Music (if used): sparse, low-profile, no melody. Let the voice carry.',
        'B-roll options: CDP data visualizations, the CDP portal, global team shots, Earth imagery.',
        'Export deliverables: 16:9 master, 9:16 for LinkedIn/Instagram vertical, 1:1 square.',
        'Subtitles: CDP operates globally — closed captions on all deliverables as standard.',
    ]:
        story.append(Paragraph(f'- {b}', styles['bullet']))

    story.append(Spacer(1, 0.3*inch))
    story.append(Paragraph(
        '"Environmental risk is now financial risk. The data exists. The question is whether we act on it."',
        styles['callout']))
    story.append(GreenRule(aw, thickness=1.5))

    return story

# ── MAIN ─────────────────────────────────────────────────────────────────────
def build():
    styles = make_styles()
    aw = W - LM - RM

    doc = SimpleDocTemplate(OUTPUT, pagesize=letter,
        leftMargin=LM, rightMargin=RM, topMargin=TM, bottomMargin=BM)

    cover_frame = Frame(LM, BM, aw, H - TM - BM, id='cover')
    content_frame = Frame(LM, BM, aw, H - TM - BM, id='content')
    cover_tmpl = PageTemplate(id='cover', frames=[cover_frame], onPage=cover_bg)
    content_tmpl = PageTemplate(id='content', frames=[content_frame], onPage=content_bg)
    doc.pageTemplates = [cover_tmpl, content_tmpl]

    from reportlab.platypus import NextPageTemplate
    story = [NextPageTemplate('content')] + make_story(styles, aw)
    doc.build(story)
    print(f'Done: {OUTPUT}')

if __name__ == '__main__':
    build()
