Can you prepare me a pdf on topic of a cell cycle Make it short because I have to present it but content should be there with all headings

Reading File
Reading File
Finding Sources
Searching Images

cell cycle phases diagram G1 S G2 M phase

A pathophysiology diagram illustrating the human cell cycle phases (Interphase and M-phase) integrated with specific DNA Double-Strand Break (DSB) repair pathways. The central circular flow depicts G1, S, and G2 phases of interphase, and the M (Mitosis) phase comprising prophase, prometaphase, metaphase, anaphase, telophase, and cytokinesis. Key molecular events are highlighted: G1 involves cellular content duplication and canonical non-homologous end joining (C-NHEJ); the S phase features DNA replication and chromosome duplication; and G2 focuses on mitotic preparation and damage repair via homologous recombination (HR) and microhomology-mediated end joining (MMEJ). The diagram visually connects the cell cycle to DNA structural elements, showing histones as blue cylinders and the DNA double helix within a nucleus. Clinical concepts such as replication fork stalling, genome instability, and DSBs are mapped to their respective phases, emphasizing the relationship between cell division stages and DNA maintenance mechanisms in human genetics and oncology.

A pathophysiology diagram illustrating the human cell cycle phases (Interphase and M-phase) integrated with specific DNA Double-Strand Break (DSB) repair pathways. The central circular flow depicts G1, S, and G2 phases of interphase, and the M (Mitosis) phase comprising prophase, prometaphase, metaphase, anaphase, telophase, and cytokinesis. Key molecular events are highlighted: G1 involves cellular content duplication and canonical non-homologous end joining (C-NHEJ); the S phase features DNA replication and chromosome duplication; and G2 focuses on mitotic preparation and damage repair via homologous recombination (HR) and microhomology-mediated end joining (MMEJ). The diagram visually connects the cell cycle to DNA structural elements, showing histones as blue cylinders and the DNA double helix within a nucleus. Clinical concepts such as replication fork stalling, genome instability, and DSBs are mapped to their respective phases, emphasizing the relationship between cell division stages and DNA maintenance mechanisms in human genetics and oncology.

A pathophysiology diagram illustrating the regulatory influence of the Myc oncoprotein on the cell cycle machinery. The bottom section displays a circular flow of the cell cycle phases: G1, S (DNA replication), G2, and M (mitosis), marked with specific checkpoints (G1, G2, and M). The top section details the molecular signaling pathways involving the Max/Myc heterodimer complex. The Max/Myc complex is shown stimulating the Cyclin D2-CDK4 complex and CDK2, while simultaneously inhibiting Cki p27, a cyclin-dependent kinase inhibitor. These actions lead to the inactivation of the Retinoblastoma protein (Rb) through phosphorylation, indicated by a red 'P' tag. The downstream effect of Rb phosphorylation is depicted as the 'Initiation of S phase,' facilitating the transition from G1 to S phase. The diagram serves as an educational tool for understanding oncogenic signaling and cell cycle dysregulation in cancer biology.

A pathophysiology diagram illustrating the regulatory influence of the Myc oncoprotein on the cell cycle machinery. The bottom section displays a circular flow of the cell cycle phases: G1, S (DNA replication), G2, and M (mitosis), marked with specific checkpoints (G1, G2, and M). The top section details the molecular signaling pathways involving the Max/Myc heterodimer complex. The Max/Myc complex is shown stimulating the Cyclin D2-CDK4 complex and CDK2, while simultaneously inhibiting Cki p27, a cyclin-dependent kinase inhibitor. These actions lead to the inactivation of the Retinoblastoma protein (Rb) through phosphorylation, indicated by a red 'P' tag. The downstream effect of Rb phosphorylation is depicted as the 'Initiation of S phase,' facilitating the transition from G1 to S phase. The diagram serves as an educational tool for understanding oncogenic signaling and cell cycle dysregulation in cancer biology.

This medical illustration depicts the biological roles of the RB1 tumor suppressor. Panel A shows a Pathophysiology Diagram of the cell cycle (G1, S, G2, M phases) highlighting the canonical G1 phase arrest mechanism. It visualizes the inhibition of E2F transcription factors by RB1 and the subsequent release of E2F following RB1 phosphorylation by Cyclin/CDK complexes (Cyclin C/CDK3, Cyclin D/CDK4/6, and Cyclin E/CDK2). Specific checkpoints (M/G1, G1/S, G2/M) and the G0 resting phase are indicated along the circular pathway. Panel B is a Comparison Chart of non-canonical RB1 and E2F functions, using symbolic icons to represent cell fate determination (differentiation), homologous recombination (DNA repair), silencing of repetitive regions (chromatin remodeling), centromere/pericentromeric and telomere structural maintenance (chromosomal stability), and immune responsiveness and evasion. The diagram serves as an educational resource for understanding cancer biology, cell cycle regulation, and the multi-faceted nature of tumor suppressor proteins.

This medical illustration depicts the biological roles of the RB1 tumor suppressor. Panel A shows a Pathophysiology Diagram of the cell cycle (G1, S, G2, M phases) highlighting the canonical G1 phase arrest mechanism. It visualizes the inhibition of E2F transcription factors by RB1 and the subsequent release of E2F following RB1 phosphorylation by Cyclin/CDK complexes (Cyclin C/CDK3, Cyclin D/CDK4/6, and Cyclin E/CDK2). Specific checkpoints (M/G1, G1/S, G2/M) and the G0 resting phase are indicated along the circular pathway. Panel B is a Comparison Chart of non-canonical RB1 and E2F functions, using symbolic icons to represent cell fate determination (differentiation), homologous recombination (DNA repair), silencing of repetitive regions (chromatin remodeling), centromere/pericentromeric and telomere structural maintenance (chromosomal stability), and immune responsiveness and evasion. The diagram serves as an educational resource for understanding cancer biology, cell cycle regulation, and the multi-faceted nature of tumor suppressor proteins.

Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Running Command

mkdir -p /tmp/workspace/cell-cycle-pdf && ls /tmp/workspace/

Writing File

~/cell-cycle-pdf/generate_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, PageBreak, KeepTogether
)
from reportlab.platypus.flowables import Flowable
from reportlab.graphics.shapes import Drawing, Circle, Rect, String, Line, Polygon, Wedge, Arc
from reportlab.graphics.charts.piecharts import Pie
from reportlab.graphics import renderPDF
import math

# ── Colour Palette ──────────────────────────────────────────────────────────
DEEP_BLUE   = colors.HexColor("#1A3A5C")
MID_BLUE    = colors.HexColor("#2E6DA4")
LIGHT_BLUE  = colors.HexColor("#D6E8F7")
ACCENT      = colors.HexColor("#E8A020")
ACCENT2     = colors.HexColor("#2ECC71")
BG_LIGHT    = colors.HexColor("#F4F8FC")
PHASE_G1    = colors.HexColor("#3498DB")
PHASE_S     = colors.HexColor("#E74C3C")
PHASE_G2    = colors.HexColor("#9B59B6")
PHASE_M     = colors.HexColor("#27AE60")
PHASE_G0    = colors.HexColor("#95A5A6")
TEXT_DARK   = colors.HexColor("#1C2833")
TEXT_MED    = colors.HexColor("#2C3E50")
GOLD        = colors.HexColor("#F39C12")
PINK        = colors.HexColor("#E91E8C")

# ── Styles ───────────────────────────────────────────────────────────────────
def make_styles():
    base = getSampleStyleSheet()
    styles = {}

    styles['cover_title'] = ParagraphStyle(
        'cover_title', parent=base['Title'],
        fontSize=38, leading=46, textColor=colors.white,
        fontName='Helvetica-Bold', alignment=TA_CENTER, spaceAfter=8
    )
    styles['cover_sub'] = ParagraphStyle(
        'cover_sub', parent=base['Normal'],
        fontSize=15, leading=20, textColor=colors.HexColor("#D6E8F7"),
        fontName='Helvetica', alignment=TA_CENTER, spaceAfter=4
    )
    styles['cover_tag'] = ParagraphStyle(
        'cover_tag', parent=base['Normal'],
        fontSize=11, leading=14, textColor=colors.HexColor("#A8C8E8"),
        fontName='Helvetica-Oblique', alignment=TA_CENTER
    )
    styles['section_head'] = ParagraphStyle(
        'section_head', parent=base['Heading1'],
        fontSize=16, leading=20, textColor=colors.white,
        fontName='Helvetica-Bold', spaceBefore=14, spaceAfter=6,
        backColor=DEEP_BLUE, borderPad=8, leftIndent=-12, rightIndent=-12
    )
    styles['sub_head'] = ParagraphStyle(
        'sub_head', parent=base['Heading2'],
        fontSize=12, leading=16, textColor=DEEP_BLUE,
        fontName='Helvetica-Bold', spaceBefore=10, spaceAfter=4,
        borderPadding=(0, 0, 2, 0)
    )
    styles['body'] = ParagraphStyle(
        'body', parent=base['Normal'],
        fontSize=9.5, leading=14, textColor=TEXT_MED,
        fontName='Helvetica', spaceAfter=6, alignment=TA_JUSTIFY
    )
    styles['bullet'] = ParagraphStyle(
        'bullet', parent=base['Normal'],
        fontSize=9.5, leading=13, textColor=TEXT_MED,
        fontName='Helvetica', leftIndent=16, spaceAfter=3,
        bulletIndent=4
    )
    styles['caption'] = ParagraphStyle(
        'caption', parent=base['Normal'],
        fontSize=8.5, leading=11, textColor=colors.HexColor("#5D6D7E"),
        fontName='Helvetica-Oblique', alignment=TA_CENTER, spaceAfter=6
    )
    styles['table_hdr'] = ParagraphStyle(
        'table_hdr', parent=base['Normal'],
        fontSize=9, leading=12, textColor=colors.white,
        fontName='Helvetica-Bold', alignment=TA_CENTER
    )
    styles['table_cell'] = ParagraphStyle(
        'table_cell', parent=base['Normal'],
        fontSize=8.5, leading=11, textColor=TEXT_MED,
        fontName='Helvetica', alignment=TA_LEFT
    )
    styles['highlight_box'] = ParagraphStyle(
        'highlight_box', parent=base['Normal'],
        fontSize=9.5, leading=14, textColor=TEXT_MED,
        fontName='Helvetica', alignment=TA_JUSTIFY,
        backColor=LIGHT_BLUE, borderPad=10, leftIndent=8, rightIndent=8,
        spaceAfter=8
    )
    styles['key_point'] = ParagraphStyle(
        'key_point', parent=base['Normal'],
        fontSize=9, leading=13, textColor=DEEP_BLUE,
        fontName='Helvetica-Bold', leftIndent=20, spaceAfter=4
    )
    return styles

# ── Custom Flowables ──────────────────────────────────────────────────────────

class CoverPage(Flowable):
    def __init__(self, w, h):
        Flowable.__init__(self)
        self.width = w
        self.height = h

    def draw(self):
        c = self.canv
        # Gradient background (approximated with bands)
        bands = 40
        for i in range(bands):
            ratio = i / bands
            r = int(26 + ratio * (46 - 26))
            g = int(58 + ratio * (90 - 58))
            b = int(92 + ratio * (140 - 92))
            c.setFillColorRGB(r/255, g/255, b/255)
            c.rect(0, self.height * i / bands,
                   self.width, self.height / bands + 1, stroke=0, fill=1)

        # Decorative circles (DNA-like bubbles)
        for cx, cy, r, alpha in [
            (50, self.height - 60, 80, 0.08),
            (self.width - 40, 80, 100, 0.07),
            (self.width / 2, self.height - 30, 120, 0.05),
            (30, self.height / 2, 60, 0.06),
        ]:
            c.setFillColorRGB(1, 1, 1, alpha)
            c.circle(cx, cy, r, stroke=0, fill=1)

        # Top accent bar
        c.setFillColor(ACCENT)
        c.rect(0, self.height - 8, self.width, 8, stroke=0, fill=1)

        # Bottom accent bar
        c.setFillColor(ACCENT)
        c.rect(0, 0, self.width, 6, stroke=0, fill=1)

        # Cell cycle wheel (decorative)
        cx = self.width / 2
        cy = self.height / 2 + 30
        R = 95
        # Sectors
        phases = [
            (PHASE_G1, 0, 90, "G1"),
            (PHASE_S, 90, 180, "S"),
            (PHASE_G2, 180, 270, "G2"),
            (PHASE_M, 270, 360, "M"),
        ]
        for col, a1, a2, label in phases:
            c.setFillColor(col)
            c.setStrokeColor(colors.white)
            c.setLineWidth(2)
            c.wedge(cx - R, cy - R, cx + R, cy + R, a1, a2 - a1, stroke=1, fill=1)
            # Label
            mid_a = math.radians((a1 + a2) / 2)
            lx = cx + (R * 0.60) * math.cos(mid_a)
            ly = cy + (R * 0.60) * math.sin(mid_a)
            c.setFillColor(colors.white)
            c.setFont("Helvetica-Bold", 13)
            c.drawCentredString(lx, ly - 5, label)

        # Centre circle (white)
        c.setFillColor(colors.white)
        c.setStrokeColor(DEEP_BLUE)
        c.setLineWidth(2)
        c.circle(cx, cy, R * 0.32, stroke=1, fill=1)
        c.setFillColor(DEEP_BLUE)
        c.setFont("Helvetica-Bold", 9)
        c.drawCentredString(cx, cy + 4, "CELL")
        c.drawCentredString(cx, cy - 8, "CYCLE")

        # Title text
        c.setFillColor(colors.white)
        c.setFont("Helvetica-Bold", 36)
        c.drawCentredString(self.width / 2, self.height * 0.82, "THE CELL CYCLE")
        c.setFont("Helvetica", 14)
        c.setFillColor(colors.HexColor("#A8D8EA"))
        c.drawCentredString(self.width / 2, self.height * 0.76,
                            "Growth • Division • Regulation • Clinical Relevance")

        # Bottom info strip
        c.setFillColorRGB(0, 0, 0, 0.25)
        c.rect(0, 28, self.width, 36, stroke=0, fill=1)
        c.setFillColor(colors.HexColor("#A8C8E8"))
        c.setFont("Helvetica", 10)
        c.drawCentredString(self.width / 2, 42,
            "Source: Histology – A Text and Atlas | Berek & Novak's Gynecology | Scott-Brown's Otorhinolaryngology")


class CellCycleWheel(Flowable):
    """Annotated cell-cycle diagram."""
    def __init__(self, size=260):
        Flowable.__init__(self)
        self.size = size
        self.width = size
        self.height = size + 30

    def draw(self):
        c = self.canv
        cx = self.size / 2
        cy = self.size / 2 + 10
        R = self.size * 0.38
        inner_R = R * 0.42

        phases = [
            (PHASE_G1, 90,  180, "G1 Phase", "9-12 h"),
            (PHASE_S,  180, 270, "S Phase",  "10 h"),
            (PHASE_G2, 270, 340, "G2 Phase", "5 h"),
            (PHASE_M,  340, 360+90, "M Phase", "1 h"),
        ]
        for col, a1, a2, label, dur in phases:
            c.setFillColor(col)
            c.setStrokeColor(colors.white)
            c.setLineWidth(2.5)
            c.wedge(cx - R, cy - R, cx + R, cy + R, a1, a2 - a1, stroke=1, fill=1)
            mid_a = math.radians((a1 + a2) / 2)
            lx = cx + (R * 0.67) * math.cos(mid_a)
            ly = cy + (R * 0.67) * math.sin(mid_a)
            c.setFillColor(colors.white)
            c.setFont("Helvetica-Bold", 8)
            c.drawCentredString(lx, ly + 4, label)
            c.setFont("Helvetica", 7)
            c.drawCentredString(lx, ly - 6, dur)

        # Inner white circle
        c.setFillColor(colors.white)
        c.setStrokeColor(DEEP_BLUE)
        c.setLineWidth(2)
        c.circle(cx, cy, inner_R, stroke=1, fill=1)
        c.setFillColor(DEEP_BLUE)
        c.setFont("Helvetica-Bold", 8)
        c.drawCentredString(cx, cy + 6, "INTER-")
        c.drawCentredString(cx, cy - 6, "PHASE")

        # G0 branch arrow
        g0_start_angle = math.radians(135)  # mid G1
        ax = cx + R * math.cos(g0_start_angle)
        ay = cy + R * math.sin(g0_start_angle)
        ex = ax - 38
        ey = ay + 22
        c.setStrokeColor(PHASE_G0)
        c.setFillColor(PHASE_G0)
        c.setLineWidth(1.5)
        c.line(ax, ay, ex, ey)
        c.circle(ex, ey, 12, stroke=1, fill=1)
        c.setFillColor(colors.white)
        c.setFont("Helvetica-Bold", 8)
        c.drawCentredString(ex, ey - 3, "G0")

        # Checkpoint markers (small diamonds)
        checkpoints = [
            (math.radians(180), "R"),   # Restriction checkpoint G1/S
            (math.radians(270), "S-CP"),
            (math.radians(340), "G2/M"),
        ]
        for angle, label in checkpoints:
            px = cx + R * math.cos(angle)
            py = cy + R * math.sin(angle)
            c.setFillColor(GOLD)
            c.setStrokeColor(colors.white)
            c.setLineWidth(1)
            size = 7
            p = c.beginPath()
            p.moveTo(px, py + size)
            p.lineTo(px + size, py)
            p.lineTo(px, py - size)
            p.lineTo(px - size, py)
            p.close()
            c.drawPath(p, stroke=1, fill=1)

        # Legend
        legend_items = [
            (PHASE_G1, "G1 – Gap 1 (growth)"),
            (PHASE_S,  "S  – DNA Synthesis"),
            (PHASE_G2, "G2 – Gap 2 (prep)"),
            (PHASE_M,  "M  – Mitosis"),
            (PHASE_G0, "G0 – Resting"),
            (GOLD,     "Checkpoints"),
        ]
        lx0 = 4
        ly0 = 18
        for col, txt in legend_items:
            c.setFillColor(col)
            c.rect(lx0, ly0, 10, 8, stroke=0, fill=1)
            c.setFillColor(TEXT_MED)
            c.setFont("Helvetica", 6.5)
            c.drawString(lx0 + 13, ly0 + 1, txt)
            lx0 += 82

        # Caption
        c.setFillColor(colors.HexColor("#5D6D7E"))
        c.setFont("Helvetica-Oblique", 7.5)
        c.drawCentredString(cx, 6, "Figure 1. The Eukaryotic Cell Cycle with Checkpoints and Timing")


class CheckpointDiagram(Flowable):
    """Horizontal checkpoint strip."""
    def __init__(self, w=480, h=70):
        Flowable.__init__(self)
        self.width = w
        self.height = h

    def draw(self):
        c = self.canv
        phases = [
            (PHASE_G0, "G0", 0.08),
            (PHASE_G1, "G1 Phase\n9-12 h", 0.24),
            (PHASE_S,  "S Phase\n10 h", 0.24),
            (PHASE_G2, "G2 Phase\n5 h", 0.20),
            (PHASE_M,  "M Phase\n1 h", 0.16),
        ]
        x = 4
        bar_h = 36
        bar_y = self.height / 2 - bar_h / 2 + 8
        total_w = self.width - 8

        for col, label, frac in phases:
            seg_w = total_w * frac
            c.setFillColor(col)
            c.setStrokeColor(colors.white)
            c.setLineWidth(1.5)
            c.roundRect(x, bar_y, seg_w - 2, bar_h, 4, stroke=1, fill=1)
            c.setFillColor(colors.white)
            c.setFont("Helvetica-Bold", 7.5)
            lines = label.split('\n')
            for i, line in enumerate(lines):
                c.drawCentredString(x + (seg_w - 2) / 2,
                                    bar_y + bar_h / 2 + 4 - i * 10, line)
            x += seg_w

        # Checkpoint diamonds
        cps = [
            (0.32 * total_w + 4, "Restriction\nPoint"),
            (0.56 * total_w + 4, "S-phase\nCheckpoint"),
            (0.76 * total_w + 4, "G2/M\nCheckpoint"),
        ]
        for cpx, lbl in cps:
            dy = 7
            c.setFillColor(GOLD)
            c.setStrokeColor(DEEP_BLUE)
            c.setLineWidth(1)
            p = c.beginPath()
            p.moveTo(cpx, bar_y + bar_h + dy + 6)
            p.lineTo(cpx + 7, bar_y + bar_h + dy)
            p.lineTo(cpx, bar_y + bar_h + dy - 6)
            p.lineTo(cpx - 7, bar_y + bar_h + dy)
            p.close()
            c.drawPath(p, stroke=1, fill=1)
            c.setFillColor(TEXT_MED)
            c.setFont("Helvetica", 6)
            lines = lbl.split('\n')
            for i, line in enumerate(lines):
                c.drawCentredString(cpx, bar_y + bar_h + dy + 18 + i * 8, line)

        # Caption
        c.setFillColor(colors.HexColor("#5D6D7E"))
        c.setFont("Helvetica-Oblique", 7)
        c.drawCentredString(self.width / 2, 4, "Figure 2. Linear representation of the cell cycle with checkpoint positions")


class MitosisSteps(Flowable):
    """Simplified mitosis stage strip."""
    def __init__(self, w=480, h=90):
        Flowable.__init__(self)
        self.width = w
        self.height = h

    def _draw_cell(self, c, cx, cy, r, stage, col, chrom_lines):
        # Outer cell
        c.setFillColor(colors.HexColor("#EBF5FB"))
        c.setStrokeColor(col)
        c.setLineWidth(1.5)
        c.circle(cx, cy, r, stroke=1, fill=1)
        # Nucleus or chromosomes
        c.setStrokeColor(col)
        c.setLineWidth(1.2)
        for lx1, ly1, lx2, ly2 in chrom_lines:
            c.setFillColor(col)
            c.line(cx + lx1, cy + ly1, cx + lx2, cy + ly2)
        # Label
        c.setFillColor(TEXT_DARK)
        c.setFont("Helvetica-Bold", 7)
        c.drawCentredString(cx, cy - r - 10, stage)

    def draw(self):
        c = self.canv
        stages = [
            ("Prophase",     [(−8, 4, −4, 10), (−2, 6, 2, 12), (4, 4, 8, 10),
                              (−8,−10, −4,−4), (−2,−12, 2,−6), (4,−10, 8,−4)]),
            ("Metaphase",    [(−10, 0, −4, 0), (−2, 0, 4, 0), (6, 0, 12, 0),
                              (−10, 4, −4, 4), (−2, 4, 4, 4), (6, 4, 12, 4)]),
            ("Anaphase",     [(−8, 7, −4, 12), (−2, 8, 2, 13),
                              (−8,−12, −4,−7), (−2,−13, 2,−8)]),
            ("Telophase",    [(−6, 5, −2, 5), (0, 7, 4, 7),
                              (−6,−7, −2,−7), (0,−5, 4,−5)]),
            ("Cytokinesis",  [(−5, 3, 5, 3), (−5,−3, 5,−3)]),
        ]
        n = len(stages)
        step = self.width / n
        r = 28
        cy = self.height / 2 + 6
        for i, (stage, lines) in enumerate(stages):
            cx = step * i + step / 2
            self._draw_cell(c, cx, cy, r, stage, PHASE_M, lines)
            # Arrow between cells
            if i < n - 1:
                ax = cx + r + 4
                ay = cy
                c.setStrokeColor(PHASE_M)
                c.setLineWidth(1)
                c.line(ax, ay, ax + step - 2 * r - 8, ay)
                # arrowhead
                ex = ax + step - 2 * r - 8
                c.line(ex, ay, ex - 5, ay + 3)
                c.line(ex, ay, ex - 5, ay - 3)

        c.setFillColor(colors.HexColor("#5D6D7E"))
        c.setFont("Helvetica-Oblique", 7)
        c.drawCentredString(self.width / 2, 4,
            "Figure 3. Stages of Mitosis (M Phase)")


class CyclinCDKBar(Flowable):
    """Cyclin-CDK activity bar chart across cell cycle."""
    def __init__(self, w=480, h=90):
        Flowable.__init__(self)
        self.width = w
        self.height = h

    def draw(self):
        c = self.canv
        pairs = [
            ("Cyclin D/CDK4,6", PHASE_G1,   [(0.05,0.3),(0.20,0.85),(0.32,0.70),(0.40,0.10)]),
            ("Cyclin E/CDK2",   PHASE_S,    [(0.20,0.10),(0.32,0.95),(0.40,0.80),(0.50,0.10)]),
            ("Cyclin A/CDK2",   PHASE_G2,   [(0.35,0.10),(0.50,0.90),(0.65,0.85),(0.72,0.10)]),
            ("Cyclin B/CDK1",   PHASE_M,    [(0.60,0.10),(0.72,0.95),(0.82,0.85),(0.90,0.05)]),
        ]
        bar_y = 22
        chart_h = self.height - 38
        chart_w = self.width - 60
        x0 = 55

        # Axis
        c.setStrokeColor(TEXT_MED)
        c.setLineWidth(0.8)
        c.line(x0, bar_y, x0, bar_y + chart_h)
        c.line(x0, bar_y, x0 + chart_w, bar_y)
        c.setFillColor(TEXT_MED)
        c.setFont("Helvetica", 6.5)
        c.drawString(2, bar_y + chart_h / 2 - 4, "Activity")
        # Phase labels on x axis
        for label, frac, col in [("G0/G1", 0.13, PHASE_G1), ("S", 0.43, PHASE_S),
                                  ("G2", 0.65, PHASE_G2), ("M", 0.83, PHASE_M)]:
            c.setFillColor(col)
            c.setFont("Helvetica-Bold", 7)
            c.drawCentredString(x0 + frac * chart_w, bar_y - 8, label)

        # Draw curves
        for name, col, pts in pairs:
            c.setStrokeColor(col)
            c.setLineWidth(1.8)
            path = c.beginPath()
            first = True
            for fx, fy in pts:
                px = x0 + fx * chart_w
                py = bar_y + fy * chart_h
                if first:
                    path.moveTo(px, py)
                    first = False
                else:
                    path.lineTo(px, py)
            c.drawPath(path, stroke=1, fill=0)

        # Legend
        lx = x0
        for name, col, _ in pairs:
            c.setFillColor(col)
            c.rect(lx, self.height - 12, 10, 8, stroke=0, fill=1)
            c.setFillColor(TEXT_MED)
            c.setFont("Helvetica", 6.5)
            c.drawString(lx + 12, self.height - 11, name)
            lx += 115

        c.setFillColor(colors.HexColor("#5D6D7E"))
        c.setFont("Helvetica-Oblique", 7)
        c.drawCentredString(self.width / 2, 4,
            "Figure 4. Cyclin-CDK Complex Activity Across the Cell Cycle")


# ── Section Header Helper ─────────────────────────────────────────────────────
class SectionHeader(Flowable):
    def __init__(self, text, w=480, num=None):
        Flowable.__init__(self)
        self.text = text
        self.width = w
        self.height = 28
        self.num = num

    def draw(self):
        c = self.canv
        # Background
        c.setFillColor(DEEP_BLUE)
        c.roundRect(0, 0, self.width, self.height, 4, stroke=0, fill=1)
        # Left accent strip
        c.setFillColor(ACCENT)
        c.roundRect(0, 0, 6, self.height, 3, stroke=0, fill=1)
        # Number badge
        if self.num:
            c.setFillColor(ACCENT)
            c.circle(20, self.height / 2, 10, stroke=0, fill=1)
            c.setFillColor(colors.white)
            c.setFont("Helvetica-Bold", 10)
            c.drawCentredString(20, self.height / 2 - 4, str(self.num))
        # Text
        c.setFillColor(colors.white)
        c.setFont("Helvetica-Bold", 13)
        tx = 36 if self.num else 14
        c.drawString(tx, self.height / 2 - 5, self.text)


class InfoBox(Flowable):
    """Coloured info box."""
    def __init__(self, lines, col=LIGHT_BLUE, border_col=MID_BLUE, w=480):
        Flowable.__init__(self)
        self.lines = lines
        self.col = col
        self.border_col = border_col
        self.width = w
        self.height = 14 * len(lines) + 16

    def draw(self):
        c = self.canv
        c.setFillColor(self.col)
        c.setStrokeColor(self.border_col)
        c.setLineWidth(1.2)
        c.roundRect(0, 0, self.width, self.height, 5, stroke=1, fill=1)
        # Left stripe
        c.setFillColor(self.border_col)
        c.roundRect(0, 0, 5, self.height, 4, stroke=0, fill=1)
        c.setFillColor(TEXT_DARK)
        c.setFont("Helvetica", 9)
        for i, line in enumerate(self.lines):
            y = self.height - 14 * (i + 1) - 2
            c.drawString(12, y, line)


# ── Build Document ────────────────────────────────────────────────────────────

def build_pdf(path):
    W, H = A4
    doc = SimpleDocTemplate(
        path, pagesize=A4,
        leftMargin=2.2*cm, rightMargin=2.2*cm,
        topMargin=2*cm, bottomMargin=2*cm,
        title="The Cell Cycle", author="Orris Medical AI"
    )

    styles = make_styles()
    S = styles
    story = []

    # ── COVER ────────────────────────────────────────────────────────────────
    story.append(CoverPage(W, H))
    story.append(PageBreak())

    # ── PAGE 2 – OVERVIEW ────────────────────────────────────────────────────
    story.append(SectionHeader("1.  Overview of the Cell Cycle", num=1))
    story.append(Spacer(1, 8))
    story.append(Paragraph(
        "The cell cycle is a self-regulated sequence of events that controls cell growth and "
        "cell division. Its ultimate goal is to produce two genetically identical daughter cells, "
        "each with the same chromosome number and DNA content as the parent cell. The cycle "
        "incorporates two principal phases: <b>interphase</b> (continuous growth) and the "
        "<b>M phase</b> (mitosis or meiosis, where the genome is partitioned).",
        S['body']))
    story.append(Paragraph(
        "Most human cells complete the cell cycle in approximately <b>24 hours</b>. "
        "The duration of each phase is: G1 ~9-12 h, S ~10 h, G2 ~5 h, M ~30-60 min. "
        "Cells that stop dividing exit into the <b>G0 (resting/quiescent)</b> phase.",
        S['body']))
    story.append(Spacer(1, 10))
    story.append(CellCycleWheel(260))
    story.append(Spacer(1, 6))
    story.append(CheckpointDiagram(480, 72))
    story.append(Spacer(1, 10))

    # Quick-reference box
    story.append(InfoBox([
        "KEY FACT:  Rapidly renewing human cells complete the full cycle in ~24 hours.",
        "G0 cells can re-enter the cycle when stimulated by growth factors or steroid hormones.",
        "Terminally differentiated cells (neurons, RBCs, cardiac muscle) CANNOT re-enter the cycle.",
    ], col=LIGHT_BLUE, border_col=MID_BLUE))
    story.append(PageBreak())

    # ── PAGE 3 – PHASES ──────────────────────────────────────────────────────
    story.append(SectionHeader("2.  Phases of the Cell Cycle", num=2))
    story.append(Spacer(1, 8))

    phase_data = [
        [Paragraph("<b>Phase</b>", S['table_hdr']),
         Paragraph("<b>Key Events</b>", S['table_hdr']),
         Paragraph("<b>Duration</b>", S['table_hdr'])],
        [Paragraph("<b>G0</b>\n(Resting)", S['table_cell']),
         Paragraph("Quiescent; cell has exited the cycle. Re-entry triggered by mitogens.", S['table_cell']),
         Paragraph("Variable\n(days–lifetime)", S['table_cell'])],
        [Paragraph("<b>G1</b>\n(Gap 1)", S['table_cell']),
         Paragraph(
             "• Cell increases in size\n"
             "• Synthesises RNA and proteins needed for DNA replication\n"
             "• Contains the Restriction Checkpoint (point of no return)\n"
             "• p53 monitors DNA damage; if irreparable → apoptosis",
             S['table_cell']),
         Paragraph("9-12 h\n(longest phase)", S['table_cell'])],
        [Paragraph("<b>S Phase</b>\n(Synthesis)", S['table_cell']),
         Paragraph(
             "• DNA is replicated (genome doubles from 2N → 4N)\n"
             "• Each chromosome duplicated into two sister chromatids\n"
             "• S-phase DNA-damage checkpoint monitors replication fidelity",
             S['table_cell']),
         Paragraph("~10 h", S['table_cell'])],
        [Paragraph("<b>G2</b>\n(Gap 2)", S['table_cell']),
         Paragraph(
             "• Cell continues to grow and prepares for division\n"
             "• Checks quality of newly synthesised DNA\n"
             "• G2 DNA-damage checkpoint & unreplicated DNA checkpoint active",
             S['table_cell']),
         Paragraph("~5 h", S['table_cell'])],
        [Paragraph("<b>M Phase</b>\n(Mitosis)", S['table_cell']),
         Paragraph(
             "• Chromosome segregation and nuclear division\n"
             "• 4 sub-phases: Prophase → Metaphase → Anaphase → Telophase\n"
             "• Ends with Cytokinesis (cytoplasm division)\n"
             "• Produces 2 genetically identical daughter cells",
             S['table_cell']),
         Paragraph("30-60 min", S['table_cell'])],
    ]
    phase_table = Table(phase_data, colWidths=[80, 310, 90])
    phase_table.setStyle(TableStyle([
        ('BACKGROUND', (0, 0), (-1, 0), DEEP_BLUE),
        ('BACKGROUND', (0, 1), (-1, 1), PHASE_G0),
        ('BACKGROUND', (0, 2), (-1, 2), colors.HexColor("#D6EAF8")),
        ('BACKGROUND', (0, 3), (-1, 3), colors.HexColor("#FADBD8")),
        ('BACKGROUND', (0, 4), (-1, 4), colors.HexColor("#E8DAEF")),
        ('BACKGROUND', (0, 5), (-1, 5), colors.HexColor("#D5F5E3")),
        ('TEXTCOLOR', (0, 1), (-1, 1), colors.white),
        ('ROWBACKGROUNDS', (0, 0), (-1, 0), [DEEP_BLUE]),
        ('ALIGN', (0, 0), (-1, 0), 'CENTER'),
        ('VALIGN', (0, 0), (-1, -1), 'TOP'),
        ('GRID', (0, 0), (-1, -1), 0.5, colors.white),
        ('TOPPADDING', (0, 0), (-1, -1), 6),
        ('BOTTOMPADDING', (0, 0), (-1, -1), 6),
        ('LEFTPADDING', (0, 0), (-1, -1), 8),
        ('RIGHTPADDING', (0, 0), (-1, -1), 8),
        ('ROWBACKGROUNDS', (0, 1), (-1, -1), [
            PHASE_G0,
            colors.HexColor("#D6EAF8"),
            colors.HexColor("#FADBD8"),
            colors.HexColor("#E8DAEF"),
            colors.HexColor("#D5F5E3"),
        ]),
    ]))
    story.append(phase_table)
    story.append(Spacer(1, 12))
    story.append(PageBreak())

    # ── PAGE 4 – CHECKPOINTS ─────────────────────────────────────────────────
    story.append(SectionHeader("3.  Cell Cycle Checkpoints", num=3))
    story.append(Spacer(1, 8))
    story.append(Paragraph(
        "Checkpoints are biochemical surveillance pathways that monitor the integrity and "
        "completion of each stage before permitting progression to the next. They act as "
        "quality-control gates throughout the cycle.", S['body']))
    story.append(Spacer(1, 8))

    cp_data = [
        [Paragraph("<b>Checkpoint</b>", S['table_hdr']),
         Paragraph("<b>Location</b>", S['table_hdr']),
         Paragraph("<b>What It Monitors</b>", S['table_hdr']),
         Paragraph("<b>Key Molecules</b>", S['table_hdr'])],
        [Paragraph("Restriction Point (R)", S['table_cell']),
         Paragraph("Late G1", S['table_cell']),
         Paragraph("Cell size, nutrient availability, extracellular signals", S['table_cell']),
         Paragraph("Rb, E2F, Cyclin D/CDK4,6", S['table_cell'])],
        [Paragraph("G1 DNA-Damage", S['table_cell']),
         Paragraph("G1", S['table_cell']),
         Paragraph("Integrity of DNA before replication", S['table_cell']),
         Paragraph("p53, p21, ATM/ATR kinases", S['table_cell'])],
        [Paragraph("S-Phase DNA-Damage", S['table_cell']),
         Paragraph("S phase", S['table_cell']),
         Paragraph("Replication fork stalling; DNA strand breaks", S['table_cell']),
         Paragraph("CHK1, CHK2, ATR", S['table_cell'])],
        [Paragraph("G2/M DNA-Damage", S['table_cell']),
         Paragraph("Late G2", S['table_cell']),
         Paragraph("Completeness and accuracy of DNA replication", S['table_cell']),
         Paragraph("Cyclin B/CDK1, CDC25C, p53", S['table_cell'])],
        [Paragraph("Spindle-Assembly (SAC)", S['table_cell']),
         Paragraph("M phase", S['table_cell']),
         Paragraph("Attachment of all chromosomes to spindle microtubules", S['table_cell']),
         Paragraph("MAD1, MAD2, BUB1, BUBR1", S['table_cell'])],
    ]
    cp_table = Table(cp_data, colWidths=[100, 60, 160, 140])
    cp_table.setStyle(TableStyle([
        ('BACKGROUND', (0, 0), (-1, 0), DEEP_BLUE),
        ('ALIGN', (0, 0), (-1, 0), 'CENTER'),
        ('VALIGN', (0, 0), (-1, -1), 'TOP'),
        ('GRID', (0, 0), (-1, -1), 0.4, colors.HexColor("#BDC3C7")),
        ('ROWBACKGROUNDS', (0, 1), (-1, -1), [
            colors.HexColor("#EBF5FB"), colors.white,
            colors.HexColor("#EBF5FB"), colors.white,
            colors.HexColor("#EBF5FB"),
        ]),
        ('TOPPADDING', (0, 0), (-1, -1), 5),
        ('BOTTOMPADDING', (0, 0), (-1, -1), 5),
        ('LEFTPADDING', (0, 0), (-1, -1), 7),
        ('RIGHTPADDING', (0, 0), (-1, -1), 7),
    ]))
    story.append(cp_table)
    story.append(Spacer(1, 10))
    story.append(InfoBox([
        "CLINICAL PEARL:  When the G1 DNA-damage checkpoint detects irreparable DNA damage,",
        "p53 accumulates and triggers APOPTOSIS, preventing propagation of mutant cells.",
        "Mutations in TP53 (p53 gene) are found in >50% of all human cancers.",
    ], col=colors.HexColor("#FEF9E7"), border_col=GOLD))
    story.append(PageBreak())

    # ── PAGE 5 – MITOSIS + MEIOSIS ───────────────────────────────────────────
    story.append(SectionHeader("4.  Mitosis", num=4))
    story.append(Spacer(1, 6))
    story.append(Paragraph(
        "Mitosis is the process of chromosome segregation, nuclear division, and cell division "
        "that produces two genetically identical daughter cells. It follows the S phase and "
        "consists of four continuous phases plus cytokinesis.", S['body']))
    story.append(Spacer(1, 8))
    story.append(MitosisSteps(480, 88))
    story.append(Spacer(1, 8))

    mitosis_data = [
        [Paragraph("<b>Stage</b>", S['table_hdr']),
         Paragraph("<b>Key Events</b>", S['table_hdr'])],
        [Paragraph("Prophase", S['table_cell']),
         Paragraph("Chromosomes condense and become visible; nuclear envelope disassembles; "
                   "mitotic spindle forms from microtubules originating at centrosomes.", S['table_cell'])],
        [Paragraph("Metaphase", S['table_cell']),
         Paragraph("Chromosomes align at the cell equator (metaphase plate); "
                   "spindle-assembly checkpoint verifies kinetochore attachment.", S['table_cell'])],
        [Paragraph("Anaphase", S['table_cell']),
         Paragraph("Sister chromatids separate and are pulled to opposite poles "
                   "by shortening spindle fibres.", S['table_cell'])],
        [Paragraph("Telophase", S['table_cell']),
         Paragraph("Nuclear envelope reconstructs around each set of chromosomes; "
                   "chromosomes decondense; two nuclei form.", S['table_cell'])],
        [Paragraph("Cytokinesis", S['table_cell']),
         Paragraph("Cytoplasm divides via the contractile ring (actin/myosin), "
                   "producing two complete daughter cells.", S['table_cell'])],
    ]
    mit_table = Table(mitosis_data, colWidths=[90, 380])
    mit_table.setStyle(TableStyle([
        ('BACKGROUND', (0, 0), (-1, 0), PHASE_M),
        ('ALIGN', (0, 0), (-1, 0), 'CENTER'),
        ('VALIGN', (0, 0), (-1, -1), 'TOP'),
        ('GRID', (0, 0), (-1, -1), 0.4, colors.HexColor("#BDC3C7")),
        ('ROWBACKGROUNDS', (0, 1), (-1, -1), [
            colors.HexColor("#EAFAF1"), colors.white,
            colors.HexColor("#EAFAF1"), colors.white,
            colors.HexColor("#EAFAF1"),
        ]),
        ('TOPPADDING', (0, 0), (-1, -1), 5),
        ('BOTTOMPADDING', (0, 0), (-1, -1), 5),
        ('LEFTPADDING', (0, 0), (-1, -1), 7),
        ('RIGHTPADDING', (0, 0), (-1, -1), 7),
    ]))
    story.append(mit_table)
    story.append(Spacer(1, 12))

    story.append(SectionHeader("5.  Meiosis (vs Mitosis)", num=5))
    story.append(Spacer(1, 6))

    meiosis_data = [
        [Paragraph("<b>Feature</b>", S['table_hdr']),
         Paragraph("<b>Mitosis</b>", S['table_hdr']),
         Paragraph("<b>Meiosis</b>", S['table_hdr'])],
        ["Purpose", "Growth & tissue repair", "Gamete production"],
        ["Divisions", "1", "2 (Meiosis I + II)"],
        ["Daughter cells", "2 diploid (2N)", "4 haploid (N)"],
        ["Genetic identity", "Identical to parent", "Genetically unique"],
        ["Crossing-over", "Does not occur", "Occurs in Prophase I"],
        ["Occurs in", "All somatic cells", "Gonads only"],
    ]
    mei_table = Table(meiosis_data, colWidths=[130, 170, 170])
    mei_table.setStyle(TableStyle([
        ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor("#8E44AD")),
        ('ALIGN', (0, 0), (-1, 0), 'CENTER'),
        ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
        ('GRID', (0, 0), (-1, -1), 0.4, colors.HexColor("#BDC3C7")),
        ('ROWBACKGROUNDS', (0, 1), (-1, -1), [
            colors.HexColor("#F5EEF8"), colors.white,
            colors.HexColor("#F5EEF8"), colors.white,
            colors.HexColor("#F5EEF8"), colors.white,
        ]),
        ('FONTNAME', (0, 1), (0, -1), 'Helvetica-Bold'),
        ('FONTSIZE', (0, 0), (-1, -1), 8.5),
        ('TOPPADDING', (0, 0), (-1, -1), 5),
        ('BOTTOMPADDING', (0, 0), (-1, -1), 5),
        ('LEFTPADDING', (0, 0), (-1, -1), 8),
    ]))
    story.append(mei_table)
    story.append(PageBreak())

    # ── PAGE 6 – CYCLINS & CDKs ──────────────────────────────────────────────
    story.append(SectionHeader("6.  Cyclins and Cyclin-Dependent Kinases (CDKs)", num=6))
    story.append(Spacer(1, 6))
    story.append(Paragraph(
        "Progression through the cell cycle is driven by a two-protein complex: "
        "<b>cyclin</b> (regulatory subunit) and <b>cyclin-dependent kinase (CDK)</b> "
        "(catalytic subunit). Cyclins are synthesised and degraded at regular intervals, "
        "providing oscillatory control of CDK activity.", S['body']))
    story.append(Spacer(1, 8))
    story.append(CyclinCDKBar(480, 90))
    story.append(Spacer(1, 8))

    cdk_data = [
        [Paragraph("<b>Cyclin-CDK Complex</b>", S['table_hdr']),
         Paragraph("<b>Phase Active</b>", S['table_hdr']),
         Paragraph("<b>Main Function</b>", S['table_hdr'])],
        ["Cyclin D / CDK4,6", "G1", "Phosphorylates Rb → releases E2F → drives G1 progression"],
        ["Cyclin E / CDK2",   "G1→S", "Triggers entry into S phase; initiates DNA replication"],
        ["Cyclin A / CDK2",   "S→G2", "Sustains DNA replication; promotes G2 entry"],
        ["Cyclin A / CDK1",   "G2",   "Promotes mitotic entry"],
        ["Cyclin B / CDK1",   "M phase", "MPF (Maturation-Promoting Factor); drives mitosis; degraded at end of M"],
    ]
    cdk_table = Table(cdk_data, colWidths=[140, 80, 250])
    cdk_table.setStyle(TableStyle([
        ('BACKGROUND', (0, 0), (-1, 0), DEEP_BLUE),
        ('ALIGN', (0, 0), (-1, 0), 'CENTER'),
        ('VALIGN', (0, 0), (-1, -1), 'TOP'),
        ('GRID', (0, 0), (-1, -1), 0.4, colors.HexColor("#BDC3C7")),
        ('ROWBACKGROUNDS', (0, 1), (-1, -1), [
            colors.HexColor("#D6EAF8"), colors.white,
            colors.HexColor("#D6EAF8"), colors.white,
            colors.HexColor("#D6EAF8"),
        ]),
        ('FONTNAME', (0, 1), (0, -1), 'Helvetica-Bold'),
        ('FONTSIZE', (0, 0), (-1, -1), 8.5),
        ('TOPPADDING', (0, 0), (-1, -1), 5),
        ('BOTTOMPADDING', (0, 0), (-1, -1), 5),
        ('LEFTPADDING', (0, 0), (-1, -1), 7),
    ]))
    story.append(cdk_table)
    story.append(Spacer(1, 10))
    story.append(InfoBox([
        "CDK INHIBITORS (CKIs): Proteins like p21, p27, p57 (CIP/KIP family) and p16, p15 (INK4 family)",
        "bind to cyclin-CDK complexes and INHIBIT their activity, halting cell cycle progression.",
        "CDK4/6 inhibitors (palbociclib, ribociclib) are FDA-approved cancer drugs.",
    ], col=colors.HexColor("#EBF5FB"), border_col=MID_BLUE))
    story.append(PageBreak())

    # ── PAGE 7 – CELL CYCLE REGULATION & CANCER ──────────────────────────────
    story.append(SectionHeader("7.  Regulation of the Cell Cycle", num=7))
    story.append(Spacer(1, 6))
    story.append(Paragraph(
        "Cell cycle progression is tightly regulated by a balance of positive (pro-proliferative) "
        "and negative (anti-proliferative) signals. Disruption of this balance leads to uncontrolled "
        "proliferation (cancer) or failure to divide.", S['body']))
    story.append(Spacer(1, 6))

    reg_data = [
        [Paragraph("<b>Regulator</b>", S['table_hdr']),
         Paragraph("<b>Type</b>", S['table_hdr']),
         Paragraph("<b>Role</b>", S['table_hdr'])],
        ["Rb (Retinoblastoma protein)", "Tumour suppressor",
         "Binds and inhibits E2F; when phosphorylated by Cyclin D/CDK4,6 → releases E2F → S phase entry"],
        ["p53 (TP53 gene)", "Tumour suppressor",
         "Senses DNA damage; induces p21 (CDK inhibitor) → G1 arrest; triggers apoptosis if damage irreparable"],
        ["E2F transcription factors", "Pro-proliferative",
         "When released from Rb, activates genes needed for S phase (thymidine kinase, DNA polymerase)"],
        ["Growth factors (EGF, PDGF)", "Mitogen",
         "Bind surface receptors → activate RAS/MAPK → induce Cyclin D → drive G1 progression"],
        ["CDK inhibitors (p21, p27, p16)", "Negative regulators",
         "Bind and inhibit cyclin-CDK complexes; key targets of p53 signalling"],
        ["Proto-oncogenes (RAS, MYC)", "Positive regulators",
         "When mutated become oncogenes; drive uncontrolled proliferation"],
    ]
    reg_table = Table(reg_data, colWidths=[130, 100, 240])
    reg_table.setStyle(TableStyle([
        ('BACKGROUND', (0, 0), (-1, 0), DEEP_BLUE),
        ('ALIGN', (0, 0), (-1, 0), 'CENTER'),
        ('VALIGN', (0, 0), (-1, -1), 'TOP'),
        ('GRID', (0, 0), (-1, -1), 0.4, colors.HexColor("#BDC3C7")),
        ('ROWBACKGROUNDS', (0, 1), (-1, -1), [
            colors.HexColor("#FDEDEC"), colors.white,
            colors.HexColor("#FDEDEC"), colors.white,
            colors.HexColor("#FDEDEC"), colors.white,
        ]),
        ('FONTNAME', (0, 1), (0, -1), 'Helvetica-Bold'),
        ('FONTSIZE', (0, 0), (-1, -1), 8.5),
        ('TOPPADDING', (0, 0), (-1, -1), 5),
        ('BOTTOMPADDING', (0, 0), (-1, -1), 5),
        ('LEFTPADDING', (0, 0), (-1, -1), 7),
    ]))
    story.append(reg_table)
    story.append(Spacer(1, 10))
    story.append(PageBreak())

    # ── PAGE 8 – CLINICAL RELEVANCE ──────────────────────────────────────────
    story.append(SectionHeader("8.  Clinical Relevance", num=8))
    story.append(Spacer(1, 6))

    story.append(Paragraph("<b>A. Cell Cycle Deregulation in Cancer</b>", S['sub_head']))
    story.append(Paragraph(
        "Cancer fundamentally results from deregulation of the cell cycle. Cells acquire "
        "hallmark mutations that override checkpoints, disable tumour suppressors, or "
        "constitutively activate pro-proliferative signals:", S['body']))

    cancer_bullets = [
        "Loss of Rb function → unchecked E2F activity → continuous G1→S transition",
        "TP53 mutation (>50% of cancers) → no G1 arrest or apoptosis after DNA damage",
        "Cyclin D/CDK4 amplification → accelerated passage through Restriction Point",
        "Oncogenic RAS/MYC → bypass of growth factor requirements",
        "Chromosomal instability from defective spindle-assembly checkpoint",
    ]
    for b in cancer_bullets:
        story.append(Paragraph(f"• {b}", S['bullet']))
    story.append(Spacer(1, 8))

    story.append(Paragraph("<b>B. Cell Cycle-Targeted Therapeutics</b>", S['sub_head']))
    drug_data = [
        [Paragraph("<b>Drug Class / Agent</b>", S['table_hdr']),
         Paragraph("<b>Target Phase</b>", S['table_hdr']),
         Paragraph("<b>Mechanism</b>", S['table_hdr'])],
        ["Alkylating agents\n(cyclophosphamide)", "Any phase (most effective S/G2)",
         "Cross-link DNA strands → strand breaks → apoptosis"],
        ["Antimetabolites\n(methotrexate, 5-FU)", "S phase",
         "Inhibit DNA/RNA synthesis; folate antagonism → arrest"],
        ["Taxanes\n(paclitaxel, docetaxel)", "M phase",
         "Stabilise microtubules → prevent spindle disassembly → M arrest"],
        ["Vinca alkaloids\n(vincristine)", "M phase",
         "Inhibit tubulin polymerisation → disrupt spindle formation"],
        ["CDK4/6 inhibitors\n(palbociclib, ribociclib)", "G1 phase",
         "Block Rb phosphorylation → prevent G1→S transition"],
        ["Topoisomerase inhibitors\n(etoposide, irinotecan)", "S/G2 phase",
         "Induce DNA double-strand breaks → S and G2 arrest"],
        ["PARP inhibitors\n(olaparib)", "S phase",
         "Block DNA repair → synthetic lethality in BRCA-mutant cancers"],
    ]
    drug_table = Table(drug_data, colWidths=[130, 100, 240])
    drug_table.setStyle(TableStyle([
        ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor("#C0392B")),
        ('ALIGN', (0, 0), (-1, 0), 'CENTER'),
        ('VALIGN', (0, 0), (-1, -1), 'TOP'),
        ('GRID', (0, 0), (-1, -1), 0.4, colors.HexColor("#BDC3C7")),
        ('ROWBACKGROUNDS', (0, 1), (-1, -1), [
            colors.HexColor("#FDEDEC"), colors.white,
            colors.HexColor("#FDEDEC"), colors.white,
            colors.HexColor("#FDEDEC"), colors.white,
            colors.HexColor("#FDEDEC"),
        ]),
        ('FONTNAME', (0, 1), (0, -1), 'Helvetica-Bold'),
        ('FONTSIZE', (0, 0), (-1, -1), 8.5),
        ('TOPPADDING', (0, 0), (-1, -1), 5),
        ('BOTTOMPADDING', (0, 0), (-1, -1), 5),
        ('LEFTPADDING', (0, 0), (-1, -1), 7),
    ]))
    story.append(drug_table)
    story.append(Spacer(1, 10))
    story.append(PageBreak())

    # ── PAGE 9 – APOPTOSIS & KEY SUMMARY ─────────────────────────────────────
    story.append(SectionHeader("9.  Apoptosis and Cell Death", num=9))
    story.append(Spacer(1, 6))
    story.append(Paragraph(
        "Apoptosis (programmed cell death) is a normal physiologic process that balances "
        "cell proliferation in tissues. It is activated when checkpoint-repair mechanisms "
        "fail, ensuring that damaged cells do not propagate.", S['body']))
    story.append(Spacer(1, 4))

    apop_data = [
        [Paragraph("<b>Type</b>", S['table_hdr']),
         Paragraph("<b>Trigger</b>", S['table_hdr']),
         Paragraph("<b>Features</b>", S['table_hdr'])],
        ["Intrinsic pathway", "DNA damage, hypoxia, oxidative stress",
         "Mitochondria release cytochrome c → activates caspase-9 → caspase-3"],
        ["Extrinsic pathway", "Death receptor ligands (FasL, TNF-α)",
         "Fas/TNFR activation → caspase-8 → caspase-3 → apoptosis"],
        ["Necrosis (non-programmed)", "Severe injury, toxins",
         "Cell swelling → membrane rupture → inflammation; no caspase involvement"],
        ["Anoikis", "Loss of ECM attachment",
         "Cells deprived of substrate → apoptosis; prevents metastasis"],
    ]
    apop_table = Table(apop_data, colWidths=[120, 160, 190])
    apop_table.setStyle(TableStyle([
        ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor("#922B21")),
        ('ALIGN', (0, 0), (-1, 0), 'CENTER'),
        ('VALIGN', (0, 0), (-1, -1), 'TOP'),
        ('GRID', (0, 0), (-1, -1), 0.4, colors.HexColor("#BDC3C7")),
        ('ROWBACKGROUNDS', (0, 1), (-1, -1), [
            colors.HexColor("#FDEDEC"), colors.white,
            colors.HexColor("#FDEDEC"), colors.white,
        ]),
        ('FONTNAME', (0, 1), (0, -1), 'Helvetica-Bold'),
        ('FONTSIZE', (0, 0), (-1, -1), 8.5),
        ('TOPPADDING', (0, 0), (-1, -1), 5),
        ('BOTTOMPADDING', (0, 0), (-1, -1), 5),
        ('LEFTPADDING', (0, 0), (-1, -1), 7),
    ]))
    story.append(apop_table)
    story.append(Spacer(1, 12))

    story.append(SectionHeader("10.  Key Summary Points", num=10))
    story.append(Spacer(1, 6))
    summary_pts = [
        "The cell cycle = G1 → S → G2 → M, with G0 as a quiescent state.",
        "Full cycle takes ~24 h; G1 is the longest and most variable phase.",
        "Checkpoints prevent propagation of DNA errors; p53 is the master guardian.",
        "Cyclins rise and fall rhythmically; CDKs are constitutive but need cyclin binding.",
        "The Restriction Point in G1 is the point of no return; Rb/E2F axis controls it.",
        "Mitosis produces 2 identical 2N daughter cells; meiosis produces 4 unique N cells.",
        "Cancer = deregulated cell cycle; most oncogenes/tumour suppressors map to checkpoint pathways.",
        "Many anticancer drugs exploit phase-specific vulnerabilities (S phase, M phase).",
        "CDK4/6 inhibitors (palbociclib etc.) are a clinical success story of checkpoint targeting.",
        "Apoptosis and the cell cycle are coupled: irreparable DNA damage → apoptosis, not division.",
    ]
    for i, pt in enumerate(summary_pts, 1):
        story.append(Paragraph(f"<b>{i}.</b>  {pt}", S['bullet']))

    story.append(Spacer(1, 10))
    story.append(InfoBox([
        "Sources: Histology – A Text and Atlas with Correlated Cell and Molecular Biology (Wolters Kluwer)",
        "         Berek & Novak's Gynecology, 16th ed. | Scott-Brown's Otorhinolaryngology Head & Neck Surgery",
    ], col=BG_LIGHT, border_col=DEEP_BLUE))

    # ── BUILD ────────────────────────────────────────────────────────────────
    def on_page(canvas, doc):
        # Header/Footer on all pages except cover
        if doc.page > 1:
            canvas.saveState()
            canvas.setFillColor(DEEP_BLUE)
            canvas.setFont("Helvetica-Bold", 8)
            canvas.drawString(2.2*cm, H - 1.4*cm, "THE CELL CYCLE")
            canvas.setFont("Helvetica", 8)
            canvas.drawRightString(W - 2.2*cm, H - 1.4*cm, "Orris Medical AI")
            canvas.setStrokeColor(ACCENT)
            canvas.setLineWidth(0.8)
            canvas.line(2.2*cm, H - 1.6*cm, W - 2.2*cm, H - 1.6*cm)
            # Footer
            canvas.setFont("Helvetica", 7.5)
            canvas.setFillColor(colors.HexColor("#7F8C8D"))
            canvas.drawCentredString(W/2, 1.2*cm, f"Page {doc.page - 1}")
            canvas.setStrokeColor(colors.HexColor("#BDC3C7"))
            canvas.setLineWidth(0.5)
            canvas.line(2.2*cm, 1.6*cm, W - 2.2*cm, 1.6*cm)
            canvas.restoreState()

    doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
    print(f"PDF saved to: {path}")


if __name__ == "__main__":
    out = "/tmp/workspace/cell-cycle-pdf/Cell_Cycle.pdf"
    build_pdf(out)
Your credits are exhausted. You can purchase a top-up or subscribe to a plan to continue using Orris. If you're already subscribed, your daily credits will reset tomorrow.

Where is the pdf

Your credits are exhausted. You can purchase a top-up or subscribe to a plan to continue using Orris. If you're already subscribed, your daily credits will reset tomorrow.
This is a shared conversation. Sign in to Orris to start your own chat.