attachment
attachment

Give syllabus

Here is the Mark Distribution for Practical Exam from the image:

Hematology — 40 Marks

ComponentMarks
Major15
Minor5
Amphibian chart10
Problem chart5
Endocrine or Non-Endocrine chart5
Total40

Clinical — 40 Marks

ComponentMarks
Major15
Minor5
2 Human Experiments20
Total40

Theory Viva — 20 Marks


Grand Total: 40 + 40 + 20 = 100 Marks


Additional Notes:

  • Theory viva covers all systems
  • Practical also covers all systems
  • Practical exam follows typical university exam pattern
  • Some students have not submitted their record (reminder noted)

Create a study guide document for each exam component

Reading File
Reading File
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Running Command

mkdir -p /home/daytona/workspace/physiology-study-guide && ls /home/daytona/work…

Writing File

~/physiology-study-guide/create_guide.js

const {
  Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
  HeadingLevel, AlignmentType, LevelFormat, BorderStyle, WidthType,
  ShadingType, VerticalAlign, PageNumber, PageBreak, UnderlineType
} = require('docx');
const fs = require('fs');

// Numbering config
const numberingConfig = {
  config: [
    {
      reference: "bullets",
      levels: [{
        level: 0, format: LevelFormat.BULLET, text: "\u2022", alignment: AlignmentType.LEFT,
        style: { paragraph: { indent: { left: 720, hanging: 360 } } }
      }]
    },
    {
      reference: "sub-bullets",
      levels: [{
        level: 0, format: LevelFormat.BULLET, text: "\u25E6", alignment: AlignmentType.LEFT,
        style: { paragraph: { indent: { left: 1080, hanging: 360 } } }
      }]
    },
    {
      reference: "numbers",
      levels: [{
        level: 0, format: LevelFormat.DECIMAL, text: "%1.", alignment: AlignmentType.LEFT,
        style: { paragraph: { indent: { left: 720, hanging: 360 } } }
      }]
    }
  ]
};

function heading1(text) {
  return new Paragraph({
    heading: HeadingLevel.HEADING_1,
    children: [new TextRun({ text, font: "Arial", size: 36, bold: true, color: "1F4E79" })]
  });
}

function heading2(text) {
  return new Paragraph({
    heading: HeadingLevel.HEADING_2,
    children: [new TextRun({ text, font: "Arial", size: 28, bold: true, color: "2E75B6" })]
  });
}

function heading3(text) {
  return new Paragraph({
    heading: HeadingLevel.HEADING_3,
    children: [new TextRun({ text, font: "Arial", size: 24, bold: true, color: "404040" })]
  });
}

function bullet(text, bold_part = null) {
  const children = bold_part
    ? [new TextRun({ text: bold_part + " ", font: "Arial", size: 22, bold: true }), new TextRun({ text: text, font: "Arial", size: 22 })]
    : [new TextRun({ text, font: "Arial", size: 22 })];
  return new Paragraph({ numbering: { reference: "bullets", level: 0 }, children });
}

function subBullet(text) {
  return new Paragraph({ numbering: { reference: "sub-bullets", level: 0 }, children: [new TextRun({ text, font: "Arial", size: 20 })] });
}

function body(text) {
  return new Paragraph({ children: [new TextRun({ text, font: "Arial", size: 22 })], spacing: { after: 100 } });
}

function bold_body(text) {
  return new Paragraph({ children: [new TextRun({ text, font: "Arial", size: 22, bold: true })], spacing: { after: 100 } });
}

function pageBreak() {
  return new Paragraph({ children: [new PageBreak()] });
}

function spacer() {
  return new Paragraph({ children: [new TextRun("")], spacing: { after: 120 } });
}

function markBox(label, marks) {
  return new Table({
    width: { size: 100, type: WidthType.PERCENTAGE },
    rows: [
      new TableRow({
        children: [
          new TableCell({
            shading: { type: ShadingType.SOLID, color: "1F4E79" },
            children: [new Paragraph({ alignment: AlignmentType.CENTER, children: [new TextRun({ text: label, font: "Arial", size: 24, bold: true, color: "FFFFFF" })] })],
            verticalAlign: VerticalAlign.CENTER,
            width: { size: 70, type: WidthType.PERCENTAGE }
          }),
          new TableCell({
            shading: { type: ShadingType.SOLID, color: "2E75B6" },
            children: [new Paragraph({ alignment: AlignmentType.CENTER, children: [new TextRun({ text: marks + " Marks", font: "Arial", size: 24, bold: true, color: "FFFFFF" })] })],
            verticalAlign: VerticalAlign.CENTER,
            width: { size: 30, type: WidthType.PERCENTAGE }
          })
        ]
      })
    ]
  });
}

function simpleTable(headers, rows) {
  const headerRow = new TableRow({
    children: headers.map(h => new TableCell({
      shading: { type: ShadingType.SOLID, color: "D6E4F0" },
      children: [new Paragraph({ children: [new TextRun({ text: h, font: "Arial", size: 20, bold: true })] })]
    }))
  });
  const dataRows = rows.map(row => new TableRow({
    children: row.map(cell => new TableCell({
      children: [new Paragraph({ children: [new TextRun({ text: cell, font: "Arial", size: 20 })] })]
    }))
  }));
  return new Table({
    width: { size: 100, type: WidthType.PERCENTAGE },
    rows: [headerRow, ...dataRows]
  });
}

// ===================== DOCUMENT CONTENT =====================

const doc = new Document({
  numbering: numberingConfig,
  styles: {
    default: { document: { run: { font: "Arial", size: 22 } } },
    paragraphStyles: [
      {
        id: "Heading1", name: "Heading 1", basedOn: "Normal", next: "Normal", quickFormat: true,
        run: { size: 36, bold: true, font: "Arial", color: "1F4E79" },
        paragraph: { spacing: { before: 300, after: 200 }, outlineLevel: 0 }
      },
      {
        id: "Heading2", name: "Heading 2", basedOn: "Normal", next: "Normal", quickFormat: true,
        run: { size: 28, bold: true, font: "Arial", color: "2E75B6" },
        paragraph: { spacing: { before: 240, after: 160 }, outlineLevel: 1 }
      },
      {
        id: "Heading3", name: "Heading 3", basedOn: "Normal", next: "Normal", quickFormat: true,
        run: { size: 24, bold: true, font: "Arial", color: "404040" },
        paragraph: { spacing: { before: 180, after: 120 }, outlineLevel: 2 }
      }
    ]
  },
  sections: [
    {
      children: [
        // ==================== COVER PAGE ====================
        spacer(), spacer(), spacer(),
        new Paragraph({
          alignment: AlignmentType.CENTER,
          children: [new TextRun({ text: "PHYSIOLOGY PRACTICAL EXAM", font: "Arial", size: 52, bold: true, color: "1F4E79" })]
        }),
        new Paragraph({
          alignment: AlignmentType.CENTER,
          children: [new TextRun({ text: "STUDY GUIDE", font: "Arial", size: 52, bold: true, color: "2E75B6" })]
        }),
        spacer(),
        new Paragraph({
          alignment: AlignmentType.CENTER,
          children: [new TextRun({ text: "Complete Preparation for All Exam Components", font: "Arial", size: 26, color: "595959", italics: true })]
        }),
        spacer(), spacer(),
        simpleTable(
          ["Exam Component", "Marks"],
          [
            ["Hematology - Major", "15"],
            ["Hematology - Minor", "5"],
            ["Amphibian Chart", "10"],
            ["Problem Chart", "5"],
            ["Endocrine / Non-Endocrine Chart", "5"],
            ["Clinical - Major", "15"],
            ["Clinical - Minor", "5"],
            ["2 Human Experiments", "20"],
            ["Theory Viva (All Systems)", "20"],
            ["GRAND TOTAL", "100"]
          ]
        ),
        spacer(),
        new Paragraph({
          alignment: AlignmentType.CENTER,
          children: [new TextRun({ text: "Covers: All Systems | Typical University Exam Pattern", font: "Arial", size: 22, bold: true, color: "1F4E79" })]
        }),
        pageBreak(),

        // ==================== SECTION 1: HEMATOLOGY (40 MARKS) ====================
        heading1("SECTION 1: HEMATOLOGY (40 Marks)"),
        body("Hematology forms the largest section of the exam. You will be tested on major and minor practicals, as well as chart-based questions."),
        spacer(),

        // --- 1A: Major (15 marks) ---
        markBox("HEMATOLOGY MAJOR", 15),
        spacer(),
        heading2("1A. Major Hematology (15 Marks)"),
        body("The major hematology practical typically involves a complete blood count (CBC) analysis and identification of a blood disorder from a prepared slide or report."),

        heading3("Complete Blood Count (CBC) - Key Parameters"),
        simpleTable(
          ["Parameter", "Normal Range (Adult)", "Significance"],
          [
            ["Hemoglobin (Hb)", "M: 13-17 g/dL | F: 12-15 g/dL", "Oxygen carrying capacity"],
            ["RBC Count", "M: 4.5-5.5 million/mm³ | F: 3.8-4.8", "Erythrocyte number"],
            ["WBC Count", "4,000-11,000/mm³", "Immune defense"],
            ["Platelet Count", "1.5-4.0 lakh/mm³", "Hemostasis"],
            ["PCV/Hematocrit", "M: 40-50% | F: 35-45%", "Packed cell volume"],
            ["MCV", "80-100 fL", "Size of RBCs"],
            ["MCH", "27-32 pg", "Hb content per RBC"],
            ["MCHC", "31-36 g/dL", "Hb concentration in RBCs"],
            ["ESR", "M: 0-15 mm/hr | F: 0-20 mm/hr", "Inflammation marker"]
          ]
        ),
        spacer(),

        heading3("Blood Indices and Their Interpretation"),
        bullet("Microcytic hypochromic (low MCV, low MCH): Iron deficiency anemia, thalassemia"),
        bullet("Normocytic normochromic (normal MCV, normal MCH): Acute blood loss, aplastic anemia, hemolytic anemia"),
        bullet("Macrocytic (high MCV): Vitamin B12/folate deficiency, megaloblastic anemia"),
        bullet("Dimorphic picture: Mixed deficiency, post-transfusion"),
        spacer(),

        heading3("Hemoglobin Estimation Methods"),
        bullet("Sahli's acid hematin method - standard method in practicals"),
        subBullet("Principle: Hb + dilute HCl → acid hematin (brown color) → compared with standard"),
        subBullet("Normal: 14.5 g% in males, 13.5 g% in females"),
        bullet("Cyanmethemoglobin method - most accurate, used in labs"),
        bullet("Dare's method - visual comparison"),
        spacer(),

        heading3("Widal Test (for Typhoid - commonly asked)"),
        bullet("Agglutination test for Salmonella typhi antibodies"),
        bullet("Antigens tested: O (somatic), H (flagellar), AH, BH"),
        bullet("Positive titre: O antigen ≥1:80, H antigen ≥1:160"),
        bullet("Rising titre in paired samples is more significant"),
        spacer(),

        heading3("Blood Grouping (ABO and Rh)"),
        simpleTable(
          ["Blood Group", "Antigen on RBC", "Antibody in Plasma", "Can Donate To", "Can Receive From"],
          [
            ["A", "A", "Anti-B", "A, AB", "A, O"],
            ["B", "B", "Anti-A", "B, AB", "B, O"],
            ["AB", "A and B", "None", "AB only", "All groups"],
            ["O", "None", "Anti-A and Anti-B", "All groups", "O only"]
          ]
        ),
        spacer(),
        bullet("Rh factor: Rh+ has D antigen; Rh- lacks D antigen"),
        bullet("Rh incompatibility: Erythroblastosis fetalis in 2nd Rh+ baby of Rh- mother"),
        spacer(),

        heading3("Differential Leukocyte Count (DLC)"),
        simpleTable(
          ["Cell Type", "Normal %", "Increased In", "Decreased In"],
          [
            ["Neutrophils", "50-70%", "Bacterial infections, stress", "Viral infections, bone marrow failure"],
            ["Lymphocytes", "20-40%", "Viral infections, TB", "AIDS, immunosuppression"],
            ["Eosinophils", "1-4%", "Allergy, parasites", "Steroid use"],
            ["Monocytes", "2-8%", "Chronic infection, monocytic leukemia", "Bone marrow suppression"],
            ["Basophils", "0-1%", "CML, allergic reactions", "Hyperthyroidism"]
          ]
        ),
        spacer(),

        // --- 1B: Minor (5 marks) ---
        markBox("HEMATOLOGY MINOR", 5),
        spacer(),
        heading2("1B. Minor Hematology (5 Marks)"),
        body("Minor practicals are shorter, focused tasks. Common examples include:"),
        bullet("Bleeding time (BT) - Duke's method: Normal 1-6 minutes"),
        subBullet("Tests: platelet function and capillary wall integrity"),
        bullet("Clotting time (CT) - Capillary tube method: Normal 3-8 minutes"),
        subBullet("Tests: intrinsic coagulation pathway"),
        bullet("Erythrocyte Sedimentation Rate (ESR) - Westergren method"),
        subBullet("Setup: Sodium citrate anticoagulated blood in Westergren tube"),
        subBullet("Read at 1 hour"),
        bullet("Preparation of blood smear - peripheral blood film"),
        subBullet("Leishman stain: methylene blue + eosin"),
        subBullet("Cells identifiable: all WBC types, RBC morphology, platelets"),
        bullet("Osmotic fragility test - tests RBC membrane stability"),
        spacer(),

        // --- 1C: Amphibian Chart (10 marks) ---
        markBox("AMPHIBIAN CHART", 10),
        spacer(),
        heading2("1C. Amphibian Chart (10 Marks)"),
        body("Amphibian (frog) experiments are classical physiology practicals. The chart tests your ability to record and interpret results from experiments on frog nerve-muscle preparation, frog heart, etc."),

        heading3("Frog Nerve-Muscle Preparation Experiments"),
        bullet("All-or-none law - stimulus either produces full response or no response"),
        bullet("Threshold stimulus - minimum stimulus needed for contraction"),
        bullet("Summation - repeated stimuli cause increased response"),
        bullet("Tetanus - sustained contraction with rapid stimuli"),
        bullet("Fatigue - gradual decrease in response with repeated stimuli"),
        bullet("Refractory period - period after stimulation when muscle cannot respond"),
        subBullet("Absolute refractory period: no response to any stimulus"),
        subBullet("Relative refractory period: response only to stronger stimulus"),
        spacer(),

        heading3("Frog Heart Experiments"),
        bullet("Stannius ligature experiment - demonstrates SA node as pacemaker"),
        subBullet("1st ligature (SVC-atria junction): ventricle stops, atria beats"),
        subBullet("2nd ligature (AV junction): ventricle may resume at slower rate"),
        bullet("Vagal stimulation - slows heart (negative chronotropy, dromotropy)"),
        bullet("Effect of temperature: warming increases rate, cooling decreases rate"),
        bullet("Ionic effects on heart:"),
        subBullet("Ca²⁺ excess: sustained contraction (calcium rigor)"),
        subBullet("K⁺ excess: depresses heart (heart block)"),
        subBullet("Na⁺ excess: weakens contractions"),
        bullet("Adrenaline - increases heart rate and force"),
        bullet("Acetylcholine - slows heart rate"),
        spacer(),

        heading3("Chart Drawing Tips"),
        bullet("Label axes clearly: Y-axis = muscle tension / heart contraction; X-axis = time"),
        bullet("Show baseline, threshold, and supramaximal responses"),
        bullet("Mark duration of stimulation and recovery phase"),
        bullet("Use proper tracings for summation and tetanus"),
        spacer(),

        // --- 1D: Problem Chart (5 marks) ---
        markBox("PROBLEM CHART", 5),
        spacer(),
        heading2("1D. Problem Chart (5 Marks)"),
        body("Problem charts are clinical scenario-based questions where you analyze given lab data and identify the condition."),

        heading3("Common Problem Chart Scenarios"),
        bullet("Anemia workup: given Hb, MCV, MCH, reticulocyte count - identify type"),
        bullet("Leukemia identification: given WBC count and differential"),
        bullet("Coagulation disorder: given PT, aPTT, BT, CT values"),
        bullet("Polycythemia: elevated RBC, Hb, PCV"),
        spacer(),

        heading3("Approach to Problem Chart"),
        new Paragraph({ numbering: { reference: "numbers", level: 0 }, children: [new TextRun({ text: "Read all given values carefully", font: "Arial", size: 22 })] }),
        new Paragraph({ numbering: { reference: "numbers", level: 0 }, children: [new TextRun({ text: "Identify abnormal values (compare with normal ranges)", font: "Arial", size: 22 })] }),
        new Paragraph({ numbering: { reference: "numbers", level: 0 }, children: [new TextRun({ text: "Determine pattern (e.g. low Hb + low MCV + low MCH = IDA)", font: "Arial", size: 22 })] }),
        new Paragraph({ numbering: { reference: "numbers", level: 0 }, children: [new TextRun({ text: "Write diagnosis and brief justification", font: "Arial", size: 22 })] }),
        spacer(),

        heading3("Key Anemia Types at a Glance"),
        simpleTable(
          ["Anemia Type", "Hb", "MCV", "MCH", "Reticulocytes", "Cause"],
          [
            ["Iron Deficiency", "↓", "↓", "↓", "↓/N", "Poor diet, blood loss"],
            ["Megaloblastic", "↓", "↑", "↑", "↓", "B12/Folate deficiency"],
            ["Hemolytic", "↓", "N/↑", "N", "↑↑", "RBC destruction"],
            ["Aplastic", "↓", "N", "N", "↓↓", "Bone marrow failure"],
            ["Thalassemia (minor)", "N/↓", "↓", "↓", "N/↑", "Genetic Hb defect"]
          ]
        ),
        spacer(),

        // --- 1E: Endocrine/Non-Endocrine Chart (5 marks) ---
        markBox("ENDOCRINE / NON-ENDOCRINE CHART", 5),
        spacer(),
        heading2("1E. Endocrine / Non-Endocrine Chart (5 Marks)"),

        heading3("Endocrine Glands and Hormones"),
        simpleTable(
          ["Gland", "Hormone", "Function", "Deficiency", "Excess"],
          [
            ["Anterior Pituitary", "GH", "Growth stimulation", "Dwarfism", "Gigantism / Acromegaly"],
            ["Anterior Pituitary", "TSH, ACTH, FSH, LH, Prolactin", "Tropic functions", "Hypopituitarism", "Various hyperfunction"],
            ["Posterior Pituitary", "ADH (Vasopressin)", "Water retention", "Diabetes insipidus", "SIADH"],
            ["Posterior Pituitary", "Oxytocin", "Uterine contraction, lactation", "-", "-"],
            ["Thyroid", "T3, T4", "Metabolism regulation", "Hypothyroidism (Cretinism in child)", "Hyperthyroidism (Graves)"],
            ["Thyroid", "Calcitonin", "Lowers blood Ca²⁺", "-", "-"],
            ["Parathyroid", "PTH", "Raises blood Ca²⁺", "Hypocalcemia, tetany", "Hypercalcemia, stones"],
            ["Adrenal Cortex", "Cortisol", "Stress response, anti-inflammatory", "Addison disease", "Cushing syndrome"],
            ["Adrenal Cortex", "Aldosterone", "Na⁺/K⁺ balance", "Salt wasting", "Conn syndrome"],
            ["Adrenal Medulla", "Adrenaline, Noradrenaline", "Fight-or-flight response", "-", "Pheochromocytoma"],
            ["Pancreas (β cells)", "Insulin", "Lowers blood glucose", "Type 1 Diabetes mellitus", "Hypoglycemia"],
            ["Pancreas (α cells)", "Glucagon", "Raises blood glucose", "Hypoglycemia", "-"],
            ["Gonads (Testis)", "Testosterone", "Male characteristics, spermatogenesis", "Hypogonadism", "Precocious puberty"],
            ["Gonads (Ovary)", "Estrogen, Progesterone", "Female cycle, pregnancy", "Menopause effects", "PCOS (relative)"]
          ]
        ),
        spacer(),

        heading3("Non-Endocrine Chart Topics"),
        bullet("Cardiovascular charts: ECG interpretation, heart sounds, pulse tracings"),
        bullet("Respiratory charts: Spirometry, lung volumes and capacities"),
        bullet("Renal charts: GFR, clearance, tubular functions"),
        bullet("Nerve conduction: action potential graph, velocity measurement"),
        spacer(),

        heading3("Lung Volumes Quick Reference"),
        simpleTable(
          ["Parameter", "Value (Adult Male)", "Definition"],
          [
            ["Tidal Volume (TV)", "500 mL", "Normal breathing volume"],
            ["IRV", "3000 mL", "Extra air inspired forcefully"],
            ["ERV", "1100 mL", "Extra air expired forcefully"],
            ["Residual Volume (RV)", "1200 mL", "Air remaining after max expiration"],
            ["Vital Capacity (VC)", "4600 mL", "TV + IRV + ERV"],
            ["FRC", "2300 mL", "ERV + RV"],
            ["TLC", "5800 mL", "All lung volumes combined"],
            ["FEV1/FVC", ">0.80 (80%)", "Obstructive if <70%"]
          ]
        ),
        spacer(),
        pageBreak(),

        // ==================== SECTION 2: CLINICAL (40 MARKS) ====================
        heading1("SECTION 2: CLINICAL (40 Marks)"),
        body("The clinical section tests bedside examination skills, knowledge of signs and reflexes, and ability to interpret findings. It is divided into major, minor, and two human experiments."),
        spacer(),

        // --- 2A: Clinical Major (15 marks) ---
        markBox("CLINICAL MAJOR", 15),
        spacer(),
        heading2("2A. Clinical Major (15 Marks)"),
        body("Clinical major involves a full clinical examination of a body system - cardiovascular, respiratory, or neurological."),

        heading3("Cardiovascular Examination"),
        bullet("Inspection: chest shape, visible pulsations, apex beat"),
        bullet("Palpation: apex beat (normal: 5th ICS, MCL), thrills, heaves"),
        bullet("Percussion: cardiac dullness boundaries"),
        bullet("Auscultation: 4 areas (mitral, tricuspid, aortic, pulmonary)"),
        subBullet("S1 (lub): mitral + tricuspid closure at systole start"),
        subBullet("S2 (dub): aortic + pulmonary closure at diastole start"),
        subBullet("S3: ventricular filling sound (normal in children, pathological in adults)"),
        subBullet("S4: atrial contraction sound (always pathological)"),
        spacer(),

        heading3("Respiratory Examination"),
        bullet("Inspection: respiratory rate (normal 14-20/min), pattern, use of accessory muscles"),
        bullet("Palpation: tracheal position, chest expansion, tactile fremitus"),
        bullet("Percussion: resonant (normal), dull (consolidation/pleural effusion), hyperresonant (pneumothorax)"),
        bullet("Auscultation:"),
        subBullet("Vesicular breath sounds: normal, heard peripherally"),
        subBullet("Bronchial breath sounds: over trachea/consolidation (harsh, blowing)"),
        subBullet("Added sounds: crackles (pulmonary edema, fibrosis), wheeze (asthma, COPD), pleural rub"),
        spacer(),

        heading3("Neurological Examination"),
        bullet("Higher functions: consciousness, orientation, memory, speech"),
        bullet("Cranial nerves: CN I-XII testing methods"),
        bullet("Motor system: tone, power (MRC grading 0-5), coordination"),
        bullet("Sensory system: light touch, pain, temperature, vibration, proprioception"),
        bullet("Reflexes: deep tendon reflexes (DTR), superficial reflexes, plantar response"),
        spacer(),

        heading3("Deep Tendon Reflexes"),
        simpleTable(
          ["Reflex", "Nerve Root", "Method", "Normal Response"],
          [
            ["Biceps jerk", "C5, C6", "Strike biceps tendon", "Elbow flexion"],
            ["Triceps jerk", "C7, C8", "Strike triceps tendon", "Elbow extension"],
            ["Knee jerk (patellar)", "L3, L4", "Strike patellar tendon", "Knee extension"],
            ["Ankle jerk", "S1, S2", "Strike Achilles tendon", "Plantar flexion"],
            ["Plantar reflex", "L5, S1", "Stroke sole of foot", "Normal: plantar flexion; Babinski: dorsiflexion of big toe"]
          ]
        ),
        spacer(),
        bullet("Grading of reflexes: 0 (absent) → 1 (diminished) → 2 (normal) → 3 (brisk) → 4 (clonus)"),
        bullet("Upper Motor Neuron (UMN) lesion: increased tone, exaggerated reflexes, Babinski positive"),
        bullet("Lower Motor Neuron (LMN) lesion: decreased tone, absent reflexes, wasting"),
        spacer(),

        // --- 2B: Clinical Minor (5 marks) ---
        markBox("CLINICAL MINOR", 5),
        spacer(),
        heading2("2B. Clinical Minor (5 Marks)"),
        body("Clinical minor includes a shorter clinical task such as pulse examination, blood pressure measurement, or a specific reflex test."),

        heading3("Pulse Examination"),
        bullet("Sites: radial (most common), carotid, brachial, femoral, dorsalis pedis"),
        bullet("Rate: Normal 60-100 bpm (adults)"),
        bullet("Rhythm: regular or irregular (atrial fibrillation = irregularly irregular)"),
        bullet("Volume: full, weak, thready, collapsing (aortic regurgitation - water hammer)"),
        bullet("Character: slow rising (AS), collapsing (AR), bisferiens (mixed AS+AR)"),
        bullet("Radioradial delay: Subclavian artery compression/aortic stenosis"),
        spacer(),

        heading3("Blood Pressure Measurement"),
        bullet("Instrument: mercury sphygmomanometer or aneroid"),
        bullet("Method: Korotkoff sounds (Phase I = systolic; Phase V = diastolic)"),
        bullet("Normal: 120/80 mmHg; Hypertension: ≥140/90 mmHg"),
        bullet("Pulse pressure = Systolic - Diastolic (Normal: 40 mmHg)"),
        bullet("Mean Arterial Pressure (MAP) = DBP + 1/3 × PP (Normal: ~70-100 mmHg)"),
        spacer(),

        heading3("Superficial Reflexes"),
        bullet("Corneal reflex: CN V (afferent) and CN VII (efferent) - blink on corneal touch"),
        bullet("Gag reflex: CN IX (afferent) and CN X (efferent)"),
        bullet("Abdominal reflex: scratching abdominal wall → umbilicus moves toward stimulus"),
        bullet("Cremasteric reflex: L1, L2 - thigh stroking causes testicular retraction"),
        spacer(),

        // --- 2C: Human Experiments (20 marks) ---
        markBox("2 HUMAN EXPERIMENTS", 20),
        spacer(),
        heading2("2C. Two Human Experiments (20 Marks)"),
        body("Each experiment is worth approximately 10 marks. These are performed on volunteer subjects (usually classmates) during the exam. Common experiments include:"),

        heading3("Experiment 1: Cardiovascular Experiments"),
        bullet("Measurement of blood pressure (sitting, standing, lying)"),
        subBullet("Postural hypotension: >20 mmHg drop in systolic on standing"),
        bullet("Pulse rate in various conditions: resting, post-exercise, cold pressor"),
        bullet("Cold pressor test: hand in ice water → BP and HR change"),
        bullet("Valsalva maneuver: forced expiration against closed glottis → increases intrathoracic pressure → affects venous return"),
        bullet("Effect of exercise on cardiovascular parameters"),
        subBullet("Heart rate increases proportionally with workload"),
        subBullet("Systolic BP increases; diastolic relatively unchanged"),
        spacer(),

        heading3("Experiment 2: Respiratory Experiments"),
        bullet("Vital capacity measurement using spirometer"),
        subBullet("VC = TV + IRV + ERV"),
        subBullet("Normal: 4-5 L in males, 3-4 L in females"),
        bullet("Breath-holding time: Normal 30-60 seconds; reduced in respiratory disease"),
        bullet("Effect of re-breathing on respiratory rate and depth"),
        bullet("Respiratory rate measurement (Normal: 14-20/min)"),
        bullet("Peak expiratory flow rate (PEFR) - using peak flow meter"),
        spacer(),

        heading3("Experiment 3: Neurological/Sensory Experiments"),
        bullet("Visual acuity - Snellen chart (Normal 6/6 or 20/20)"),
        bullet("Color vision - Ishihara chart"),
        bullet("Visual field testing - confrontation method"),
        bullet("Hearing tests: Weber (lateralization) and Rinne (AC vs BC comparison)"),
        bullet("Reaction time measurement"),
        bullet("Two-point discrimination - skin sensory acuity"),
        spacer(),

        heading3("Common Experiment Recording Format"),
        bullet("Title of experiment"),
        bullet("Aim / Objective"),
        bullet("Materials required"),
        bullet("Method / Procedure (step-by-step)"),
        bullet("Observations (tabulate values)"),
        bullet("Results with graphs/charts if applicable"),
        bullet("Discussion - explain physiological basis"),
        bullet("Conclusion"),
        spacer(),
        pageBreak(),

        // ==================== SECTION 3: THEORY VIVA (20 MARKS) ====================
        heading1("SECTION 3: THEORY VIVA (20 Marks)"),
        body("The theory viva covers ALL SYSTEMS. Examiners typically ask 2-3 questions from different systems. Below is a system-wise preparation guide."),
        spacer(),

        markBox("THEORY VIVA - ALL SYSTEMS", 20),
        spacer(),

        heading2("3A. Cardiovascular System"),
        heading3("Must-Know Topics"),
        bullet("Cardiac cycle: systole, diastole, pressure-volume changes, heart sounds"),
        bullet("ECG: waves (P, QRS, T), intervals, normal values"),
        subBullet("PR interval: 0.12-0.20s | QRS: <0.12s | QT: <0.44s"),
        bullet("Cardiac output: CO = HR × SV (Normal: 5 L/min)"),
        bullet("Starling's law of heart: increased preload → increased stroke volume"),
        bullet("Blood pressure regulation: short-term (baroreceptors) and long-term (RAAS, ADH)"),
        bullet("Coronary circulation: left = LAD + LCX; right = RCA"),
        bullet("Cardiac muscle properties: automaticity, rhythmicity, conductivity, contractility"),
        spacer(),

        heading2("3B. Respiratory System"),
        heading3("Must-Know Topics"),
        bullet("Mechanics of breathing: inspiration (diaphragm + external intercostals) vs expiration (passive)"),
        bullet("Lung compliance, surface tension, surfactant"),
        bullet("Dead space: anatomical (150 mL) and physiological dead space"),
        bullet("Ventilation-perfusion (V/Q) ratio: normal = 0.8"),
        bullet("Oxygen transport: 97% as oxyhemoglobin, 3% dissolved"),
        bullet("CO2 transport: 70% as bicarbonate, 23% as carbaminohemoglobin, 7% dissolved"),
        bullet("Oxygen dissociation curve: shifts (Right = decreased O2 affinity: ↑CO2, ↑H⁺, ↑temp, ↑2,3-DPG)"),
        bullet("Central chemoreceptors (CO2/H⁺) and peripheral chemoreceptors (O2)"),
        spacer(),

        heading2("3C. Renal System"),
        heading3("Must-Know Topics"),
        bullet("Nephron: glomerulus, proximal tubule, loop of Henle, distal tubule, collecting duct"),
        bullet("GFR: Normal 125 mL/min; measured by inulin clearance or creatinine clearance"),
        bullet("Juxtaglomerular apparatus: renin secretion, macula densa, regulation"),
        bullet("Tubular reabsorption: glucose (Tm = 320 mg/min), amino acids, Na⁺"),
        bullet("Countercurrent mechanism: concentrating urine up to 1200 mOsm/kg"),
        bullet("ADH and aldosterone effects on collecting duct"),
        bullet("Renal regulation of acid-base balance"),
        spacer(),

        heading2("3D. Digestive System"),
        heading3("Must-Know Topics"),
        bullet("Swallowing: oral, pharyngeal, esophageal phases"),
        bullet("Gastric acid secretion: HCl by parietal cells; regulated by ACh, gastrin, histamine"),
        bullet("Phases of digestion: cephalic, gastric, intestinal"),
        bullet("Pancreatic enzymes: lipase, amylase, proteases (trypsinogen, chymotrypsinogen)"),
        bullet("Bile: composition, enterohepatic circulation, roles in fat digestion/absorption"),
        bullet("Absorption: glucose (Na⁺-linked), amino acids, fat (chylomicrons via lacteals)"),
        bullet("GI hormones: gastrin, secretin, CCK, GIP, motilin"),
        spacer(),

        heading2("3E. Nervous System"),
        heading3("Must-Know Topics"),
        bullet("Resting membrane potential: -70 mV (inside negative), maintained by Na⁺/K⁺ ATPase"),
        bullet("Action potential: depolarization (Na⁺ in), repolarization (K⁺ out), hyperpolarization"),
        bullet("Synapse: neurotransmitter release, receptors, excitatory/inhibitory postsynaptic potentials"),
        bullet("Reflexes: components (receptor, afferent, center, efferent, effector)"),
        bullet("Ascending tracts: dorsal column (fine touch, proprioception), spinothalamic (pain, temp)"),
        bullet("Descending tracts: corticospinal (voluntary movement), reticulospinal, rubrospinal"),
        bullet("Cerebellum: coordination, balance, skilled voluntary movement"),
        bullet("Basal ganglia: initiation and control of movement; dopamine pathway"),
        bullet("Autonomic nervous system: SNS (adrenergic) vs PNS (cholinergic) effects"),
        spacer(),

        heading2("3F. Endocrine System"),
        heading3("Must-Know Topics"),
        bullet("Hypothalamic-pituitary axis: releasing hormones → anterior pituitary hormones"),
        bullet("GH: IGF-1 mediated growth; deficiency = dwarfism; excess = gigantism/acromegaly"),
        bullet("Thyroid hormones (T3, T4): metabolism, growth, development; feedback via TSH"),
        bullet("Insulin: glucose uptake into cells (GLUT4); anabolic; deficiency = diabetes mellitus"),
        bullet("Glucagon: glycogenolysis, gluconeogenesis; raises blood glucose"),
        bullet("Cortisol: gluconeogenesis, anti-inflammatory, immunosuppressive"),
        bullet("Aldosterone: Na⁺ retention, K⁺ excretion in distal tubule"),
        bullet("PTH vs Calcitonin: PTH raises Ca²⁺; calcitonin lowers Ca²⁺"),
        spacer(),

        heading2("3G. Blood and Immune System"),
        heading3("Must-Know Topics"),
        bullet("Erythropoiesis: from proerythroblast to mature RBC (7 days); EPO regulated"),
        bullet("Hemostasis: vascular phase → platelet plug → coagulation cascade"),
        subBullet("Extrinsic pathway: tissue factor + Factor VII"),
        subBullet("Intrinsic pathway: factors XII, XI, IX, VIII"),
        subBullet("Common pathway: Factor X → prothrombin → thrombin → fibrinogen → fibrin"),
        bullet("Anticoagulants: heparin (antithrombin III), warfarin (Vit K antagonist)"),
        bullet("Immunity: innate (non-specific) vs adaptive (T cells, B cells, antibodies)"),
        bullet("Blood groups and transfusion reactions"),
        spacer(),

        heading2("3H. Reproductive System"),
        heading3("Must-Know Topics"),
        bullet("Menstrual cycle: follicular (day 1-14), ovulation (day 14), luteal (day 15-28)"),
        bullet("Hormonal control: FSH → follicle growth; LH surge → ovulation; progesterone → luteal phase"),
        bullet("Spermatogenesis: spermatogonia → primary spermatocyte → spermatid → sperm (72 days)"),
        bullet("Fertilization and implantation: hCG maintains corpus luteum"),
        bullet("Pregnancy hormones: hCG (1st trimester), estrogen + progesterone (2nd and 3rd trimester, from placenta)"),
        spacer(),
        pageBreak(),

        // ==================== EXAM TIPS ====================
        heading1("EXAM STRATEGY & TIPS"),
        spacer(),

        heading2("General Tips"),
        bullet("Practicals follow typical university exam pattern - practice correct procedure and documentation"),
        bullet("Theory viva covers ALL systems - prepare each briefly"),
        bullet("For charts: label axes, write normal values, and highlight abnormalities clearly"),
        bullet("Record file must be submitted before the exam"),
        spacer(),

        heading2("Mark-wise Priority"),
        simpleTable(
          ["Component", "Marks", "Priority", "Key Focus"],
          [
            ["Human Experiments (Clinical)", "20", "HIGHEST", "Practice procedure + physiological explanation"],
            ["Hematology Major", "15", "HIGH", "CBC interpretation, blood grouping, Hb estimation"],
            ["Clinical Major", "15", "HIGH", "Full system examination with correct findings"],
            ["Amphibian Chart", "10", "HIGH", "Stannius ligature, NM preparation, tracings"],
            ["Theory Viva", "20", "ESSENTIAL", "All 8 systems - at least 10 key points each"],
            ["Problem Chart", "5", "MODERATE", "Anemia and coagulation disorder interpretation"],
            ["Endocrine/Non-Endocrine Chart", "5", "MODERATE", "Hormone table, lung volumes, ECG basics"],
            ["Hematology Minor", "5", "MODERATE", "BT, CT, ESR - normal values and methods"],
            ["Clinical Minor", "5", "MODERATE", "BP, pulse examination technique"]
          ]
        ),
        spacer(),

        heading2("Day Before Exam Checklist"),
        bullet("Review normal values for all blood parameters"),
        bullet("Revise frog heart experiment (Stannius ligature) - very commonly asked"),
        bullet("Know normal values: BP, HR, RR, SpO2, temperature"),
        bullet("Revise reflex arc and major reflexes with nerve roots"),
        bullet("Quick review of hormone deficiency/excess syndromes"),
        bullet("Ensure record file is complete and signed"),
        spacer(),

        new Paragraph({
          alignment: AlignmentType.CENTER,
          children: [new TextRun({ text: "Good luck in your exam!", font: "Arial", size: 28, bold: true, color: "1F4E79" })]
        }),
        spacer(),
        new Paragraph({
          alignment: AlignmentType.CENTER,
          children: [new TextRun({ text: "Physiology Practical Study Guide | All Systems | 100 Marks", font: "Arial", size: 20, italics: true, color: "595959" })]
        }),
      ]
    }
  ]
});

Packer.toBuffer(doc).then(buffer => {
  fs.writeFileSync("/home/daytona/workspace/physiology-study-guide/Physiology_Practical_Study_Guide.docx", buffer);
  console.log("Document created successfully!");
}).catch(err => {
  console.error("Error:", err);
});
Running Command

cd /home/daytona/workspace/physiology-study-guide && node create_guide.js 2>&1

Running Command

cd /home/daytona/workspace/physiology-study-guide && python /home/daytona/skills…

Running Command

ls -lh /home/daytona/workspace/physiology-study-guide/Physiology_Practical_Study…

Your study guide is ready! Download it here:

Physiology Practical Study Guide

Word Document · DOCX


Here is what the document covers for each of the 9 exam components (100 marks total):

Section 1 - Hematology (40 Marks)

ComponentMarksContent in Guide
Major15CBC with normal ranges, blood indices, Hb estimation (Sahli's), blood grouping ABO/Rh, Widal test, DLC table
Minor5BT/CT methods, ESR (Westergren), blood smear preparation, osmotic fragility
Amphibian Chart10Stannius ligature, NM preparation (all-or-none, tetanus, fatigue, refractory period), ionic/drug effects on frog heart, chart drawing tips
Problem Chart5Step-by-step approach, anemia type comparison table (IDA, megaloblastic, hemolytic, aplastic, thalassemia)
Endocrine/Non-Endocrine Chart5Hormone table with deficiency/excess syndromes, lung volumes reference table, ECG/spirometry basics

Section 2 - Clinical (40 Marks)

ComponentMarksContent in Guide
Major15CVS, respiratory, and neurological examination with full IPPA method, heart sounds, breath sounds
Minor5Pulse examination (rate, rhythm, volume, character), BP measurement (Korotkoff), superficial reflexes
2 Human Experiments20CVS experiments (BP postural, cold pressor, Valsalva), respiratory experiments (VC, PEFR, breath-holding), neurological experiments (Snellen, Ishihara, Weber/Rinne), standard recording format

Section 3 - Theory Viva (20 Marks)

Covers all 8 systems with must-know bullet points each:
  • Cardiovascular, Respiratory, Renal, Digestive, Nervous, Endocrine, Blood/Immune, Reproductive
Plus an Exam Strategy section with mark-wise priority table and a day-before checklist.

Create a revision flashcard PDF for quick recap before exam

Reading File
Running Command

python3 -c "from reportlab.lib.pagesizes import A4; print('reportlab ok')" 2>&1

Writing File

~/physiology-study-guide/create_flashcards.py

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

OUTPUT = "/home/daytona/workspace/physiology-study-guide/Physiology_Flashcards.pdf"

# ── Colour palette ──────────────────────────────────────────────────────────
NAVY      = colors.HexColor("#1F4E79")
BLUE      = colors.HexColor("#2E75B6")
LBLUE     = colors.HexColor("#D6E4F0")
TEAL      = colors.HexColor("#00695C")
LTEAL     = colors.HexColor("#E0F2F1")
ORANGE    = colors.HexColor("#E65100")
LORANGE   = colors.HexColor("#FFF3E0")
PURPLE    = colors.HexColor("#4A148C")
LPURPLE   = colors.HexColor("#F3E5F5")
RED       = colors.HexColor("#B71C1C")
LRED      = colors.HexColor("#FFEBEE")
GREEN     = colors.HexColor("#1B5E20")
LGREEN    = colors.HexColor("#E8F5E9")
GOLD      = colors.HexColor("#F57F17")
LGOLD     = colors.HexColor("#FFFDE7")
GREY      = colors.HexColor("#424242")
LGREY     = colors.HexColor("#F5F5F5")
WHITE     = colors.white
BLACK     = colors.black

W, H = A4   # 595 x 842 pts

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

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

cover_title   = S("CoverTitle",   fontName="Helvetica-Bold",  fontSize=30, textColor=WHITE,     alignment=TA_CENTER, spaceAfter=6)
cover_sub     = S("CoverSub",     fontName="Helvetica",       fontSize=13, textColor=LBLUE,     alignment=TA_CENTER, spaceAfter=4)
cover_small   = S("CoverSmall",   fontName="Helvetica",       fontSize=10, textColor=WHITE,     alignment=TA_CENTER)

sec_title     = S("SecTitle",     fontName="Helvetica-Bold",  fontSize=15, textColor=WHITE,     alignment=TA_LEFT,   leading=18)
card_q        = S("CardQ",        fontName="Helvetica-Bold",  fontSize=11, textColor=NAVY,      alignment=TA_LEFT,   leading=14, spaceAfter=3)
card_a        = S("CardA",        fontName="Helvetica",       fontSize=10, textColor=GREY,      alignment=TA_LEFT,   leading=13)
card_a_bold   = S("CardABold",    fontName="Helvetica-Bold",  fontSize=10, textColor=GREY,      alignment=TA_LEFT,   leading=13)
card_label    = S("CardLabel",    fontName="Helvetica-Bold",  fontSize=7,  textColor=WHITE,     alignment=TA_LEFT)
normal_small  = S("NormSmall",    fontName="Helvetica",       fontSize=8.5,textColor=GREY,      alignment=TA_LEFT,   leading=11)
bold_small    = S("BoldSmall",    fontName="Helvetica-Bold",  fontSize=8.5,textColor=GREY,      alignment=TA_LEFT,   leading=11)
header_style  = S("HeaderStyle",  fontName="Helvetica-Bold",  fontSize=8.5,textColor=WHITE,     alignment=TA_CENTER)
table_cell    = S("TableCell",    fontName="Helvetica",       fontSize=8,  textColor=GREY,      alignment=TA_LEFT,   leading=10)
table_head    = S("TableHead",    fontName="Helvetica-Bold",  fontSize=8,  textColor=WHITE,     alignment=TA_CENTER, leading=10)
tip_style     = S("TipStyle",     fontName="Helvetica-BoldOblique", fontSize=9, textColor=GOLD, alignment=TA_CENTER)

# ── Helpers ──────────────────────────────────────────────────────────────────
def page_bg(c, doc, bg=LGREY, stripe=NAVY):
    """Draw a subtle background stripe at top of every page."""
    c.saveState()
    c.setFillColor(bg)
    c.rect(0, 0, W, H, fill=1, stroke=0)
    c.setFillColor(stripe)
    c.rect(0, H-22, W, 22, fill=1, stroke=0)
    c.setFillColor(WHITE)
    c.setFont("Helvetica-Bold", 8)
    c.drawString(15, H-15, "PHYSIOLOGY PRACTICAL — QUICK REVISION FLASHCARDS")
    c.setFont("Helvetica", 8)
    c.drawRightString(W-15, H-15, f"Page {doc.page}")
    # Footer
    c.setFillColor(NAVY)
    c.rect(0, 0, W, 14, fill=1, stroke=0)
    c.setFillColor(WHITE)
    c.setFont("Helvetica", 7)
    c.drawCentredString(W/2, 4, "Hematology · Clinical · Amphibian · Endocrine · Theory Viva — All Systems")
    c.restoreState()

def section_banner(text, color=NAVY, sub=None):
    """Full-width coloured section header."""
    inner = [Paragraph(text, sec_title)]
    if sub:
        inner.append(Paragraph(sub, S("SecSub", fontName="Helvetica", fontSize=9, textColor=LBLUE, leading=11)))
    t = Table([[inner]], colWidths=[W - 40])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), color),
        ("TOPPADDING",    (0,0), (-1,-1), 7),
        ("BOTTOMPADDING", (0,0), (-1,-1), 7),
        ("LEFTPADDING",   (0,0), (-1,-1), 12),
        ("RIGHTPADDING",  (0,0), (-1,-1), 12),
        ("ROUNDEDCORNERS", [4]),
    ]))
    return t

def card(q_text, a_lines, accent=BLUE, bg=LBLUE, label=None):
    """
    Single flashcard: coloured left border, Q in bold, A as bullets.
    a_lines: list of strings (or list of (bold_prefix, rest) tuples)
    """
    q_para = Paragraph(q_text, card_q)

    a_paras = []
    for line in a_lines:
        if isinstance(line, tuple):
            bold, rest = line
            a_paras.append(Paragraph(f"<b>{bold}</b> {rest}", card_a))
        else:
            a_paras.append(Paragraph(f"• {line}", card_a))

    label_cell = ""
    if label:
        label_cell = Paragraph(label, card_label)

    content_col = [q_para] + a_paras
    if label:
        content_col = [Paragraph(f'<font size="6" color="white"><b> {label} </b></font>', 
                                  S("LabelInline", fontName="Helvetica-Bold", fontSize=6, 
                                    textColor=WHITE, backColor=accent))] + content_col

    accent_bar = Table([[ "" ]], colWidths=[5])
    accent_bar.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), accent),
        ("TOPPADDING",    (0,0), (-1,-1), 0),
        ("BOTTOMPADDING", (0,0), (-1,-1), 0),
    ]))

    main_cell = content_col
    outer = Table(
        [[accent_bar, main_cell]],
        colWidths=[5, W - 40 - 5]
    )
    outer.setStyle(TableStyle([
        ("BACKGROUND",    (1,0), (1,0), bg),
        ("TOPPADDING",    (0,0), (-1,-1), 6),
        ("BOTTOMPADDING", (0,0), (-1,-1), 6),
        ("LEFTPADDING",   (1,0), (1,0), 8),
        ("RIGHTPADDING",  (1,0), (1,0), 8),
        ("TOPPADDING",    (1,0), (1,0), 6),
        ("BOTTOMPADDING", (1,0), (1,0), 6),
        ("VALIGN",        (0,0), (-1,-1), "TOP"),
        ("ROWBACKGROUNDS", (0,0), (-1,-1), [bg]),
    ]))
    return outer

def mini_table(headers, rows, col_widths=None, hdr_color=NAVY):
    total = W - 40
    if col_widths is None:
        n = len(headers)
        col_widths = [total/n]*n
    hdr_row = [Paragraph(h, table_head) for h in headers]
    data = [hdr_row]
    for row in rows:
        data.append([Paragraph(str(c), table_cell) for c in row])
    t = Table(data, colWidths=col_widths)
    style = [
        ("BACKGROUND",    (0,0), (-1,0),  hdr_color),
        ("BACKGROUND",    (0,1), (-1,-1), WHITE),
        ("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, LGREY]),
        ("GRID",          (0,0), (-1,-1), 0.4, colors.HexColor("#BDBDBD")),
        ("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), "MIDDLE"),
    ]
    t.setStyle(TableStyle(style))
    return t

def sp(h=4): return Spacer(1, h)
def hr(color=LBLUE): return HRFlowable(width="100%", thickness=0.5, color=color, spaceAfter=4, spaceBefore=4)

# ── 2-column card grid helper ─────────────────────────────────────────────────
def two_col_cards(card_list, accent=BLUE, bg=LBLUE):
    """Lay two slim cards side by side."""
    rows = []
    for i in range(0, len(card_list), 2):
        left  = card_list[i]
        right = card_list[i+1] if i+1 < len(card_list) else ""
        rows.append([left, right])
    t = Table(rows, colWidths=[(W-50)/2, (W-50)/2], hAlign="LEFT")
    t.setStyle(TableStyle([
        ("VALIGN",        (0,0), (-1,-1), "TOP"),
        ("LEFTPADDING",   (0,0), (-1,-1), 3),
        ("RIGHTPADDING",  (0,0), (-1,-1), 3),
        ("TOPPADDING",    (0,0), (-1,-1), 3),
        ("BOTTOMPADDING", (0,0), (-1,-1), 3),
    ]))
    return t

def slim_card(q, a_lines, accent=BLUE, bg=LBLUE):
    """Compact card for 2-column layout."""
    content = [Paragraph(q, S("SlimQ", fontName="Helvetica-Bold", fontSize=9.5, textColor=NAVY, leading=12, spaceAfter=2))]
    for line in a_lines:
        if isinstance(line, tuple):
            b, r = line
            content.append(Paragraph(f"<b>{b}</b> {r}", S("SlimA", fontName="Helvetica", fontSize=8.5, textColor=GREY, leading=11)))
        else:
            content.append(Paragraph(f"• {line}", S("SlimA2", fontName="Helvetica", fontSize=8.5, textColor=GREY, leading=11)))
    bar = Table([[""]], colWidths=[4])
    bar.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),accent), ("TOPPADDING",(0,0),(-1,-1),0),("BOTTOMPADDING",(0,0),(-1,-1),0)]))
    outer = Table([[bar, content]], colWidths=[4, (W-50)/2 - 4])
    outer.setStyle(TableStyle([
        ("BACKGROUND",    (1,0),(1,0), bg),
        ("TOPPADDING",    (1,0),(1,0), 5),
        ("BOTTOMPADDING", (1,0),(1,0), 5),
        ("LEFTPADDING",   (1,0),(1,0), 6),
        ("RIGHTPADDING",  (1,0),(1,0), 6),
        ("VALIGN",        (0,0),(-1,-1),"TOP"),
    ]))
    return outer

# ════════════════════════════════════════════════════════════════════════════
# BUILD DOCUMENT
# ════════════════════════════════════════════════════════════════════════════
doc = BaseDocTemplate(
    OUTPUT, pagesize=A4,
    leftMargin=20, rightMargin=20, topMargin=30, bottomMargin=20
)
frame = Frame(20, 20, W-40, H-50, id="main")

def page_cb(c, doc): page_bg(c, doc)

doc.addPageTemplates([PageTemplate(id="main", frames=[frame], onPage=page_cb)])

story = []

# ══════════════════════ COVER ═════════════════════════════════════════════════
def cover_page(c, doc):
    c.saveState()
    # Gradient-like background
    c.setFillColor(NAVY)
    c.rect(0, 0, W, H, fill=1, stroke=0)
    c.setFillColor(BLUE)
    c.rect(0, H*0.55, W, H*0.45, fill=1, stroke=0)
    # Decorative circles
    c.setFillColor(colors.HexColor("#FFFFFF10"))
    c.circle(W*0.85, H*0.85, 120, fill=1, stroke=0)
    c.circle(W*0.1,  H*0.2,  80,  fill=1, stroke=0)
    # Title
    c.setFillColor(WHITE)
    c.setFont("Helvetica-Bold", 36)
    c.drawCentredString(W/2, H*0.72, "PHYSIOLOGY")
    c.setFont("Helvetica-Bold", 28)
    c.drawCentredString(W/2, H*0.65, "PRACTICAL EXAM")
    c.setFillColor(GOLD)
    c.setFont("Helvetica-Bold", 22)
    c.drawCentredString(W/2, H*0.58, "QUICK REVISION FLASHCARDS")
    # Divider
    c.setStrokeColor(GOLD)
    c.setLineWidth(2)
    c.line(W*0.2, H*0.55, W*0.8, H*0.55)
    # Boxes row
    boxes = [
        ("HEMATOLOGY", "40 Marks", BLUE),
        ("CLINICAL",   "40 Marks", TEAL),
        ("THEORY VIVA","20 Marks", ORANGE),
    ]
    bw, bh, by = 140, 55, H*0.40
    bx_start = (W - len(boxes)*bw - (len(boxes)-1)*10) / 2
    for i,(lbl,marks,col) in enumerate(boxes):
        bx = bx_start + i*(bw+10)
        c.setFillColor(col)
        c.roundRect(bx, by, bw, bh, 6, fill=1, stroke=0)
        c.setFillColor(WHITE)
        c.setFont("Helvetica-Bold", 11)
        c.drawCentredString(bx+bw/2, by+bh-18, lbl)
        c.setFont("Helvetica", 10)
        c.drawCentredString(bx+bw/2, by+8, marks)
    # Total
    c.setFillColor(GOLD)
    c.setFont("Helvetica-Bold", 16)
    c.drawCentredString(W/2, H*0.34, "TOTAL: 100 MARKS")
    # Subtitle
    c.setFillColor(LBLUE)
    c.setFont("Helvetica", 11)
    c.drawCentredString(W/2, H*0.27, "All Systems  •  All Components  •  Key Values")
    c.setFont("Helvetica", 9)
    c.drawCentredString(W/2, H*0.22, "University Exam Pattern")
    # Footer
    c.setFillColor(colors.HexColor("#FFFFFF30"))
    c.rect(0, 0, W, 30, fill=1, stroke=0)
    c.setFillColor(WHITE)
    c.setFont("Helvetica", 8)
    c.drawCentredString(W/2, 10, "Flip through each card — Q on top, Answer below the line")
    c.restoreState()

doc.addPageTemplates([
    PageTemplate(id="cover",  frames=[Frame(0,0,W,H,0,0,0,0)], onPage=cover_page),
    PageTemplate(id="main",   frames=[frame], onPage=page_cb),
])

story.append(NextPageTemplate("cover"))
story.append(PageBreak())
story.append(NextPageTemplate("main"))
story.append(PageBreak())

# We need NextPageTemplate import
from reportlab.platypus import NextPageTemplate

story = []
story.append(NextPageTemplate("cover"))
story.append(PageBreak())
story.append(NextPageTemplate("main"))
story.append(PageBreak())

# ══════════════════════ SECTION 1: HEMATOLOGY ════════════════════════════════
story.append(section_banner("📋  SECTION 1: HEMATOLOGY  (40 Marks)", NAVY,
    "Major 15 · Minor 5 · Amphibian Chart 10 · Problem Chart 5 · Endocrine/Non-Endocrine Chart 5"))
story.append(sp(6))

# ── 1A Major ─────────────────────────────────────────────────────────────────
story.append(section_banner("1A · HEMATOLOGY MAJOR  (15 Marks)", BLUE))
story.append(sp(5))

story.append(card(
    "CBC Normal Values (must memorise)",
    [
        ("Hb (M):", "13–17 g/dL   |   Hb (F): 12–15 g/dL"),
        ("RBC:", "M 4.5–5.5 mill/mm³   |   F 3.8–4.8"),
        ("WBC:", "4,000–11,000 /mm³"),
        ("Platelets:", "1.5–4.0 lakh/mm³"),
        ("PCV:", "M 40–50%   |   F 35–45%"),
        ("MCV:", "80–100 fL   |   MCH: 27–32 pg   |   MCHC: 31–36 g/dL"),
        ("ESR:", "M 0–15 mm/hr   |   F 0–20 mm/hr"),
    ], BLUE, LBLUE))
story.append(sp(4))

story.append(mini_table(
    ["Anemia Type", "Hb", "MCV", "MCH", "Retics", "Key Cause"],
    [
        ["Iron Deficiency (IDA)", "↓", "↓ (<80)", "↓", "↓/N", "Poor diet / blood loss"],
        ["Megaloblastic",         "↓", "↑ (>100)","↑", "↓",   "B12 / Folate deficiency"],
        ["Hemolytic",             "↓", "N/↑",     "N", "↑↑",  "RBC destruction"],
        ["Aplastic",              "↓", "N",        "N", "↓↓",  "Bone marrow failure"],
        ["Thalassemia minor",     "N/↓","↓",       "↓", "N/↑", "Genetic Hb defect"],
    ],
    col_widths=[105,28,45,28,32,W-40-238],
    hdr_color=NAVY
))
story.append(sp(5))

story.append(card(
    "Hemoglobin Estimation — Sahli's Acid Hematin Method",
    [
        "Hb + dilute HCl  →  Acid hematin (brown colour)",
        "Dilute with distilled water till colour matches standard",
        ("Normal:", "14.5 g% male   |   13.5 g% female"),
        "Cyanmethemoglobin method = most accurate (lab standard)",
    ], BLUE, LBLUE))
story.append(sp(4))

story.append(two_col_cards([
    slim_card("Blood Grouping — ABO",
        [("A:", "Antigen A, Anti-B Ab"),
         ("B:", "Antigen B, Anti-A Ab"),
         ("AB:", "A+B antigens, NO Ab → universal recipient"),
         ("O:", "No antigen, Anti-A+B → universal donor")],
        BLUE, LBLUE),
    slim_card("Rh Factor",
        ["Rh+ → D antigen present",
         "Rh– → D antigen absent",
         "Erythroblastosis fetalis: 2nd Rh+ baby of Rh– mother",
         "Anti-D immunoglobulin prevents sensitisation"],
        TEAL, LTEAL),
]))
story.append(sp(4))

story.append(card(
    "Widal Test — Typhoid Diagnosis",
    [
        "Antigens tested: O (somatic), H (flagellar), AH, BH",
        ("Positive titre:", "O antigen ≥ 1:80   |   H antigen ≥ 1:160"),
        "Rising titre in paired samples = more significant",
        "False positive: other Salmonella, malaria, liver disease",
    ], BLUE, LBLUE))
story.append(sp(4))

story.append(card(
    "Differential Leukocyte Count (DLC)",
    [
        ("Neutrophils 50–70%:", "↑ bacterial infection   |   ↓ viral, bone marrow failure"),
        ("Lymphocytes 20–40%:", "↑ viral, TB   |   ↓ AIDS, immunosuppression"),
        ("Eosinophils 1–4%:",   "↑ allergy, parasites   |   ↓ steroid use"),
        ("Monocytes 2–8%:",     "↑ chronic infection, monocytic leukaemia"),
        ("Basophils 0–1%:",     "↑ CML, allergic reactions"),
    ], BLUE, LBLUE))
story.append(sp(8))

# ── 1B Minor ─────────────────────────────────────────────────────────────────
story.append(section_banner("1B · HEMATOLOGY MINOR  (5 Marks)", colors.HexColor("#1565C0")))
story.append(sp(5))

story.append(two_col_cards([
    slim_card("Bleeding Time (BT) — Duke's Method",
        [("Normal:", "1–6 minutes"),
         "Ear lobe puncture; blot every 30 sec",
         "Tests: platelet function + capillary wall integrity",
         "↑ in thrombocytopenia, von Willebrand disease"],
        BLUE, LBLUE),
    slim_card("Clotting Time (CT) — Capillary Tube Method",
        [("Normal:", "3–8 minutes"),
         "Finger prick; fill 3 capillary tubes",
         "Break tube every 30 sec until fibrin thread seen",
         "Tests: intrinsic coagulation pathway"],
        TEAL, LTEAL),
]))
story.append(sp(4))

story.append(two_col_cards([
    slim_card("ESR — Westergren Method",
        [("Anticoagulant:", "Sodium citrate (4:1 ratio)"),
         ("Tube length:", "200 mm; read at 1 hour"),
         ("Normal:", "M 0–15 mm/hr   |   F 0–20 mm/hr"),
         "↑ in infection, inflammation, malignancy, pregnancy"],
        BLUE, LBLUE),
    slim_card("Peripheral Blood Smear",
        ["Leishman stain (methylene blue + eosin)",
         "Fix with methanol; stain 10–15 min",
         "Identify: RBC morphology, WBC types, platelets",
         "Thin smear at feathered edge for best morphology"],
        PURPLE, LPURPLE),
]))
story.append(sp(8))

# ── 1C Amphibian Chart ───────────────────────────────────────────────────────
story.append(section_banner("1C · AMPHIBIAN CHART  (10 Marks)", TEAL,
    "Frog Nerve-Muscle & Frog Heart Experiments"))
story.append(sp(5))

story.append(card(
    "Stannius Ligature — Frog Heart Pacemaker",
    [
        "Demonstrates SA node as primary pacemaker",
        ("1st ligature (SVC–atria junction):", "Ventricle STOPS; atria continues beating"),
        ("2nd ligature (AV junction):", "Ventricle may restart at SLOWER rate (idioventricular)"),
        "Proves: SA node > AV node > Purkinje in automaticity",
    ], TEAL, LTEAL))
story.append(sp(4))

story.append(two_col_cards([
    slim_card("Nerve-Muscle Preparation Responses",
        [("Threshold:", "Minimum stimulus for contraction"),
         ("All-or-None:", "Full response OR no response"),
         ("Summation:", "Sub-threshold stimuli add up"),
         ("Tetanus:", "Sustained contraction with rapid stimuli"),
         ("Fatigue:", "Gradual decrease with repeated stimuli")],
        TEAL, LTEAL),
    slim_card("Refractory Periods",
        [("Absolute:", "No response to ANY stimulus"),
         ("Relative:", "Response to STRONGER stimulus only"),
         "Absolute period = duration of action potential spike",
         "Important for: preventing re-excitation, one-way conduction"],
        GREEN, LGREEN),
]))
story.append(sp(4))

story.append(card(
    "Effects on Frog Heart — Ionic & Drug Effects",
    [
        ("Ca²⁺ excess:", "Sustained contraction → Calcium rigor"),
        ("K⁺ excess:", "Depresses heart → AV block, cardiac arrest in diastole"),
        ("Na⁺ excess:", "Weakens contractions (reduces action potential amplitude)"),
        ("Adrenaline:", "↑ HR + ↑ force (positive chrono + inotrope)"),
        ("Acetylcholine:", "↓ HR + ↓ force (negative chrono + inotrope)"),
        ("Warm Ringer's:", "↑ HR   |   Cold Ringer's: ↓ HR"),
    ], TEAL, LTEAL))
story.append(sp(4))

story.append(card(
    "Chart Drawing Tips — Muscle/Heart Tracing",
    [
        "Y-axis = muscle tension (g) or heart contraction height",
        "X-axis = time (seconds)",
        "Show baseline → threshold response → supramaximal response",
        "Tetanus: partial (wavy line) vs complete (flat plateau)",
        "Mark stimulation period with arrows or brackets below X-axis",
        "Label all key points: onset, peak, relaxation, recovery",
    ], TEAL, LTEAL))
story.append(sp(8))

# ── 1D Problem Chart ─────────────────────────────────────────────────────────
story.append(section_banner("1D · PROBLEM CHART  (5 Marks)", ORANGE))
story.append(sp(5))

story.append(card(
    "Approach to Problem Chart (4-Step Method)",
    [
        "1. List all given values and mark ↑ or ↓ vs normal",
        "2. Identify the pattern (e.g. ↓Hb + ↓MCV + ↓MCH = IDA)",
        "3. Write diagnosis with one-line justification",
        "4. Suggest cause and one confirmatory test",
    ], ORANGE, LORANGE))
story.append(sp(4))

story.append(mini_table(
    ["Scenario", "Key Findings", "Diagnosis", "Confirm With"],
    [
        ["Low Hb, low MCV, low MCH",       "Microcytic hypochromic",  "Iron Deficiency Anaemia",  "Serum ferritin, iron studies"],
        ["Low Hb, high MCV, high MCH",      "Macrocytic",              "Megaloblastic Anaemia",    "B12/Folate levels, bone marrow"],
        ["Low Hb, normal MCV, ↑ retics",   "Normocytic + haemolysis", "Haemolytic Anaemia",       "Coomb's test, LDH, bilirubin"],
        ["Pancytopenia, ↓↓ retics",         "All cell lines ↓",        "Aplastic Anaemia",         "Bone marrow biopsy"],
        ["↑ WBC (>30,000), immature cells", "Leukaemia picture",       "Leukaemia",                "Bone marrow + cytogenetics"],
        ["↑↑ BT, normal CT",               "Platelet/vascular defect","Thrombocytopenia/VWD",     "Platelet count, VWF assay"],
        ["Normal BT, ↑↑ CT",              "Coagulation pathway defect","Haemophilia A or B",       "Factor VIII / IX levels"],
    ],
    col_widths=[115, 90, 105, W-40-310],
    hdr_color=ORANGE
))
story.append(sp(8))

# ── 1E Endocrine Chart ───────────────────────────────────────────────────────
story.append(section_banner("1E · ENDOCRINE / NON-ENDOCRINE CHART  (5 Marks)", PURPLE))
story.append(sp(5))

story.append(mini_table(
    ["Gland", "Hormone", "↓ Deficiency", "↑ Excess"],
    [
        ["Ant. Pituitary", "GH",          "Dwarfism",              "Gigantism / Acromegaly"],
        ["Post. Pituitary","ADH",          "Diabetes Insipidus",    "SIADH"],
        ["Thyroid",        "T3, T4",       "Hypothyroidism/Cretinism","Hyperthyroidism/Graves"],
        ["Parathyroid",    "PTH",          "Hypocalcaemia, Tetany", "Hypercalcaemia, Stones"],
        ["Adrenal Cortex", "Cortisol",     "Addison Disease",       "Cushing Syndrome"],
        ["Adrenal Cortex", "Aldosterone",  "Salt wasting, ↓BP",    "Conn Syndrome, ↑BP"],
        ["Adrenal Medulla","Adrenaline",   "—",                     "Phaeochromocytoma"],
        ["Pancreas β",     "Insulin",      "Diabetes Mellitus T1",  "Hypoglycaemia"],
        ["Pancreas α",     "Glucagon",     "Hypoglycaemia",         "Hyperglycaemia"],
    ],
    col_widths=[80, 75, 130, W-40-285],
    hdr_color=PURPLE
))
story.append(sp(4))

story.append(card(
    "Lung Volumes — Non-Endocrine Chart (Spirometry)",
    [
        ("TV:", "500 mL  |  IRV: 3000 mL  |  ERV: 1100 mL  |  RV: 1200 mL"),
        ("VC:", "4600 mL (TV+IRV+ERV)   |   TLC: 5800 mL (VC+RV)"),
        ("FRC:", "2300 mL (ERV+RV)   |   FEV₁/FVC: >80% normal"),
        "FEV₁/FVC <70% → Obstructive (asthma, COPD)",
        "↓ TLC + ↓ VC + normal FEV₁/FVC → Restrictive (fibrosis)",
    ], PURPLE, LPURPLE))
story.append(sp(6))

story.append(PageBreak())

# ══════════════════════ SECTION 2: CLINICAL ══════════════════════════════════
story.append(section_banner("📋  SECTION 2: CLINICAL  (40 Marks)", TEAL,
    "Major 15 · Minor 5 · 2 Human Experiments 20"))
story.append(sp(6))

story.append(section_banner("2A · CLINICAL MAJOR  (15 Marks)", TEAL))
story.append(sp(5))

story.append(card(
    "Cardiovascular Examination — Auscultation",
    [
        ("S1 (lub):", "Mitral + tricuspid closure → START of systole"),
        ("S2 (dub):", "Aortic + pulmonary closure → START of diastole"),
        ("S3:", "Ventricular filling; normal in children, pathological in adults (LVF)"),
        ("S4:", "Atrial contraction sound; ALWAYS pathological (LV hypertrophy)"),
        ("Murmurs:", "Systolic ejection (AS, PS) vs Pansystolic (MR, TR, VSD) vs Diastolic (MS, AR)"),
    ], TEAL, LTEAL))
story.append(sp(4))

story.append(two_col_cards([
    slim_card("Apex Beat",
        [("Normal:", "5th ICS, midclavicular line"),
         ("Displaced laterally:", "LV enlargement, cardiomegaly"),
         ("Heaving:", "LV pressure overload (AS, HT)"),
         ("Tapping:", "Mitral stenosis (palpable S1)"),
         ("Hyperdynamic:", "Volume overload (AR, MR)")],
        TEAL, LTEAL),
    slim_card("Respiratory IPPA Summary",
        [("Inspection:", "Rate, rhythm, shape, use of accessory muscles"),
         ("Palpation:", "Trachea midline, chest expansion, tactile fremitus"),
         ("Percussion:", "Resonant=normal, Dull=consolidation/effusion, Hyperresonant=pneumothorax"),
         ("Auscultation:", "Vesicular vs bronchial; added sounds")],
        GREEN, LGREEN),
]))
story.append(sp(4))

story.append(card(
    "Deep Tendon Reflexes — Nerve Roots & Response",
    [
        ("Biceps jerk C5,C6:", "Strike biceps tendon → elbow flexion"),
        ("Triceps jerk C7,C8:", "Strike triceps tendon → elbow extension"),
        ("Knee jerk L3,L4:", "Strike patellar tendon → knee extension"),
        ("Ankle jerk S1,S2:", "Strike Achilles tendon → plantar flexion"),
        ("Plantar L5,S1:", "Normal = plantar flexion   |   Babinski = dorsiflexion big toe (UMN)"),
    ], TEAL, LTEAL))
story.append(sp(4))

story.append(two_col_cards([
    slim_card("UMN vs LMN Lesion",
        [("UMN:", "↑ tone, ↑ reflexes, Babinski +ve, no wasting, spastic"),
         ("LMN:", "↓ tone, ↓/absent reflexes, Babinski –ve, wasting, fasciculation, flaccid"),
         "UMN: above cord (cortex, capsule, brainstem)",
         "LMN: anterior horn cell + peripheral nerve"],
        RED, LRED),
    slim_card("Reflex Grading Scale",
        [("0:", "Absent (areflexia)"),
         ("1+:", "Diminished"),
         ("2+:", "Normal"),
         ("3+:", "Brisk / exaggerated"),
         ("4+:", "Clonus present (pathological)"),
         "Document as e.g. Knee jerk 2+ bilaterally"],
        ORANGE, LORANGE),
]))
story.append(sp(8))

story.append(section_banner("2B · CLINICAL MINOR  (5 Marks)", colors.HexColor("#00796B")))
story.append(sp(5))

story.append(two_col_cards([
    slim_card("Pulse Examination — 7 Characters",
        [("1 Rate:", "Normal 60–100 bpm"),
         ("2 Rhythm:", "Regular / irregular"),
         ("3 Volume:", "Full / weak / thready / collapsing"),
         ("4 Character:", "Slow-rising (AS), collapsing (AR)"),
         ("5 Vessel wall:", "Normal / thickened / tortuous"),
         ("6 Radioradial delay:", "Subclavian / aortic stenosis"),
         ("7 All peripheral pulses:", "Compare both sides")],
        TEAL, LTEAL),
    slim_card("Blood Pressure Measurement",
        [("Normal:", "120/80 mmHg"),
         ("Hypertension:", "≥140/90 mmHg (Stage 1 ≥130/80 per ACC/AHA)"),
         ("Korotkoff I:", "First sound = SYSTOLIC"),
         ("Korotkoff V:", "Sound disappears = DIASTOLIC"),
         ("Pulse pressure:", "SBP – DBP   (Normal 40 mmHg)"),
         ("MAP:", "DBP + 1/3 × PP   (Normal 70–100 mmHg)")],
        BLUE, LBLUE),
]))
story.append(sp(4))

story.append(card(
    "Superficial Reflexes — Nerve Arcs",
    [
        ("Corneal reflex:", "Afferent CN V  |  Efferent CN VII  →  blink"),
        ("Gag reflex:", "Afferent CN IX  |  Efferent CN X"),
        ("Abdominal reflex:", "T8–T12 — umbilicus moves toward stimulus"),
        ("Cremasteric reflex:", "L1, L2 — thigh stroke → testicular retraction"),
        ("Light reflex:", "CN II (afferent) → CN III (efferent) → pupil constriction; both direct + consensual"),
    ], TEAL, LTEAL))
story.append(sp(8))

story.append(section_banner("2C · TWO HUMAN EXPERIMENTS  (20 Marks — 10 each)", colors.HexColor("#004D40")))
story.append(sp(5))

story.append(card(
    "CVS Experiments — Common Types",
    [
        ("BP Postural:", "Lying → Sitting → Standing; Postural hypotension = >20 mmHg drop in SBP on standing"),
        ("Cold Pressor Test:", "Hand in ice water (1–2 min) → ↑ BP + ↑ HR due to sympathetic activation"),
        ("Valsalva Maneuver:", "Forced expiration vs closed glottis → ↑ intrathoracic pressure → ↓ venous return → ↓ BP → reflex ↑ HR"),
        ("Exercise test:", "HR and BP measured before, immediately after, and 5 min recovery; ↑ SBP, HR proportional to workload"),
    ], GREEN, LGREEN))
story.append(sp(4))

story.append(card(
    "Respiratory Experiments — Common Types",
    [
        ("Vital Capacity:", "Spirometer; deep inspiration → maximal expiration; Normal M: 4–5 L  |  F: 3–4 L"),
        ("Breath-Holding Time:", "Normal 30–60 sec; reduced in respiratory disease; CO₂ rise triggers resumption"),
        ("PEFR:", "Peak flow meter; Normal M: 500–700 L/min  |  F: 350–500 L/min"),
        ("Re-breathing CO₂:", "↑ ventilation rate and depth as CO₂ builds up — demonstrates central chemoreceptor role"),
    ], TEAL, LTEAL))
story.append(sp(4))

story.append(card(
    "Neurological/Sensory Experiments",
    [
        ("Visual Acuity:", "Snellen chart; Normal 6/6 (20/20); tested at 6 metres"),
        ("Colour Vision:", "Ishihara chart; 38 plates; defects: red-green most common (X-linked)"),
        ("Visual Fields:", "Confrontation test; defects: bitemporal hemianopia (pituitary tumour)"),
        ("Weber/Rinne:", "Weber = lateralises to affected ear in conductive; Rinne: AC>BC normal; BC>AC = conductive loss"),
        ("Two-point discrimination:", "Fingertip 2–4 mm; back 40–70 mm; tests sensory cortex resolution"),
    ], PURPLE, LPURPLE))
story.append(sp(4))

story.append(card(
    "Standard Experiment Recording Format (marks awarded for this)",
    [
        "1. Title of experiment",
        "2. Aim / Objective",
        "3. Materials required",
        "4. Method / Procedure (numbered steps)",
        "5. Observations — tabulate before/after values",
        "6. Results with graph or diagram if applicable",
        "7. Discussion — physiological basis (most marks here)",
        "8. Conclusion — one or two sentences",
    ], GREEN, LGREEN))
story.append(sp(6))

story.append(PageBreak())

# ══════════════════════ SECTION 3: THEORY VIVA ═══════════════════════════════
story.append(section_banner("📋  SECTION 3: THEORY VIVA  (20 Marks) — ALL SYSTEMS", NAVY,
    "Examiners ask 2–3 questions from different systems"))
story.append(sp(6))

# CVS
story.append(section_banner("CARDIOVASCULAR SYSTEM", BLUE))
story.append(sp(4))
story.append(two_col_cards([
    slim_card("Cardiac Output",
        [("CO = HR × SV", "(Normal ~5 L/min)"),
         ("Starling's Law:", "↑ preload → ↑ SV (up to a limit)"),
         ("Factors ↑ CO:", "Exercise, fever, pregnancy, anaemia"),
         ("Factors ↓ CO:", "Cardiogenic shock, tamponade, heart failure"),
         "Ejection fraction (EF) = SV/EDV × 100%; Normal >55%"],
        BLUE, LBLUE),
    slim_card("ECG Intervals — Normal Values",
        [("P wave:", "< 0.12 sec (3 small squares)"),
         ("PR interval:", "0.12–0.20 sec"),
         ("QRS complex:", "< 0.12 sec"),
         ("QT interval:", "< 0.44 sec (rate-corrected QTc)"),
         ("RR interval:", "0.6–1.0 sec (60–100 bpm)"),
         "PR ↑ = AV block  |  QRS ↑ = bundle branch block"],
        TEAL, LTEAL),
]))
story.append(sp(4))

story.append(card(
    "Blood Pressure Regulation",
    [
        ("Short-term (baroreceptors):", "Carotid sinus + aortic arch → medullary cardiovascular centre → autonomic adjustment"),
        ("Long-term (hormonal):", "RAAS: renin → angiotensin I → ACE → angiotensin II → aldosterone → Na⁺/water retention"),
        ("ADH:", "Released when plasma osmolality ↑ or volume ↓ → water retention → ↑ BP"),
        ("ANP:", "Released by atria when stretched → natriuresis → ↓ BP (opposes RAAS)"),
    ], BLUE, LBLUE))
story.append(sp(6))

# RESPIRATORY
story.append(section_banner("RESPIRATORY SYSTEM", colors.HexColor("#2E7D32")))
story.append(sp(4))
story.append(two_col_cards([
    slim_card("O₂ & CO₂ Transport",
        [("O₂:", "97% as oxyhaemoglobin  |  3% dissolved"),
         ("CO₂:", "70% as bicarbonate  |  23% carbaminoHb  |  7% dissolved"),
         ("Hb-O₂ curve RIGHT shift:", "↑ CO₂, ↑ H⁺, ↑ temp, ↑ 2,3-DPG → ↓ affinity"),
         ("LEFT shift:", "↓ CO₂, ↓ H⁺, fetal Hb, ↑ affinity for O₂"),
         "P50 = PO₂ at 50% saturation; normal ~26 mmHg"],
        GREEN, LGREEN),
    slim_card("Control of Breathing",
        [("Central chemoreceptors:", "Medulla; respond to ↑ CO₂ / ↓ pH"),
         ("Peripheral chemoreceptors:", "Carotid + aortic bodies; respond to ↓ PaO₂ (<60 mmHg), ↑ CO₂, ↓ pH"),
         ("Primary drive:", "CO₂ / pH (central)"),
         ("Hypoxic drive:", "Takes over in COPD patients on O₂ therapy"),
         "Hering-Breuer reflex: lung inflation inhibits inspiration"],
        TEAL, LTEAL),
]))
story.append(sp(6))

# RENAL
story.append(section_banner("RENAL SYSTEM", colors.HexColor("#1565C0")))
story.append(sp(4))
story.append(card(
    "GFR & Clearance — Key Values",
    [
        ("Normal GFR:", "125 mL/min  |  180 L/day filtered  |  1.5 L/day urine"),
        ("Inulin clearance:", "= GFR exactly (freely filtered, not reabsorbed/secreted)"),
        ("Creatinine clearance:", "≈ GFR (slightly overestimates due to tubular secretion)"),
        ("Glucose Tm:", "320 mg/min; glycosuria when plasma glucose >180 mg/dL (renal threshold)"),
        ("Urine concentration:", "Max 1200 mOsm/kg (countercurrent mechanism in medulla)"),
        ("ADH effect:", "↑ water permeability of collecting duct → concentrated urine"),
        ("Aldosterone:", "↑ Na⁺ reabsorption and K⁺ secretion in distal tubule / collecting duct"),
    ], BLUE, LBLUE))
story.append(sp(6))

# NERVOUS SYSTEM
story.append(section_banner("NERVOUS SYSTEM", NAVY))
story.append(sp(4))
story.append(two_col_cards([
    slim_card("Action Potential",
        [("RMP:", "–70 mV (inside negative)"),
         ("Depolarisation:", "Na⁺ rushes IN → reaches +30 mV"),
         ("Repolarisation:", "K⁺ rushes OUT → returns to –70 mV"),
         ("Hyperpolarisation:", "Briefly below –70 mV"),
         ("Na⁺/K⁺ ATPase:", "Restores 3 Na⁺ out, 2 K⁺ in"),
         "Myelinated fibres: saltatory conduction → faster"],
        NAVY, LBLUE),
    slim_card("Ascending & Descending Tracts",
        [("Dorsal column:", "Fine touch, vibration, proprioception → ipsilateral"),
         ("Spinothalamic:", "Pain, temperature → crosses at cord level"),
         ("Corticospinal:", "Voluntary movement; crosses at medulla (pyramidal decussation)"),
         ("Cerebellar tracts:", "Coordination, balance, skilled movement"),
         "Upper cord lesion → UMN signs BELOW lesion"],
        PURPLE, LPURPLE),
]))
story.append(sp(4))

story.append(card(
    "Autonomic Nervous System — Key Effects",
    [
        ("SNS (adrenergic):", "↑ HR, ↑ BP, bronchodilation, mydriasis, ↓ gut motility, glycogenolysis"),
        ("PNS (cholinergic):", "↓ HR, bronchoconstriction, ↑ gut motility, miosis, ↑ secretions"),
        ("Neurotransmitters:", "SNS → noradrenaline  |  PNS → acetylcholine"),
        ("Receptors:", "α1 (vasoconstriction), β1 (heart), β2 (bronchodilation), M (muscarinic PNS)"),
    ], NAVY, LBLUE))
story.append(sp(6))

# ENDOCRINE
story.append(section_banner("ENDOCRINE SYSTEM", PURPLE))
story.append(sp(4))
story.append(two_col_cards([
    slim_card("Insulin vs Glucagon",
        [("Insulin (β cells):", "Released when ↑ blood glucose"),
         "Actions: ↑ glucose uptake (GLUT4), glycogen synthesis, protein synthesis, fat storage",
         ("Glucagon (α cells):", "Released when ↓ blood glucose"),
         "Actions: glycogenolysis, gluconeogenesis, lipolysis",
         "Insulin:glucagon ratio determines metabolic state"],
        PURPLE, LPURPLE),
    slim_card("Thyroid Hormones",
        [("Synthesis:", "Thyroglobulin + iodine + TPO → T3 (active) + T4 (prohormone)"),
         ("Regulate:", "BMR, growth, CNS development, heart rate, temperature"),
         ("Hypothyroidism:", "↓ BMR, weight gain, cold intolerance, bradycardia, myxedema"),
         ("Hyperthyroidism:", "↑ BMR, weight loss, heat intolerance, tachycardia, exophthalmos"),
         ("Control:", "TRH → TSH → T3/T4 → negative feedback"),],
        TEAL, LTEAL),
]))
story.append(sp(6))

# BLOOD & IMMUNE
story.append(section_banner("BLOOD & HAEMOSTASIS", RED))
story.append(sp(4))
story.append(card(
    "Coagulation Cascade — Simplified",
    [
        ("Extrinsic pathway:", "Tissue factor (TF) + Factor VII → X activation"),
        ("Intrinsic pathway:", "XII → XI → IX → VIII → X activation"),
        ("Common pathway:", "X + V → prothrombin → thrombin → fibrinogen → fibrin clot"),
        ("PT:", "Tests extrinsic + common pathway (Factors II, V, VII, X)"),
        ("aPTT:", "Tests intrinsic + common pathway (Factors VIII, IX, XI, XII)"),
        ("Anticoagulants:", "Heparin activates antithrombin III  |  Warfarin blocks Vit K (II, VII, IX, X)"),
    ], RED, LRED))
story.append(sp(6))

# DIGESTIVE
story.append(section_banner("DIGESTIVE SYSTEM", ORANGE))
story.append(sp(4))
story.append(two_col_cards([
    slim_card("GI Hormones — Quick Table",
        [("Gastrin (G cells, antrum):", "↑ HCl, ↑ pepsinogen, ↑ motility; stimulated by protein, vagus"),
         ("Secretin (S cells, duodenum):", "↑ pancreatic HCO₃⁻; stimulated by acid in duodenum"),
         ("CCK (I cells, duodenum):", "↑ pancreatic enzymes, gallbladder contraction; stimulated by fat + protein"),
         ("GIP:", "Inhibits gastric acid; stimulates insulin release")],
        ORANGE, LORANGE),
    slim_card("Fat Absorption",
        ["Emulsification by bile salts",
         "Hydrolysis by pancreatic lipase → fatty acids + monoglycerides",
         "Micelle formation with bile salts",
         "Absorbed into enterocytes → reassembled as triglycerides",
         "Packaged into chylomicrons → enter LACTEALS (lymphatics)",
         "Reach blood via thoracic duct → left subclavian vein"],
        GREEN, LGREEN),
]))
story.append(sp(6))

story.append(PageBreak())

# ══════════════════════ LAST PAGE: EXAM CHEAT SHEET ═════════════════════════
story.append(section_banner("⭐  EXAM DAY CHEAT SHEET  — CRITICAL NUMBERS", GOLD))
story.append(sp(5))

story.append(mini_table(
    ["Parameter", "Normal Value", "Parameter", "Normal Value"],
    [
        ["Hb (Male)",        "13–17 g/dL",       "BP (Normal)",         "120/80 mmHg"],
        ["Hb (Female)",      "12–15 g/dL",       "Heart Rate",          "60–100 bpm"],
        ["WBC",              "4,000–11,000/mm³",  "Respiratory Rate",    "14–20 /min"],
        ["Platelets",        "1.5–4 lakh/mm³",    "SpO₂",               "95–100%"],
        ["MCV",              "80–100 fL",          "Temp (oral)",         "36.1–37.2°C"],
        ["ESR (M/F)",        "0–15 / 0–20 mm/hr", "Cardiac Output",      "5 L/min"],
        ["Bleeding Time",    "1–6 min (Duke)",     "GFR",                 "125 mL/min"],
        ["Clotting Time",    "3–8 min (cap tube)", "Vital Capacity (M)",  "4–5 L"],
        ["Blood glucose FBS","70–110 mg/dL",       "FEV₁/FVC",            ">80% normal"],
        ["PR interval",      "0.12–0.20 sec",      "QRS width",           "<0.12 sec"],
    ],
    col_widths=[110, 80, 140, W-40-330],
    hdr_color=NAVY
))
story.append(sp(6))

story.append(card(
    "Mark-wise Preparation Priority",
    [
        ("20 marks — Human Experiments:", "Practice the procedure + write full discussion"),
        ("15 marks — Hematology Major:", "CBC interpretation, blood grouping, Sahli's method"),
        ("15 marks — Clinical Major:", "Full system examination — CVS, Respiratory, Neuro"),
        ("20 marks — Theory Viva:", "10 key points per system × 8 systems = 80 facts"),
        ("10 marks — Amphibian Chart:", "Stannius ligature + NM preparation tracings"),
        (" 5 marks — Problem Chart:", "4-step approach; anemia pattern recognition"),
        (" 5 marks — Endocrine Chart:", "Hormone deficiency/excess table from memory"),
        (" 5 marks — Hematology Minor:", "BT, CT, ESR normal values + methods"),
        (" 5 marks — Clinical Minor:", "BP Korotkoff method + 7 characters of pulse"),
    ], GOLD, LGOLD))
story.append(sp(4))

story.append(Paragraph(
    "All the best for your exam! 🎓",
    S("GoodLuck", fontName="Helvetica-Bold", fontSize=16, textColor=NAVY, alignment=TA_CENTER, spaceAfter=4)
))
story.append(Paragraph(
    "Physiology Practical Flashcards — 100 Marks Total",
    S("Footer2", fontName="Helvetica", fontSize=9, textColor=GREY, alignment=TA_CENTER)
))

# ── BUILD ─────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF created: {OUTPUT}")
print(f"Size: {os.path.getsize(OUTPUT)/1024:.1f} KB")
Running Command

cd /home/daytona/workspace/physiology-study-guide && python3 create_flashcards.p…

Editing File

~/physiology-study-guide/create_flashcards.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/physiology-study-guide/create_flashcards.py'
Editing File

~/physiology-study-guide/create_flashcards.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/physiology-study-guide/create_flashcards.py'
Running Command

cd /home/daytona/workspace/physiology-study-guide && python3 create_flashcards.p…

Editing File

~/physiology-study-guide/create_flashcards.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/physiology-study-guide/create_flashcards.py'
Running Command

cd /home/daytona/workspace/physiology-study-guide && python3 create_flashcards.p…

Writing File

~/physiology-study-guide/create_flashcards.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.platypus import (SimpleDocTemplate, Paragraph, Spacer, Table,
                                 TableStyle, PageBreak, HRFlowable,
                                 BaseDocTemplate, Frame, PageTemplate, NextPageTemplate)
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from reportlab.pdfgen import canvas as pdfcanvas
import os

OUTPUT = "/home/daytona/workspace/physiology-study-guide/Physiology_Flashcards.pdf"
W, H = A4

# ── Colours ──────────────────────────────────────────────────────────────────
NAVY   = colors.HexColor("#1F4E79")
BLUE   = colors.HexColor("#2E75B6")
LBLUE  = colors.HexColor("#EBF3FB")
TEAL   = colors.HexColor("#00695C")
LTEAL  = colors.HexColor("#E8F5F3")
ORANGE = colors.HexColor("#E65100")
LORANGE= colors.HexColor("#FFF3E0")
PURPLE = colors.HexColor("#4A148C")
LPURPLE= colors.HexColor("#F5EEF8")
RED    = colors.HexColor("#B71C1C")
LRED   = colors.HexColor("#FDEDEC")
GREEN  = colors.HexColor("#1B5E20")
LGREEN = colors.HexColor("#EAF7EA")
GOLD   = colors.HexColor("#F57F17")
LGOLD  = colors.HexColor("#FFFDE7")
GREY   = colors.HexColor("#424242")
LGREY  = colors.HexColor("#FAFAFA")
WHITE  = colors.white

MARGIN = 20
CONTENT_W = W - 2*MARGIN   # 555 pts

# ── Style helpers ─────────────────────────────────────────────────────────────
def PS(name, font="Helvetica", size=10, color=GREY, align=TA_LEFT,
       bold=False, leading=None, spaceBefore=0, spaceAfter=0):
    fn = "Helvetica-Bold" if bold else font
    return ParagraphStyle(name, fontName=fn, fontSize=size,
                          textColor=color, alignment=align,
                          leading=leading or size*1.3,
                          spaceBefore=spaceBefore, spaceAfter=spaceAfter)

def sp(h=4):  return Spacer(1, h)
def hr():     return HRFlowable(width="100%", thickness=0.4,
                                 color=colors.HexColor("#CCCCCC"), spaceAfter=3, spaceBefore=3)

# ── Page templates ────────────────────────────────────────────────────────────
def draw_cover(c, doc):
    c.saveState()
    c.setFillColor(NAVY);  c.rect(0, 0, W, H, fill=1, stroke=0)
    c.setFillColor(BLUE);  c.rect(0, H*0.5, W, H*0.5, fill=1, stroke=0)
    # Decorative circles
    c.setFillColor(colors.HexColor("#FFFFFF15"))
    c.circle(W*0.85, H*0.82, 110, fill=1, stroke=0)
    c.circle(W*0.08, H*0.18, 70,  fill=1, stroke=0)
    # Main title
    c.setFillColor(WHITE); c.setFont("Helvetica-Bold", 34)
    c.drawCentredString(W/2, H*0.70, "PHYSIOLOGY PRACTICAL")
    c.setFont("Helvetica-Bold", 26)
    c.drawCentredString(W/2, H*0.63, "EXAM — QUICK REVISION")
    c.setFillColor(GOLD); c.setFont("Helvetica-Bold", 20)
    c.drawCentredString(W/2, H*0.57, "FLASHCARDS")
    # Divider
    c.setStrokeColor(GOLD); c.setLineWidth(2)
    c.line(W*0.25, H*0.54, W*0.75, H*0.54)
    # Boxes
    bdata = [("HEMATOLOGY\n40 Marks", BLUE),
             ("CLINICAL\n40 Marks", TEAL),
             ("THEORY VIVA\n20 Marks", ORANGE)]
    bw, bh = 130, 52
    gap = 12
    total_bw = len(bdata)*bw + (len(bdata)-1)*gap
    bx0 = (W - total_bw) / 2
    by  = H*0.42
    for i,(txt,col) in enumerate(bdata):
        bx = bx0 + i*(bw+gap)
        c.setFillColor(col); c.roundRect(bx, by, bw, bh, 6, fill=1, stroke=0)
        c.setFillColor(WHITE); c.setFont("Helvetica-Bold", 10)
        lines = txt.split("\n")
        c.drawCentredString(bx+bw/2, by+bh-18, lines[0])
        c.setFont("Helvetica", 9)
        c.drawCentredString(bx+bw/2, by+6, lines[1])
    # Total
    c.setFillColor(GOLD); c.setFont("Helvetica-Bold", 15)
    c.drawCentredString(W/2, H*0.36, "TOTAL: 100 MARKS")
    # Subtitle
    c.setFillColor(colors.HexColor("#D0E8FF")); c.setFont("Helvetica", 10)
    c.drawCentredString(W/2, H*0.30, "All Systems  •  All Components  •  Key Values")
    c.setFont("Helvetica", 8.5)
    c.drawCentredString(W/2, H*0.25, "University Exam Pattern")
    # Footer strip
    c.setFillColor(colors.HexColor("#FFFFFF18"))
    c.rect(0, 0, W, 28, fill=1, stroke=0)
    c.setFillColor(WHITE); c.setFont("Helvetica", 7.5)
    c.drawCentredString(W/2, 10, "Q shown above each answer  •  Flip to test yourself")
    c.restoreState()

def draw_page(c, doc):
    c.saveState()
    # Background
    c.setFillColor(LGREY); c.rect(0, 0, W, H, fill=1, stroke=0)
    # Header bar
    c.setFillColor(NAVY); c.rect(0, H-22, W, 22, fill=1, stroke=0)
    c.setFillColor(WHITE); c.setFont("Helvetica-Bold", 7.5)
    c.drawString(14, H-14, "PHYSIOLOGY PRACTICAL — QUICK REVISION FLASHCARDS")
    c.setFont("Helvetica", 7.5)
    c.drawRightString(W-14, H-14, f"Page {doc.page}")
    # Footer bar
    c.setFillColor(NAVY); c.rect(0, 0, W, 13, fill=1, stroke=0)
    c.setFillColor(WHITE); c.setFont("Helvetica", 6.5)
    c.drawCentredString(W/2, 4, "Hematology  •  Clinical  •  Amphibian  •  Endocrine  •  Theory Viva — All Systems")
    c.restoreStore = c.restoreState
    c.restoreState()

# Doc setup
doc = BaseDocTemplate(OUTPUT, pagesize=A4,
                      leftMargin=MARGIN, rightMargin=MARGIN,
                      topMargin=30, bottomMargin=18)
cover_frame = Frame(0, 0, W, H, 0, 0, 0, 0, id="cover")
main_frame  = Frame(MARGIN, 18, CONTENT_W, H-50, id="main")
doc.addPageTemplates([
    PageTemplate(id="cover", frames=[cover_frame], onPage=draw_cover),
    PageTemplate(id="main",  frames=[main_frame],  onPage=draw_page),
])

# ── Section banner ─────────────────────────────────────────────────────────────
def banner(text, color=NAVY, sub=None):
    items = [Paragraph(text, PS("BH", bold=True, size=12, color=WHITE, leading=15))]
    if sub:
        items.append(Paragraph(sub, PS("BS", size=8, color=colors.HexColor("#C8E6FF"), leading=10)))
    t = Table([[items]], colWidths=[CONTENT_W])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,-1), color),
        ("TOPPADDING",    (0,0),(-1,-1), 7),
        ("BOTTOMPADDING", (0,0),(-1,-1), 7),
        ("LEFTPADDING",   (0,0),(-1,-1), 10),
        ("RIGHTPADDING",  (0,0),(-1,-1), 10),
    ]))
    return t

# ── Single full-width card ─────────────────────────────────────────────────────
def card(q, items, accent=BLUE, bg=LBLUE):
    """items: list of str or (bold, rest) tuples"""
    BAR = 5
    INNER = CONTENT_W - BAR
    q_p = Paragraph(q, PS("CQ", bold=True, size=10.5, color=NAVY, leading=14, spaceAfter=2))
    a_ps = []
    for it in items:
        if isinstance(it, tuple):
            b, r = it
            a_ps.append(Paragraph(f"<b>{b}</b> {r}",
                                   PS("CA", size=9.5, color=GREY, leading=12)))
        else:
            a_ps.append(Paragraph(f"• {it}",
                                   PS("CA2", size=9.5, color=GREY, leading=12)))
    content = [q_p] + a_ps
    bar_t = Table([[""]], colWidths=[BAR])
    bar_t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,-1), accent),
        ("TOPPADDING",    (0,0),(-1,-1), 0),
        ("BOTTOMPADDING", (0,0),(-1,-1), 0),
        ("LEFTPADDING",   (0,0),(-1,-1), 0),
        ("RIGHTPADDING",  (0,0),(-1,-1), 0),
    ]))
    outer = Table([[bar_t, content]], colWidths=[BAR, INNER])
    outer.setStyle(TableStyle([
        ("BACKGROUND",    (1,0),(1,0), bg),
        ("TOPPADDING",    (1,0),(1,0), 7),
        ("BOTTOMPADDING", (1,0),(1,0), 7),
        ("LEFTPADDING",   (1,0),(1,0), 9),
        ("RIGHTPADDING",  (1,0),(1,0), 9),
        ("TOPPADDING",    (0,0),(0,0), 0),
        ("BOTTOMPADDING", (0,0),(0,0), 0),
        ("LEFTPADDING",   (0,0),(0,0), 0),
        ("RIGHTPADDING",  (0,0),(0,0), 0),
        ("VALIGN",        (0,0),(-1,-1), "TOP"),
    ]))
    return outer

# ── Two-column cards ───────────────────────────────────────────────────────────
# Leave 6pt gutter; each column = (CONTENT_W - 6) / 2
COL = (CONTENT_W - 6) / 2

def slim(q, items, accent=BLUE, bg=LBLUE):
    BAR = 5
    INNER = COL - BAR
    q_p = Paragraph(q, PS("SQ", bold=True, size=9.5, color=NAVY, leading=12, spaceAfter=1))
    a_ps = []
    for it in items:
        if isinstance(it, tuple):
            b, r = it
            a_ps.append(Paragraph(f"<b>{b}</b> {r}",
                                   PS("SA", size=8.5, color=GREY, leading=11)))
        else:
            a_ps.append(Paragraph(f"• {it}",
                                   PS("SA2", size=8.5, color=GREY, leading=11)))
    content = [q_p] + a_ps
    bar_t = Table([[""]], colWidths=[BAR])
    bar_t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,-1), accent),
        ("TOPPADDING",    (0,0),(-1,-1), 0),
        ("BOTTOMPADDING", (0,0),(-1,-1), 0),
        ("LEFTPADDING",   (0,0),(-1,-1), 0),
        ("RIGHTPADDING",  (0,0),(-1,-1), 0),
    ]))
    outer = Table([[bar_t, content]], colWidths=[BAR, INNER])
    outer.setStyle(TableStyle([
        ("BACKGROUND",    (1,0),(1,0), bg),
        ("TOPPADDING",    (1,0),(1,0), 6),
        ("BOTTOMPADDING", (1,0),(1,0), 6),
        ("LEFTPADDING",   (1,0),(1,0), 6),
        ("RIGHTPADDING",  (1,0),(1,0), 5),
        ("TOPPADDING",    (0,0),(0,0), 0),
        ("BOTTOMPADDING", (0,0),(0,0), 0),
        ("LEFTPADDING",   (0,0),(0,0), 0),
        ("RIGHTPADDING",  (0,0),(0,0), 0),
        ("VALIGN",        (0,0),(-1,-1), "TOP"),
    ]))
    return outer

def two(left, right):
    t = Table([[left, right]], colWidths=[COL, COL])
    t.setStyle(TableStyle([
        ("VALIGN",        (0,0),(-1,-1), "TOP"),
        ("LEFTPADDING",   (0,0),(-1,-1), 0),
        ("RIGHTPADDING",  (0,0),(-1,-1), 0),
        ("TOPPADDING",    (0,0),(-1,-1), 0),
        ("BOTTOMPADDING", (0,0),(-1,-1), 0),
        ("RIGHTPADDING",  (0,0),(0,-1), 6),
    ]))
    return t

# ── Mini table ─────────────────────────────────────────────────────────────────
def tbl(headers, rows, widths=None, hc=NAVY):
    if widths is None:
        n = len(headers)
        widths = [CONTENT_W/n]*n
    hdr = [Paragraph(h, PS("TH", bold=True, size=8, color=WHITE, align=TA_CENTER)) for h in headers]
    data = [hdr]
    for i, row in enumerate(rows):
        bg = WHITE if i%2==0 else colors.HexColor("#F0F4F8")
        data.append([Paragraph(str(c), PS("TC", size=8, color=GREY, leading=10)) for c in row])
    t = Table(data, colWidths=widths)
    styles_list = [
        ("BACKGROUND",    (0,0),(-1,0),  hc),
        ("GRID",          (0,0),(-1,-1), 0.3, colors.HexColor("#C0C0C0")),
        ("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), "MIDDLE"),
    ]
    for i in range(1, len(rows)+1):
        if i%2 == 0:
            styles_list.append(("BACKGROUND", (0,i),(-1,i), colors.HexColor("#F0F4F8")))
    t.setStyle(TableStyle(styles_list))
    return t

# ══════════════════════════════════════════════════════════════════════════════
#  STORY
# ══════════════════════════════════════════════════════════════════════════════
story = []
story.append(NextPageTemplate("cover"))
story.append(PageBreak())
story.append(NextPageTemplate("main"))
story.append(PageBreak())

# ─── SECTION 1: HEMATOLOGY ────────────────────────────────────────────────────
story.append(banner("SECTION 1: HEMATOLOGY  (40 Marks)", NAVY,
    "Major 15  ·  Minor 5  ·  Amphibian Chart 10  ·  Problem Chart 5  ·  Endocrine/Non-Endocrine Chart 5"))
story.append(sp(5))

story.append(banner("1A · HEMATOLOGY MAJOR  (15 Marks)", BLUE))
story.append(sp(4))

story.append(card("CBC — Normal Values (Must Memorise)", [
    ("Hb Male:", "13–17 g/dL     |     Hb Female: 12–15 g/dL"),
    ("RBC:", "Male 4.5–5.5 mill/mm³     |     Female 3.8–4.8 mill/mm³"),
    ("WBC:", "4,000–11,000 /mm³"),
    ("Platelets:", "1.5–4.0 lakh/mm³  (150,000–400,000/mm³)"),
    ("PCV:", "Male 40–50%     |     Female 35–45%"),
    ("MCV:", "80–100 fL     |     MCH: 27–32 pg     |     MCHC: 31–36 g/dL"),
    ("ESR:", "Male 0–15 mm/hr     |     Female 0–20 mm/hr  (Westergren)"),
], BLUE, LBLUE))
story.append(sp(4))

story.append(tbl(
    ["Anemia Type", "Hb", "MCV", "MCH", "Retics", "Key Cause"],
    [
        ["Iron Deficiency (IDA)", "↓", "↓ <80", "↓", "↓/N", "Poor diet / blood loss"],
        ["Megaloblastic",         "↓", "↑ >100","↑", "↓",   "B12 / Folate deficiency"],
        ["Hemolytic",             "↓", "N/↑",   "N", "↑↑",  "RBC destruction"],
        ["Aplastic",              "↓", "N",      "N", "↓↓",  "Bone marrow failure"],
        ["Thalassemia minor",     "N/↓","↓",     "↓", "N/↑", "Genetic Hb defect"],
    ],
    widths=[105, 28, 46, 28, 34, CONTENT_W-241], hc=NAVY))
story.append(sp(4))

story.append(card("Hemoglobin Estimation — Sahli's Acid Hematin Method", [
    "Hb + dilute HCl  →  Acid hematin (brown colour); dilute until colour matches comparator",
    ("Normal:", "14.5 g% male   |   13.5 g% female"),
    "Cyanmethemoglobin method = most accurate (used in labs)",
    "Dare's method = simple visual comparison",
], BLUE, LBLUE))
story.append(sp(4))

story.append(two(
    slim("Blood Grouping — ABO System", [
        ("A:", "Antigen A on RBC; Anti-B antibody in plasma"),
        ("B:", "Antigen B on RBC; Anti-A antibody in plasma"),
        ("AB:", "A+B antigens; NO antibodies — universal recipient"),
        ("O:", "No antigens; Anti-A+B antibodies — universal donor"),
    ], BLUE, LBLUE),
    slim("Rh Factor & Widal Test", [
        ("Rh+:", "D antigen present; Rh–: D antigen absent"),
        ("EBF:", "2nd Rh+ baby of Rh– mother — erythroblastosis fetalis"),
        ("Widal O titre:", "≥1:80 positive for typhoid"),
        ("Widal H titre:", "≥1:160 positive for typhoid"),
        "Rising titre in paired samples is more significant",
    ], TEAL, LTEAL)
))
story.append(sp(4))

story.append(card("Differential Leukocyte Count (DLC)", [
    ("Neutrophils 50–70%:", "↑ bacterial infection, stress  |  ↓ viral infections, bone marrow failure"),
    ("Lymphocytes 20–40%:", "↑ viral infections, TB  |  ↓ AIDS, immunosuppression"),
    ("Eosinophils 1–4%:",   "↑ allergy, parasitic infections  |  ↓ steroid use"),
    ("Monocytes 2–8%:",     "↑ chronic infection, monocytic leukaemia"),
    ("Basophils 0–1%:",     "↑ CML, allergic reactions"),
], BLUE, LBLUE))
story.append(sp(6))

story.append(banner("1B · HEMATOLOGY MINOR  (5 Marks)", colors.HexColor("#1565C0")))
story.append(sp(4))

story.append(two(
    slim("Bleeding Time (BT) — Duke's Method", [
        ("Normal:", "1–6 minutes"),
        "Ear lobe puncture; blot with filter paper every 30 sec",
        "Tests: platelet function + capillary wall integrity",
        "↑ in thrombocytopenia, von Willebrand disease, aspirin use",
    ], BLUE, LBLUE),
    slim("Clotting Time (CT) — Capillary Tube Method", [
        ("Normal:", "3–8 minutes"),
        "Finger-prick blood; fill 3 capillary tubes",
        "Break one tube every 30 sec until fibrin thread appears",
        "Tests: intrinsic coagulation pathway",
    ], TEAL, LTEAL)
))
story.append(sp(4))

story.append(two(
    slim("ESR — Westergren Method", [
        ("Anticoagulant:", "Sodium citrate (blood:citrate = 4:1)"),
        ("Setup:", "200 mm tube; read at 1 hour"),
        ("Normal:", "Male 0–15 mm/hr   |   Female 0–20 mm/hr"),
        "↑ in infection, inflammation, malignancy, pregnancy, anaemia",
    ], BLUE, LBLUE),
    slim("Peripheral Blood Smear", [
        ("Stain:", "Leishman stain (methylene blue + eosin)"),
        "Fix with methanol 30 sec; flood with stain 10–15 min",
        "Identify: RBC morphology, all WBC types, platelet clumps",
        "Feathered edge of smear = best area for differential count",
    ], PURPLE, LPURPLE)
))
story.append(sp(6))

story.append(banner("1C · AMPHIBIAN CHART  (10 Marks)", TEAL,
    "Frog Nerve-Muscle Preparation & Frog Heart Experiments"))
story.append(sp(4))

story.append(card("Stannius Ligature — Demonstrates SA Node as Pacemaker", [
    "1st ligature at SVC–atria junction: ventricle STOPS; atria continues",
    "2nd ligature at AV junction: ventricle MAY restart at SLOWER idioventricular rate",
    "Proves hierarchy: SA node > AV node > Purkinje fibres in automaticity",
    "Without SA node: AV node rate ~40–60 bpm; Purkinje ~15–40 bpm",
], TEAL, LTEAL))
story.append(sp(4))

story.append(two(
    slim("Nerve-Muscle Preparation Responses", [
        ("All-or-None Law:", "Full response OR no response"),
        ("Threshold:", "Minimum stimulus to produce contraction"),
        ("Summation:", "Sub-threshold stimuli accumulate to cross threshold"),
        ("Tetanus:", "Sustained contraction with rapid stimuli — incomplete vs complete"),
        ("Fatigue:", "Progressive ↓ in response with repeated stimulation"),
    ], TEAL, LTEAL),
    slim("Refractory Periods", [
        ("Absolute:", "No response to ANY stimulus — duration = AP spike"),
        ("Relative:", "Response ONLY to stronger-than-normal stimulus"),
        "Significance: prevents re-excitation; ensures one-way conduction",
        "Heart ARP: entire systole — prevents tetanus in cardiac muscle",
    ], GREEN, LGREEN)
))
story.append(sp(4))

story.append(card("Effects on Frog Heart", [
    ("Ca²⁺ excess:", "Sustained contraction = calcium rigor (systolic arrest)"),
    ("K⁺ excess:", "Depresses heart → AV block → cardiac arrest in DIASTOLE"),
    ("Adrenaline:", "↑ HR + ↑ force — positive chronotropy + inotropy"),
    ("Acetylcholine:", "↓ HR + ↓ force — negative chronotropy + inotropy"),
    ("Warm Ringer's:", "↑ HR   |   Cold Ringer's: ↓ HR   (Q10 effect)"),
    ("Vagal stimulation:", "↓ HR → may produce vagal escape after prolonged stimulation"),
], TEAL, LTEAL))
story.append(sp(4))

story.append(card("Chart Drawing Rules", [
    "Y-axis = muscle tension (g) or heart contraction height (mm)",
    "X-axis = time (seconds)",
    "Show baseline → threshold response → supramaximal response",
    "Tetanus: partial = wavy plateau; complete = flat plateau",
    "Mark stimulation brackets below X-axis; label all key phases",
    "Fatigue curve: decreasing amplitude with constant stimuli",
], TEAL, LTEAL))
story.append(sp(6))

story.append(banner("1D · PROBLEM CHART  (5 Marks)", ORANGE))
story.append(sp(4))

story.append(card("4-Step Approach to Problem Chart", [
    "1. List all given values; mark each as ↑, ↓, or N vs normal range",
    "2. Identify the pattern (e.g. ↓Hb + ↓MCV + ↓MCH = microcytic hypochromic = IDA)",
    "3. Write diagnosis with one-line justification",
    "4. Suggest underlying cause and one confirmatory test",
], ORANGE, LORANGE))
story.append(sp(4))

story.append(tbl(
    ["Scenario", "Pattern", "Diagnosis", "Confirmatory Test"],
    [
        ["↓Hb, ↓MCV, ↓MCH",      "Microcytic hypochromic",   "Iron Deficiency Anaemia",  "Serum ferritin, iron studies"],
        ["↓Hb, ↑MCV, ↑MCH",      "Macrocytic",               "Megaloblastic Anaemia",    "B12 / Folate levels"],
        ["↓Hb, N MCV, ↑ retics",  "Normocytic + haemolysis",  "Haemolytic Anaemia",       "Coombs test, LDH, bilirubin"],
        ["Pancytopenia, ↓↓ retics","All cell lines ↓",         "Aplastic Anaemia",         "Bone marrow biopsy"],
        ["↑ WBC, immature cells",  "Leukaemia picture",         "Leukaemia",                "Bone marrow + cytogenetics"],
        ["↑↑ BT, normal CT",      "Platelet/vascular defect",  "Thrombocytopenia / VWD",   "Platelet count, VWF assay"],
        ["Normal BT, ↑↑ CT",     "Coagulation defect",         "Haemophilia A or B",       "Factor VIII / IX levels"],
    ],
    widths=[105, 100, 130, CONTENT_W-335], hc=ORANGE))
story.append(sp(6))

story.append(banner("1E · ENDOCRINE / NON-ENDOCRINE CHART  (5 Marks)", PURPLE))
story.append(sp(4))

story.append(tbl(
    ["Gland", "Hormone", "Deficiency", "Excess"],
    [
        ["Ant. Pituitary", "GH",           "Dwarfism",                 "Gigantism / Acromegaly"],
        ["Post. Pituitary","ADH",           "Diabetes Insipidus",       "SIADH"],
        ["Thyroid",        "T3, T4",        "Hypothyroidism / Cretinism","Hyperthyroidism / Graves"],
        ["Parathyroid",    "PTH",           "Hypocalcaemia, Tetany",    "Hypercalcaemia, Renal stones"],
        ["Adrenal Cortex", "Cortisol",      "Addison Disease",          "Cushing Syndrome"],
        ["Adrenal Cortex", "Aldosterone",   "Salt wasting, ↓ BP",      "Conn Syndrome, ↑ BP"],
        ["Adrenal Medulla","Adrenaline",    "—",                        "Phaeochromocytoma"],
        ["Pancreas β",     "Insulin",       "Diabetes Mellitus Type 1", "Hypoglycaemia"],
        ["Pancreas α",     "Glucagon",      "Hypoglycaemia",            "Hyperglycaemia"],
    ],
    widths=[80, 72, 130, CONTENT_W-282], hc=PURPLE))
story.append(sp(4))

story.append(card("Lung Volumes — Spirometry Quick Reference", [
    ("TV:", "500 mL     |     IRV: 3000 mL     |     ERV: 1100 mL     |     RV: 1200 mL"),
    ("VC:", "4600 mL = TV+IRV+ERV     |     TLC: 5800 mL = VC+RV"),
    ("FRC:", "2300 mL = ERV+RV     |     FEV₁/FVC: >80% = normal"),
    "FEV₁/FVC <70%  →  Obstructive pattern (asthma, COPD)",
    "↓TLC + ↓VC + normal FEV₁/FVC  →  Restrictive pattern (fibrosis)",
], PURPLE, LPURPLE))
story.append(sp(4))
story.append(PageBreak())

# ─── SECTION 2: CLINICAL ──────────────────────────────────────────────────────
story.append(banner("SECTION 2: CLINICAL  (40 Marks)", TEAL,
    "Major 15  ·  Minor 5  ·  2 Human Experiments 20"))
story.append(sp(5))

story.append(banner("2A · CLINICAL MAJOR  (15 Marks)", TEAL))
story.append(sp(4))

story.append(card("Cardiovascular Examination — Heart Sounds", [
    ("S1 (lub):", "Mitral + tricuspid closure  →  START of systole"),
    ("S2 (dub):", "Aortic + pulmonary closure  →  START of diastole"),
    ("S3:", "Ventricular filling sound; normal in children; pathological in adults = LVF"),
    ("S4:", "Atrial contraction sound; ALWAYS pathological = LV hypertrophy"),
    ("Murmurs:", "Systolic ejection (AS, PS)  |  Pansystolic (MR, TR, VSD)  |  Diastolic (MS, AR)"),
], TEAL, LTEAL))
story.append(sp(4))

story.append(two(
    slim("Apex Beat Characters", [
        ("Normal:", "5th ICS, midclavicular line"),
        ("Displaced laterally:", "LV enlargement, cardiomegaly"),
        ("Heaving:", "LV pressure overload — AS, hypertension"),
        ("Tapping:", "Mitral stenosis (palpable S1)"),
        ("Hyperdynamic:", "Volume overload — AR, MR, VSD"),
    ], TEAL, LTEAL),
    slim("Respiratory IPPA Summary", [
        ("Inspection:", "Rate, rhythm, shape, accessory muscles"),
        ("Palpation:", "Trachea midline, chest expansion, fremitus"),
        ("Percussion:", "Resonant=normal; Dull=consolidation/effusion; Hyperresonant=pneumothorax"),
        ("Auscultation:", "Vesicular vs bronchial; crackles, wheeze, pleural rub"),
    ], GREEN, LGREEN)
))
story.append(sp(4))

story.append(card("Deep Tendon Reflexes — Nerve Roots", [
    ("Biceps C5,C6:", "Strike biceps tendon  →  elbow flexion"),
    ("Triceps C7,C8:", "Strike triceps tendon  →  elbow extension"),
    ("Knee L3,L4:", "Strike patellar tendon  →  knee extension"),
    ("Ankle S1,S2:", "Strike Achilles tendon  →  plantar flexion"),
    ("Plantar L5,S1:", "Normal = toe flexion  |  Babinski sign = dorsiflexion of big toe (UMN lesion)"),
    ("Grading:", "0=absent · 1+=diminished · 2+=normal · 3+=brisk · 4+=clonus"),
], TEAL, LTEAL))
story.append(sp(4))

story.append(two(
    slim("UMN vs LMN Lesion", [
        ("UMN:", "↑ tone (spastic), ↑ reflexes, Babinski +, no wasting"),
        ("LMN:", "↓ tone (flaccid), ↓/absent reflexes, wasting, fasciculation, Babinski –"),
        "UMN = lesion above anterior horn cell",
        "LMN = anterior horn cell or peripheral nerve",
    ], RED, LRED),
    slim("Cranial Nerve Quick Reference", [
        ("I Olfactory:", "Smell  |  II Optic: Vision  |  III/IV/VI: Eye movements"),
        ("V Trigeminal:", "Facial sensation + mastication  |  VII Facial: Expression"),
        ("VIII Vestibulocochlear:", "Hearing + balance"),
        ("IX/X:", "Gag reflex, swallowing, voice  |  XI: SCM/trapezius"),
        ("XII Hypoglossal:", "Tongue movement — deviation to side of lesion"),
    ], ORANGE, LORANGE)
))
story.append(sp(6))

story.append(banner("2B · CLINICAL MINOR  (5 Marks)", colors.HexColor("#00796B")))
story.append(sp(4))

story.append(two(
    slim("Pulse Examination — 7 Characters", [
        ("1 Rate:", "Normal 60–100 bpm"),
        ("2 Rhythm:", "Regular / irregular (AF = irregularly irregular)"),
        ("3 Volume:", "Full / weak / thready / collapsing (AR = water hammer)"),
        ("4 Character:", "Slow-rising (AS)  |  Bisferiens (mixed AS+AR)"),
        ("5 Vessel wall:", "Thickened in arteriosclerosis (pipe-stem)"),
        ("6 Radioradial delay:", "Subclavian stenosis / coarctation"),
    ], TEAL, LTEAL),
    slim("Blood Pressure — Key Values & Method", [
        ("Normal:", "120/80 mmHg"),
        ("Hypertension:", "≥140/90 mmHg"),
        ("Korotkoff I:", "First tapping sound = SYSTOLIC BP"),
        ("Korotkoff V:", "Complete disappearance of sound = DIASTOLIC BP"),
        ("Pulse pressure:", "SBP – DBP = Normal ~40 mmHg"),
        ("MAP:", "DBP + 1/3 × (SBP–DBP) = Normal 70–100 mmHg"),
    ], BLUE, LBLUE)
))
story.append(sp(4))

story.append(card("Superficial Reflexes & Light Reflex", [
    ("Corneal:", "Afferent CN V  |  Efferent CN VII  →  blink response"),
    ("Gag:", "Afferent CN IX  |  Efferent CN X  →  pharyngeal contraction"),
    ("Abdominal T8–T12:", "Scratch abdominal wall  →  umbilicus moves toward stimulus"),
    ("Cremasteric L1,L2:", "Thigh stroke  →  testicular retraction"),
    ("Light reflex:", "CN II afferent  |  CN III efferent  →  direct + consensual pupil constriction"),
], TEAL, LTEAL))
story.append(sp(6))

story.append(banner("2C · TWO HUMAN EXPERIMENTS  (20 Marks — 10 each)", colors.HexColor("#004D40")))
story.append(sp(4))

story.append(card("CVS Experiments", [
    ("BP Postural:", "Measure lying → sitting → standing; postural hypotension = >20 mmHg drop in SBP on standing"),
    ("Cold Pressor Test:", "Hand in ice water 1–2 min  →  ↑ BP + ↑ HR (sympathetic activation)"),
    ("Valsalva Maneuver:", "Forced expiration vs closed glottis  →  ↑ intrathoracic pressure  →  ↓ venous return  →  ↓ BP  →  reflex ↑ HR"),
    ("Exercise Test:", "Measure HR+BP before, immediately after, and at 5-min recovery; SBP ↑ proportional to workload"),
], GREEN, LGREEN))
story.append(sp(4))

story.append(card("Respiratory & Neurological Experiments", [
    ("Vital Capacity:", "Spirometer; max inspiration then max expiration; Normal M: 4–5 L  |  F: 3–4 L"),
    ("Breath-Holding:", "Normal 30–60 sec; reduced in lung disease; terminated by rising CO₂"),
    ("PEFR:", "Peak flow meter; Normal M: 500–700 L/min  |  F: 350–500 L/min; reduced in obstruction"),
    ("Visual Acuity:", "Snellen chart at 6 metres; Normal 6/6 (20/20)"),
    ("Weber / Rinne:", "Weber lateralises to affected ear in conductive loss; Rinne: AC>BC = normal, BC>AC = conductive loss"),
    ("Two-point discrimination:", "Fingertip 2–4 mm; back 40–70 mm; tests sensory cortical resolution"),
], TEAL, LTEAL))
story.append(sp(4))

story.append(card("Experiment Write-Up Format (Marks Awarded Per Section)", [
    "1. Title of the experiment",
    "2. Aim / Objective",
    "3. Materials required",
    "4. Method / Procedure (numbered steps)",
    "5. Observations — table of before/after values with units",
    "6. Results — graph or chart if applicable",
    "7. Discussion — physiological basis (highest mark allocation)",
    "8. Conclusion — 1 to 2 sentences summarising findings",
], GREEN, LGREEN))
story.append(sp(4))
story.append(PageBreak())

# ─── SECTION 3: THEORY VIVA ───────────────────────────────────────────────────
story.append(banner("SECTION 3: THEORY VIVA  (20 Marks) — ALL SYSTEMS", NAVY,
    "Examiners ask 2–3 questions from different systems  •  Prepare each system for 10 key points"))
story.append(sp(5))

story.append(banner("CARDIOVASCULAR SYSTEM", BLUE))
story.append(sp(4))

story.append(two(
    slim("Cardiac Output & Starling's Law", [
        ("CO = HR × SV:", "Normal ~5 L/min at rest"),
        ("Starling's Law:", "↑ preload (EDV)  →  ↑ SV  →  ↑ CO (up to limit)"),
        ("Factors ↑ CO:", "Exercise, fever, pregnancy, anaemia, anxiety"),
        ("Factors ↓ CO:", "Cardiogenic shock, cardiac tamponade, heart failure"),
        ("EF:", "SV/EDV × 100%; Normal >55%; <40% = systolic dysfunction"),
    ], BLUE, LBLUE),
    slim("ECG — Normal Intervals", [
        ("P wave:", "<0.12 sec (3 small squares) — atrial depolarisation"),
        ("PR interval:", "0.12–0.20 sec — AV node conduction"),
        ("QRS:", "<0.12 sec — ventricular depolarisation"),
        ("QT:", "<0.44 sec (QTc corrected) — ventricular repolarisation"),
        ("PR prolonged:", "AV block  |  QRS widened: bundle branch block"),
        ("ST elevation:", "STEMI  |  ST depression: ischaemia / NSTEMI"),
    ], TEAL, LTEAL)
))
story.append(sp(4))

story.append(card("Blood Pressure Regulation — Short & Long Term", [
    ("Short-term baroreceptors:", "Carotid sinus + aortic arch  →  medullary CV centre  →  ANS adjustment within seconds"),
    ("Long-term RAAS:", "Renin (kidney)  →  Angiotensin I  →  ACE (lung)  →  Angiotensin II  →  Aldosterone  →  Na⁺/water retention  →  ↑ BP"),
    ("ADH:", "Released when osmolality ↑ or volume ↓; water retention in collecting duct"),
    ("ANP:", "Released by atria when stretched; ↑ natriuresis; opposes RAAS; ↓ BP"),
], BLUE, LBLUE))
story.append(sp(5))

story.append(banner("RESPIRATORY SYSTEM", GREEN))
story.append(sp(4))

story.append(two(
    slim("O₂ & CO₂ Transport", [
        ("O₂ Transport:", "97% as oxyhaemoglobin  |  3% dissolved in plasma"),
        ("CO₂ Transport:", "70% as bicarbonate  |  23% carbaminoHb  |  7% dissolved"),
        ("Oxyhaemoglobin curve RIGHT:", "↑CO₂, ↑H⁺, ↑temp, ↑2,3-DPG  →  ↓Hb affinity for O₂"),
        ("LEFT shift:", "↓CO₂, fetal Hb, CO poisoning  →  ↑ Hb affinity"),
        ("P50:", "PO₂ at 50% saturation = 26 mmHg (normal)"),
    ], GREEN, LGREEN),
    slim("Control of Breathing", [
        ("Central chemoreceptors:", "Medulla; detect ↑ CO₂ / ↓ pH in CSF; primary drive"),
        ("Peripheral chemoreceptors:", "Carotid+aortic bodies; detect ↓ PaO₂ (<60 mmHg), ↑CO₂, ↓pH"),
        ("COPD:", "Hypoxic drive takes over if chronic CO₂ retention"),
        ("Hering-Breuer:", "Lung inflation activates stretch receptors  →  inhibits inspiration"),
    ], TEAL, LTEAL)
))
story.append(sp(5))

story.append(banner("RENAL SYSTEM", BLUE))
story.append(sp(4))

story.append(card("GFR, Clearance & Tubular Functions", [
    ("Normal GFR:", "125 mL/min  |  180 L filtered/day  |  ~1.5 L urine/day"),
    ("Inulin clearance:", "Gold standard for GFR (freely filtered, not reabsorbed or secreted)"),
    ("Creatinine clearance:", "Clinical estimate of GFR; slightly overestimates due to tubular secretion"),
    ("Glucose Tm:", "320 mg/min; glycosuria when plasma glucose >180 mg/dL (renal threshold)"),
    ("Max urine concentration:", "1200 mOsm/kg (countercurrent mechanism, loop of Henle + medullary interstitium)"),
    ("ADH:", "↑ water permeability of collecting duct  →  concentrated urine"),
    ("Aldosterone:", "↑ Na⁺ reabsorption + K⁺ secretion in distal tubule / collecting duct"),
], BLUE, LBLUE))
story.append(sp(5))

story.append(banner("NERVOUS SYSTEM", NAVY))
story.append(sp(4))

story.append(two(
    slim("Action Potential — Ionic Basis", [
        ("RMP:", "–70 mV inside negative; maintained by Na⁺/K⁺ ATPase (3 Na⁺ out, 2 K⁺ in)"),
        ("Depolarisation:", "Na⁺ rushes IN via voltage-gated channels  →  +30 mV"),
        ("Repolarisation:", "K⁺ rushes OUT  →  returns to –70 mV"),
        ("Hyperpolarisation:", "Briefly <–70 mV (relative refractory period)"),
        ("Saltatory conduction:", "Myelinated fibres; faster; node of Ranvier"),
    ], NAVY, LBLUE),
    slim("Ascending & Descending Tracts", [
        ("Dorsal column:", "Fine touch, vibration, proprioception; crosses at medulla; ipsilateral cord"),
        ("Spinothalamic:", "Pain and temperature; crosses at cord level; contralateral"),
        ("Corticospinal:", "Voluntary movement; crosses at pyramidal decussation in medulla"),
        ("Cerebellar tracts:", "Coordination and balance; ipsilateral cerebellum"),
        "Upper cord lesion  →  UMN signs below; contralateral pain/temp loss",
    ], PURPLE, LPURPLE)
))
story.append(sp(4))

story.append(card("Autonomic Nervous System — Key Effects", [
    ("SNS (sympathetic):", "↑ HR, ↑ BP, bronchodilation, mydriasis, ↓ gut motility, glycogenolysis, sweating"),
    ("PNS (parasympathetic):", "↓ HR, bronchoconstriction, ↑ gut motility, miosis, ↑ glandular secretions"),
    ("SNS transmitter:", "Noradrenaline (norepinephrine)  |  Receptors: α1 (vasoconstriction), β1 (heart ↑), β2 (bronchodilation)"),
    ("PNS transmitter:", "Acetylcholine  |  Receptors: M (muscarinic) at effectors; N (nicotinic) at ganglia + NMJ"),
], NAVY, LBLUE))
story.append(sp(5))

story.append(banner("ENDOCRINE SYSTEM", PURPLE))
story.append(sp(4))

story.append(two(
    slim("Insulin vs Glucagon", [
        ("Insulin (β cells):", "Released by ↑ blood glucose + amino acids"),
        "Actions: ↑ glucose uptake (GLUT4 in muscle/fat), glycogen synthesis, protein + fat synthesis",
        ("Glucagon (α cells):", "Released by ↓ blood glucose"),
        "Actions: glycogenolysis, gluconeogenesis, lipolysis",
        "Insulin:glucagon ratio determines fed vs fasting state",
    ], PURPLE, LPURPLE),
    slim("Thyroid Hormones", [
        ("Synthesis:", "Thyroglobulin + I₂ + TPO  →  T3 (active) + T4 (prohormone)"),
        ("Actions:", "↑ BMR, growth, CNS development, HR, thermogenesis"),
        ("Hypothyroid:", "↓ BMR, weight gain, cold intolerance, bradycardia, myxoedema"),
        ("Hyperthyroid:", "↑ BMR, weight loss, heat intolerance, tachycardia, exophthalmos"),
        ("Control:", "TRH → TSH → T3/T4 → negative feedback to hypothalamus + pituitary"),
    ], TEAL, LTEAL)
))
story.append(sp(5))

story.append(banner("BLOOD & HAEMOSTASIS", RED))
story.append(sp(4))

story.append(card("Coagulation Cascade — Simplified", [
    ("Extrinsic pathway:", "Tissue factor (TF) + Factor VII  →  activates Factor X"),
    ("Intrinsic pathway:", "FXII  →  XI  →  IX  →  VIII  →  activates Factor X"),
    ("Common pathway:", "FX + FV  →  prothrombin  →  thrombin  →  fibrinogen  →  fibrin clot"),
    ("PT (prothrombin time):", "Tests extrinsic + common pathway (Factors II, V, VII, X)  |  ↑ in warfarin, Vit K deficiency"),
    ("aPTT:", "Tests intrinsic + common pathway (Factors VIII, IX, XI, XII)  |  ↑ in haemophilia"),
    ("Anticoagulants:", "Heparin: activates antithrombin III (immediate)  |  Warfarin: blocks Vit K (Factors II, VII, IX, X)"),
], RED, LRED))
story.append(sp(5))

story.append(banner("DIGESTIVE & REPRODUCTIVE SYSTEMS", ORANGE))
story.append(sp(4))

story.append(two(
    slim("GI Hormones", [
        ("Gastrin (G cells, antrum):", "↑ HCl, ↑ pepsinogen; stimulated by protein + vagus"),
        ("Secretin (S cells, duodenum):", "↑ pancreatic HCO₃⁻; stimulated by acid in duodenum"),
        ("CCK (I cells, duodenum):", "↑ pancreatic enzymes + gallbladder contraction; fat + protein stimulus"),
        ("GIP:", "Inhibits gastric acid; stimulates insulin release"),
        ("Fat absorption:", "Chylomicrons  →  lacteals  →  thoracic duct  →  blood"),
    ], ORANGE, LORANGE),
    slim("Reproductive System — Quick Facts", [
        ("Menstrual cycle:", "Day 1–14: follicular (FSH → follicle); Day 14: LH surge → ovulation; Day 15–28: luteal (progesterone)"),
        ("Spermatogenesis:", "72 days; spermatogonia → primary SC → secondary SC → spermatid → sperm"),
        ("hCG:", "Produced by trophoblast; maintains corpus luteum in 1st trimester"),
        ("Pregnancy hormones:", "Placenta produces oestrogen + progesterone from 10 weeks onward"),
    ], GREEN, LGREEN)
))
story.append(sp(4))
story.append(PageBreak())

# ─── CHEAT SHEET PAGE ─────────────────────────────────────────────────────────
story.append(banner("EXAM DAY CHEAT SHEET  —  CRITICAL NUMBERS AT A GLANCE", GOLD))
story.append(sp(5))

story.append(tbl(
    ["Parameter", "Normal Value", "Parameter", "Normal Value"],
    [
        ["Hb (Male)",        "13–17 g/dL",        "BP (Normal)",          "120/80 mmHg"],
        ["Hb (Female)",      "12–15 g/dL",        "Heart Rate",           "60–100 bpm"],
        ["WBC",              "4,000–11,000/mm³",  "Respiratory Rate",     "14–20 /min"],
        ["Platelets",        "1.5–4 lakh/mm³",    "SpO₂",                "95–100%"],
        ["MCV",              "80–100 fL",          "Temperature (oral)",   "36.1–37.2°C"],
        ["ESR (M/F)",        "0–15 / 0–20 mm/hr", "Cardiac Output",       "5 L/min"],
        ["Bleeding Time",    "1–6 min (Duke)",     "GFR",                  "125 mL/min"],
        ["Clotting Time",    "3–8 min (cap)",      "Vital Capacity (M)",   "4–5 L"],
        ["FBS glucose",      "70–110 mg/dL",       "FEV₁/FVC normal",     ">80%"],
        ["PR interval",      "0.12–0.20 sec",      "QRS width",            "<0.12 sec"],
        ["P50 (Hb-O₂)",     "~26 mmHg",           "Pulse pressure",       "~40 mmHg"],
        ["Inulin Cl",        "= GFR (125 mL/min)", "Max urine conc.",      "1200 mOsm/kg"],
    ],
    widths=[110, 82, 145, CONTENT_W-337], hc=NAVY))
story.append(sp(6))

story.append(card("Mark-wise Priority for Exam Day", [
    ("20 marks — Human Experiments:", "Know procedure + write full discussion with physiology"),
    ("15 marks — Hematology Major:", "CBC interpretation, blood grouping, Sahli's Hb estimation"),
    ("15 marks — Clinical Major:", "IPPA for CVS, respiratory, neurological examination"),
    ("20 marks — Theory Viva:", "10 key points per system × 8 systems"),
    ("10 marks — Amphibian Chart:", "Stannius ligature + NM preparation tracings (label correctly)"),
    (" 5 marks — Problem Chart:", "4-step approach; anemia pattern from memory"),
    (" 5 marks — Endocrine Chart:", "Hormone deficiency/excess table; lung volume numbers"),
    (" 5 marks — Hematology Minor:", "BT, CT, ESR — normal values + correct method name"),
    (" 5 marks — Clinical Minor:", "BP Korotkoff sounds + 7 characteristics of pulse"),
], GOLD, LGOLD))
story.append(sp(6))

story.append(Paragraph(
    "All the best for your exam!",
    PS("GL", bold=True, size=18, color=NAVY, align=TA_CENTER)))
story.append(sp(4))
story.append(Paragraph(
    "Physiology Practical Flashcards  •  100 Marks  •  All Systems",
    PS("FL", size=9, color=GREY, align=TA_CENTER)))

# ── Build ──────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"Created: {OUTPUT}")
print(f"Size: {os.path.getsize(OUTPUT)/1024:.1f} KB")
Running Command

rm /home/daytona/workspace/physiology-study-guide/create_flashcards.py

This is a shared conversation. Sign in to Orris to start your own chat.