Tft in detail for notes and in clinical use simple way and understanding

Reading File
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Finding Sources
I have very thorough material now. Let me compile the comprehensive, well-organized notes on TFT:

Thyroid Function Tests (TFT) - Complete Notes

1. The Hypothalamic-Pituitary-Thyroid (HPT) Axis - Understanding the Foundation

Before TFTs make sense, you need to picture the axis:
Hypothalamus → TRH (Thyrotropin-Releasing Hormone)
      ↓
Pituitary → TSH (Thyroid-Stimulating Hormone)
      ↓
Thyroid gland → T4 (Thyroxine) + T3 (Triiodothyronine)
      ↓
Negative feedback back to hypothalamus + pituitary
Key concept (memorize this): TSH and free T4 have a log-linear inverse relationship - small changes in free T4 produce large, amplified swings in TSH. This is why TSH is the most sensitive early indicator of thyroid dysfunction.

2. The Tests - What They Measure and Why

A. TSH (Thyroid-Stimulating Hormone)

  • Normal range: ~0.5-4.5 mIU/L (lower in early pregnancy: ~0.1-4.0 mIU/L)
  • Made by the anterior pituitary
  • Third-generation ultrasensitive assay can detect levels as low as 0.01 mU/L - this is the gold standard test
  • Because of the log-linear inverse relationship, TSH rises early even when T4 is still within normal range - it is the single most sensitive screening test for primary thyroid dysfunction
  • A normal TSH essentially excludes thyroid dysfunction in most patients - no further testing needed
  • Schwartz's Surgery - the ultrasensitive TSH assay is the most sensitive and specific test for both hyper- and hypothyroidism

B. Total T4

  • Normal range: 55-150 nmol/L
  • Measures both free and protein-bound T4 (>99% is bound - mostly to TBG, some to albumin and transthyretin)
  • Problems: affected by anything that changes TBG levels (pregnancy, estrogens, androgens, liver disease, nephrotic syndrome) - these change total T4 without changing actual thyroid function
  • Not used as first-line test for this reason

C. Free T4 (fT4)

  • Normal range: 12-28 pmol/L
  • Measures only the biologically active unbound fraction
  • Reliable in most settings; used when TSH is abnormal to confirm and grade dysfunction
  • Use: confirms overt hypo/hyperthyroidism, rules out TBG interference

D. Total T3

  • Normal range: 1.5-3.5 nmol/L
  • Reflects mainly peripheral conversion of T4 → T3 (not thyroid output directly)
  • Not suitable as a general screening test
  • Key use: T3 toxicosis - about 5% of hyperthyroid patients have normal T4 but elevated T3 (Graves disease/toxic nodular goiter preferentially secrete T3)
  • In early hypothyroidism, T3 levels are often preserved or even elevated (body compensates by increasing T4→T3 conversion)

E. Free T3 (fT3)

  • Normal range: 3-9 pmol/L
  • Most useful to confirm early hyperthyroidism (free T4 and free T3 rise before total T4/T3)
  • Difficult to measure accurately at low levels - total T3 often used instead in practice

F. T3 Resin Uptake (T3RU) - Indirect Test

  • An older indirect measure of TBG saturation
  • If free T4 is high: fewer TBG binding sites are available for radiolabeled T3 → more T3 binds the resin → T3RU is HIGH
  • Useful to calculate Free T4 Index (FT4I = Total T4 × T3RU) when direct fT4 assays aren't available

G. TRH Stimulation Test

  • Administer 500 mcg TRH IV; measure TSH at 30 and 60 minutes
  • Normal response: TSH rises by at least 6 μIU/mL from baseline
  • Use: largely replaced by sensitive TSH assays; still used occasionally to confirm pituitary hypothyroidism (central hypothyroidism)
  • Inappropriate TSH response to TRH = pituitary hypothyroidism confirmed

3. The "TSH-First" Algorithm - Clinical Approach

Step 1: Measure TSH
│
├─ TSH NORMAL → Thyroid dysfunction essentially excluded (stop)
│
├─ TSH HIGH → Add free T4
│     ├─ High TSH + Low fT4 = OVERT HYPOTHYROIDISM
│     └─ High TSH + Normal fT4 = SUBCLINICAL HYPOTHYROIDISM
│
└─ TSH LOW → Add free T4 AND free/total T3
      ├─ Low TSH + High fT4/T3 = OVERT HYPERTHYROIDISM
      ├─ Low TSH + Normal fT4 → Check free T3
      │     ├─ High T3 = T3 TOXICOSIS
      │     └─ Normal T3 = SUBCLINICAL HYPERTHYROIDISM
      └─ Very low/undetectable TSH alone = significant thyrotoxicosis

4. Interpretation Summary Table

ConditionTSHfT4T3Notes
Overt hypothyroidism↑↑↓ or normalMost common: Hashimoto
Subclinical hypothyroidismNormalNormalEarliest form
Overt hyperthyroidism↓↓Most common: Graves
Subclinical hyperthyroidismNormalNormalTreat if symptomatic
T3 toxicosisNormal↑↑~5% of hyperthyroid cases
Central hypothyroidism (pituitary)Low/normalTSH fails to rise despite low T4
Euthyroid sick syndromeLow/normal↓↓, rT3 ↑Critically ill patients
Pregnancy/estrogens (normal)NormalNormalNormal (fT4)Total T4 ↑ due to TBG, but fT4 normal

5. Thyroid Antibodies

AntibodyWhat it Tells YouAssociated Condition
Anti-TPO (anti-microsomal)Autoimmune thyroid diseaseHashimoto (high sensitivity), also Graves
Anti-Tg (anti-thyroglobulin)Autoimmune thyroid diseaseHashimoto; interferes with Tg tumor marker
TRAb / TSI / LATS (TSH receptor antibody)Highly specific for Graves diseaseGraves (stimulating antibody mimics TSH)
  • Anti-TPO + Anti-Tg do NOT tell you thyroid function - they indicate the underlying disorder
  • ~80% of Hashimoto patients have elevated antibody levels
  • TRAb are highly sensitive AND specific for Graves disease

Serum Thyroglobulin (Tg)

  • Only made by normal or abnormal thyroid tissue
  • Main clinical use: tumor marker for differentiated thyroid cancer surveillance after total thyroidectomy + RAI ablation
  • Always check anti-Tg antibodies alongside Tg (they interfere with the assay)

6. When to Abandon the "TSH-First" Rule

Three situations where TSH alone misleads you:
1. Critically ill patients (Euthyroid Sick Syndrome)
  • Cytokines from systemic illness suppress the HPT axis
  • Pattern: ↓T3, ↓T4, ↑reverse T3 (rT3), normal or low TSH
  • Patient is actually euthyroid - the tests are abnormal, not the thyroid
  • Rule: Do NOT routinely check TFTs in critically ill patients unless there is strong clinical suspicion of pre-existing thyroid disease
2. During thyroid therapy transitions
  • After treating hyperthyroidism: TSH may remain suppressed for months (prolonged thyrotroph cell suppression)
  • After starting levothyroxine: TSH may remain elevated for weeks (thyrotroph hyperplasia)
  • Wait at least 6-8 weeks after a dose change before rechecking TSH (steady state reached ~end of 2nd month in compliant patients)
3. Central (pituitary/hypothalamic) disease suspected
  • TSH will be inappropriately low or normal despite low T4
  • Must interpret TSH and fT4 together - TSH alone will miss central hypothyroidism
  • Clue: TSH is rarely the only pituitary hormone deficient - check all pituitary axes

7. Drugs and TFTs - Clinically Vital

Drugs that Cause TRUE Thyroid Dysfunction

DrugEffectMechanism
AmiodaroneHypo or hyperContains ~37% iodine by weight; direct thyroid toxicity + iodine load. Hypo in iodine-sufficient patients; Hyper in iodine-deficient or multinodular goiter patients
LithiumHypothyroidism (15-50%)Inhibits thyroid hormone synthesis AND secretion; concentrated by thyroid gland
Iodine/contrast mediaHypo (Wolff-Chaikoff) or hyper (Jod-Basedow)Excess iodine → hypothyroidism (Wolff-Chaikoff); iodine deficiency + iodine load → hyperthyroidism (Jod-Basedow)
Tyrosine kinase inhibitorsHypothyroidismVaries by agent
Immune modulators (IFN-α, checkpoint inhibitors)Hypo or hyperAutoimmune thyroiditis

Drugs that Alter TESTS Without Affecting True Function

DrugEffect on TestsTSHMechanism
Estrogens, tamoxifen, raloxifene↑ Total T4, ↑ Total T3Normal↑ TBG production
Androgens↓ Total T4Normal↓ TBG
Furosemide (high dose), salicylates↓ Total T4NormalCompete with T4 for TBG binding
Phenytoin, carbamazepine, rifampin, phenobarbital↓ Total T4 (+ accelerate T4 clearance)Normal or ↓Displace T4 from TBG; increase T4 metabolism
Heparin/LMWH↑ Free T4 (artifact)NormalLiberate free fatty acids that displace T4 from TBG in vitro
Glucocorticoids, dopamine↓ TSHNormal T4/T3Suppress TSH secretion directly
Propranolol (high dose)↓ T3NormalInhibits peripheral T4→T3 conversion
BiotinSpurious results in ALL thyroid assaysFalseInterferes with immunoassay streptavidin-biotin system; hold 1-2 days before testing
Clinical tip: In patients on estrogens or OCPs - total T4/T3 will be high, but free T4 and TSH are normal. Patient is euthyroid. No intervention needed.

8. Specific Clinical Scenarios

Graves Disease

  • Autoantibody (TRAb/TSI) acts as a TSH agonist → continuous unregulated stimulation
  • TFT: Low/undetectable TSH, high fT4, high T3 (T3:T4 ratio >20:1 suggests Graves or toxic nodule over thyroiditis)
  • Confirm: TRAb titer highly sensitive + specific
  • Also has: exophthalmos, pretibial myxedema (not from TFT but clinical features)

Hashimoto Thyroiditis

  • Most common cause of hypothyroidism in developed countries
  • TFT: elevated TSH, low/normal fT4
  • Antibodies: anti-TPO + anti-Tg elevated
  • Note: TSI (TRAb) is NOT found in Hashimoto - this distinguishes it from Graves

Subacute (De Quervain) Thyroiditis

  • Painful thyroid, elevated ESR, often follows viral illness
  • Releases stored hormones → transient hyperthyroidism → then hypothyroidism → recovery
  • T3:T4 ratio lower than Graves (reflects ratio of stored hormones)
  • ESR elevated - useful diagnostic clue

Monitoring Thyroid Cancer

  • After total thyroidectomy + RAI ablation: use serum Tg as tumor marker
  • Always check anti-Tg antibodies simultaneously (they interfere with Tg assay)
  • TSH stimulation (by stopping levothyroxine or using recombinant TSH) enhances Tg sensitivity for detecting recurrence

9. Special Populations

Pregnancy

  • Normal TSH range is lower in pregnancy (~0.1-4.0 mIU/L in 1st trimester)
  • hCG cross-reacts with TSH receptors → slight T4 elevation + TSH suppression in 1st trimester (physiologic)
  • ↑ TBG from estrogen → ↑ Total T4, but free T4 remains normal
  • Hypothyroid women on levothyroxine often need 25-50% dose increase in pregnancy

Neonatal Screening (Congenital Hypothyroidism)

  • Screened at 48-72 hours of age; some advocate a second screen at 2-6 weeks
  • Approaches vary: primary TSH, primary T4 with backup TSH, or both simultaneously
  • TSH-only approach misses: central hypothyroidism + delayed TSH rise cases
  • Most common cause: abnormal thyroid gland development (agenesis/dysgenesis)
  • Untreated: irreversible intellectual and growth retardation (cretinism)

10. Quick Reference - Clinical Pearls

  1. TSH is always first - most sensitive test, amplifies small T4 changes
  2. Normal TSH = normal thyroid function (in most patients, most settings)
  3. Add fT4 when TSH is abnormal to confirm and grade severity
  4. Add T3 when TSH is low but fT4 is normal - look for T3 toxicosis
  5. In central disease - TSH and fT4 must be read together, not TSH alone
  6. In critical illness - euthyroid sick syndrome mimics central hypothyroidism; avoid TFTs unless strong suspicion
  7. After dose changes - wait 6-8 weeks before rechecking (TSH lags)
  8. Amiodarone does everything to TFTs - inhibits T4→T3 conversion (↑T4, ↓T3 even in euthyroid patients) + can cause either hypo or hyperthyroidism
  9. Biotin supplements interfere with assays - hold 1-2 days before testing
  10. Estrogens raise total T4/T3 but not free T4 or TSH - no treatment needed

Sources: Quick Compendium of Clinical Pathology (5th ed.) | Schwartz's Principles of Surgery (11th ed.) | Goldman-Cecil Medicine | Washington Manual of Medical Therapeutics | Henry's Clinical Diagnosis and Management by Laboratory Methods

Create a downloadable quick reference PDF for TFT interpretation

Reading File
Running Command

ls -la /home/daytona/workspace/ 2>/dev/null || mkdir -p /home/daytona/workspace && echo "workspace ready"

Running Command

mkdir -p /home/daytona/workspace/tft-pdf && python3 -c "import reportlab; print('reportlab OK')" && python3 -c "from reportlab.platypus import SimpleDocTemplate; print('platypus OK')"

Writing File

~/tft-pdf/make_tft_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether, PageBreak
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.platypus import Flowable
import reportlab.platypus as plat

# ── Colour palette ─────────────────────────────────────────────────────────────
NAVY      = colors.HexColor("#1B2A4A")
TEAL      = colors.HexColor("#0D7377")
MINT      = colors.HexColor("#14BDAC")
LIGHT_BG  = colors.HexColor("#F0F7F7")
AMBER     = colors.HexColor("#F5A623")
RED_SOFT  = colors.HexColor("#E74C3C")
GREEN_SOFT= colors.HexColor("#27AE60")
GREY_LITE = colors.HexColor("#ECF0F1")
GREY_MID  = colors.HexColor("#BDC3C7")
WHITE     = colors.white
BLACK     = colors.HexColor("#1A1A1A")

W, H = A4   # 595.28 x 841.89 pt

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

def S(name, **kw):
    return ParagraphStyle(name, **kw)

HDR_TITLE = S("HDR_TITLE", fontName="Helvetica-Bold", fontSize=22,
              textColor=WHITE, alignment=TA_CENTER, leading=28)
HDR_SUB   = S("HDR_SUB",   fontName="Helvetica",     fontSize=10,
              textColor=colors.HexColor("#CCE8E8"), alignment=TA_CENTER, leading=14)

SEC_TITLE = S("SEC_TITLE", fontName="Helvetica-Bold", fontSize=11,
              textColor=WHITE, alignment=TA_LEFT, leading=14, spaceBefore=2)
SEC_BODY  = S("SEC_BODY",  fontName="Helvetica", fontSize=8.5,
              textColor=BLACK, leading=12, spaceAfter=2)
SEC_BOLD  = S("SEC_BOLD",  fontName="Helvetica-Bold", fontSize=8.5,
              textColor=BLACK, leading=12)
SMALL     = S("SMALL",     fontName="Helvetica", fontSize=7.5,
              textColor=colors.HexColor("#555555"), leading=10)
FOOTER_S  = S("FOOTER_S",  fontName="Helvetica", fontSize=7,
              textColor=colors.HexColor("#888888"), alignment=TA_CENTER)
PEARL     = S("PEARL",     fontName="Helvetica", fontSize=8,
              textColor=BLACK, leading=12, leftIndent=8)
PEARL_HDR = S("PEARL_HDR", fontName="Helvetica-Bold", fontSize=8.5,
              textColor=TEAL, leading=13, leftIndent=0)

# ── Helper: coloured banner ────────────────────────────────────────────────────
def banner(text, bg=TEAL, style=SEC_TITLE, pad=4):
    tbl = Table([[Paragraph(text, style)]], colWidths=[W - 2*cm])
    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), bg),
        ("TOPPADDING",    (0,0), (-1,-1), pad),
        ("BOTTOMPADDING", (0,0), (-1,-1), pad),
        ("LEFTPADDING",   (0,0), (-1,-1), 8),
        ("RIGHTPADDING",  (0,0), (-1,-1), 8),
        ("ROUNDEDCORNERS", [4, 4, 4, 4]),
    ]))
    return tbl

def spacer(h=4): return Spacer(1, h)

# ── Page canvas (header stripe + footer) ──────────────────────────────────────
def on_page(canvas, doc):
    canvas.saveState()
    # top stripe
    canvas.setFillColor(NAVY)
    canvas.rect(0, H - 18*mm, W, 18*mm, fill=1, stroke=0)
    canvas.setFillColor(MINT)
    canvas.rect(0, H - 20*mm, W, 2*mm, fill=1, stroke=0)
    # header text
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica-Bold", 13)
    canvas.drawString(cm, H - 12*mm, "TFT Quick Reference")
    canvas.setFont("Helvetica", 8)
    canvas.setFillColor(colors.HexColor("#9EC8C8"))
    canvas.drawRightString(W - cm, H - 12*mm, "Thyroid Function Tests | Clinical Reference Card")
    # page number footer
    canvas.setFillColor(colors.HexColor("#AAAAAA"))
    canvas.setFont("Helvetica", 7)
    canvas.drawCentredString(W/2, 8*mm, f"Page {doc.page}")
    canvas.setFillColor(MINT)
    canvas.rect(0, 5*mm, W, 0.5*mm, fill=1, stroke=0)
    canvas.restoreState()

# ── Document setup ─────────────────────────────────────────────────────────────
OUT = "/home/daytona/workspace/tft-pdf/TFT_Quick_Reference.pdf"
doc = SimpleDocTemplate(
    OUT, pagesize=A4,
    leftMargin=cm, rightMargin=cm,
    topMargin=2.4*cm, bottomMargin=1.6*cm,
    title="TFT Quick Reference",
    author="Orris Medical Reference",
    subject="Thyroid Function Tests - Clinical Quick Reference"
)

story = []

# ═══════════════════════════════════════════════════════════════════════════════
# TITLE BLOCK
# ═══════════════════════════════════════════════════════════════════════════════
title_tbl = Table(
    [[Paragraph("THYROID FUNCTION TESTS", HDR_TITLE)],
     [Paragraph("Quick Reference Card  ·  Interpretation  ·  Clinical Use  ·  Drug Effects", HDR_SUB)]],
    colWidths=[W - 2*cm]
)
title_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), NAVY),
    ("TOPPADDING",    (0,0), (-1,-1), 10),
    ("BOTTOMPADDING", (0,0), (-1,-1), 10),
    ("LEFTPADDING",   (0,0), (-1,-1), 12),
    ("RIGHTPADDING",  (0,0), (-1,-1), 12),
    ("LINEBELOW", (0,1), (-1,1), 2, MINT),
]))
story += [title_tbl, spacer(8)]

# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 1: HPT AXIS
# ═══════════════════════════════════════════════════════════════════════════════
story += [banner("1  THE HPT AXIS — UNDERSTANDING THE FEEDBACK LOOP", NAVY), spacer(4)]

axis_data = [
    [Paragraph("<b>Hypothalamus</b>", SEC_BODY),
     Paragraph("Releases <b>TRH</b> (Thyrotropin-Releasing Hormone)", SEC_BODY)],
    [Paragraph("↓", SEC_BODY), Paragraph("", SEC_BODY)],
    [Paragraph("<b>Anterior Pituitary</b>", SEC_BODY),
     Paragraph("Releases <b>TSH</b> (Thyroid-Stimulating Hormone)", SEC_BODY)],
    [Paragraph("↓", SEC_BODY), Paragraph("", SEC_BODY)],
    [Paragraph("<b>Thyroid Gland</b>", SEC_BODY),
     Paragraph("Releases <b>T4</b> (Thyroxine) + <b>T3</b> (Triiodothyronine)", SEC_BODY)],
    [Paragraph("↑ (Negative Feedback)", SMALL),
     Paragraph("T3/T4 inhibit both hypothalamus and pituitary", SMALL)],
]
axis_tbl = Table(axis_data, colWidths=[4.5*cm, W - 2*cm - 4.5*cm])
axis_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), LIGHT_BG),
    ("ROWBACKGROUNDS", (0,0), (-1,-1), [LIGHT_BG, colors.HexColor("#E8F4F4")]),
    ("TOPPADDING",    (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 8),
    ("BOX", (0,0), (-1,-1), 0.5, GREY_MID),
    ("LINEBELOW", (0,1), (-1,1), 0.3, GREY_MID),
    ("LINEBELOW", (0,3), (-1,3), 0.3, GREY_MID),
]))
story += [axis_tbl, spacer(4)]

key_concept = Table(
    [[Paragraph("⚠  KEY CONCEPT: TSH ↔ fT4 have a <b>LOG-LINEAR INVERSE</b> relationship — small changes in fT4 cause large amplified swings in TSH. This makes TSH the most sensitive early marker of thyroid dysfunction.", SEC_BODY)]],
    colWidths=[W - 2*cm]
)
key_concept.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#FFF8E1")),
    ("TOPPADDING",    (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING",   (0,0), (-1,-1), 10),
    ("BOX", (0,0), (-1,-1), 1, AMBER),
    ("LINEAFTER", (0,0), (0,-1), 4, AMBER),
]))
story += [key_concept, spacer(10)]

# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 2: THE TESTS
# ═══════════════════════════════════════════════════════════════════════════════
story += [banner("2  THE TESTS — WHAT THEY MEASURE", TEAL), spacer(4)]

tests_header = ["Test", "Normal Range", "Measures / Key Points"]
tests_data = [
    ["TSH", "0.5–4.5 mIU/L\n(0.1–4.0 in pregnancy)",
     "Best first-line test. Amplifies T4 changes 10×. Third-generation assay detects 0.01 mU/L. Normal TSH = thyroid OK in most patients."],
    ["Free T4\n(fT4)", "12–28 pmol/L",
     "Biologically active unbound fraction. Use when TSH is abnormal to confirm and grade severity. Reliable in most settings."],
    ["Total T4", "55–150 nmol/L",
     "Includes protein-bound T4 (>99%). Affected by TBG changes (estrogens ↑, androgens ↓). Not first-line screening."],
    ["Free T3\n(fT3)", "3–9 pmol/L",
     "Most useful in early hyperthyroidism (rises before total T4/T3). Difficult to measure accurately — total T3 often used instead."],
    ["Total T3", "1.5–3.5 nmol/L",
     "Reflects peripheral T4→T3 conversion more than thyroid output. KEY USE: T3 toxicosis (high T3, normal T4, low TSH ~5% of hyper cases)."],
    ["TRH Stim.\nTest", "TSH rise ≥6 µIU/mL\nat 30 & 60 min",
     "500 µg TRH IV → measure TSH at 30 & 60 min. Largely replaced by sensitive TSH. Still used to confirm central (pituitary) hypothyroidism."],
]

col_w = [2.2*cm, 3.0*cm, W - 2*cm - 5.2*cm]
tests_tbl = Table([tests_header] + tests_data, colWidths=col_w, repeatRows=1)
tests_tbl.setStyle(TableStyle([
    # Header
    ("BACKGROUND", (0,0), (-1,0), NAVY),
    ("TEXTCOLOR",  (0,0), (-1,0), WHITE),
    ("FONTNAME",   (0,0), (-1,0), "Helvetica-Bold"),
    ("FONTSIZE",   (0,0), (-1,0), 8.5),
    ("TOPPADDING",    (0,0), (-1,0), 5),
    ("BOTTOMPADDING", (0,0), (-1,0), 5),
    # Body
    ("FONTNAME",   (0,1), (-1,-1), "Helvetica"),
    ("FONTSIZE",   (0,1), (-1,-1), 8),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, GREY_LITE]),
    ("TOPPADDING",    (0,1), (-1,-1), 4),
    ("BOTTOMPADDING", (0,1), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 6),
    ("VALIGN",    (0,0), (-1,-1), "MIDDLE"),
    ("BOX",       (0,0), (-1,-1), 0.5, GREY_MID),
    ("INNERGRID", (0,0), (-1,-1), 0.3, GREY_MID),
    # Highlight TSH row
    ("BACKGROUND", (0,1), (-1,1), colors.HexColor("#E8F8F0")),
    ("FONTNAME",   (0,1), (0,1), "Helvetica-Bold"),
]))

# Convert multiline strings to paragraphs
p_data = [[Paragraph(tests_header[i], S("th", fontName="Helvetica-Bold", fontSize=8.5, textColor=WHITE, leading=11)) for i in range(3)]]
for row in tests_data:
    p_data.append([Paragraph(row[0], SEC_BOLD), Paragraph(row[1], SMALL), Paragraph(row[2], SEC_BODY)])

tests_tbl2 = Table(p_data, colWidths=col_w, repeatRows=1)
tests_tbl2.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), NAVY),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, GREY_LITE]),
    ("BACKGROUND", (0,1), (-1,1), colors.HexColor("#E8F8F0")),
    ("TOPPADDING",    (0,0), (-1,-1), 4), ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 6), ("RIGHTPADDING",  (0,0), (-1,-1), 6),
    ("VALIGN",    (0,0), (-1,-1), "MIDDLE"),
    ("BOX",       (0,0), (-1,-1), 0.5, GREY_MID),
    ("INNERGRID", (0,0), (-1,-1), 0.3, GREY_MID),
]))
story += [tests_tbl2, spacer(10)]

# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 3: TSH-FIRST ALGORITHM (visual flowchart as table)
# ═══════════════════════════════════════════════════════════════════════════════
story += [banner("3  THE TSH-FIRST ALGORITHM", TEAL), spacer(4)]

def flow_box(text, bg, tc=BLACK, fs=8.5, bold=False):
    fn = "Helvetica-Bold" if bold else "Helvetica"
    st = S("fb", fontName=fn, fontSize=fs, textColor=tc, alignment=TA_CENTER, leading=12)
    tbl = Table([[Paragraph(text, st)]], colWidths=[None])
    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), bg),
        ("TOPPADDING",    (0,0), (-1,-1), 5),
        ("BOTTOMPADDING", (0,0), (-1,-1), 5),
        ("LEFTPADDING",   (0,0), (-1,-1), 6),
        ("RIGHTPADDING",  (0,0), (-1,-1), 6),
        ("BOX", (0,0), (-1,-1), 0.8, colors.HexColor("#AAAAAA")),
    ]))
    return tbl

arrow = Paragraph("↓", S("arr", fontName="Helvetica-Bold", fontSize=14,
                          textColor=TEAL, alignment=TA_CENTER))

alg_col = 5.5*cm
side_col = (W - 2*cm - alg_col - 0.6*cm) / 2

alg = [
    # Start
    [flow_box("STEP 1: Measure TSH", NAVY, tc=WHITE, bold=True), "", ""],
    ["", arrow, ""],
    # TSH branches
    [flow_box("TSH  NORMAL\n0.5–4.5 mIU/L", GREEN_SOFT, tc=WHITE, bold=True),
     flow_box("TSH  HIGH\n> 4.5 mIU/L", RED_SOFT, tc=WHITE, bold=True),
     flow_box("TSH  LOW\n< 0.5 mIU/L", AMBER, tc=BLACK, bold=True)],
    # Outcome row
    [flow_box("Thyroid dysfunction\nexcluded. STOP.", colors.HexColor("#D5F5E3")),
     flow_box("Add  FREE T4", LIGHT_BG),
     flow_box("Add  FREE T4  +  T3", LIGHT_BG)],
    # Sub-outcomes left side
    ["",
     flow_box("↑TSH + ↓fT4\n→ OVERT HYPOTHYROID", RED_SOFT, tc=WHITE),
     flow_box("↓TSH + ↑fT4/T3\n→ OVERT HYPERTHYROID", RED_SOFT, tc=WHITE)],
    ["",
     flow_box("↑TSH + Normal fT4\n→ SUBCLINICAL HYPOTHYROID", AMBER, tc=BLACK),
     flow_box("↓TSH + Normal fT4\n→ Check FREE T3", AMBER, tc=BLACK)],
    ["", "",
     flow_box("↓TSH + ↑T3 (normal fT4)\n→ T3 TOXICOSIS", RED_SOFT, tc=WHITE)],
    ["", "",
     flow_box("↓TSH + Normal T3 + Normal fT4\n→ SUBCLINICAL HYPERTHYROID", AMBER, tc=BLACK)],
]

flow_cw = [alg_col, alg_col, alg_col]
flow_tbl = Table(
    [[flow_box("STEP 1: Measure TSH (Best First Test)", NAVY, tc=WHITE, bold=True, fs=9)],
     [Spacer(1, 6)],
     [Table([
         [flow_box("TSH NORMAL\n0.5–4.5 mIU/L", GREEN_SOFT, tc=WHITE, bold=True),
          flow_box("TSH HIGH\n> 4.5 mIU/L", RED_SOFT, tc=WHITE, bold=True),
          flow_box("TSH LOW\n< 0.5 mIU/L", colors.HexColor("#E67E22"), tc=WHITE, bold=True)],
         [Spacer(1,4), Spacer(1,4), Spacer(1,4)],
         [flow_box("Thyroid disease\nexcluded. STOP.", colors.HexColor("#ABEBC6")),
          flow_box("Add  Free T4", LIGHT_BG),
          flow_box("Add  Free T4 + T3", LIGHT_BG)],
         [Spacer(1,4), Spacer(1,4), Spacer(1,4)],
         [Paragraph("", SEC_BODY),
          flow_box("↑TSH + ↓fT4\n→ OVERT HYPOTHYROID", RED_SOFT, tc=WHITE),
          flow_box("↓TSH + ↑fT4/T3\n→ OVERT HYPERTHYROID", RED_SOFT, tc=WHITE)],
         [Paragraph("", SEC_BODY),
          flow_box("↑TSH + Normal fT4\n→ SUBCLINICAL HYPOTHYROID", AMBER, tc=BLACK),
          flow_box("↓TSH + Normal fT4\n→ Check Free T3", colors.HexColor("#F39C12"), tc=BLACK)],
         [Paragraph("", SEC_BODY),
          Paragraph("", SEC_BODY),
          flow_box("↓TSH + ↑T3 (nml fT4)\n→ T3 TOXICOSIS", RED_SOFT, tc=WHITE)],
         [Paragraph("", SEC_BODY),
          Paragraph("", SEC_BODY),
          flow_box("↓TSH + nml T3+fT4\n→ SUBCLINICAL HYPER", AMBER, tc=BLACK)],
     ], colWidths=[alg_col, alg_col, alg_col])],
    ],
    colWidths=[W - 2*cm]
)
flow_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#FAFAFA")),
    ("BOX", (0,0), (-1,-1), 0.5, GREY_MID),
    ("TOPPADDING",    (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING",   (0,0), (-1,-1), 6),
]))
story += [flow_tbl, spacer(10)]

# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 4: INTERPRETATION TABLE
# ═══════════════════════════════════════════════════════════════════════════════
story += [banner("4  INTERPRETATION SUMMARY TABLE", TEAL), spacer(4)]

interp_header = ["Condition", "TSH", "fT4", "T3", "Notes"]
interp_data = [
    ["Overt Hypothyroidism",      "↑↑",     "↓",      "↓/Nml", "Most common: Hashimoto thyroiditis"],
    ["Subclinical Hypothyroidism","↑",      "Normal", "Normal","Earliest stage; treat if symptomatic or TSH >10"],
    ["Overt Hyperthyroidism",     "↓↓",     "↑",      "↑",     "Most common: Graves disease"],
    ["Subclinical Hyperthyroidism","↓",     "Normal", "Normal","Treat if symptomatic / age >65 / AF risk"],
    ["T3 Toxicosis",              "↓",      "Normal", "↑↑",    "~5% of hyper cases; Graves or toxic nodule"],
    ["Central Hypothyroidism",    "Low/Nml","↓",      "↓",     "Pituitary/hypothalamic disease; TSH misleads"],
    ["Euthyroid Sick Syndrome",   "Low/Nml","↓",      "↓↓",    "Critically ill; rT3 ↑; don't treat — patient is euthyroid"],
    ["Pregnancy (normal)",        "Normal*","Normal", "Normal","*Lower TSH cutoff; Total T4 ↑ due to ↑TBG — use fT4"],
    ["Estrogen/OCP (normal)",     "Normal", "Normal", "Normal","Total T4/T3 ↑ via TBG ↑; fT4 + TSH normal — no action"],
    ["Graves Disease",            "↓↓",     "↑",      "↑",     "TRAb positive; T3:T4 ratio >20:1 typical"],
    ["Hashimoto Thyroiditis",     "↑",      "↓/Nml",  "↓/Nml","Anti-TPO + Anti-Tg elevated; TRAb absent"],
]

def colour_tsH(val):
    if "↑↑" in val or "↑" in val: return RED_SOFT
    if "↓↓" in val or "↓" in val: return GREEN_SOFT
    if "Low/Nml" in val: return colors.HexColor("#E67E22")
    return colors.HexColor("#7F8C8D")

i_cw = [3.8*cm, 1.2*cm, 1.2*cm, 1.2*cm, W - 2*cm - 7.4*cm]

i_head_row = [Paragraph(h, S("ih", fontName="Helvetica-Bold", fontSize=8, textColor=WHITE, leading=10))
              for h in interp_header]
i_rows = [i_head_row]
for i, row in enumerate(interp_data):
    bg = WHITE if i % 2 == 0 else GREY_LITE
    i_rows.append([
        Paragraph(row[0], S("ic", fontName="Helvetica-Bold" if "Overt" in row[0] else "Helvetica",
                             fontSize=8, textColor=BLACK, leading=10)),
        Paragraph(f"<b>{row[1]}</b>", S("iv", fontName="Helvetica-Bold", fontSize=9,
                   textColor=RED_SOFT if "↑" in row[1] else (GREEN_SOFT if "↓" in row[1] else colors.HexColor("#E67E22")),
                   alignment=TA_CENTER, leading=11)),
        Paragraph(f"<b>{row[2]}</b>", S("iv2", fontName="Helvetica-Bold", fontSize=9,
                   textColor=RED_SOFT if "↑" in row[2] else (GREEN_SOFT if "↓" in row[2] else colors.HexColor("#555555")),
                   alignment=TA_CENTER, leading=11)),
        Paragraph(f"<b>{row[3]}</b>", S("iv3", fontName="Helvetica-Bold", fontSize=9,
                   textColor=RED_SOFT if "↑" in row[3] else (GREEN_SOFT if "↓" in row[3] else colors.HexColor("#555555")),
                   alignment=TA_CENTER, leading=11)),
        Paragraph(row[4], SMALL),
    ])

i_tbl = Table(i_rows, colWidths=i_cw, repeatRows=1)
i_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), NAVY),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, GREY_LITE]),
    ("TOPPADDING",    (0,0), (-1,-1), 3), ("BOTTOMPADDING", (0,0), (-1,-1), 3),
    ("LEFTPADDING",   (0,0), (-1,-1), 5), ("RIGHTPADDING",  (0,0), (-1,-1), 5),
    ("VALIGN",    (0,0), (-1,-1), "MIDDLE"),
    ("BOX",       (0,0), (-1,-1), 0.5, GREY_MID),
    ("INNERGRID", (0,0), (-1,-1), 0.3, GREY_MID),
    ("ALIGN",     (1,0), (3,-1), "CENTER"),
]))
story += [i_tbl, spacer(6)]

legend = Paragraph(
    "<font color='#E74C3C'>↑ = elevated</font>   &nbsp;&nbsp;"
    "<font color='#27AE60'>↓ = decreased</font>   &nbsp;&nbsp;"
    "<font color='#555555'>Nml = normal</font>   &nbsp;&nbsp;"
    "rT3 = reverse T3 (inactive)",
    S("leg", fontName="Helvetica", fontSize=7.5, textColor=colors.HexColor("#555555"),
      alignment=TA_CENTER, leading=10)
)
story += [legend, spacer(10)]

# ═══════════════════════════════════════════════════════════════════════════════
# PAGE 2
# ═══════════════════════════════════════════════════════════════════════════════
story += [PageBreak()]

# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 5: THYROID ANTIBODIES
# ═══════════════════════════════════════════════════════════════════════════════
story += [banner("5  THYROID ANTIBODIES + SPECIAL MARKERS", NAVY), spacer(4)]

ab_header = ["Antibody", "Full Name", "Tells You", "Disease"]
ab_data = [
    ["Anti-TPO\n(Anti-microsomal)", "Anti-thyroid peroxidase",
     "Autoimmune thyroid disease\n~80% sensitivity in Hashimoto", "Hashimoto > Graves (not specific)"],
    ["Anti-Tg", "Anti-thyroglobulin",
     "Autoimmune thyroid disease\nInterferes with Tg assay", "Hashimoto (less sensitive than Anti-TPO)"],
    ["TRAb / TSI / LATS", "TSH receptor antibody\n(stimulating type)",
     "Acts as TSH agonist →\ncontinuous stimulation", "HIGHLY specific for Graves disease"],
    ["Serum Thyroglobulin\n(Tg)", "Thyroglobulin protein",
     "Tumor marker — post-thyroidectomy\n+ RAI ablation surveillance", "Differentiated thyroid cancer monitoring"],
    ["Calcitonin", "C-cell hormone",
     "Tumor marker for C-cell origin", "Medullary thyroid cancer"],
]

ab_cw = [3.2*cm, 3.5*cm, 5.2*cm, W - 2*cm - 11.9*cm]
ab_rows = [[Paragraph(h, S("abh", fontName="Helvetica-Bold", fontSize=8, textColor=WHITE, leading=10))
            for h in ab_header]]
for i, row in enumerate(ab_data):
    bg = WHITE if i % 2 == 0 else GREY_LITE
    ab_rows.append([Paragraph(c, SEC_BODY) for c in row])

ab_tbl = Table(ab_rows, colWidths=ab_cw, repeatRows=1)
ab_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), TEAL),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, GREY_LITE]),
    ("TOPPADDING",    (0,0), (-1,-1), 4), ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 6), ("RIGHTPADDING",  (0,0), (-1,-1), 6),
    ("VALIGN",    (0,0), (-1,-1), "TOP"),
    ("BOX",       (0,0), (-1,-1), 0.5, GREY_MID),
    ("INNERGRID", (0,0), (-1,-1), 0.3, GREY_MID),
    # Highlight TRAb
    ("BACKGROUND", (0,3), (-1,3), colors.HexColor("#FEF9E7")),
    ("FONTNAME",   (0,3), (-1,3), "Helvetica-Bold"),
]))
story += [ab_tbl, spacer(10)]

# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 6: WHEN TSH-FIRST RULE FAILS
# ═══════════════════════════════════════════════════════════════════════════════
story += [banner("6  WHEN TO ABANDON TSH-FIRST", colors.HexColor("#C0392B")), spacer(4)]

fail_data = [
    ["1. Critically Ill Patients\n(Euthyroid Sick Syndrome)",
     "Cytokines suppress HPT axis. Pattern: ↓T3, ↓T4, ↑rT3, normal/↓TSH. Patient is euthyroid.\n"
     "→ Do NOT routinely check TFTs in ICU unless strong prior suspicion of thyroid disease."],
    ["2. Thyroid Therapy\nTransitions",
     "After treating hyperthyroidism: TSH stays low for months (thyrotroph suppression).\n"
     "After starting levothyroxine: TSH stays high for weeks.\n"
     "→ Wait 6–8 weeks after any dose change before rechecking (steady state ~end of month 2)."],
    ["3. Central Disease\nSuspected",
     "Pituitary/hypothalamic disease → TSH inappropriately low/normal despite ↓fT4.\n"
     "→ Must interpret TSH + fT4 together. TSH is NEVER the only pituitary hormone deficient."],
]

fail_cw = [3.5*cm, W - 2*cm - 3.5*cm]
fail_rows = []
for row in fail_data:
    fail_rows.append([
        Paragraph(row[0], S("fb2", fontName="Helvetica-Bold", fontSize=8.5, textColor=WHITE, leading=12)),
        Paragraph(row[1], SEC_BODY)
    ])

fail_tbl = Table(fail_rows, colWidths=fail_cw)
fail_tbl.setStyle(TableStyle([
    ("ROWBACKGROUNDS", (0,0), (-1,-1), [colors.HexColor("#FDEDEC"), colors.HexColor("#FEF9E7")]),
    ("BACKGROUND", (0,0), (0,-1), colors.HexColor("#C0392B")),
    ("TOPPADDING",    (0,0), (-1,-1), 6), ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING",   (0,0), (-1,-1), 7), ("RIGHTPADDING",  (0,0), (-1,-1), 7),
    ("VALIGN",    (0,0), (-1,-1), "TOP"),
    ("BOX",       (0,0), (-1,-1), 0.5, colors.HexColor("#C0392B")),
    ("INNERGRID", (0,0), (-1,-1), 0.5, GREY_MID),
]))
story += [fail_tbl, spacer(10)]

# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 7: DRUGS AND TFTs (two-column layout)
# ═══════════════════════════════════════════════════════════════════════════════
story += [banner("7  DRUGS AND TFTs — CAUSES TRUE DYSFUNCTION vs. ALTERS TESTS ONLY", TEAL), spacer(4)]

# Left: true dysfunction
left_title = Table([[Paragraph("TRUE Thyroid Dysfunction (TSH Changes)", S("ct", fontName="Helvetica-Bold", fontSize=9, textColor=WHITE, alignment=TA_CENTER, leading=11))]],
                   colWidths=[(W - 2*cm - 0.3*cm)/2])
left_title.setStyle(TableStyle([("BACKGROUND", (0,0), (-1,-1), RED_SOFT),
                                 ("TOPPADDING", (0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4)]))

drug_true = [
    ["Amiodarone", "Hypo OR Hyper", "37% iodine; hypo in iodine-sufficient; hyper if iodine-deficient / MNG"],
    ["Lithium", "Hypothyroidism", "Inhibits thyroid hormone synthesis & secretion; 15-50% of patients"],
    ["Iodine / CT contrast", "Hypo (Wolff-Chaikoff)\nor Hyper (Jod-Basedow)", "Excess iodine → hypo; iodine deficiency + load → hyper"],
    ["Checkpoint inhibitors\nIFN-α", "Hypo or Hyper", "Immune-mediated thyroiditis"],
    ["Tyrosine kinase\ninhibitors", "Hypothyroidism", "Multiple mechanisms; monitor TSH"],
]
dt_rows = [[Paragraph(r[0], S("d0", fontName="Helvetica-Bold", fontSize=7.5, textColor=BLACK, leading=10)),
            Paragraph(r[1], S("d1", fontName="Helvetica-Bold", fontSize=7.5, textColor=RED_SOFT, leading=10)),
            Paragraph(r[2], SMALL)] for r in drug_true]
dt_cw = [2.0*cm, 2.3*cm, (W-2*cm-0.3*cm)/2 - 4.3*cm]
dt_tbl = Table(dt_rows, colWidths=dt_cw)
dt_tbl.setStyle(TableStyle([
    ("ROWBACKGROUNDS", (0,0), (-1,-1), [WHITE, GREY_LITE]),
    ("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3),
    ("LEFTPADDING",(0,0),(-1,-1),4),("RIGHTPADDING",(0,0),(-1,-1),4),
    ("VALIGN",(0,0),(-1,-1),"TOP"),
    ("BOX",(0,0),(-1,-1),0.5,GREY_MID),("INNERGRID",(0,0),(-1,-1),0.3,GREY_MID),
]))
left_col = Table([[left_title],[dt_tbl]], colWidths=[(W-2*cm-0.3*cm)/2])
left_col.setStyle(TableStyle([("TOPPADDING",(0,0),(-1,-1),0),("BOTTOMPADDING",(0,0),(-1,-1),0),
                               ("LEFTPADDING",(0,0),(-1,-1),0),("RIGHTPADDING",(0,0),(-1,-1),0)]))

# Right: alters tests only
right_title = Table([[Paragraph("Tests ONLY Affected (TSH Normal = Euthyroid)", S("ct2", fontName="Helvetica-Bold", fontSize=9, textColor=WHITE, alignment=TA_CENTER, leading=11))]],
                    colWidths=[(W - 2*cm - 0.3*cm)/2])
right_title.setStyle(TableStyle([("BACKGROUND", (0,0), (-1,-1), TEAL),
                                   ("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4)]))

drug_test = [
    ["Estrogens / OCP / Tamoxifen", "↑ Total T4, ↑ Total T3", "↑ TBG; fT4 & TSH remain normal"],
    ["Androgens", "↓ Total T4", "↓ TBG; fT4 & TSH normal"],
    ["Furosemide (high dose)\nSalicylates", "↓ Total T4", "Compete with T4 for TBG binding"],
    ["Phenytoin / Carbamazepine\nRifampin / Phenobarbital", "↓ Total T4", "Displace T4 from TBG; accelerate T4 clearance"],
    ["Heparin / LMWH", "↑ Free T4 (artifact)", "Free fatty acids displace T4 from TBG in vitro"],
    ["Glucocorticoids / Dopamine", "↓ TSH", "Suppress TSH secretion directly; T4 normal"],
    ["Propranolol (high dose)", "↓ T3", "Inhibits peripheral T4→T3 conversion"],
    ["Biotin (supplements)", "Spurious all assays", "⚠ Hold 1-2 days before TFTs — immunoassay interference"],
]
dtest_rows = [[Paragraph(r[0], S("dt0", fontName="Helvetica-Bold", fontSize=7.5, textColor=BLACK, leading=10)),
               Paragraph(r[1], S("dt1", fontName="Helvetica-Bold", fontSize=7.5, textColor=TEAL, leading=10)),
               Paragraph(r[2], SMALL)] for r in drug_test]
dtest_cw = [2.5*cm, 2.3*cm, (W-2*cm-0.3*cm)/2 - 4.8*cm]
dtest_tbl = Table(dtest_rows, colWidths=dtest_cw)
dtest_tbl.setStyle(TableStyle([
    ("ROWBACKGROUNDS", (0,0), (-1,-1), [WHITE, GREY_LITE]),
    ("BACKGROUND", (0,7), (-1,7), colors.HexColor("#FFF8E1")),
    ("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3),
    ("LEFTPADDING",(0,0),(-1,-1),4),("RIGHTPADDING",(0,0),(-1,-1),4),
    ("VALIGN",(0,0),(-1,-1),"TOP"),
    ("BOX",(0,0),(-1,-1),0.5,GREY_MID),("INNERGRID",(0,0),(-1,-1),0.3,GREY_MID),
]))
right_col = Table([[right_title],[dtest_tbl]], colWidths=[(W-2*cm-0.3*cm)/2])
right_col.setStyle(TableStyle([("TOPPADDING",(0,0),(-1,-1),0),("BOTTOMPADDING",(0,0),(-1,-1),0),
                                ("LEFTPADDING",(0,0),(-1,-1),0),("RIGHTPADDING",(0,0),(-1,-1),0)]))

drugs_outer = Table([[left_col, Spacer(0.3*cm, 1), right_col]],
                    colWidths=[(W-2*cm-0.3*cm)/2, 0.3*cm, (W-2*cm-0.3*cm)/2])
drugs_outer.setStyle(TableStyle([
    ("TOPPADDING",(0,0),(-1,-1),0),("BOTTOMPADDING",(0,0),(-1,-1),0),
    ("LEFTPADDING",(0,0),(-1,-1),0),("RIGHTPADDING",(0,0),(-1,-1),0),
    ("VALIGN",(0,0),(-1,-1),"TOP"),
]))
story += [drugs_outer, spacer(10)]

# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 8: 10 CLINICAL PEARLS
# ═══════════════════════════════════════════════════════════════════════════════
story += [banner("8  10 CLINICAL PEARLS", NAVY), spacer(4)]

pearls = [
    ("<b>1.</b>", "TSH ALWAYS FIRST — most sensitive test. Amplifies small fT4 changes 10×."),
    ("<b>2.</b>", "Normal TSH = thyroid function essentially normal (in most patients, most settings). STOP."),
    ("<b>3.</b>", "Add <b>fT4</b> when TSH is abnormal — confirms and grades severity."),
    ("<b>4.</b>", "Add <b>T3</b> when TSH is low but fT4 is normal — rule out T3 toxicosis (5% of hyper cases)."),
    ("<b>5.</b>", "Central disease: TSH + fT4 together. TSH alone will MISS pituitary hypothyroidism."),
    ("<b>6.</b>", "Critically ill patients: Euthyroid Sick Syndrome mimics central hypothyroidism. Don't treat."),
    ("<b>7.</b>", "Wait <b>6–8 weeks</b> after any dose change before rechecking TSH (steady state takes time)."),
    ("<b>8.</b>", "Amiodarone: inhibits T4→T3 (↑T4, ↓T3 even in euthyroid) + can cause hypo OR hyperthyroidism."),
    ("<b>9.</b>", "Biotin supplements → spurious results in ALL thyroid immunoassays. Hold 1–2 days before testing."),
    ("<b>10.</b>", "Estrogens/OCP → ↑ Total T4/T3 (↑TBG) but fT4 and TSH are normal. Patient is euthyroid. No action."),
]

pearl_rows = []
for num, text in pearls:
    pearl_rows.append([
        Paragraph(num, S("pn", fontName="Helvetica-Bold", fontSize=9, textColor=TEAL,
                         alignment=TA_CENTER, leading=12)),
        Paragraph(text, PEARL)
    ])

pearl_tbl = Table(pearl_rows, colWidths=[0.7*cm, W - 2*cm - 0.7*cm])
pearl_tbl.setStyle(TableStyle([
    ("ROWBACKGROUNDS", (0,0), (-1,-1), [WHITE, GREY_LITE]),
    ("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
    ("LEFTPADDING",(0,0),(-1,-1),6),("RIGHTPADDING",(0,0),(-1,-1),6),
    ("VALIGN",(0,0),(-1,-1),"MIDDLE"),
    ("BOX",(0,0),(-1,-1),0.5,GREY_MID),("INNERGRID",(0,0),(-1,-1),0.3,GREY_MID),
    ("LINEBEFORE",(0,0),(0,-1),3,TEAL),
]))
story += [pearl_tbl, spacer(8)]

# ═══════════════════════════════════════════════════════════════════════════════
# FOOTER NOTE
# ═══════════════════════════════════════════════════════════════════════════════
footer_note = Table(
    [[Paragraph(
        "Sources: Quick Compendium of Clinical Pathology 5e · Schwartz's Principles of Surgery 11e · "
        "Goldman-Cecil Medicine · Washington Manual of Medical Therapeutics · Henry's Clinical Diagnosis by Lab Methods · "
        "Harrison's Principles of Internal Medicine 22e",
        S("fn", fontName="Helvetica", fontSize=6.5, textColor=colors.HexColor("#888888"),
          alignment=TA_CENTER, leading=9)
    )]],
    colWidths=[W - 2*cm]
)
footer_note.setStyle(TableStyle([
    ("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
    ("BACKGROUND",(0,0),(-1,-1),GREY_LITE),
    ("BOX",(0,0),(-1,-1),0.3,GREY_MID),
]))
story += [footer_note]

# ═══════════════════════════════════════════════════════════════════════════════
# BUILD
# ═══════════════════════════════════════════════════════════════════════════════
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print(f"PDF saved to: {OUT}")
Running Command

cd /home/daytona/workspace/tft-pdf && python3 make_tft_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/tft-pdf/TFT_Quick_Reference.pdf

Your TFT Quick Reference PDF is ready:

TFT Quick Reference

PDF Document · PDF


Here's what's inside the 2-page reference card:
Page 1
  • HPT Axis diagram - the feedback loop visualised as a table with the key log-linear concept highlighted in amber
  • The Tests table - TSH, fT4, Total T4, fT3, Total T3, TRH Stim test with normal ranges and clinical notes
  • TSH-First Algorithm flowchart - colour-coded branching from normal/high/low TSH to all diagnoses (overt hypo, subclinical hypo, overt hyper, subclinical hyper, T3 toxicosis)
  • Interpretation Summary Table - 11 conditions with colour-coded TSH/fT4/T3 arrows (red = elevated, green = decreased)
Page 2
  • Thyroid Antibodies table - Anti-TPO, Anti-Tg, TRAb/TSI, Thyroglobulin, Calcitonin with disease associations
  • When TSH-First Fails - red alert section covering euthyroid sick syndrome, therapy transitions, and central disease
  • Drugs & TFTs (two-column) - left column = true dysfunction (amiodarone, lithium, iodine, checkpoint inhibitors), right column = test artifact only (estrogens, phenytoin, heparin, biotin warning)
  • 10 Clinical Pearls - teal-highlighted numbered list with the most clinically actionable points
  • Source footnote from authoritative textbooks
This is a shared conversation. Sign in to Orris to start your own chat.