Describe the steps of TRANSCRIPTION(Eukaryotes & prokaryotes) with the help of a diagram. b) Add a note on post transcriponal modificaons***

Reading File
Finding Sources
Searching Images

transcription prokaryote eukaryote RNA polymerase diagram steps

Searching Images

post transcriptional modification mRNA capping polyadenylation splicing

Reading File
Reading File
Finding Sources
Loading Image
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Reading File
Loading Image
Loading Image
Reading File
Reading File
Reading File
Reading File
Reading File
Loading Image
Loading Image
I now have comprehensive material from the textbooks to deliver a thorough, well-illustrated answer. Let me compile the full response.

Transcription: Steps in Prokaryotes and Eukaryotes

What is Transcription?

Transcription is the process by which the information stored in a DNA sequence is copied into a complementary RNA molecule by the enzyme RNA polymerase. The DNA strand that serves as the template is read in the 3'→5' direction, while the RNA product is synthesized in the 5'→3' direction. The non-transcribed strand (coding/sense strand) has the same sequence as the RNA produced (with U in place of T).

PART A: Steps of Transcription


I. PROKARYOTIC TRANSCRIPTION

The RNA Polymerase

The prokaryotic RNA polymerase consists of two distinct forms:
  • Core enzyme: 5 subunits (2α, 1β, 1β', 1ω) - responsible for template binding and polymerase activity, but cannot recognize the promoter alone.
  • Holoenzyme: Core enzyme + σ (sigma) factor - the sigma factor enables the enzyme to specifically recognize promoter sequences. The predominant sigma factor is σ70.

Step 1 - Initiation

The holoenzyme binds to the promoter region (which is not itself transcribed). Prokaryotic promoters contain two well-conserved consensus sequences:
Prokaryotic promoter region showing -35 sequence (TTGACA) and Pribnow box (TATAAT) centered at -10
Figure: Structure of the prokaryotic promoter region - Lippincott's Illustrated Reviews in Biochemistry, 8th ed.
  • -35 Sequence (5'-TTGACA-3'): The initial point of holoenzyme contact; a closed complex is formed.
  • Pribnow box / -10 Sequence (5'-TATAAT-3'): The holoenzyme moves to cover this region and melts ~14 base pairs of DNA, forming the transcription bubble (open complex).
  • RNA pol then begins synthesizing short RNA fragments. Once the transcript exceeds ~10 nucleotides, the sigma factor is released, and the core enzyme clears the promoter to begin elongation.

Step 2 - Elongation

  • The DNA helix continues to locally unwind ahead of the polymerase as it moves along the template strand.
  • Ribonucleoside triphosphates (NTPs) are added sequentially, complementary to the template, with release of pyrophosphate.
  • A short DNA-RNA hybrid helix is maintained within the transcription bubble.
  • Synthesis is always 5'→3'.
  • Unlike DNA polymerase, RNA pol requires no primer and has no proofreading (3'→5' exonuclease) activity.
  • DNA topoisomerases relieve the supercoiling generated ahead of the moving polymerase.

Step 3 - Termination

Two mechanisms exist:
a) Rho-independent (intrinsic) termination:
Rho-independent termination: hairpin structure formed in nascent RNA with poly-U tail
Figure: Rho-independent termination of prokaryotic transcription - Lippincott's Illustrated Reviews in Biochemistry, 8th ed.
  • A self-complementary sequence in the nascent RNA folds to form a GC-rich hairpin structure.
  • Just downstream of the hairpin, the RNA transcript contains a run of U residues.
  • The weak U:A base pairing (RNA-DNA hybrid) at this point, combined with the hairpin, destabilizes the transcription complex and causes RNA release.
b) Rho-dependent termination:
  • The rho (ρ) protein is a hexameric ATPase with helicase activity.
  • Rho binds a C-rich rho utilization (rut) site near the 5' end of the nascent RNA.
  • It travels along the RNA using ATPase activity until it reaches an RNA pol paused at the termination site.
  • Rho's ATP-dependent helicase activity then separates the RNA-DNA hybrid, releasing the transcript.
Antibiotic note: Rifampin (rifampicin) inhibits prokaryotic transcription by binding the β subunit of RNA pol, blocking chain elongation beyond 3 nucleotides. It is used in treating tuberculosis.

Key Difference: Prokaryotic mRNA is NOT extensively processed

In prokaryotes, because there is no nuclear membrane, translation begins at the 5' end of the mRNA while transcription is still occurring at the 3' end (coupled transcription-translation). Prokaryotic mRNA is generally identical to its primary transcript - no capping, no polyadenylation, no splicing.

II. EUKARYOTIC TRANSCRIPTION

Eukaryotic transcription is far more complex. Key differences from prokaryotes:
  • Three distinct nuclear RNA polymerases (RNA pol I, II, III), each for different gene classes
  • Transcription factors (TFs) are required - RNA pol cannot bind promoters alone
  • Occurs in the nucleus, separated from translation
  • Primary transcript (pre-mRNA/hnRNA) undergoes extensive processing
RNA PolymeraseProducts
RNA Pol I28S, 18S, 5.8S rRNA (in nucleolus)
RNA Pol IImRNA precursors (hnRNA), snRNA
RNA Pol IIItRNA, 5S rRNA, some snRNA/snoRNA
Inhibitor note: α-Amanitin (toxin of the "death cap" mushroom Amanita phalloides) tightly inhibits RNA Pol II, blocking mRNA synthesis.

Step 1 - Initiation in Eukaryotes

  • Chromatin remodeling must occur first: histone acetyltransferases (HATs) acetylate lysine residues on histones, reducing their affinity for DNA and opening euchromatin for access.
  • The core promoter for RNA pol II genes contains:
    • TATA box (TATA[A/T]A), centered at ~-25 (the "Hogness box") - present in ~12.5% of eukaryotic promoters
    • Initiator element (Inr) at +1
    • Downstream promoter element (DPE)
    • TFIIB-recognition element (BRE)
  • General Transcription Factors (GTFs: TFIIA, TFIIB, TFIID, TFIIE, TFIIF, TFIIH) assemble sequentially at the promoter to form the preinitiation complex (PIC).
  • TFIID (containing TBP - TATA-binding protein) binds first, followed by other GTFs and finally RNA pol II.
  • TFIIH has kinase activity that phosphorylates the C-terminal domain (CTD) of RNA pol II, triggering promoter escape and elongation.
  • Enhancers - special DNA sequences that can be upstream or downstream of the gene - bind specific transcription factors (STFs) and stimulate transcription through DNA looping.

Step 2 - Elongation in Eukaryotes

  • RNA pol II moves along the template strand in the 3'→5' direction, synthesizing RNA 5'→3'.
  • The 5' cap is added co-transcriptionally to the nascent RNA almost immediately after the 5' end emerges from RNA pol II.
  • The gene contains both exons (coding sequences) and introns (non-coding sequences) - the entire gene including introns is transcribed into a primary transcript called pre-mRNA (also called heterogeneous nuclear RNA, hnRNA).

Step 3 - Termination in Eukaryotes

  • For RNA pol II, termination is linked to the polyadenylation signal.
  • The AAUAAA signal sequence near the 3' end of the transcript triggers cleavage of the RNA and subsequent polyadenylation.
  • Termination occurs at a variable distance downstream of the cleavage/polyadenylation site.

Flow of information - DNA → mRNA → Protein (Eukaryotic Overview):

Flow of information: transcription showing nontranscribed/transcribed strands, RNA processing with CAP and polyA addition, RNA splicing, nuclear transport, and translation
Figure: Flow of information from DNA to RNA to protein for a gene with 3 exons and 2 introns. Steps include transcription, RNA processing and splicing, nuclear transport, and translation - Thompson & Thompson Genetics and Genomics in Medicine, 9th ed.

PART B: Post-Transcriptional Modifications (Eukaryotes)

Post-transcriptional modifications convert the primary transcript (hnRNA/pre-mRNA) into a mature, translatable mRNA. All major modifications occur in the nucleus. Prokaryotic mRNA generally undergoes none of these.
Overview of eukaryotic mRNA synthesis: hnRNA → 5' cap addition + poly(A) tail → splicing → mature mRNA → nuclear export
Figure: Overview of eukaryotic mRNA synthesis - Basic Medical Biochemistry: A Clinical Approach, 6th ed.

1. 5' Capping

7-Methylguanosine triphosphate cap connected via unusual 5'-to-5' triphosphate linkage; poly-A tail at 3' end; polyadenylation signal AAUAAA
Figure: Posttranscriptional modification of mRNA showing the 7-methylguanosine cap and poly-A tail - Lippincott's Illustrated Reviews in Biochemistry, 8th ed.
  • Occurs co-transcriptionally (as the 5' end of the pre-mRNA emerges from RNA pol II).
  • Steps:
    1. The 5'-terminal triphosphate loses one phosphate → 5'-diphosphate.
    2. The enzyme guanylyltransferase catalyzes addition of GMP via an unusual 5'-to-5' triphosphate linkage.
    3. Guanine-7-methyltransferase methylates position 7 of the added guanine, using S-adenosylmethionine (SAM) as the methyl donor → forms the 7-methylguanosine (m7G) cap.
    4. Additional methylations may occur at the 2'-OH of the first (Cap 1) or second (Cap 2) nucleotide.
Functions of the 5' cap:
  • Protects mRNA from 5' exonucleases (increases stability)
  • Required for efficient initiation of translation (recognized by eIF4E)
  • Facilitates nuclear export
  • Marks the mRNA as "self" (prevents innate immune activation)

2. 3' Polyadenylation (Poly-A Tail Addition)

  • The pre-mRNA is cleaved at a specific site downstream of the polyadenylation signal sequence (5'-AAUAAA-3') near the 3' end.
  • Polyadenylate polymerase then adds a chain of 40-250 adenylate residues (AMP) to the new 3'-OH end, using ATP as substrate.
  • The poly-A tail is NOT encoded in the DNA; it is added post-transcriptionally.
Functions of the poly-A tail:
  • Increases mRNA stability (protects from 3' exonuclease degradation)
  • Facilitates nuclear export via poly-A binding protein (PABP)
  • Aids ribosome recruitment and translation
  • Gradually shortened after the mRNA enters the cytosol

3. RNA Splicing (Removal of Introns)

  • The primary transcript contains both introns (intervening sequences) and exons (expressed sequences).
  • Splicing removes introns and joins the exons to produce the mature, continuous coding mRNA.
  • Carried out by the spliceosome - a large ribonucleoprotein complex composed of five snRNPs (small nuclear ribonucleoproteins): U1, U2, U4, U5, U6.
  • U1 snRNP binds the 5' splice site (donor site: GU at the intron start).
  • U2 snRNP binds an adenine nucleotide at the branch point within the intron.
  • The 2'-OH of the branch-point A attacks the 5' splice site, forming a lariat intermediate.
  • The freed 3'-OH of the upstream exon then attacks the 3' splice site (AG at the intron end), joining the exons and releasing the lariat intron for degradation.
Significance of splicing:
  • Alternative splicing - different combinations of exons can be joined from a single pre-mRNA, generating multiple protein isoforms from one gene (a major source of proteome diversity in eukaryotes)

4. Modifications of tRNA (Both Prokaryotes and Eukaryotes)

  • tRNAs are transcribed as longer precursors (~100 nucleotides).
  • RNase P cleaves the 5' end; endonucleases cleave the 3' end.
  • A -CCA sequence is added to the 3' terminus by nucleotidyltransferase (required for amino acid attachment).
  • Intronic sequences in the anticodon loop are removed by endonucleases and rejoined by RNA ligase.
  • Specific bases are chemically modified at defined positions: dihydrouracil (D), ribothymidine (T), pseudouridine (ψ), inosine - these modifications give each tRNA species its unique identity and structural stability.

5. Modifications of rRNA (Both Prokaryotes and Eukaryotes)

  • rRNA is transcribed as a large pre-rRNA precursor.
    • Prokaryotes: one pre-rRNA → 23S, 16S, 5S rRNA
    • Eukaryotes: one 45S pre-rRNA → 28S, 18S, 5.8S rRNA (5S rRNA transcribed separately by RNA Pol III)
  • Ribonucleases cleave and trim the precursor into the mature rRNA species.
  • In eukaryotes, processing occurs in the nucleolus, assisted by snoRNA (small nucleolar RNA), which guide base and 2'-OH ribose methylations.

Summary Comparison Table

FeatureProkaryotesEukaryotes
RNA polymeraseSingle RNA pol (holoenzyme with σ factor)Three nuclear RNA pols (I, II, III)
Promoter elements-35 (TTGACA) + Pribnow box (TATAAT)TATA box (~-25), Inr, DPE, BRE + enhancers
Transcription factorsσ factorMultiple general TFs (TFIIA-H) + specific TFs
Site of transcriptionCytoplasm (no nucleus)Nucleus
Coupled to translation?Yes (simultaneous)No (separated by nuclear envelope)
mRNA processingMinimal (none for mRNA)Extensive: 5' cap, poly-A tail, splicing
IntronsAbsent (in most prokaryotes)Present; removed by spliceosome
TerminationRho-independent or rho-dependentLinked to polyadenylation signal
Antibiotic targetRifampin (β subunit of RNA pol)α-Amanitin (RNA Pol II)

Sources: Lippincott's Illustrated Reviews in Biochemistry, 8th ed. | Basic Medical Biochemistry: A Clinical Approach, 6th ed. | Thompson & Thompson Genetics and Genomics in Medicine, 9th ed. | Medical Microbiology, 9th ed.

Generate a visual study guide (PDF) summarizing transcription steps and post-transcriptional modifications

Reading File
Running Command

ls /tmp/workspace/ 2>/dev/null || mkdir -p /tmp/workspace && echo "workspace ready"

Running Command

mkdir -p /tmp/workspace/transcription-guide && echo "dir created"

Writing File

~/transcription-guide/generate_guide.py

"""
Visual Study Guide: Transcription (Prokaryotes & Eukaryotes) + Post-Transcriptional Modifications
Generated using ReportLab
"""

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

# ── Colour Palette ──────────────────────────────────────────────────────────
NAVY       = colors.HexColor("#1A3A5C")
TEAL       = colors.HexColor("#0E7490")
CYAN_LIGHT = colors.HexColor("#CFFAFE")
BLUE_MID   = colors.HexColor("#3B82F6")
BLUE_LIGHT = colors.HexColor("#DBEAFE")
GREEN_DARK = colors.HexColor("#065F46")
GREEN_MID  = colors.HexColor("#10B981")
GREEN_LIGHT= colors.HexColor("#D1FAE5")
PURPLE_MID = colors.HexColor("#7C3AED")
PURPLE_LIGHT=colors.HexColor("#EDE9FE")
ORANGE_MID = colors.HexColor("#D97706")
ORANGE_LIGHT=colors.HexColor("#FEF3C7")
RED_MID    = colors.HexColor("#DC2626")
RED_LIGHT  = colors.HexColor("#FEE2E2")
GREY_LIGHT = colors.HexColor("#F1F5F9")
GREY_MID   = colors.HexColor("#94A3B8")
GREY_DARK  = colors.HexColor("#334155")
WHITE      = colors.white
BLACK      = colors.black
PINK_LIGHT = colors.HexColor("#FCE7F3")
PINK_MID   = colors.HexColor("#DB2777")

PAGE_W, PAGE_H = A4

# ── Styles ───────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()

def make_style(name, parent="Normal", **kwargs):
    return ParagraphStyle(name, parent=styles[parent], **kwargs)

S_TITLE     = make_style("Title2",   fontName="Helvetica-Bold",  fontSize=22, textColor=WHITE,       alignment=TA_CENTER, spaceAfter=4)
S_SUBTITLE  = make_style("Sub2",     fontName="Helvetica",       fontSize=11, textColor=CYAN_LIGHT,  alignment=TA_CENTER, spaceAfter=2)
S_H1        = make_style("H1",       fontName="Helvetica-Bold",  fontSize=14, textColor=WHITE,       spaceBefore=6, spaceAfter=4)
S_H2        = make_style("H2",       fontName="Helvetica-Bold",  fontSize=11, textColor=NAVY,        spaceBefore=4, spaceAfter=3)
S_H3        = make_style("H3",       fontName="Helvetica-Bold",  fontSize=9.5,textColor=TEAL,        spaceBefore=3, spaceAfter=2)
S_BODY      = make_style("Body2",    fontName="Helvetica",       fontSize=8.5,textColor=GREY_DARK,   spaceAfter=2, leading=12)
S_BULLET    = make_style("Bullet2",  fontName="Helvetica",       fontSize=8,  textColor=GREY_DARK,   leftIndent=12, bulletIndent=4, spaceAfter=1, leading=11)
S_CAPTION   = make_style("Caption2", fontName="Helvetica-Oblique",fontSize=7.5,textColor=GREY_MID,   alignment=TA_CENTER, spaceAfter=2)
S_LABEL     = make_style("Label2",   fontName="Helvetica-Bold",  fontSize=8,  textColor=WHITE,       alignment=TA_CENTER)
S_TABLE_H   = make_style("TH",       fontName="Helvetica-Bold",  fontSize=8,  textColor=WHITE,       alignment=TA_CENTER)
S_TABLE_B   = make_style("TB",       fontName="Helvetica",       fontSize=7.5,textColor=GREY_DARK,   alignment=TA_CENTER)
S_TABLE_BL  = make_style("TBL",      fontName="Helvetica",       fontSize=7.5,textColor=GREY_DARK,   alignment=TA_LEFT)
S_NOTE      = make_style("Note",     fontName="Helvetica-Oblique",fontSize=7.5,textColor=GREY_DARK,  spaceAfter=2)
S_BOX_TITLE = make_style("BoxTitle", fontName="Helvetica-Bold",  fontSize=9,  textColor=WHITE,       alignment=TA_CENTER)
S_BOX_BODY  = make_style("BoxBody",  fontName="Helvetica",       fontSize=8,  textColor=GREY_DARK,   leading=11)
S_STEP_NUM  = make_style("StepNum",  fontName="Helvetica-Bold",  fontSize=16, textColor=WHITE,       alignment=TA_CENTER)
S_STEP_TXT  = make_style("StepTxt",  fontName="Helvetica-Bold",  fontSize=9,  textColor=NAVY,        spaceAfter=1)


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

class ColorBanner(Flowable):
    """Full-width colored banner with title and subtitle."""
    def __init__(self, title, subtitle="", bg=NAVY, height=55*mm):
        super().__init__()
        self.title = title
        self.subtitle = subtitle
        self.bg = bg
        self.bh = height
        self.width = PAGE_W - 2*cm

    def wrap(self, aw, ah):
        self.width = aw
        return (aw, self.bh)

    def draw(self):
        c = self.canv
        w, h = self.width, self.bh
        # Background
        c.setFillColor(self.bg)
        c.roundRect(0, 0, w, h, 8, fill=1, stroke=0)
        # Decorative circles
        c.setFillColor(colors.HexColor("#FFFFFF20"))
        c.circle(w - 30, h - 20, 40, fill=1, stroke=0)
        c.circle(w - 60, 10, 25, fill=1, stroke=0)
        c.circle(20, h + 5, 30, fill=1, stroke=0)
        # Title
        c.setFillColor(WHITE)
        c.setFont("Helvetica-Bold", 20)
        c.drawCentredString(w/2, h - 28, self.title)
        # Subtitle
        if self.subtitle:
            c.setFillColor(CYAN_LIGHT)
            c.setFont("Helvetica", 10)
            c.drawCentredString(w/2, h - 44, self.subtitle)
        # Bottom accent line
        c.setStrokeColor(TEAL)
        c.setLineWidth(2)
        c.line(w*0.2, 8, w*0.8, 8)


class SectionHeader(Flowable):
    """Colored section header bar."""
    def __init__(self, text, bg=TEAL, text_color=WHITE, height=10*mm):
        super().__init__()
        self.text = text
        self.bg = bg
        self.text_color = text_color
        self.bh = height

    def wrap(self, aw, ah):
        self.width = aw
        return (aw, self.bh)

    def draw(self):
        c = self.canv
        w, h = self.width, self.bh
        c.setFillColor(self.bg)
        c.roundRect(0, 0, w, h, 5, fill=1, stroke=0)
        c.setFillColor(self.text_color)
        c.setFont("Helvetica-Bold", 11)
        c.drawString(10, h/2 - 4, self.text)


class StepBox(Flowable):
    """Numbered step box with title and bullet items."""
    def __init__(self, number, title, bullets, bg=BLUE_LIGHT, accent=BLUE_MID, width=None, height=None):
        super().__init__()
        self.number = number
        self.title = title
        self.bullets = bullets
        self.bg = bg
        self.accent = accent
        self._width = width or 85*mm
        self._height = height or 55*mm

    def wrap(self, aw, ah):
        return (self._width, self._height)

    def draw(self):
        c = self.canv
        w, h = self._width, self._height
        # Background
        c.setFillColor(self.bg)
        c.roundRect(0, 0, w, h, 6, fill=1, stroke=0)
        # Accent left bar
        c.setFillColor(self.accent)
        c.roundRect(0, 0, 6, h, 6, fill=1, stroke=0)
        c.rect(3, 0, 3, h, fill=1, stroke=0)  # square right side of bar
        # Step circle
        c.setFillColor(self.accent)
        c.circle(22, h - 16, 12, fill=1, stroke=0)
        c.setFillColor(WHITE)
        c.setFont("Helvetica-Bold", 13)
        c.drawCentredString(22, h - 20, str(self.number))
        # Title
        c.setFillColor(NAVY)
        c.setFont("Helvetica-Bold", 9.5)
        c.drawString(40, h - 20, self.title)
        # Divider
        c.setStrokeColor(self.accent)
        c.setLineWidth(0.5)
        c.line(12, h - 28, w - 8, h - 28)
        # Bullets
        c.setFillColor(GREY_DARK)
        c.setFont("Helvetica", 7.5)
        y = h - 40
        for b in self.bullets:
            # Bullet dot
            c.setFillColor(self.accent)
            c.circle(20, y + 2.5, 2, fill=1, stroke=0)
            c.setFillColor(GREY_DARK)
            # Text wrapping
            max_chars = int((w - 36) / 4.3)
            words = b.split()
            line = ""
            first = True
            for word in words:
                test = (line + " " + word).strip()
                if len(test) <= max_chars:
                    line = test
                else:
                    c.drawString(26, y, line)
                    y -= 10
                    line = word
                    first = False
            if line:
                c.drawString(26, y, line)
                y -= 11
            if y < 8:
                break


class ArrowDiagram(Flowable):
    """Horizontal flow arrow diagram for transcription steps."""
    def __init__(self, steps, colors_list, width=None, height=22*mm):
        super().__init__()
        self.steps = steps
        self.colors_list = colors_list
        self._width = width or PAGE_W - 2*cm
        self._height = height

    def wrap(self, aw, ah):
        self._width = aw
        return (aw, self._height)

    def draw(self):
        c = self.canv
        n = len(self.steps)
        w, h = self._width, self._height
        box_w = (w - (n-1)*8) / n
        bh = h - 4

        for i, (step, col) in enumerate(zip(self.steps, self.colors_list)):
            x = i * (box_w + 8)
            # Chevron shape
            if i < n - 1:
                # Draw arrow shape
                pts = [
                    x, bh,
                    x + box_w - 6, bh,
                    x + box_w + 2, bh/2,
                    x + box_w - 6, 0,
                    x, 0,
                    x + 6, bh/2,
                ]
                if i == 0:
                    pts = [
                        x, bh,
                        x + box_w - 6, bh,
                        x + box_w + 2, bh/2,
                        x + box_w - 6, 0,
                        x, 0,
                    ]
                c.setFillColor(col)
                p = c.beginPath()
                p.moveTo(pts[0], pts[1])
                for j in range(2, len(pts), 2):
                    p.lineTo(pts[j], pts[j+1])
                p.close()
                c.drawPath(p, fill=1, stroke=0)
            else:
                c.setFillColor(col)
                c.roundRect(x, 0, box_w, bh, 4, fill=1, stroke=0)

            # Text
            c.setFillColor(WHITE)
            c.setFont("Helvetica-Bold", 7.5)
            txt_x = x + box_w/2 + (3 if i > 0 else 0)
            lines = step.split("\n")
            start_y = bh/2 + (len(lines)-1) * 5
            for li, ln in enumerate(lines):
                c.drawCentredString(txt_x, start_y - li*10, ln)


class ComparisonTable(Flowable):
    """Side-by-side comparison panel."""
    def __init__(self, headers, rows, col_colors, width=None, height=None):
        super().__init__()
        self.headers = headers
        self.rows = rows
        self.col_colors = col_colors
        self._width = width
        self._height = height

    def wrap(self, aw, ah):
        self._width = self._width or aw
        return (self._width, self._height or 60*mm)

    def draw(self):
        c = self.canv
        w = self._width
        n_cols = len(self.headers)
        col_w = w / n_cols
        row_h = 14
        header_h = 16

        # Header row
        for i, (hdr, col) in enumerate(zip(self.headers, self.col_colors)):
            c.setFillColor(col)
            c.rect(i * col_w, self._height - header_h, col_w, header_h, fill=1, stroke=0)
            c.setFillColor(WHITE)
            c.setFont("Helvetica-Bold", 8)
            c.drawCentredString(i * col_w + col_w/2, self._height - header_h + 5, hdr)

        # Data rows
        for r, row in enumerate(self.rows):
            y = self._height - header_h - (r+1) * row_h
            bg = GREY_LIGHT if r % 2 == 0 else WHITE
            c.setFillColor(bg)
            c.rect(0, y, w, row_h, fill=1, stroke=0)
            for ci, cell in enumerate(row):
                is_feature = (ci == 0)
                c.setFillColor(GREY_DARK if not is_feature else NAVY)
                c.setFont("Helvetica-Bold" if is_feature else "Helvetica", 7.2)
                # Left-align feature column, center others
                if is_feature:
                    c.drawString(ci * col_w + 4, y + 4, cell)
                else:
                    c.drawCentredString(ci * col_w + col_w/2, y + 4, cell)
            # Row border
            c.setStrokeColor(GREY_LIGHT)
            c.setLineWidth(0.3)
            c.line(0, y, w, y)

        # Outer border
        c.setStrokeColor(GREY_MID)
        c.setLineWidth(0.7)
        c.rect(0, self._height - header_h - len(self.rows)*row_h,
               w, header_h + len(self.rows)*row_h, fill=0, stroke=1)


class ModBox(Flowable):
    """Colored modification card."""
    def __init__(self, number, title, subtitle, points, bg, accent, width=None, height=50*mm):
        super().__init__()
        self.number = number
        self.title = title
        self.subtitle = subtitle
        self.points = points
        self.bg = bg
        self.accent = accent
        self._width = width or 85*mm
        self._height = height

    def wrap(self, aw, ah):
        if self._width is None:
            self._width = aw
        return (self._width, self._height)

    def draw(self):
        c = self.canv
        w, h = self._width, self._height
        # Background card
        c.setFillColor(self.bg)
        c.roundRect(0, 0, w, h, 7, fill=1, stroke=0)
        # Top accent bar
        c.setFillColor(self.accent)
        c.roundRect(0, h - 22, w, 22, 7, fill=1, stroke=0)
        c.rect(0, h - 22, w, 11, fill=1, stroke=0)
        # Number badge
        c.setFillColor(WHITE)
        c.setFillColorRGB(1, 1, 1, alpha=0.25)
        c.circle(18, h - 11, 10, fill=1, stroke=0)
        c.setFillColor(WHITE)
        c.setFont("Helvetica-Bold", 12)
        c.drawCentredString(18, h - 15, str(self.number))
        # Title
        c.setFillColor(WHITE)
        c.setFont("Helvetica-Bold", 9)
        c.drawString(32, h - 15, self.title)
        # Subtitle
        c.setFillColor(self.accent)
        c.setFont("Helvetica-Oblique", 7.5)
        c.drawString(10, h - 32, self.subtitle)
        # Divider
        c.setStrokeColor(self.accent)
        c.setLineWidth(0.5)
        c.line(8, h - 36, w - 8, h - 36)
        # Points
        c.setFont("Helvetica", 7.5)
        y = h - 46
        for pt in self.points:
            c.setFillColor(self.accent)
            c.circle(14, y + 2.5, 2.5, fill=1, stroke=0)
            c.setFillColor(GREY_DARK)
            max_chars = int((w - 30) / 4.3)
            words = pt.split()
            line = ""
            for word in words:
                test = (line + " " + word).strip()
                if len(test) <= max_chars:
                    line = test
                else:
                    c.drawString(21, y, line)
                    y -= 10
                    line = word
            if line:
                c.drawString(21, y, line)
                y -= 11
            if y < 8:
                break


class DNADiagram(Flowable):
    """Simple ASCII-art style DNA-to-mRNA transcription diagram."""
    def __init__(self, width=None, height=48*mm):
        super().__init__()
        self._width = width
        self._height = height

    def wrap(self, aw, ah):
        if self._width is None:
            self._width = aw
        return (self._width, self._height)

    def draw(self):
        c = self.canv
        w, h = self._width, self._height
        mid = w / 2
        # DNA double helix representation (simplified)
        # Top strand label
        c.setFillColor(NAVY)
        c.setFont("Helvetica-Bold", 8)
        c.drawString(8, h - 12, "5'")
        c.drawString(w - 16, h - 12, "3'")
        c.setFont("Helvetica", 7)
        c.setFillColor(GREY_DARK)
        c.drawCentredString(mid, h - 12, "Non-template (coding) strand  5' → 3'")

        # Draw DNA strands
        strand_y1 = h - 22
        strand_y2 = h - 34
        c.setStrokeColor(NAVY)
        c.setLineWidth(2.5)
        c.line(30, strand_y1, w - 30, strand_y1)
        c.setStrokeColor(TEAL)
        c.setLineWidth(2.5)
        c.line(30, strand_y2, w - 30, strand_y2)

        # Base pairs
        c.setStrokeColor(GREY_MID)
        c.setLineWidth(0.8)
        for i in range(8):
            bx = 40 + i * (w - 80) / 7
            c.line(bx, strand_y1, bx, strand_y2)

        # Labels on strands
        c.setFillColor(NAVY)
        c.setFont("Helvetica-Bold", 7.5)
        c.drawString(8, strand_y1 - 3, "")
        c.setFillColor(TEAL)
        c.drawString(8, strand_y2 - 3, "")

        c.setFillColor(GREY_DARK)
        c.setFont("Helvetica", 7)
        c.drawCentredString(mid, strand_y2 - 9, "Template (antisense) strand  3' → 5'")

        # Arrow down
        c.setStrokeColor(ORANGE_MID)
        c.setFillColor(ORANGE_MID)
        c.setLineWidth(1.5)
        arrow_x = mid
        c.line(arrow_x, strand_y2 - 18, arrow_x, strand_y2 - 28)
        # Arrowhead
        c.beginPath()
        c.moveTo(arrow_x - 5, strand_y2 - 25)
        c.lineTo(arrow_x + 5, strand_y2 - 25)
        c.lineTo(arrow_x, strand_y2 - 32)
        c.closePath()
        c.fill()

        # RNA pol label
        c.setFillColor(ORANGE_MID)
        c.setFont("Helvetica-Bold", 8)
        c.drawString(arrow_x + 8, strand_y2 - 22, "RNA Polymerase")

        # mRNA strand
        mrna_y = strand_y2 - 42
        c.setStrokeColor(RED_MID)
        c.setLineWidth(2.5)
        c.line(30, mrna_y, w - 30, mrna_y)
        c.setFillColor(RED_MID)
        c.setFont("Helvetica-Bold", 7.5)
        c.drawString(8, mrna_y - 3, "5'")
        c.drawString(w - 22, mrna_y - 3, "3'")
        c.setFont("Helvetica", 7)
        c.setFillColor(GREY_DARK)
        c.drawCentredString(mid, mrna_y - 10, "Primary RNA transcript (mRNA)  5' → 3'")


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

def build_pdf(path):
    doc = SimpleDocTemplate(
        path,
        pagesize=A4,
        leftMargin=1.5*cm,
        rightMargin=1.5*cm,
        topMargin=1.2*cm,
        bottomMargin=1.2*cm,
        title="Transcription Visual Study Guide",
        author="Orris Medical",
    )

    story = []
    usable_w = PAGE_W - 3*cm

    # ── PAGE 1: COVER / OVERVIEW ───────────────────────────────────────────
    story.append(ColorBanner(
        "TRANSCRIPTION",
        "Visual Study Guide  |  Prokaryotes & Eukaryotes  |  Post-Transcriptional Modifications",
        bg=NAVY,
        height=52*mm
    ))
    story.append(Spacer(1, 5*mm))

    # Big overview flow diagram
    story.append(SectionHeader("  Overview: Flow of Genetic Information", bg=TEAL))
    story.append(Spacer(1, 3*mm))
    steps_overview = ["DNA\nTemplate", "RNA Poly-\nmerase Binds", "Initiation", "Elongation",
                      "Termination", "Primary\nTranscript", "Post-Tx\nModification", "Mature\nmRNA"]
    cols_overview  = [NAVY, TEAL, BLUE_MID, GREEN_MID, PURPLE_MID, ORANGE_MID, PINK_MID, RED_MID]
    story.append(ArrowDiagram(steps_overview, cols_overview, height=20*mm))
    story.append(Spacer(1, 3*mm))

    # DNA diagram
    story.append(DNADiagram(height=42*mm))
    story.append(Spacer(1, 4*mm))

    # Key facts box
    story.append(SectionHeader("  Key Concepts at a Glance", bg=GREY_DARK))
    story.append(Spacer(1, 3*mm))
    key_data = [
        [Paragraph("<b>Definition</b>", S_TABLE_H),
         Paragraph("Synthesis of RNA from a DNA template by RNA polymerase. RNA is made 5'→3', template read 3'→5'.", S_TABLE_BL)],
        [Paragraph("<b>Template strand</b>", S_TABLE_H),
         Paragraph("Antisense/noncoding strand (read 3'→5'). Coding strand = sense strand = same sequence as mRNA (T→U).", S_TABLE_BL)],
        [Paragraph("<b>Substrate</b>", S_TABLE_H),
         Paragraph("Ribonucleoside triphosphates (ATP, GTP, CTP, UTP). Each addition releases pyrophosphate.", S_TABLE_BL)],
        [Paragraph("<b>Primer?</b>", S_TABLE_H),
         Paragraph("None required. RNA pol starts de novo (unlike DNA pol which needs a primer).", S_TABLE_BL)],
        [Paragraph("<b>Proofreading?</b>", S_TABLE_H),
         Paragraph("No 3'→5' exonuclease activity. Higher error rate than replication. RNA pol pauses and backtracks on misincorporation.", S_TABLE_BL)],
    ]
    key_table = Table(key_data, colWidths=[3.5*cm, usable_w - 3.5*cm])
    key_table.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (0, -1), NAVY),
        ("BACKGROUND", (1, 0), (1, -1), WHITE),
        ("ROWBACKGROUNDS", (1, 0), (1, -1), [GREY_LIGHT, WHITE]),
        ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
        ("TOPPADDING", (0, 0), (-1, -1), 5),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
        ("LEFTPADDING", (0, 0), (-1, -1), 6),
        ("GRID", (0, 0), (-1, -1), 0.4, GREY_MID),
        ("ROUNDEDCORNERS", [4]),
    ]))
    story.append(key_table)
    story.append(PageBreak())

    # ── PAGE 2: PROKARYOTIC TRANSCRIPTION ─────────────────────────────────
    story.append(ColorBanner("PROKARYOTIC TRANSCRIPTION",
                              "E. coli model | Single RNA Polymerase | No nuclear envelope",
                              bg=TEAL, height=38*mm))
    story.append(Spacer(1, 4*mm))

    # RNA Pol info
    story.append(SectionHeader("  RNA Polymerase Structure", bg=TEAL))
    story.append(Spacer(1, 3*mm))
    pol_data = [
        [Paragraph("<b>Form</b>", S_TABLE_H),
         Paragraph("<b>Subunits</b>", S_TABLE_H),
         Paragraph("<b>Function</b>", S_TABLE_H)],
        [Paragraph("Core Enzyme", S_TABLE_B),
         Paragraph("2α + β + β' + ω", S_TABLE_B),
         Paragraph("Template binding (β'), polymerase activity (β), assembly (α, ω). Cannot recognize promoter alone.", S_TABLE_BL)],
        [Paragraph("Holoenzyme", S_TABLE_B),
         Paragraph("Core + σ (sigma) factor", S_TABLE_B),
         Paragraph("σ factor enables promoter recognition. σ70 is the predominant sigma factor. After initiation, σ is released.", S_TABLE_BL)],
    ]
    pol_table = Table(pol_data, colWidths=[3*cm, 4*cm, usable_w - 7*cm])
    pol_table.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (-1, 0), NAVY),
        ("ROWBACKGROUNDS", (0, 1), (-1, -1), [BLUE_LIGHT, CYAN_LIGHT]),
        ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
        ("TOPPADDING", (0, 0), (-1, -1), 5), ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
        ("LEFTPADDING", (0, 0), (-1, -1), 5),
        ("GRID", (0, 0), (-1, -1), 0.4, GREY_MID),
    ]))
    story.append(pol_table)
    story.append(Spacer(1, 4*mm))

    # Three steps
    story.append(SectionHeader("  Steps of Prokaryotic Transcription", bg=TEAL))
    story.append(Spacer(1, 3*mm))

    half_w = (usable_w - 4*mm) / 2
    third_w = (usable_w - 8*mm) / 3

    step1 = StepBox(1, "INITIATION",
        ["Holoenzyme binds promoter region (not transcribed)",
         "-35 sequence (TTGACA): initial contact, closed complex forms",
         "Pribnow box / -10 sequence (TATAAT): DNA melts ~14 bp",
         "Open complex (transcription bubble) forms",
         "Short RNA fragments made & discarded until >10 nt",
         "σ factor released; core enzyme clears promoter"],
        bg=BLUE_LIGHT, accent=BLUE_MID, width=third_w, height=62*mm)

    step2 = StepBox(2, "ELONGATION",
        ["Core enzyme moves along template strand 3'→5'",
         "NTPs added sequentially, RNA grows 5'→3'",
         "Short DNA-RNA hybrid helix maintained in bubble",
         "Topoisomerases relieve supercoiling ahead of pol",
         "No primer needed; no proofreading (3'→5' exonuclease)",
         "Misincorporation causes pol to pause & backtrack"],
        bg=GREEN_LIGHT, accent=GREEN_MID, width=third_w, height=62*mm)

    step3 = StepBox(3, "TERMINATION",
        ["Rho-independent: GC-rich hairpin + poly-U tail",
         "Hairpin in nascent RNA destabilizes transcription complex",
         "Weak U:A base pairs facilitate RNA release",
         "Rho-dependent: ρ protein (hexameric ATPase/helicase)",
         "ρ binds rut site, chases polymerase, unwinds hybrid",
         "RNA transcript released from DNA"],
        bg=PURPLE_LIGHT, accent=PURPLE_MID, width=third_w, height=62*mm)

    steps_row = Table([[step1, Spacer(4*mm, 1), step2, Spacer(4*mm, 1), step3]],
                      colWidths=[third_w, 4*mm, third_w, 4*mm, third_w])
    steps_row.setStyle(TableStyle([("VALIGN", (0,0), (-1,-1), "TOP"), ("TOPPADDING", (0,0),(-1,-1),0), ("LEFTPADDING",(0,0),(-1,-1),0)]))
    story.append(steps_row)
    story.append(Spacer(1, 4*mm))

    # Promoter info
    story.append(SectionHeader("  Prokaryotic Promoter Elements", bg=NAVY))
    story.append(Spacer(1, 3*mm))

    prom_data = [
        [Paragraph("<b>Element</b>", S_TABLE_H),
         Paragraph("<b>Position</b>", S_TABLE_H),
         Paragraph("<b>Consensus Sequence</b>", S_TABLE_H),
         Paragraph("<b>Function</b>", S_TABLE_H)],
        [Paragraph("-35 Sequence", S_TABLE_B),
         Paragraph("~35 bp upstream", S_TABLE_B),
         Paragraph("5'-TTGACA-3'", S_TABLE_B),
         Paragraph("Initial holoenzyme docking; closed complex", S_TABLE_BL)],
        [Paragraph("Pribnow Box", S_TABLE_B),
         Paragraph("~10 bp upstream", S_TABLE_B),
         Paragraph("5'-TATAAT-3'", S_TABLE_B),
         Paragraph("DNA melting site; open complex (transcription bubble)", S_TABLE_BL)],
        [Paragraph("Start site", S_TABLE_B),
         Paragraph("+1", S_TABLE_B),
         Paragraph("Usually a purine", S_TABLE_B),
         Paragraph("First nucleotide incorporated into RNA transcript", S_TABLE_BL)],
    ]
    prom_table = Table(prom_data, colWidths=[3*cm, 3*cm, 4*cm, usable_w - 10*cm])
    prom_table.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (-1, 0), NAVY),
        ("ROWBACKGROUNDS", (0, 1), (-1, -1), [CYAN_LIGHT, WHITE]),
        ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
        ("TOPPADDING", (0, 0), (-1, -1), 5), ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
        ("LEFTPADDING", (0, 0), (-1, -1), 5),
        ("GRID", (0, 0), (-1, -1), 0.4, GREY_MID),
    ]))
    story.append(prom_table)
    story.append(Spacer(1, 4*mm))

    # Antibiotic note
    antibiotic_data = [[
        Paragraph("ANTIBIOTIC TARGETS", S_BOX_TITLE),
        Paragraph(
            "<b>Rifampin (Rifampicin):</b> Binds β subunit of prokaryotic RNA pol → blocks chain elongation beyond 3 nt. "
            "Key drug in tuberculosis treatment.<br/>"
            "<b>Actinomycin D (Dactinomycin):</b> Intercalates between DNA bases → inhibits both initiation and elongation. Used in tumour chemotherapy.",
            S_BOX_BODY)
    ]]
    atab = Table(antibiotic_data, colWidths=[4.5*cm, usable_w - 4.5*cm])
    atab.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (0, 0), RED_MID),
        ("BACKGROUND", (1, 0), (1, 0), RED_LIGHT),
        ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
        ("TOPPADDING", (0, 0), (-1, -1), 7), ("BOTTOMPADDING", (0, 0), (-1, -1), 7),
        ("LEFTPADDING", (0, 0), (-1, -1), 7),
        ("ROUNDEDCORNERS", [5]),
        ("BOX", (0, 0), (-1, -1), 0.5, RED_MID),
    ]))
    story.append(atab)
    story.append(PageBreak())

    # ── PAGE 3: EUKARYOTIC TRANSCRIPTION ──────────────────────────────────
    story.append(ColorBanner("EUKARYOTIC TRANSCRIPTION",
                              "Three RNA Polymerases | Transcription Factors | Occurs in Nucleus",
                              bg=PURPLE_MID, height=38*mm))
    story.append(Spacer(1, 4*mm))

    # Three RNA Pols
    story.append(SectionHeader("  Three Nuclear RNA Polymerases", bg=PURPLE_MID))
    story.append(Spacer(1, 3*mm))

    rpol_data = [
        [Paragraph("<b>Enzyme</b>", S_TABLE_H),
         Paragraph("<b>Location</b>", S_TABLE_H),
         Paragraph("<b>Products</b>", S_TABLE_H),
         Paragraph("<b>Inhibitor</b>", S_TABLE_H)],
        [Paragraph("RNA Pol I", S_TABLE_B),
         Paragraph("Nucleolus", S_TABLE_B),
         Paragraph("28S, 18S, 5.8S rRNA (~80% of all cellular RNA)", S_TABLE_BL),
         Paragraph("Not α-amanitin sensitive", S_TABLE_B)],
        [Paragraph("RNA Pol II", S_TABLE_B),
         Paragraph("Nucleoplasm", S_TABLE_B),
         Paragraph("hnRNA (pre-mRNA), snRNA — all protein-coding genes", S_TABLE_BL),
         Paragraph("α-Amanitin (high sensitivity)", S_TABLE_B)],
        [Paragraph("RNA Pol III", S_TABLE_B),
         Paragraph("Nucleoplasm", S_TABLE_B),
         Paragraph("tRNA, 5S rRNA, some snRNA & snoRNA", S_TABLE_BL),
         Paragraph("α-Amanitin (low sensitivity)", S_TABLE_B)],
    ]
    rpol_table = Table(rpol_data, colWidths=[2.8*cm, 2.8*cm, usable_w - 9*cm, 4*cm])
    rpol_table.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (-1, 0), PURPLE_MID),
        ("ROWBACKGROUNDS", (0, 1), (-1, -1), [PURPLE_LIGHT, WHITE]),
        ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
        ("TOPPADDING", (0, 0), (-1, -1), 5), ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
        ("LEFTPADDING", (0, 0), (-1, -1), 5),
        ("GRID", (0, 0), (-1, -1), 0.4, GREY_MID),
    ]))
    story.append(rpol_table)
    story.append(Spacer(1, 4*mm))

    # Steps eukaryotic
    story.append(SectionHeader("  Steps of Eukaryotic Transcription (RNA Pol II)", bg=PURPLE_MID))
    story.append(Spacer(1, 3*mm))

    e_step1 = StepBox(1, "CHROMATIN REMODELING",
        ["Transcribed genes in euchromatin (decondensed)",
         "HATs (histone acetyltransferases) acetylate histone lysines",
         "Acetylation reduces histone-DNA affinity, opens chromatin",
         "HDACs reverse this: restore positive charge, condense chromatin",
         "ATP-dependent nucleosome repositioning also required"],
        bg=ORANGE_LIGHT, accent=ORANGE_MID, width=third_w, height=60*mm)

    e_step2 = StepBox(2, "INITIATION",
        ["General TFs (TFIIA, B, D, E, F, H) assemble at core promoter",
         "TFIID (TBP subunit) binds TATA box first",
         "Other GTFs and RNA Pol II join sequentially",
         "TFIIH phosphorylates CTD of RNA Pol II",
         "Promoter escape occurs; pol clears the promoter",
         "Enhancers + specific TFs increase transcription rate via DNA looping"],
        bg=BLUE_LIGHT, accent=BLUE_MID, width=third_w, height=60*mm)

    e_step3 = StepBox(3, "ELONGATION & TERMINATION",
        ["DNA locally unwound; RNA synthesized 5'→3'",
         "5' cap added co-transcriptionally as RNA emerges",
         "Entire gene (exons + introns) transcribed = pre-mRNA/hnRNA",
         "Termination linked to polyadenylation signal (AAUAAA)",
         "Pre-mRNA cleaved downstream of signal",
         "Poly-A tail added; pol terminates at variable downstream site"],
        bg=GREEN_LIGHT, accent=GREEN_MID, width=third_w, height=60*mm)

    e_steps_row = Table([[e_step1, Spacer(4*mm, 1), e_step2, Spacer(4*mm, 1), e_step3]],
                        colWidths=[third_w, 4*mm, third_w, 4*mm, third_w])
    e_steps_row.setStyle(TableStyle([("VALIGN", (0,0),(-1,-1),"TOP"),("TOPPADDING",(0,0),(-1,-1),0),("LEFTPADDING",(0,0),(-1,-1),0)]))
    story.append(e_steps_row)
    story.append(Spacer(1, 4*mm))

    # Core promoter elements
    story.append(SectionHeader("  Eukaryotic Core Promoter Elements (RNA Pol II)", bg=NAVY))
    story.append(Spacer(1, 3*mm))
    ep_data = [
        [Paragraph("<b>Element</b>", S_TABLE_H),
         Paragraph("<b>Position</b>", S_TABLE_H),
         Paragraph("<b>Consensus</b>", S_TABLE_H),
         Paragraph("<b>Notes</b>", S_TABLE_H)],
        [Paragraph("TATA box (Hogness box)", S_TABLE_B),
         Paragraph("~-25", S_TABLE_B),
         Paragraph("TATA(A/T)A", S_TABLE_B),
         Paragraph("Found in ~12.5% of eukaryotic promoters. Bound by TBP (subunit of TFIID).", S_TABLE_BL)],
        [Paragraph("BRE (TFIIB recognition)", S_TABLE_B),
         Paragraph("~-35 to -30", S_TABLE_B),
         Paragraph("GC-rich", S_TABLE_B),
         Paragraph("Bound by TFIIB. Helps determine transcription direction.", S_TABLE_BL)],
        [Paragraph("Initiator (Inr)", S_TABLE_B),
         Paragraph("+1", S_TABLE_B),
         Paragraph("PyPyA+1NPyPy", S_TABLE_B),
         Paragraph("Spans transcription start site; present in TATA-less promoters.", S_TABLE_BL)],
        [Paragraph("DPE (Downstream)", S_TABLE_B),
         Paragraph("+28 to +34", S_TABLE_B),
         Paragraph("AGCG", S_TABLE_B),
         Paragraph("Works with Inr in TATA-less promoters. Bound by TAF subunits of TFIID.", S_TABLE_BL)],
    ]
    ep_table = Table(ep_data, colWidths=[4*cm, 2.5*cm, 3*cm, usable_w - 9.5*cm])
    ep_table.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (-1, 0), NAVY),
        ("ROWBACKGROUNDS", (0, 1), (-1, -1), [PURPLE_LIGHT, WHITE]),
        ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
        ("TOPPADDING", (0, 0), (-1, -1), 5), ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
        ("LEFTPADDING", (0, 0), (-1, -1), 5),
        ("GRID", (0, 0), (-1, -1), 0.4, GREY_MID),
    ]))
    story.append(ep_table)
    story.append(PageBreak())

    # ── PAGE 4: POST-TRANSCRIPTIONAL MODIFICATIONS ────────────────────────
    story.append(ColorBanner("POST-TRANSCRIPTIONAL MODIFICATIONS",
                              "Eukaryotes only (mRNA)  |  All occur in the nucleus  |  hnRNA → Mature mRNA",
                              bg=GREEN_DARK, height=38*mm))
    story.append(Spacer(1, 4*mm))

    # Flow: hnRNA to mRNA
    story.append(SectionHeader("  Processing Pathway: hnRNA → Mature mRNA", bg=GREEN_DARK))
    story.append(Spacer(1, 3*mm))
    ptm_steps = ["Pre-mRNA\n(hnRNA)", "5' Capping\n(co-Tx)", "3' Poly-A\nTail", "RNA Splicing\n(Spliceosome)", "Mature\nmRNA", "Nuclear\nExport", "Translation\n(Cytoplasm)"]
    ptm_cols  = [TEAL, BLUE_MID, ORANGE_MID, PURPLE_MID, GREEN_MID, NAVY, RED_MID]
    story.append(ArrowDiagram(ptm_steps, ptm_cols, height=20*mm))
    story.append(Spacer(1, 4*mm))

    # Four modification cards
    mod_w = (usable_w - 6*mm) / 2

    mod1 = ModBox(1, "5' CAPPING",
        "Occurs co-transcriptionally as 5' end emerges",
        ["Terminal 5'-triphosphate loses one phosphate",
         "Guanylyltransferase adds GMP via 5'-to-5' triphosphate linkage",
         "Methyltransferase adds CH3 at N7 of guanine using SAM",
         "Result: 7-methylguanosine (m7G) cap",
         "Additional 2'-O-methylations: Cap 0, Cap 1, Cap 2",
         "Functions: protects mRNA from 5' exonucleases, required for translation initiation (eIF4E binding), aids nuclear export"],
        bg=BLUE_LIGHT, accent=BLUE_MID, width=mod_w, height=72*mm)

    mod2 = ModBox(2, "3' POLYADENYLATION",
        "Poly-A tail of 40-250 adenylates added to 3' end",
        ["Polyadenylation signal: AAUAAA (or variant) near 3' end",
         "Pre-mRNA cleaved ~10-30 nt downstream of signal",
         "Polyadenylate polymerase adds AMP residues using ATP",
         "Poly-A tail NOT encoded in DNA — added post-transcriptionally",
         "Histone mRNAs are the major exception (no poly-A tail)",
         "Functions: stability (protects from 3' exonucleases), nuclear export, translation efficiency"],
        bg=ORANGE_LIGHT, accent=ORANGE_MID, width=mod_w, height=72*mm)

    mod3 = ModBox(3, "RNA SPLICING",
        "Introns removed; exons joined by the spliceosome",
        ["Spliceosome = 5 snRNPs: U1, U2, U4, U5, U6",
         "U1 binds 5' splice site (GU at intron start)",
         "U2 binds branch point adenosine within intron",
         "2'-OH of branch A attacks 5' splice site → lariat intermediate",
         "Freed exon 3'-OH attacks 3' splice site (AG) → exons join",
         "Lariat intron excised and degraded",
         "Alternative splicing: multiple isoforms from one gene"],
        bg=PURPLE_LIGHT, accent=PURPLE_MID, width=mod_w, height=72*mm)

    mod4 = ModBox(4, "tRNA & rRNA PROCESSING",
        "Both prokaryotes and eukaryotes modify tRNA and rRNA",
        ["tRNA precursors (~100 nt) cleaved by RNase P (5' end)",
         "CCA triplet added to 3' end by nucleotidyltransferase",
         "Introns (anticodon loop) removed by endonucleases + RNA ligase",
         "Modified bases: dihydrouracil (D), pseudouridine (Ψ), ribothymidine (T), inosine",
         "rRNA: single 45S pre-rRNA → 28S + 18S + 5.8S (eukaryotes)",
         "Processed in nucleolus; snoRNAs guide base/ribose methylations"],
        bg=RED_LIGHT, accent=RED_MID, width=mod_w, height=72*mm)

    mods_row1 = Table([[mod1, Spacer(6*mm, 1), mod2]],
                      colWidths=[mod_w, 6*mm, mod_w])
    mods_row1.setStyle(TableStyle([("VALIGN",(0,0),(-1,-1),"TOP"),("TOPPADDING",(0,0),(-1,-1),0),("LEFTPADDING",(0,0),(-1,-1),0)]))
    story.append(mods_row1)
    story.append(Spacer(1, 4*mm))
    mods_row2 = Table([[mod3, Spacer(6*mm, 1), mod4]],
                      colWidths=[mod_w, 6*mm, mod_w])
    mods_row2.setStyle(TableStyle([("VALIGN",(0,0),(-1,-1),"TOP"),("TOPPADDING",(0,0),(-1,-1),0),("LEFTPADDING",(0,0),(-1,-1),0)]))
    story.append(mods_row2)
    story.append(Spacer(1, 4*mm))

    # Clinical note
    clin_data = [[
        Paragraph("CLINICAL RELEVANCE", S_BOX_TITLE),
        Paragraph(
            "<b>Vitamins B12 & Folate:</b> Required for SAM regeneration; their deficiency impairs 5' capping (mRNA methylation).<br/>"
            "<b>α-Amanitin poisoning:</b> Death cap mushroom toxin inhibits RNA Pol II → no mRNA synthesis → hepatocellular failure.<br/>"
            "<b>Splicing mutations:</b> ~15% of point mutations causing genetic disease affect splice sites, leading to exon skipping or intron retention.",
            S_BOX_BODY)
    ]]
    ctab = Table(clin_data, colWidths=[4.5*cm, usable_w - 4.5*cm])
    ctab.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (0, 0), GREEN_DARK),
        ("BACKGROUND", (1, 0), (1, 0), GREEN_LIGHT),
        ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
        ("TOPPADDING", (0, 0), (-1, -1), 7), ("BOTTOMPADDING", (0, 0), (-1, -1), 7),
        ("LEFTPADDING", (0, 0), (-1, -1), 7),
        ("BOX", (0, 0), (-1, -1), 0.5, GREEN_MID),
    ]))
    story.append(ctab)
    story.append(PageBreak())

    # ── PAGE 5: COMPARISON TABLE ──────────────────────────────────────────
    story.append(ColorBanner("PROKARYOTES vs EUKARYOTES",
                              "Side-by-Side Comparison of Transcription",
                              bg=NAVY, height=35*mm))
    story.append(Spacer(1, 5*mm))

    comp_headers = ["Feature", "PROKARYOTES", "EUKARYOTES"]
    comp_rows = [
        ["RNA polymerase", "Single (core + σ)", "3 nuclear RNA Pols (I, II, III)"],
        ["Sigma / TFs", "σ factor for promoter recognition", "Multiple GTFs (TFIIA-H) + STFs"],
        ["Promoter (-35)", "TTGACA (~-35)", "Not conserved; upstream enhancers"],
        ["Promoter (-10)", "TATAAT (Pribnow box)", "TATA box ~-25 (only 12.5% of genes)"],
        ["Transcription site", "Cytoplasm (no nucleus)", "Nucleus"],
        ["Coupled translation?", "YES - simultaneous", "NO - separated by nuclear envelope"],
        ["Primary transcript", "= mature mRNA (mostly)", "hnRNA / pre-mRNA → needs processing"],
        ["5' Cap", "ABSENT", "7-methylguanosine (m7G)"],
        ["3' Poly-A tail", "ABSENT", "40-250 adenylates (AAUAAA signal)"],
        ["Introns / Splicing", "Absent (most prokaryotes)", "Present; removed by spliceosome"],
        ["mRNA stability", "Short-lived (mins)", "Enhanced by cap + poly-A tail"],
        ["Termination", "Rho-independent or rho-dependent", "Linked to poly-A signal cleavage"],
        ["Antibiotic/toxin", "Rifampin (β subunit)", "α-Amanitin (RNA Pol II)"],
        ["rRNA source", "Pre-rRNA → 23S, 16S, 5S", "45S pre-rRNA → 28S, 18S, 5.8S"],
    ]

    cw_feat = 4.5*cm
    cw_pro  = (usable_w - cw_feat) / 2
    cw_euk  = (usable_w - cw_feat) / 2

    comp_table_data = [
        [Paragraph(comp_headers[0], S_TABLE_H),
         Paragraph(comp_headers[1], S_TABLE_H),
         Paragraph(comp_headers[2], S_TABLE_H)]
    ]
    for row in comp_rows:
        comp_table_data.append([
            Paragraph(row[0], make_style("CTF", fontName="Helvetica-Bold", fontSize=7.5, textColor=NAVY)),
            Paragraph(row[1], S_TABLE_B),
            Paragraph(row[2], S_TABLE_B),
        ])

    ctable = Table(comp_table_data, colWidths=[cw_feat, cw_pro, cw_euk])
    row_bg = []
    for i in range(1, len(comp_table_data)):
        bg = CYAN_LIGHT if i % 2 == 0 else WHITE
        row_bg.append(("BACKGROUND", (1, i), (1, i), bg))
        row_bg.append(("BACKGROUND", (2, i), (2, i), PURPLE_LIGHT if i % 2 == 0 else WHITE))
        row_bg.append(("BACKGROUND", (0, i), (0, i), GREY_LIGHT))

    ctable.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (-1, 0), NAVY),
        ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
        ("TOPPADDING", (0, 0), (-1, -1), 4), ("BOTTOMPADDING", (0, 0), (-1, -1), 4),
        ("LEFTPADDING", (0, 0), (-1, -1), 5),
        ("GRID", (0, 0), (-1, -1), 0.3, GREY_MID),
    ] + row_bg))
    story.append(ctable)
    story.append(Spacer(1, 5*mm))

    # Quick memory tips
    story.append(SectionHeader("  Memory Tips", bg=ORANGE_MID))
    story.append(Spacer(1, 3*mm))

    tips = [
        ("Pribnow = -10 box", "Remember: P comes before T in the alphabet; Pribnow (-10) is closer to the start site than the -35 sequence."),
        ("σ70 = 70 kDa sigma", "The most common sigma factor in E. coli. 'σ70 in bacteria, TFIID in eukaryotes' — both are the first to recognize the core promoter."),
        ("AAUAAA = poly-A signal", "A mnemonic: 'AA U AAA' — the signal that says 'Add Adenines Until AAA.'"),
        ("GU-AG rule", "Introns begin with GU (5' splice site donor) and end with AG (3' splice site acceptor). 'GU...AG' = the spliceosome's address."),
        ("No cap in bacteria", "Prokaryotic mRNAs have no 5' cap and no poly-A tail — their mRNA is directly translated. Only eukaryotes need these modifications."),
    ]
    tips_data = [[Paragraph(f"<b>{t}</b>", S_H3), Paragraph(d, S_BODY)] for t, d in tips]
    tips_table = Table(tips_data, colWidths=[5*cm, usable_w - 5*cm])
    tips_table.setStyle(TableStyle([
        ("ROWBACKGROUNDS", (0, 0), (-1, -1), [ORANGE_LIGHT, WHITE]),
        ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
        ("TOPPADDING", (0, 0), (-1, -1), 5), ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
        ("LEFTPADDING", (0, 0), (-1, -1), 6),
        ("GRID", (0, 0), (-1, -1), 0.3, GREY_MID),
    ]))
    story.append(tips_table)
    story.append(Spacer(1, 4*mm))

    # Footer note
    story.append(Paragraph(
        "Sources: Lippincott's Illustrated Reviews in Biochemistry 8e | Basic Medical Biochemistry: A Clinical Approach 6e | "
        "Thompson & Thompson Genetics and Genomics in Medicine 9e | Medical Microbiology 9e",
        S_CAPTION))

    # ── Build ─────────────────────────────────────────────────────────────
    doc.build(story)
    print(f"PDF saved to: {path}")


if __name__ == "__main__":
    out = "/tmp/workspace/transcription-guide/Transcription_Visual_Study_Guide.pdf"
    build_pdf(out)
Running Command

cd /tmp/workspace/transcription-guide && python generate_guide.py 2>&1

Editing File

~/transcription-guide/generate_guide.py

Successfully replaced 1 instance(s) of the string in '/tmp/workspace/transcription-guide/generate_guide.py'
Running Command

cd /tmp/workspace/transcription-guide && python generate_guide.py 2>&1

Editing File

~/transcription-guide/generate_guide.py

Successfully replaced 1 instance(s) of the string in '/tmp/workspace/transcription-guide/generate_guide.py'
Running Command

cd /tmp/workspace/transcription-guide && python generate_guide.py 2>&1

Running Command

ls -lh /tmp/workspace/transcription-guide/Transcription_Visual_Study_Guide.pdf

Your visual study guide PDF is ready! Here's the download link:

Transcription Visual Study Guide

PDF Document · PDF


The PDF is a 5-page color-coded study guide organized as follows:
PageContent
Page 1Cover + Overview flow diagram (DNA → mRNA in 8 steps) + DNA-to-RNA diagram + Key Concepts table
Page 2Prokaryotic Transcription - RNA Pol structure (core vs holoenzyme), 3 step-boxes (Initiation / Elongation / Termination), Promoter elements table, Antibiotic targets
Page 3Eukaryotic Transcription - 3 RNA Polymerases table, 3 step-boxes (Chromatin Remodeling / Initiation / Elongation & Termination), Core Promoter Elements table
Page 4Post-Transcriptional Modifications - hnRNA → mRNA processing flow + 4 color-coded cards (5' Capping, Poly-A Tail, RNA Splicing, tRNA/rRNA Processing) + Clinical Relevance box
Page 5Full Prokaryotes vs Eukaryotes comparison table (14 features) + Memory Tips
Each section uses a distinct color scheme (teal for prokaryotes, purple for eukaryotes, green for post-Tx modifications) for quick visual navigation.
This is a shared conversation. Sign in to Orris to start your own chat.