I want gi case format for peadeatrics with why i.e logical reason to ask the question to patient

Reading File
Asking for Preferences
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Finding Sources
Finding Sources
Reading File
Finding Sources
I now have solid clinical material from two textbooks. Let me compile the full format for you.

Pediatric GI Case Format - Complete History Taking with Clinical Reasoning

Based on: Textbook of Family Medicine 9e and Tintinalli's Emergency Medicine

SECTION 1: IDENTIFICATION & DEMOGRAPHICS

QuestionWhy You Ask It
Name, age, sex, weightAge is the single most important filter - differential diagnosis for vomiting/abdominal pain is completely different by age (newborn vs toddler vs school-age). Weight tracks nutritional status and calculates drug doses.
Who brought the childHelps gauge reliability of history; grandparent may not know feeding details, while parent knows better.
Referred or self-referredIndicates severity perception and access to prior care.

SECTION 2: PRESENTING COMPLAINT (PC) & HISTORY OF PRESENTING ILLNESS (HPI)

For Any GI Complaint - Use SOCRATES + WHY


A. ABDOMINAL PAIN

QuestionWhy You Ask It
Site - Where does it hurt? Point with one finger.Localisation guides anatomy. RIF = appendix/terminal ileum/ovary. Periumbilical = small bowel/early appendicitis. Epigastric = stomach/duodenum/pancreatitis. Diffuse = peritonitis, mesenteric adenitis, functional pain.
Onset - Did it start suddenly or gradually?Sudden severe onset = perforation, volvulus, intussusception (surgical emergency). Gradual = inflammatory (appendicitis early), IBD, constipation.
Character - Crampy/colicky or constant?Colicky (comes and goes in waves) = hollow viscus obstruction - bowel, biliary, ureteric. Constant = peritoneal involvement (somatic pain).
Radiation - Does the pain go anywhere else?Biliary pain radiates to right shoulder (diaphragm irritation). Renal pain to groin. Testicular torsion pain to abdomen.
Associated symptoms - Fever, vomiting, diarrhea, constipation?Fever + RIF pain = appendicitis until proven otherwise. Vomiting before pain = often medical. Pain before vomiting = often surgical. Obstipation = bowel obstruction.
Timing - How long? Getting better or worse?Appendicitis typically worsens over 12-24 hours. Functional/recurrent pain in school-age children follows a pattern - often 3+ episodes over 3 months.
Exacerbating/relieving factors - What makes it worse? Better?Pain worse with movement = peritonism. Relieved by defaecation = large bowel origin. Worse with eating = peptic ulcer, malabsorption.
Severity - Pain score 0-10 (use faces scale for younger children)Anchors severity and helps monitor change over time. Functional pain is rarely score 10.

B. VOMITING

QuestionWhy You Ask It
When did it start? Acute or recurrent?Acute = infection, obstruction, metabolic. Recurrent since infancy = GERD. Recurrent in school-age = cyclic vomiting syndrome, migraine, psychogenic.
How many times per day?Quantifies severity and dehydration risk. >6-8 episodes/day = high risk of dehydration in infants.
What does the vomit look like?This is the most critical vomiting question: Bilious (green) = obstruction DISTAL to the ampulla of Vater - malrotation with volvulus until proven otherwise (surgical emergency in neonate). Bloody = oesophagitis, Mallory-Weiss tear, varices. Projectile, non-bilious in infant 2-8 weeks = pyloric stenosis (forceful, like "shot across the room"). Undigested food = achalasia, proximal obstruction. Clear/mucoid = non-specific.
Does vomiting come before or after pain?Vomiting before pain = gastroenteritis (medical). Pain before vomiting = appendicitis, obstruction (surgical). This is a key surgical vs medical discriminator.
Is the child able to keep anything down?Determines hydration strategy - oral vs IV rehydration.
Is the child a "happy spitter" or distressed?Happy infant who vomits but gains weight well = uncomplicated GERD (no investigation needed). Distressed infant = workup required.
Any blood or coffee-ground material?Upper GI bleed. Coffee-ground = slow bleed, oxidized blood. Fresh red blood = active bleed. Both need urgent assessment.

C. DIARRHEA

QuestionWhy You Ask It
When did it start? Sudden or gradual?Abrupt onset = infectious (viral > bacterial). Gradual onset over weeks = malabsorption (coeliac, IBD, cow's milk protein intolerance).
How many stools per day? What's normal for this child?Context matters - exclusively breastfed infants may have 8-10 loose stools/day normally. A toddler having 6 watery stools/day is abnormal.
Describe the stool - colour, consistency, blood, mucus, smellWatery = secretory (viral, toxin-mediated). Fatty/greasy/pale/foul-smelling = steatorrhoea = fat malabsorption (coeliac, cystic fibrosis, pancreatic insufficiency). Bloody + mucus = dysentery = bacterial (Salmonella, Shigella, Campylobacter, E. coli O157) or IBD. Bloody without mucus in infant = intussusception, necrotising enterocolitis. Currant-jelly stool = intussusception (classic - blood + mucus mixed). Black/tarry (melena) = upper GI bleed.
Nocturnal diarrhea?Functional/IBS pain and diarrhea does NOT wake a child from sleep. Organic disease (IBD, infection) often does. This is a high-yield differentiating question.
Is the child passing urine? How often?Assesses dehydration. Normal urine output = 1 mL/kg/hr in children. Decreased urine output = significant dehydration requiring urgent rehydration.
Any tenesmus (straining, urgency, feeling of incomplete emptying)?Tenesmus = rectal/colonic inflammation - points to dysentery or proctocolitis.
Contact history or travel?Daycare/school cluster = norovirus, rotavirus, Shigella. Recent travel to endemic area = Giardia, typhoid, cholera, amoeba.
What has the child been eating/drinking?Raw meat/eggs = Salmonella, Campylobacter. Unpasteurised milk/juice = E. coli O157, Listeria. Antibiotics recently = C. difficile-associated diarrhea.

D. RECTAL BLEEDING

QuestionWhy You Ask It
Fresh red blood or dark/altered blood?Fresh red = lower GI (anal fissure most common in infants/toddlers, polyp, Meckel's, intussusception, IBD). Dark blood = upper GI source.
Blood on surface of stool or mixed in?On surface/paper only = anorectal (fissure, haemorrhoid). Mixed throughout = colonic source (polyp, IBD, infection).
Associated with hard stool and pain on defaecation?Anal fissure - the most common cause of rectal bleeding in children. Child cries when passing stool, blood on surface, constipation history.
Painless rectal bleeding?Painless fresh bleeding = Meckel's diverticulum (ectopic gastric mucosa causes peptic ulceration). Classically in child <2 years with large painless bleed.
Age of child?Age helps narrow diagnosis: Neonate = haemorrhagic disease of newborn, NEC, swallowed maternal blood. Infant = intussusception, anal fissure. Toddler = Meckel's, polyp, fissure. School-age = IBD, polyp, infectious colitis.

E. JAUNDICE

QuestionWhy You Ask It
Age at onset of jaundice?Neonatal jaundice appearing within 24 hours = haemolytic (Rh/ABO incompatibility - pathological, not physiological). Day 2-7 = physiological jaundice (normal). Persisting >2 weeks = investigate (biliary atresia, hypothyroidism, infection). In older child = hepatitis, haemolysis, Gilbert's.
Is the jaundice isolated or with pale stools and dark urine?Pale stools + dark urine + jaundice = obstructive (conjugated) jaundice = biliary atresia, choledochal cyst, hepatitis. This triad demands urgent imaging. Jaundice without pale stools = haemolytic or Gilbert's (unconjugated).
Itching (pruritus)?Cholestasis causes bile salt deposition in skin = intense itch. Confirms obstructive picture.
Fever + jaundice?Infectious hepatitis (hepatitis A most common in children), cholangitis.
Contact with jaundiced person? Vaccination status?Hepatitis A - faecal-oral, common in unvaccinated children in endemic areas.

SECTION 3: FEEDING & NUTRITIONAL HISTORY

QuestionWhy You Ask It
Breastfed or formula fed? (for infants)Breastfed = lower infection risk, different stool pattern (yellow, seedy, frequent). Formula type matters - cow's milk formula can cause allergy/intolerance presenting as vomiting, diarrhea, blood in stool.
When were solids introduced?Gluten introduction = triggers coeliac in susceptible children (typically presents months after wheat started).
Appetite - normal, increased, decreased?Decreased appetite + weight loss = organic disease (IBD, coeliac, malignancy). Increased appetite + weight loss = malabsorption (coeliac, CF).
Any specific food avoidances or reactions?Child may have subconsciously learnt to avoid trigger foods (e.g., dairy in lactose intolerance, wheat in coeliac).
Weight trend - gaining, static, or losing?Weight loss or failure to thrive is the single most important red flag in paediatric GI - it mandates thorough investigation regardless of diagnosis.

SECTION 4: BOWEL HABIT HISTORY

QuestionWhy You Ask It
Normal stool frequency and consistency?Baseline varies widely by age and diet. Breastfed infant: multiple loose stools/day (normal). Formula-fed: 1-2/day. School-age: 1-2/day. Anything outside baseline needs context.
Has stool pattern changed?Change in bowel habit in a child = alarm symptom requiring investigation (IBD, Hirschsprung's, malignancy, coeliac).
Hard stools, straining, pain on defaecation?Functional constipation is extremely common - accounts for most rectal bleeding in children via fissures. Understanding constipation explains a huge number of paediatric abdominal presentations.
Soiling/encopresis?Overflow incontinence from severe constipation. Child with chronic constipation develops a loaded colon, liquid stool leaks around the impacted mass - looks like diarrhea but is constipation. KEY distinction.
Ribbon/pencil stools?Narrow caliber stools = colorectal narrowing (stricture, mass, Hirschsprung's long segment).

SECTION 5: SYSTEMIC & ASSOCIATED SYMPTOMS

QuestionWhy You Ask It
Fever?Infective GI pathology, appendicitis, IBD flare. Fever >38.5°C with diarrhea and blood = dysentery, treat empirically if toxic.
Weight loss or failure to thrive?RED FLAG - always document weight trend. IBD, coeliac, malignancy, chronic infection (TB), liver disease.
Mouth ulcers?Aphthous ulcers = Crohn's disease (can present years before bowel symptoms).
Skin rash?Dermatitis herpetiformis = coeliac. Erythema nodosum, pyoderma gangrenosum = IBD. Jaundice with purpura = liver failure.
Joint pains (arthralgia/arthritis)?Extra-intestinal manifestation of IBD - can precede bowel symptoms. Also seen in reactive arthritis post-infectious diarrhea (Reiter's syndrome).
Eye symptoms (redness, pain)?Uveitis, episcleritis = IBD extra-intestinal manifestation.
Urinary symptoms?Urinary tract infection commonly presents as abdominal pain in children (especially girls). Always ask - do NOT assume all abdominal pain is GI. Renal calculi cause severe loin-to-groin colicky pain with haematuria.
Respiratory symptoms?Recurrent chest infections + diarrhea + failure to thrive = cystic fibrosis. Right lower lobe pneumonia can mimic RIF pain (diaphragmatic peritoneum).
Headache with vomiting?Raised intracranial pressure presents as vomiting (especially morning vomiting without nausea, with headache = red flag for CNS cause).
Menstrual history (post-pubertal girls)?Ectopic pregnancy, ovarian torsion, mittelschmerz. Always ask LMP in adolescent girls with abdominal pain.

SECTION 6: PAST MEDICAL HISTORY

QuestionWhy You Ask It
Previous similar episodes?Recurrent abdominal pain (3+ episodes over 3 months) = functional pain syndrome or IBD. Recurrent intussusception in infant = Henoch-Schonlein Purpura, lymphoma as lead point.
Previous abdominal surgery?Adhesions = most common cause of bowel obstruction in a child with prior surgery. Stoma presence changes GI anatomy completely.
Previous GI investigations (scopes, imaging)?Avoids repeating tests; gives baseline for comparison.
Chronic conditions - coeliac, IBD, CF, liver disease?Contextualises current presentation as flare vs. new pathology.
Jaundice in newborn period? How treated?Neonatal hyperbilirubinaemia history relevant to haemolytic conditions, biliary atresia workup.

SECTION 7: DRUG & ALLERGY HISTORY

QuestionWhy You Ask It
Current medications?NSAIDs = peptic ulcer, GI bleed. Antibiotics = C. difficile, antibiotic-associated diarrhea, change in gut flora. Steroids = mask peritonism (pain absent despite serious pathology). Metformin = diarrhea. Iron supplements = constipation, black stools (mimics melena).
Recent antibiotics?C. difficile in children is increasing. Prior antibiotic use is mandatory history in any child with diarrhea.
Food allergies or intolerances?Cow's milk protein allergy in infants = vomiting, diarrhea, blood in stool. Lactose intolerance = bloating, diarrhea, cramping after dairy.
Drug allergies?Before prescribing any treatment.

SECTION 8: FAMILY HISTORY

QuestionWhy You Ask It
IBD in family?Crohn's and UC have strong genetic component. First-degree relative with IBD = 10x increased risk.
Coeliac disease in family?HLA-DQ2/DQ8 has familial clustering.
Liver disease, jaundice, gallstones?Familial hyperbilirubinaemia (Gilbert's, Dubin-Johnson). Gallstones in children often linked to haemolytic conditions (sickle cell, spherocytosis) - strong family history.
Cystic fibrosis carrier status?Autosomal recessive - ask about both parents.
Polyposis syndromes?FAP, Peutz-Jeghers - familial colorectal polyps presenting with GI bleeding in children.
Consanguinity?Increases risk of autosomal recessive conditions (CF, metabolic disorders, Hirschsprung's).

SECTION 9: SOCIAL & DEVELOPMENTAL HISTORY

QuestionWhy You Ask It
School attendance/performance?Functional abdominal pain classically causes school avoidance. "Stomach ache every Monday morning" = psychosomatic, school refusal.
Stressors - new school, family change, bullying?Functional GI disorders (recurrent abdominal pain, IBS) in children are heavily linked to psychological stress. You CANNOT diagnose functional pain without excluding organic disease, but stress history supports it.
Developmental milestones normal?Developmental regression + GI symptoms = metabolic/systemic disease.
Immunisation status?Rotavirus vaccination - reduces severity of gastroenteritis. Hepatitis A, B vaccination - prevents viral hepatitis. Unvaccinated child with jaundice = hepatitis A until proven otherwise.
Daycare/school contact with sick children?Daycare clusters = norovirus, rotavirus, Giardia, Shigella. High yield epidemiological question.
Travel history?Giardia, typhoid, hepatitis A, amoebic dysentery. Ask where, when, water source, food eaten.

SECTION 10: REVIEW OF RED FLAGS (Always Ask These)

These questions directly change management urgency:
Red FlagQuestion to AskClinical Significance
Bilious vomiting"Is the vomit green?"Surgical emergency (obstruction below ampulla) until proven otherwise - especially in neonates
Bloody stool"Any blood in the stool?"Wide differential - requires urgent workup
Severe dehydration"Is the child passing urine? Tears when crying? Eyes sunken?"Determines need for IV fluids
Failure to thrive"Has weight been normal? Plotted on growth chart?"Chronic organic disease
Nocturnal symptoms"Does pain/diarrhea wake the child from sleep?"Rules out functional disease - organic until proven otherwise
Weight loss"Has the child lost weight recently?"IBD, malignancy, coeliac, chronic infection
Persistent/progressive pain"Is it getting worse over hours?"Appendicitis, obstruction, volvulus
Age <3 months + vomiting-Any cause of vomiting in a neonate/young infant = investigate fully

QUICK SUMMARY TEMPLATE (For Case Presentation)

[Child's name], a [age]-year-old [male/female], presented with [main complaint] 
for [duration]. The [complaint] is described as [character], located at [site], 
[radiating to], [onset pattern], scored [X/10], [exacerbating/relieving factors].

Associated symptoms include: [fever / vomiting / diarrhea / weight loss / etc.]

Stool: [frequency / consistency / colour / blood / mucus]
Vomit: [frequency / character - bilious? bloody? projectile?]

Feeding: [breastfed/formula/solids - normal intake? reduced?]
Weight trend: [gaining / static / losing / FTT]

Past history: [prior episodes / surgery / conditions]
Medications: [antibiotics / NSAIDs / other]
Family history: [IBD / coeliac / CF / liver disease]
Social: [school attendance / stress / contacts / travel / immunisation status]

Red flags present/absent: bilious vomiting / bloody stool / dehydration signs / 
nocturnal symptoms / weight loss / failure to thrive

Key Clinical Principles to Remember:
  1. Age is everything in pediatric GI - the differential completely shifts at each age group
  2. Bilious vomiting in any child = surgical emergency until proven otherwise
  3. Pain before vomiting = surgical; vomiting before pain = medical
  4. Nocturnal GI symptoms = organic disease (rules out functional)
  5. Weight loss/FTT = always investigate fully regardless of suspected diagnosis
  6. Constipation with soiling ≠ diarrhea - overflow incontinence is a classic trap
  7. Urinary symptoms always ask - UTI mimics GI pain in children
Sources: Textbook of Family Medicine 9e; Tintinalli's Emergency Medicine - Vomiting, Diarrhea and Dehydration in Infants and Children

Generate a printable pediatric GI examination schema to pair with this history format

Reading File
Reading File
Finding Sources
Finding Sources
Reading File
Finding Sources
Browsing Directory

/home/daytona/skills/docx

Finding Sources
Running Command

ls /home/daytona/workspace/ 2>/dev/null && echo "---" && ls /home/daytona/skills/docx/scripts/ 2>/dev/null

Running Command

mkdir -p /home/daytona/workspace/peds-gi-schema

Writing File

~/peds-gi-schema/generate_schema.py

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

# ── Colour palette ──────────────────────────────────────────────
TEAL        = HexColor("#0D6E6E")   # dominant
TEAL_LIGHT  = HexColor("#E8F5F5")   # row shading
TEAL_MID    = HexColor("#B2DFDB")   # sub-header bg
ORANGE      = HexColor("#E65100")   # red-flag accent
ORANGE_PALE = HexColor("#FFF3E0")   # red-flag row bg
GREY_DARK   = HexColor("#37474F")   # body text
GREY_LIGHT  = HexColor("#F5F7F8")   # alt row
WHITE       = colors.white
BLACK       = colors.black

PAGE_W, PAGE_H = A4

OUTPUT = "/home/daytona/workspace/peds-gi-schema/Pediatric_GI_Examination_Schema.pdf"

# ── Page template with header/footer ────────────────────────────
class DocTemplate(SimpleDocTemplate):
    def __init__(self, filename, **kw):
        super().__init__(filename, **kw)

    def handle_pageBegin(self):
        self._handle_pageBegin()

def add_header_footer(canvas_obj, doc):
    canvas_obj.saveState()
    w, h = A4
    # Top bar
    canvas_obj.setFillColor(TEAL)
    canvas_obj.rect(0, h - 22*mm, w, 22*mm, fill=1, stroke=0)
    canvas_obj.setFillColor(WHITE)
    canvas_obj.setFont("Helvetica-Bold", 13)
    canvas_obj.drawString(18*mm, h - 13*mm, "PEDIATRIC GI EXAMINATION SCHEMA")
    canvas_obj.setFont("Helvetica", 9)
    canvas_obj.drawRightString(w - 18*mm, h - 10*mm, "All Ages | Paired with GI History Format")
    canvas_obj.drawRightString(w - 18*mm, h - 15*mm, f"Page {doc.page}")
    # Bottom bar
    canvas_obj.setFillColor(TEAL)
    canvas_obj.rect(0, 0, w, 8*mm, fill=1, stroke=0)
    canvas_obj.setFillColor(WHITE)
    canvas_obj.setFont("Helvetica-Oblique", 7.5)
    canvas_obj.drawString(18*mm, 2.5*mm,
        "Clinical examination findings to pair with Pediatric GI History Format  |  "
        "Sources: Tintinalli's Emergency Medicine; Bailey & Love's Surgery; Family Medicine 9e")
    canvas_obj.restoreState()

# ── Style helpers ────────────────────────────────────────────────
styles = getSampleStyleSheet()

def S(name, **kw):
    base = styles["Normal"]
    return ParagraphStyle(name, parent=base, **kw)

BODY   = S("body",   fontSize=8.5,  leading=12,  textColor=GREY_DARK)
BOLD   = S("bold",   fontSize=8.5,  leading=12,  textColor=GREY_DARK,  fontName="Helvetica-Bold")
RED    = S("red",    fontSize=8.5,  leading=12,  textColor=ORANGE,     fontName="Helvetica-Bold")
SMALL  = S("small",  fontSize=7.5,  leading=10,  textColor=GREY_DARK,  fontName="Helvetica-Oblique")
SMRED  = S("smred",  fontSize=7.5,  leading=10,  textColor=ORANGE,     fontName="Helvetica-Bold")
TITLE_S= S("titls",  fontSize=11,   leading=14,  textColor=WHITE,      fontName="Helvetica-Bold")
SEC    = S("sec",    fontSize=9.5,  leading=13,  textColor=WHITE,      fontName="Helvetica-Bold")
SECBIG = S("secbig", fontSize=10,   leading=14,  textColor=WHITE,      fontName="Helvetica-Bold")

COL_W = [5.5*cm, 6.5*cm, 6.5*cm]   # Finding | Normal/Abnormal | Clinical Significance
COL_W2 = [5.5*cm, 13*cm]            # two-col rows

def section_header(title, color=TEAL):
    """Full-width coloured section banner."""
    t = Table([[Paragraph(title, SEC)]], colWidths=[PAGE_W - 36*mm])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), color),
        ("TOPPADDING",  (0,0), (-1,-1), 5),
        ("BOTTOMPADDING",(0,0),(-1,-1), 5),
        ("LEFTPADDING", (0,0), (-1,-1), 8),
    ]))
    return t

def col_header_row(labels):
    row = [Paragraph(f"<b>{l}</b>", S("ch", fontSize=8, leading=11,
           textColor=WHITE, fontName="Helvetica-Bold")) for l in labels]
    return row

def make_table(rows, col_widths=None, alt=True, header_row=None):
    """Build a styled 3-col table."""
    cw = col_widths or COL_W
    data = []
    if header_row:
        data.append(header_row)
    data.extend(rows)

    t = Table(data, colWidths=cw, repeatRows=1 if header_row else 0)

    style_cmds = [
        ("FONTNAME",  (0,0), (-1,-1), "Helvetica"),
        ("FONTSIZE",  (0,0), (-1,-1), 8.5),
        ("LEADING",   (0,0), (-1,-1), 12),
        ("VALIGN",    (0,0), (-1,-1), "TOP"),
        ("TOPPADDING",(0,0), (-1,-1), 4),
        ("BOTTOMPADDING",(0,0),(-1,-1), 4),
        ("LEFTPADDING",(0,0),(-1,-1), 5),
        ("RIGHTPADDING",(0,0),(-1,-1), 5),
        ("GRID",      (0,0), (-1,-1), 0.25, HexColor("#CFD8DC")),
    ]
    if header_row:
        style_cmds += [
            ("BACKGROUND",(0,0),(-1,0), TEAL_MID),
            ("FONTNAME",  (0,0),(-1,0), "Helvetica-Bold"),
            ("FONTSIZE",  (0,0),(-1,0), 8),
            ("TEXTCOLOR", (0,0),(-1,0), GREY_DARK),
        ]
    if alt:
        start = 1 if header_row else 0
        for i in range(start, len(data)):
            bg = GREY_LIGHT if i % 2 == (1 if header_row else 0) else WHITE
            style_cmds.append(("BACKGROUND",(0,i),(-1,i), bg))

    t.setStyle(TableStyle(style_cmds))
    return t

def red_flag_table(rows):
    """Red-flag styled 3-col table."""
    cw = [5*cm, 6*cm, 7.5*cm]
    header = [Paragraph(f"<b>{l}</b>", S("rh", fontSize=8, leading=11,
              textColor=WHITE, fontName="Helvetica-Bold"))
              for l in ["Red Flag Sign", "How to Elicit", "Clinical Significance"]]
    data = [header] + rows
    t = Table(data, colWidths=cw, repeatRows=1)
    style_cmds = [
        ("FONTNAME",  (0,0),(-1,-1), "Helvetica"),
        ("FONTSIZE",  (0,0),(-1,-1), 8.5),
        ("LEADING",   (0,0),(-1,-1), 12),
        ("VALIGN",    (0,0),(-1,-1), "TOP"),
        ("TOPPADDING",(0,0),(-1,-1), 4),
        ("BOTTOMPADDING",(0,0),(-1,-1), 4),
        ("LEFTPADDING",(0,0),(-1,-1), 5),
        ("RIGHTPADDING",(0,0),(-1,-1), 5),
        ("GRID",      (0,0),(-1,-1), 0.25, HexColor("#FFCCBC")),
        ("BACKGROUND",(0,0),(-1,0), ORANGE),
        ("FONTNAME",  (0,0),(-1,0), "Helvetica-Bold"),
        ("TEXTCOLOR", (0,0),(-1,0), WHITE),
    ]
    for i in range(1, len(data)):
        bg = ORANGE_PALE if i % 2 == 1 else WHITE
        style_cmds.append(("BACKGROUND",(0,i),(-1,i), bg))
    t.setStyle(TableStyle(style_cmds))
    return t

def note_box(text):
    data = [[Paragraph(text, S("nb", fontSize=8, leading=11,
             textColor=GREY_DARK, fontName="Helvetica-Oblique"))]]
    t = Table(data, colWidths=[PAGE_W - 36*mm])
    t.setStyle(TableStyle([
        ("BACKGROUND",(0,0),(-1,-1), HexColor("#E3F2FD")),
        ("LEFTPADDING",(0,0),(-1,-1), 8),
        ("TOPPADDING", (0,0),(-1,-1), 5),
        ("BOTTOMPADDING",(0,0),(-1,-1), 5),
        ("BOX",(0,0),(-1,-1), 0.5, HexColor("#1565C0")),
    ]))
    return t

# ── CONTENT BUILDER ──────────────────────────────────────────────
story = []

# ── INTRO BOX ──
intro_data = [[
    Paragraph("<b>PURPOSE</b>", S("ib", fontSize=9, fontName="Helvetica-Bold", textColor=TEAL)),
    Paragraph(
        "Systematic physical examination guide for paediatric GI complaints. "
        "Each finding paired with its clinical significance and age-specific notes. "
        "Always examine the <b>anxious child last</b> (leave painful areas to the end). "
        "Warm hands, distract with conversation, and observe from the end of the bed first.",
        S("ib2", fontSize=8.5, leading=12, textColor=GREY_DARK))
]]
it = Table(intro_data, colWidths=[3*cm, PAGE_W - 36*mm - 3*cm])
it.setStyle(TableStyle([
    ("BACKGROUND",(0,0),(-1,-1), TEAL_LIGHT),
    ("VALIGN",(0,0),(-1,-1),"MIDDLE"),
    ("TOPPADDING",(0,0),(-1,-1),7),
    ("BOTTOMPADDING",(0,0),(-1,-1),7),
    ("LEFTPADDING",(0,0),(-1,-1),8),
    ("BOX",(0,0),(-1,-1),0.75,TEAL),
]))
story.append(it)
story.append(Spacer(1, 5*mm))

# ═══════════════════════════════════════════════════════════════
# SECTION 1: GENERAL INSPECTION
# ═══════════════════════════════════════════════════════════════
story.append(section_header("1. GENERAL INSPECTION  (Before Touching the Child)"))
story.append(Spacer(1, 1*mm))

hdr = [Paragraph(f"<b>{l}</b>", S("h", fontSize=8, textColor=GREY_DARK, fontName="Helvetica-Bold"))
       for l in ["What to Look For", "Normal Finding", "Abnormal / Significance"]]

gen_rows = [
    [Paragraph("Appearance & distress", BOLD),
     Paragraph("Comfortable, playing, alert", BODY),
     Paragraph("Lying still, knees drawn up (peritonitis). Rolling/writhing (colic). Lethargic (dehydration, sepsis).", BODY)],
    [Paragraph("Nutritional state / growth", BOLD),
     Paragraph("Weight appropriate for age", BODY),
     Paragraph("Wasted/thin = chronic disease (IBD, coeliac, CF, malignancy). Oedema = hypoalbuminaemia (liver failure, protein-losing enteropathy).", BODY)],
    [Paragraph("Skin colour", BOLD),
     Paragraph("Pink, well-perfused", BODY),
     Paragraph("Jaundice (bilirubin >35 µmol/L). Pallor (anaemia from GI bleed, coeliac). Mottling/grey = shock.", BODY)],
    [Paragraph("Face: eyes, mouth", BOLD),
     Paragraph("Moist mucous membranes, clear eyes", BODY),
     Paragraph("Sunken eyes, dry lips = dehydration. Aphthous ulcers = Crohn's disease. Angular stomatitis = iron/B12 deficiency (coeliac).", BODY)],
    [Paragraph("Hands & nails", BOLD),
     Paragraph("Pink, normal capillary refill <2 sec", BODY),
     Paragraph("Clubbing = IBD, CF, liver cirrhosis. Koilonychia = iron deficiency. Leuconychia = hypoalbuminaemia. Palmar erythema = liver disease.", BODY)],
    [Paragraph("Posture / gait", BOLD),
     Paragraph("Normal movement", BODY),
     Paragraph("Child walks bent over / guards abdomen = peritonism. Refuses to jump/walk on heels = peritoneal irritation (ask child to hop).", BODY)],
]
story.append(make_table(gen_rows, col_widths=COL_W, header_row=hdr))
story.append(Spacer(1, 3*mm))

# ═══════════════════════════════════════════════════════════════
# SECTION 2: VITAL SIGNS
# ═══════════════════════════════════════════════════════════════
story.append(section_header("2. VITAL SIGNS  (Age-Referenced)"))
story.append(Spacer(1, 1*mm))

vs_rows = [
    [Paragraph("Temperature", BOLD),
     Paragraph("36.5-37.5 °C", BODY),
     Paragraph("Fever >38°C: appendicitis, gastroenteritis, IBD, mesenteric adenitis, cholangitis. Hypothermia in neonates = sepsis.", BODY)],
    [Paragraph("Heart Rate\n<i>(Tachycardia = early dehydration/pain)</i>", S("bi", fontSize=8.5, leading=12, textColor=GREY_DARK, fontName="Helvetica-BoldOblique")),
     Paragraph("Neonate: 120-160\nInfant: 100-160\nToddler: 90-150\nSchool-age: 70-120", BODY),
     Paragraph("Persistent tachycardia beyond pain control = dehydration or haemorrhage. Bradycardia in sick child = pre-arrest.", BODY)],
    [Paragraph("Blood Pressure", BOLD),
     Paragraph("Age-appropriate (roughly 90 + 2×age mmHg systolic)", BODY),
     Paragraph("Hypotension = late dehydration, haemorrhagic shock, sepsis. Hypertension in GI context = Henoch-Schonlein purpura (renal involvement).", BODY)],
    [Paragraph("Respiratory Rate", BOLD),
     Paragraph("Infant: <50/min\nToddler: <40/min\nSchool-age: <30/min", BODY),
     Paragraph("Tachypnoea = metabolic acidosis (severe dehydration), right lower lobe pneumonia (mimics abdominal pain), diaphragmatic irritation.", BODY)],
    [Paragraph("Capillary Refill Time", BOLD),
     Paragraph("<2 seconds centrally", BODY),
     Paragraph("2-3 sec = mild-moderate dehydration. >3 sec = poor perfusion, shock. Assess centrally (sternum) not peripherally in cold child.", BODY)],
    [Paragraph("Weight (plot on chart)", BOLD),
     Paragraph("Following expected centile", BODY),
     Paragraph("Crossing 2 centile lines downward = significant failure to thrive. Essential for fluid/drug dosing and nutritional assessment.", BODY)],
]
story.append(make_table(vs_rows, col_widths=COL_W, header_row=hdr))
story.append(Spacer(1, 3*mm))

# ═══════════════════════════════════════════════════════════════
# SECTION 3: HANDS, EYES, MOUTH (PERIPHERAL SIGNS)
# ═══════════════════════════════════════════════════════════════
story.append(section_header("3. PERIPHERAL SIGNS  (Hands → Eyes → Mouth → Neck)"))
story.append(Spacer(1, 1*mm))

periph_rows = [
    [Paragraph("HANDS", RED),
     Paragraph("", BODY), Paragraph("", BODY)],
    [Paragraph("Clubbing", BOLD),
     Paragraph("Absent (Schamroth's window visible)", BODY),
     Paragraph("IBD (especially Crohn's), CF, liver cirrhosis, coeliac. Confirm: loss of Schamroth's window, fluctuant nail base.", BODY)],
    [Paragraph("Koilonychia (spoon nails)", BOLD),
     Paragraph("Normal convex nails", BODY),
     Paragraph("Chronic iron deficiency = coeliac disease, IBD, GI blood loss.", BODY)],
    [Paragraph("Leuconychia", BOLD),
     Paragraph("Pink nails, no white bands", BODY),
     Paragraph("Hypoalbuminaemia = liver failure, protein-losing enteropathy, malabsorption.", BODY)],
    [Paragraph("Palmar erythema", BOLD),
     Paragraph("Normal skin tone", BODY),
     Paragraph("Chronic liver disease (hyperdynamic circulation). Also physiological in pregnancy.", BODY)],
    [Paragraph("Dupuytren's contracture", BOLD),
     Paragraph("Full hand extension", BODY),
     Paragraph("Rare in children; if present = liver disease (alcoholic cirrhosis in adults; in children, consider genetic liver disease).", BODY)],
    [Paragraph("EYES", RED),
     Paragraph("", BODY), Paragraph("", BODY)],
    [Paragraph("Scleral icterus (jaundice)", BOLD),
     Paragraph("White sclera", BODY),
     Paragraph("Earliest sign of jaundice. Appears at bilirubin ~35 µmol/L (before skin jaundice). Confirms hepatic/haemolytic pathology.", BODY)],
    [Paragraph("Conjunctival pallor", BOLD),
     Paragraph("Pink conjunctivae", BODY),
     Paragraph("Anaemia from: GI blood loss, coeliac (B12/folate/iron malabsorption), IBD. Pull down lower lid gently.", BODY)],
    [Paragraph("Sunken eyes", BOLD),
     Paragraph("Normal eye fullness", BODY),
     Paragraph("Dehydration. Assess alongside skin turgor and mucous membranes. Sunken eyes = moderate-severe dehydration (>5-10% body weight).", BODY)],
    [Paragraph("Kayser-Fleischer rings", BOLD),
     Paragraph("Clear iris/cornea", BODY),
     Paragraph("Wilson's disease (hepatolenticular degeneration) - copper deposits in Descemet's membrane. Requires slit-lamp. Consider in child with liver disease + neuro symptoms.", BODY)],
    [Paragraph("MOUTH", RED),
     Paragraph("", BODY), Paragraph("", BODY)],
    [Paragraph("Mucous membranes - moisture", BOLD),
     Paragraph("Moist, pink", BODY),
     Paragraph("Dry/tacky = dehydration. Key dehydration sign in infants (crying without tears is complementary).", BODY)],
    [Paragraph("Aphthous ulcers", BOLD),
     Paragraph("Absent", BODY),
     Paragraph("Crohn's disease. Can precede intestinal symptoms by years. Also seen in coeliac, Behcet's, nutritional deficiency.", BODY)],
    [Paragraph("Angular stomatitis / glossitis", BOLD),
     Paragraph("Intact lip angles, normal tongue", BODY),
     Paragraph("Iron, B2, B12 deficiency = malabsorption (coeliac, IBD). Smooth glossy tongue = B12/folate deficiency.", BODY)],
    [Paragraph("Dental erosions", BOLD),
     Paragraph("Normal enamel", BODY),
     Paragraph("Chronic GERD (acid erosion of posterior teeth). Important sign in older children/adolescents with reflux.", BODY)],
    [Paragraph("NECK", RED),
     Paragraph("", BODY), Paragraph("", BODY)],
    [Paragraph("Lymphadenopathy", BOLD),
     Paragraph("No palpable nodes", BODY),
     Paragraph("Mesenteric adenitis (enlarged mesenteric nodes causing abdominal pain, often confused with appendicitis). Generalised nodes = IBD, lymphoma.", BODY)],
]

# mark section sub-rows
periph_data = periph_rows
t = Table([[Paragraph(f"<b>{l}</b>", S("h", fontSize=8, textColor=GREY_DARK, fontName="Helvetica-Bold"))
            for l in ["Sign", "Normal", "Abnormal / Significance"]]] + periph_data,
          colWidths=COL_W, repeatRows=1)

style = [
    ("FONTNAME",  (0,0),(-1,-1),"Helvetica"),
    ("FONTSIZE",  (0,0),(-1,-1),8.5),
    ("LEADING",   (0,0),(-1,-1),12),
    ("VALIGN",    (0,0),(-1,-1),"TOP"),
    ("TOPPADDING",(0,0),(-1,-1),4),
    ("BOTTOMPADDING",(0,0),(-1,-1),4),
    ("LEFTPADDING",(0,0),(-1,-1),5),
    ("GRID",      (0,0),(-1,-1),0.25,HexColor("#CFD8DC")),
    ("BACKGROUND",(0,0),(-1,0), TEAL_MID),
    ("FONTNAME",  (0,0),(-1,0),"Helvetica-Bold"),
    ("FONTSIZE",  (0,0),(-1,0),8),
]
# highlight section dividers (HANDS, EYES, MOUTH, NECK rows)
divider_rows = [i+1 for i,r in enumerate(periph_data)
                if isinstance(r[0], Paragraph) and r[0].style.name == "red"]
for dr in divider_rows:
    style.append(("BACKGROUND",(0,dr),(-1,dr), HexColor("#FFF8E1")))
    style.append(("FONTNAME",(0,dr),(-1,dr),"Helvetica-Bold"))

for i in range(1, len(periph_data)+1):
    if i not in divider_rows:
        bg = GREY_LIGHT if i % 2 == 1 else WHITE
        style.append(("BACKGROUND",(0,i),(-1,i),bg))

t.setStyle(TableStyle(style))
story.append(t)
story.append(Spacer(1, 3*mm))

# ═══════════════════════════════════════════════════════════════
# SECTION 4: ABDOMINAL EXAMINATION
# ═══════════════════════════════════════════════════════════════
story.append(section_header("4. ABDOMINAL EXAMINATION"))
story.append(Spacer(1, 1*mm))

story.append(note_box(
    "SEQUENCE: Inspection → Auscultation → LIGHT palpation → DEEP palpation → Percussion → Special tests  |  "
    "Always ask 'Show me where it hurts' first and leave that area last  |  "
    "Watch the child's face, not your hand, during palpation"))
story.append(Spacer(1, 2*mm))

# 4a Inspection
story.append(Table([[Paragraph("4a. INSPECTION", S("sub", fontSize=9, textColor=TEAL, fontName="Helvetica-Bold"))]],
             colWidths=[PAGE_W-36*mm]))
story.append(Spacer(1,1*mm))

ins_rows = [
    [Paragraph("Abdominal shape / contour", BOLD),
     Paragraph("Slightly protuberant in toddlers (normal). Flat in older children.", BODY),
     Paragraph("Distension: gaseous (obstruction, aerophagia, constipation) vs fluid (ascites - flanks full). Scaphoid = severe malnutrition.", BODY)],
    [Paragraph("Visible peristalsis", BOLD),
     Paragraph("Absent", BODY),
     Paragraph("Visible gastric peristalsis (left → right) in infant = pyloric stenosis. Visible bowel loops = obstruction.", BODY)],
    [Paragraph("Umbilicus", BOLD),
     Paragraph("Central, inverted", BODY),
     Paragraph("Everted = raised intra-abdominal pressure (ascites, mass, organomegaly). Displaced = mass effect.", BODY)],
    [Paragraph("Skin: scars, striae, collateral veins", BOLD),
     Paragraph("Intact skin, no scarring", BODY),
     Paragraph("Surgical scars = adhesions risk. Caput medusae (dilated veins radiating from umbilicus) = portal hypertension. Striae = rapid weight change, Cushing's.", BODY)],
    [Paragraph("Visible mass or asymmetry", BOLD),
     Paragraph("Symmetric", BODY),
     Paragraph("Wilms tumour (nephroblastoma), intussusception mass, hepatosplenomegaly, faecal loading (left iliac fossa). Any visible mass = urgent imaging.", BODY)],
    [Paragraph("Movement with respiration", BOLD),
     Paragraph("Abdomen moves freely with breathing", BODY),
     Paragraph("Abdomen not moving with respiration = peritonitis (child splints abdomen). Paradoxical breathing in infant = respiratory distress.", BODY)],
]
story.append(make_table(ins_rows, col_widths=COL_W, header_row=hdr))
story.append(Spacer(1,2*mm))

# 4b Auscultation
story.append(Table([[Paragraph("4b. AUSCULTATION  (Before palpation - palpation changes bowel sounds)", S("sub", fontSize=9, textColor=TEAL, fontName="Helvetica-Bold"))]],
             colWidths=[PAGE_W-36*mm]))
story.append(Spacer(1,1*mm))

aus_rows = [
    [Paragraph("Bowel sounds", BOLD),
     Paragraph("Intermittent gurgles every 5-10 sec", BODY),
     Paragraph("Absent (>2 min silence) = ileus (post-op, peritonitis, severe inflammation). High-pitched/tinkling = mechanical obstruction. Borborygmi = gastroenteritis, IBS.", BODY)],
    [Paragraph("Hepatic bruit", BOLD),
     Paragraph("Absent", BODY),
     Paragraph("Hepatocellular carcinoma, hepatic haemangioma (infant), AV malformation.", BODY)],
    [Paragraph("Renal bruit (flanks)", BOLD),
     Paragraph("Absent", BODY),
     Paragraph("Renal artery stenosis (rare in children; consider in resistant hypertension).", BODY)],
    [Paragraph("Succussion splash", BOLD),
     Paragraph("Absent when shaking abdomen", BODY),
     Paragraph("Audible splash >3 hrs post-feed = gastric outlet obstruction (pyloric stenosis, antral web).", BODY)],
]
story.append(make_table(aus_rows, col_widths=COL_W, header_row=hdr))
story.append(Spacer(1,2*mm))

# 4c Palpation
story.append(Table([[Paragraph("4c. PALPATION  (Start away from pain, use warm hands, child supine with knees flexed)", S("sub", fontSize=9, textColor=TEAL, fontName="Helvetica-Bold"))]],
             colWidths=[PAGE_W-36*mm]))
story.append(Spacer(1,1*mm))

palp_rows = [
    [Paragraph("Voluntary guarding", BOLD),
     Paragraph("Abdomen soft, relaxed", BODY),
     Paragraph("Child tenses abdomen when you approach = voluntary (pain anticipation). Distinguish from involuntary guarding (persists despite distraction).", BODY)],
    [Paragraph("Involuntary guarding / rigidity", BOLD),
     Paragraph("Absent - abdomen remains relaxed", BODY),
     Paragraph("Board-like rigidity = peritonitis (perforation, appendicitis, ruptured viscus). Rigid abdomen is a surgical emergency.", BODY)],
    [Paragraph("Tenderness - general vs localised", BOLD),
     Paragraph("Non-tender on gentle palpation", BODY),
     Paragraph("Localised RIF = appendicitis (McBurney's point: 1/3 from ASIS to umbilicus). Generalised = peritonitis, gastroenteritis. Epigastric = peptic ulcer, pancreatitis.", BODY)],
    [Paragraph("Liver edge (start RIF, move upward)", BOLD),
     Paragraph("Up to 2 cm below costal margin is normal in infants/toddlers", BODY),
     Paragraph(">3 cm in infants or any in school-age = hepatomegaly. Note texture: smooth (hepatitis, congestion) vs nodular (cirrhosis, storage disease, malignancy).", BODY)],
    [Paragraph("Spleen (start RIF, move toward LUQ)", BOLD),
     Paragraph("Not palpable (or barely tip in young infant)", BODY),
     Paragraph("Splenomegaly: portal hypertension, haemolytic anaemia (sickle cell, spherocytosis), EBV, storage diseases. Massive = malaria, CML.", BODY)],
    [Paragraph("Hepatosplenomegaly", BOLD),
     Paragraph("Not present", BODY),
     Paragraph("Both enlarged = portal hypertension, storage disease (Gaucher's, Niemann-Pick), EBV, leukaemia, haemolytic conditions.", BODY)],
    [Paragraph("Kidneys (ballottement)", BOLD),
     Paragraph("Not palpable in older children. Neonates: tip occasionally felt.", BODY),
     Paragraph("Palpable enlarged kidney = Wilms tumour (hard, smooth, crosses midline), hydronephrosis, PCKD. Wilms is the most common paediatric abdominal tumour.", BODY)],
    [Paragraph("Palpable faecal mass", BOLD),
     Paragraph("Absent", BODY),
     Paragraph("Left iliac fossa or suprapubic = constipation (indentable, non-tender). Right iliac fossa mass = appendix mass/abscess, Crohn's ileocaecal mass, caecal carcinoma.", BODY)],
    [Paragraph("Palpable bowel loop / sausage shape", BOLD),
     Paragraph("Absent", BODY),
     Paragraph("'Sausage-shaped mass' in RUQ or across abdomen = intussusception. Often with empty RIF (Dance's sign = absence of bowel in RIF). Urgent US needed.", BODY)],
    [Paragraph("Inguinal hernias / testes", BOLD),
     Paragraph("Absent hernias. Testes descended bilaterally.", BODY),
     Paragraph("Incarcerated inguinal hernia = obstruction. Undescended testes. Always examine groin in any child with abdominal pain.", BODY)],
]
story.append(make_table(palp_rows, col_widths=COL_W, header_row=hdr))
story.append(Spacer(1,2*mm))

# 4d Percussion
story.append(Table([[Paragraph("4d. PERCUSSION", S("sub", fontSize=9, textColor=TEAL, fontName="Helvetica-Bold"))]],
             colWidths=[PAGE_W-36*mm]))
story.append(Spacer(1,1*mm))

perc_rows = [
    [Paragraph("General tympany vs dullness", BOLD),
     Paragraph("Tympanic over most of abdomen", BODY),
     Paragraph("Dullness = fluid, solid mass, organomegaly. Hyper-resonance = gaseous distension (obstruction, aerophagia).", BODY)],
    [Paragraph("Liver dullness span", BOLD),
     Paragraph("Dull zone: ~6-8 cm in school-age", BODY),
     Paragraph("Increased liver span = hepatomegaly. Loss of liver dullness = pneumoperitoneum (air under diaphragm = perforation = emergency).", BODY)],
    [Paragraph("Shifting dullness", BOLD),
     Paragraph("Absent - dullness does not shift with position", BODY),
     Paragraph("Positive = ascites (>500 mL). Causes: liver failure, nephrotic syndrome, protein-losing enteropathy, malignancy.", BODY)],
    [Paragraph("Fluid thrill", BOLD),
     Paragraph("Absent", BODY),
     Paragraph("Tense ascites (large volume). One hand on flank, assistant's hand on midline to prevent fat conduction, tap opposite flank.", BODY)],
    [Paragraph("Renal angle percussion (CVA tenderness)", BOLD),
     Paragraph("Non-tender", BODY),
     Paragraph("Positive (pain on fist percussion over costovertebral angle) = pyelonephritis, renal calculi. UTI commonly mimics abdominal pain in children.", BODY)],
    [Paragraph("Percuss for bladder", BOLD),
     Paragraph("Dull only if distended", BODY),
     Paragraph("Suprapubic dullness = urinary retention (uncommon in children but seen post-surgery, with neurogenic bladder).", BODY)],
]
story.append(make_table(perc_rows, col_widths=COL_W, header_row=hdr))
story.append(Spacer(1, 3*mm))

# ═══════════════════════════════════════════════════════════════
# SECTION 5: SPECIAL / ELICITED SIGNS
# ═══════════════════════════════════════════════════════════════
story.append(section_header("5. SPECIAL SIGNS  (Elicited Tests)"))
story.append(Spacer(1, 1*mm))

spec_hdr = [Paragraph(f"<b>{l}</b>", S("sh", fontSize=8, textColor=GREY_DARK, fontName="Helvetica-Bold"))
            for l in ["Sign", "How to Elicit", "Positive Finding / Significance"]]

spec_rows = [
    [Paragraph("Rebound tenderness\n(Blumberg's sign)", BOLD),
     Paragraph("Press slowly and firmly, then release suddenly. Alternatively: percussion tenderness (gentler, preferred in children).", BODY),
     Paragraph("Pain worse on RELEASE than press = peritoneal irritation. Appendicitis, perforated viscus. Percussion tenderness = same significance, less distressing for child.", BODY)],
    [Paragraph("Rovsing's sign", BOLD),
     Paragraph("Press LIF (left iliac fossa) while watching/asking about RIF pain.", BODY),
     Paragraph("Positive = pain in RIF when LIF compressed = appendicitis (referred peritoneal irritation from right side).", BODY)],
    [Paragraph("Psoas sign", BOLD),
     Paragraph("Child lies on left side. Extend right hip passively (or ask child to raise right leg against resistance).", BODY),
     Paragraph("Positive = pain in RIF = retrocaecal appendix (lying on psoas muscle). Also positive in right-sided psoas abscess.", BODY)],
    [Paragraph("Obturator sign", BOLD),
     Paragraph("Flex and internally rotate right hip (with knee flexed).", BODY),
     Paragraph("Positive = RIF pain = pelvic appendix or pelvic abscess (appendix lies near obturator internus).", BODY)],
    [Paragraph("Heel-drop test\n(Markle's sign)", BOLD),
     Paragraph("Ask child to stand on tiptoe then drop onto heels (or lower child firmly onto heels).", BODY),
     Paragraph("Pain on heel strike = peritoneal irritation. Sensitive, non-invasive, child-friendly alternative to rebound tenderness.", BODY)],
    [Paragraph("Carnett's sign", BOLD),
     Paragraph("Locate tender area. Ask child to tense abdomen (lift head or legs). Palpate same area.", BODY),
     Paragraph("Pain UNCHANGED or WORSE with tensed muscles = abdominal wall pain (not visceral). Pain improves = intra-abdominal cause.", BODY)],
    [Paragraph("Murphy's sign", BOLD),
     Paragraph("Deep palpation in RUQ. Ask child to breathe in deeply.", BODY),
     Paragraph("Positive = sudden inspiration arrest due to pain = cholecystitis (gallbladder descends onto examining hand). Uncommon in children but seen in sickle cell, CF.", BODY)],
    [Paragraph("Dance's sign", BOLD),
     Paragraph("Palpate right iliac fossa.", BODY),
     Paragraph("Empty RIF (absent bowel gas/loops) = intussusception (bowel telescoped away from RIF). Paired with sausage-shaped mass elsewhere.", BODY)],
    [Paragraph("Cullen's sign / Grey Turner's sign", BOLD),
     Paragraph("Inspect periumbilical (Cullen's) and flank (Grey Turner's) skin.", BODY),
     Paragraph("Bruising = retroperitoneal haemorrhage = severe pancreatitis, ruptured AAA (rare in children, but pancreatitis occurs).", BODY)],
    [Paragraph("Succussion splash", BOLD),
     Paragraph("Hands on sides of abdomen, shake patient side-to-side. Listen with stethoscope or unaided.", BODY),
     Paragraph("Audible splash = fluid + air in obstructed hollow viscus. Gastric outlet obstruction (pyloric stenosis, antral pathology).", BODY)],
]
story.append(make_table(spec_rows, col_widths=[5*cm, 6*cm, 7.5*cm], header_row=spec_hdr))
story.append(Spacer(1, 3*mm))

# ═══════════════════════════════════════════════════════════════
# SECTION 6: HERNIAL ORIFICES & GENITALIA
# ═══════════════════════════════════════════════════════════════
story.append(section_header("6. HERNIAL ORIFICES, GENITALIA & RECTUM"))
story.append(Spacer(1, 1*mm))

hern_rows = [
    [Paragraph("Inguinal hernias", BOLD),
     Paragraph("No bulge at rest or on coughing/crying", BODY),
     Paragraph("Indirect inguinal hernia most common in boys <1 year. Risk of incarceration = strangulation = obstruction. ALWAYS examine groin in child with vomiting.", BODY)],
    [Paragraph("Umbilical hernia", BOLD),
     Paragraph("No persistent defect in school-age (usually closes by age 5)", BODY),
     Paragraph("Persistent in >5 years = consider repair. Incarceration rare. More common in African children and premature infants.", BODY)],
    [Paragraph("Femoral hernia", BOLD),
     Paragraph("Absent", BODY),
     Paragraph("Rare in children. Below and lateral to pubic tubercle. Higher incarceration risk than inguinal hernias.", BODY)],
    [Paragraph("Testes (males)", BOLD),
     Paragraph("Both testes palpable in scrotum bilaterally", BODY),
     Paragraph("Undescended = orchidopexy needed by age 1. Testicular torsion = sudden severe scrotal pain, absent cremasteric reflex, high-riding testis. Presents as abdominal pain - ALWAYS examine scrotum in boys with abdominal pain.", BODY)],
    [Paragraph("Cremasteric reflex", BOLD),
     Paragraph("Present (stroking medial thigh raises ipsilateral testis)", BODY),
     Paragraph("Absent in testicular torsion. Sensitive test - if absent, urgent surgical exploration needed.", BODY)],
    [Paragraph("Perianal inspection", BOLD),
     Paragraph("Intact skin, no fissures, normal tone", BODY),
     Paragraph("Anal fissure = most common cause of rectal bleeding in infants/toddlers (hard stool + pain + surface blood). Skin tags = Crohn's. Warts = consider abuse. Patulous anus = neurological cause of constipation.", BODY)],
    [Paragraph("Digital Rectal Examination\n(in children: consider carefully, only if indicated)", BOLD),
     Paragraph("Performed only when clinically necessary with consent/assent", BODY),
     Paragraph("Empty rectum in constipated child = high impaction (Hirschsprung's). Hard stool = functional constipation. Blood on glove = colitis. Tender anteriorly = pelvic appendicitis/abscess. Not routinely needed for appendicitis diagnosis (evidence does not support diagnostic utility).", BODY)],
]
story.append(make_table(hern_rows, col_widths=COL_W, header_row=hdr))
story.append(Spacer(1, 3*mm))

# ═══════════════════════════════════════════════════════════════
# SECTION 7: EXTRA-INTESTINAL MANIFESTATIONS
# ═══════════════════════════════════════════════════════════════
story.append(section_header("7. EXTRA-INTESTINAL MANIFESTATIONS  (Examine These in Every GI Case)"))
story.append(Spacer(1, 1*mm))

ext_rows = [
    [Paragraph("Skin: erythema nodosum", BOLD),
     Paragraph("Painful red nodules on shins/extensors", BODY),
     Paragraph("IBD (Crohn's > UC), sarcoidosis, Behcet's. Signals systemic inflammation.", BODY)],
    [Paragraph("Skin: pyoderma gangrenosum", BOLD),
     Paragraph("Necrotic ulcers with violaceous edge", BODY),
     Paragraph("IBD (UC > Crohn's). Pathergy present. Indicates severe/active disease.", BODY)],
    [Paragraph("Skin: dermatitis herpetiformis", BOLD),
     Paragraph("Itchy vesicular rash elbows, knees, buttocks", BODY),
     Paragraph("Gluten sensitivity = coeliac disease. Nearly pathognomonic.", BODY)],
    [Paragraph("Skin: jaundice (sclera first)", BOLD),
     Paragraph("Yellow discolouration sclera → skin", BODY),
     Paragraph("Pre-hepatic (haemolysis), hepatic (hepatitis, Wilson's, metabolic), post-hepatic (biliary atresia, choledochal cyst).", BODY)],
    [Paragraph("Joints: arthritis/arthralgia", BOLD),
     Paragraph("Swollen, warm, tender joints", BODY),
     Paragraph("IBD (peripheral arthritis - large joints, parallels bowel activity). Reactive arthritis post-GI infection (Salmonella, Campylobacter, Yersinia).", BODY)],
    [Paragraph("Eyes: uveitis / episcleritis", BOLD),
     Paragraph("Red, painful eye; photophobia", BODY),
     Paragraph("IBD extra-intestinal manifestation. Uveitis can cause blindness if untreated - always refer ophthalmology.", BODY)],
    [Paragraph("Mouth: angular cheilitis, glossitis", BOLD),
     Paragraph("Inflamed lip angles; smooth red tongue", BODY),
     Paragraph("Nutritional deficiency (iron, B12, folate, B2) = coeliac, IBD, chronic malabsorption.", BODY)],
    [Paragraph("Growth: height, weight, puberty stage", BOLD),
     Paragraph("Appropriate for age on growth chart", BODY),
     Paragraph("Delayed growth/puberty = classic in Crohn's disease. Can be presenting sign before bowel symptoms. Always plot and compare to previous measurements.", BODY)],
]
story.append(make_table(ext_rows, col_widths=[5.5*cm, 5.5*cm, 7.5*cm], header_row=[
    Paragraph("<b>Manifestation</b>", S("h", fontSize=8, textColor=GREY_DARK, fontName="Helvetica-Bold")),
    Paragraph("<b>What You See</b>", S("h", fontSize=8, textColor=GREY_DARK, fontName="Helvetica-Bold")),
    Paragraph("<b>Significance / Diagnosis</b>", S("h", fontSize=8, textColor=GREY_DARK, fontName="Helvetica-Bold")),
]))
story.append(Spacer(1, 3*mm))

# ═══════════════════════════════════════════════════════════════
# SECTION 8: DEHYDRATION ASSESSMENT
# ═══════════════════════════════════════════════════════════════
story.append(section_header("8. DEHYDRATION ASSESSMENT  (Critical in Paediatric GI)"))
story.append(Spacer(1, 1*mm))

dehyd_hdr = [Paragraph(f"<b>{l}</b>", S("dh", fontSize=8, textColor=GREY_DARK, fontName="Helvetica-Bold"))
             for l in ["Clinical Sign", "Mild (<5%)", "Moderate (5-10%)", "Severe (>10%)"]]

dehyd_rows = [
    [Paragraph("General appearance", BODY),
     Paragraph("Alert, normal", BODY),
     Paragraph("Restless, irritable", BODY),
     Paragraph("Lethargic, limp, unresponsive", BODY)],
    [Paragraph("Eyes", BODY),
     Paragraph("Normal", BODY),
     Paragraph("Slightly sunken", BODY),
     Paragraph("Deeply sunken, no tears", BODY)],
    [Paragraph("Mucous membranes", BODY),
     Paragraph("Moist", BODY),
     Paragraph("Dry", BODY),
     Paragraph("Parched, cracked", BODY)],
    [Paragraph("Skin turgor\n(pinch abdomen/thigh)", BODY),
     Paragraph("Returns instantly", BODY),
     Paragraph("Returns slowly (1-2 sec)", BODY),
     Paragraph("Returns very slowly (>2 sec) or stays tented", BODY)],
    [Paragraph("Capillary refill", BODY),
     Paragraph("<2 sec", BODY),
     Paragraph("2-3 sec", BODY),
     Paragraph(">3 sec", BODY)],
    [Paragraph("Heart rate", BODY),
     Paragraph("Normal", BODY),
     Paragraph("Mildly elevated", BODY),
     Paragraph("Significantly elevated", BODY)],
    [Paragraph("Blood pressure", BODY),
     Paragraph("Normal", BODY),
     Paragraph("Normal or slightly low", BODY),
     Paragraph("Hypotensive, undetectable", BODY)],
    [Paragraph("Urine output", BODY),
     Paragraph("Normal", BODY),
     Paragraph("Reduced, concentrated", BODY),
     Paragraph("Oliguric/anuric", BODY)],
    [Paragraph("Fontanelle (infants)", BODY),
     Paragraph("Flat", BODY),
     Paragraph("Slightly sunken", BODY),
     Paragraph("Markedly sunken", BODY)],
    [Paragraph("MANAGEMENT", RED),
     Paragraph("Oral rehydration\nsolution (ORS)", BODY),
     Paragraph("ORS 50-100 mL/kg\nover 2-4 hours", BODY),
     Paragraph("IV fluids STAT\n20 mL/kg 0.9% NaCl bolus\nRepeat as needed", BODY)],
]
dt = Table([dehyd_hdr] + dehyd_rows, colWidths=[5*cm, 4*cm, 4.5*cm, 5*cm], repeatRows=1)
dstyle = [
    ("FONTNAME",(0,0),(-1,-1),"Helvetica"),
    ("FONTSIZE",(0,0),(-1,-1),8.5),
    ("LEADING",(0,0),(-1,-1),11),
    ("VALIGN",(0,0),(-1,-1),"TOP"),
    ("TOPPADDING",(0,0),(-1,-1),4),
    ("BOTTOMPADDING",(0,0),(-1,-1),4),
    ("LEFTPADDING",(0,0),(-1,-1),5),
    ("GRID",(0,0),(-1,-1),0.25,HexColor("#CFD8DC")),
    ("BACKGROUND",(0,0),(-1,0),TEAL_MID),
    ("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),
    ("FONTSIZE",(0,0),(-1,0),8),
    # Colour severity columns
    ("BACKGROUND",(1,1),  (1,-1), HexColor("#F1F8E9")),
    ("BACKGROUND",(2,1),  (2,-1), HexColor("#FFF9C4")),
    ("BACKGROUND",(3,1),  (3,-1), HexColor("#FFEBEE")),
    # Last row (management) - bold
    ("FONTNAME",(0,-1),(-1,-1),"Helvetica-Bold"),
    ("BACKGROUND",(0,-1),(-1,-1), HexColor("#E8EAF6")),
]
dt.setStyle(TableStyle(dstyle))
story.append(dt)
story.append(Spacer(1, 3*mm))

# ═══════════════════════════════════════════════════════════════
# SECTION 9: RED FLAG SIGNS
# ═══════════════════════════════════════════════════════════════
story.append(section_header("9. RED FLAG SIGNS  (Require Immediate Action)", color=ORANGE))
story.append(Spacer(1, 1*mm))

rf_rows = [
    [Paragraph("Bilious (green) vomiting", RED),
     Paragraph("Inspect vomitus / ask specifically. Green colour confirms bile.", BODY),
     Paragraph("Bowel obstruction DISTAL to ampulla of Vater. In neonate = malrotation + volvulus (life-threatening). Surgical emergency until proven otherwise.", BODY)],
    [Paragraph("Board-like rigidity", RED),
     Paragraph("Involuntary muscle contraction persists despite distraction.", BODY),
     Paragraph("Peritonitis = perforation until proven otherwise. Immediate surgical referral + resuscitation.", BODY)],
    [Paragraph("Absent bowel sounds (>2 min)", RED),
     Paragraph("Auscultate all four quadrants for minimum 2 minutes.", BODY),
     Paragraph("Paralytic ileus (peritonitis, post-perforation, severe electrolyte disturbance). Or mechanical obstruction (late).", BODY)],
    [Paragraph("Loss of liver dullness", RED),
     Paragraph("Percussion over liver area - resonant instead of dull.", BODY),
     Paragraph("Pneumoperitoneum = air under diaphragm = perforated viscus. Confirm with erect CXR (free air under diaphragm).", BODY)],
    [Paragraph("Positive heel-drop / rebound", RED),
     Paragraph("Pain on heel strike or release of pressure.", BODY),
     Paragraph("Peritoneal irritation = appendicitis, perforated viscus, ruptured ectopic (adolescent girls).", BODY)],
    [Paragraph("Palpable RIF mass + colicky pain + currant-jelly stool", RED),
     Paragraph("Sausage-shaped mass in RUQ/transverse + empty RIF (Dance's sign).", BODY),
     Paragraph("Intussusception. Peak age 3 months - 3 years. Urgent USS + pneumatic or hydrostatic reduction.", BODY)],
    [Paragraph("Absent cremasteric reflex in boys", RED),
     Paragraph("Stroke medial thigh - no testicular elevation.", BODY),
     Paragraph("Testicular torsion until proven otherwise. 6-hour window for salvage. Urgent surgical exploration - do NOT await USS.", BODY)],
    [Paragraph("Severe dehydration signs", RED),
     Paragraph("Sunken eyes, no tears, skin tenting, CRT >3 sec, altered consciousness.", BODY),
     Paragraph("Hypovolaemic shock. IV bolus 20 mL/kg 0.9% NaCl immediately. Reassess and repeat. ICU escalation if no response.", BODY)],
    [Paragraph("Haematemesis / large PR bleed", RED),
     Paragraph("Fresh blood or coffee grounds in vomit / significant rectal blood.", BODY),
     Paragraph("Active GI haemorrhage. IV access, crossmatch, surgical + GI endoscopy team. Proton pump inhibitor if upper GI source likely.", BODY)],
]
story.append(red_flag_table(rf_rows))
story.append(Spacer(1, 3*mm))

# ═══════════════════════════════════════════════════════════════
# SECTION 10: EXAMINATION SUMMARY CHECKLIST
# ═══════════════════════════════════════════════════════════════
story.append(section_header("10. EXAMINATION SUMMARY CHECKLIST  (Quick-Reference Tick List)"))
story.append(Spacer(1, 1*mm))

check_items = [
    ("GENERAL", [
        "Child appearance (comfortable / distressed / peritonitic posture)",
        "Nutritional status (weight on centile chart)",
        "Skin colour (jaundice / pallor / perfusion)",
        "Vital signs all documented with age-referenced ranges",
    ]),
    ("PERIPHERAL", [
        "Hands: clubbing, koilonychia, leuconychia, palmar erythema",
        "Eyes: scleral icterus, conjunctival pallor, sunken eyes",
        "Mouth: mucous membrane moisture, ulcers, glossitis, dental erosions",
        "Neck: lymphadenopathy",
    ]),
    ("ABDOMEN - INSPECTION", [
        "Shape (distension / scaphoid / asymmetry)",
        "Visible peristalsis (especially infants)",
        "Umbilicus (central / everted / displaced)",
        "Skin (scars / caput medusae / striae)",
        "Movement with respiration (free / restricted)",
    ]),
    ("ABDOMEN - AUSCULTATION", [
        "Bowel sounds (normal / absent / high-pitched / tinkling)",
        "Succussion splash if gastric outlet obstruction suspected",
    ]),
    ("ABDOMEN - PALPATION", [
        "Systematic 9-quadrant or 4-quadrant light palpation (start away from pain)",
        "Deep palpation: tenderness site and character",
        "Liver: size, edge character, tenderness",
        "Spleen: size, direction of enlargement",
        "Kidneys: ballottement bilaterally",
        "Faecal mass / abnormal mass",
    ]),
    ("ABDOMEN - PERCUSSION", [
        "Liver dullness and span",
        "Splenic dullness (Traube's space)",
        "Shifting dullness (ascites)",
        "Renal angle tenderness",
    ]),
    ("SPECIAL SIGNS", [
        "Rebound / percussion tenderness (if peritonism suspected)",
        "Rovsing's sign (appendicitis)",
        "Heel-drop test (peritoneal irritation)",
        "Carnett's sign (if abdominal wall pain considered)",
    ]),
    ("HERNIAS / GENITALIA", [
        "Inguinal orifices (bilateral)",
        "Testes palpated bilaterally (males) - cremasteric reflex",
        "Perianal inspection (fissure, skin tags, warts)",
    ]),
    ("EXTRA-INTESTINAL", [
        "Skin rashes (erythema nodosum, pyoderma gangrenosum, dermatitis herpetiformis)",
        "Joints examined if arthralgia reported",
        "Growth: height and weight plotted on centile chart",
    ]),
]

for section_name, items in check_items:
    check_data = []
    check_data.append([
        Paragraph(f"<b>{section_name}</b>",
                  S("cl", fontSize=8, textColor=TEAL, fontName="Helvetica-Bold")),
        Paragraph("", BODY)
    ])
    for item in items:
        check_data.append([
            Paragraph("☐  " + item, BODY),
            Paragraph("", BODY)
        ])

    ct = Table(check_data, colWidths=[PAGE_W - 36*mm - 3*cm, 3*cm])
    cstyle = [
        ("FONTNAME",(0,0),(-1,-1),"Helvetica"),
        ("FONTSIZE",(0,0),(-1,-1),8.5),
        ("VALIGN",(0,0),(-1,-1),"TOP"),
        ("TOPPADDING",(0,0),(-1,-1),3),
        ("BOTTOMPADDING",(0,0),(-1,-1),3),
        ("LEFTPADDING",(0,0),(-1,-1),5),
        ("BACKGROUND",(0,0),(-1,0), TEAL_LIGHT),
        ("GRID",(0,0),(-1,-1),0.2,HexColor("#CFD8DC")),
    ]
    for i in range(1, len(check_data)):
        bg = GREY_LIGHT if i%2==1 else WHITE
        cstyle.append(("BACKGROUND",(0,i),(-1,i),bg))
    ct.setStyle(TableStyle(cstyle))
    story.append(ct)
    story.append(Spacer(1, 1.5*mm))

story.append(Spacer(1, 3*mm))

# ── FOOTER NOTE ──
story.append(HRFlowable(width="100%", thickness=0.5, color=TEAL))
story.append(Spacer(1, 2*mm))
fn = Table([[
    Paragraph("Sources: Tintinalli's Emergency Medicine (Vomiting, Diarrhea & Dehydration in Children); "
              "Bailey & Love's Short Practice of Surgery 28e (Clinical Signs in Appendicitis); "
              "Textbook of Family Medicine 9e (Common Paediatric GI Disorders). "
              "For educational/study use. Always apply clinical judgement.",
              S("fn", fontSize=7, leading=10, textColor=GREY_DARK, fontName="Helvetica-Oblique"))
]], colWidths=[PAGE_W - 36*mm])
fn.setStyle(TableStyle([
    ("LEFTPADDING",(0,0),(-1,-1),0),
    ("TOPPADDING",(0,0),(-1,-1),0),
]))
story.append(fn)

# ── BUILD ────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    leftMargin=18*mm,
    rightMargin=18*mm,
    topMargin=28*mm,
    bottomMargin=14*mm,
    title="Pediatric GI Examination Schema",
    author="Orris Medical Notes",
    subject="Paediatric GI Physical Examination",
)

doc.build(story, onFirstPage=add_header_footer, onLaterPages=add_header_footer)
print(f"PDF generated: {OUTPUT}")
Running Command

cd /home/daytona/workspace/peds-gi-schema && python generate_schema.py 2>&1

Running Command

ls -lh /home/daytona/workspace/peds-gi-schema/Pediatric_GI_Examination_Schema.pdf

Your printable PDF is ready:

Pediatric GI Examination Schema

PDF Document · PDF


Here is what the document contains (10 sections, A4, teal/orange colour-coded):
SectionContents
1. General InspectionAppearance, nutritional state, skin, face, hands, posture - all with significance
2. Vital SignsAge-referenced HR, BP, RR, CRT, temperature with clinical implications
3. Peripheral SignsHands (clubbing, koilonychia, leuconychia) → Eyes (jaundice, pallor, sunken) → Mouth (ulcers, glossitis) → Neck
4. Abdominal ExaminationInspection → Auscultation → Palpation (liver, spleen, kidneys, masses) → Percussion in structured sub-sections
5. Special SignsRebound, Rovsing's, Psoas, Obturator, Heel-drop, Carnett's, Murphy's, Dance's, Cullen's - each with how-to-elicit
6. Hernias & GenitaliaInguinal/umbilical/femoral hernias, testes, cremasteric reflex, perianal inspection, DRE guidance
7. Extra-intestinal ManifestationsSkin (EN, pyoderma, dermatitis herpetiformis), joints, eyes, growth - IBD/coeliac markers
8. Dehydration AssessmentColour-coded mild/moderate/severe table with management per level
9. Red Flag SignsOrange-highlighted: bilious vomiting, peritonitis, pneumoperitoneum, intussusception, testicular torsion
10. ChecklistFull tick-box rapid reference for case presentation or OSCE run-through
The document pairs directly with the history format - every examination finding maps to the "associated symptoms" and "red flags" sections covered in the history.
This is a shared conversation. Sign in to Orris to start your own chat.