Telogen Effluvium

Reading File
Finding Sources
Searching PubMed

"telogen effluvium"[MeSH Terms] AND diagnosis

Searching Images

telogen effluvium hair loss clinical

This composite of four images demonstrates clinical and diagnostic findings of Hair Loss After SARS-CoV-2 Infection (HLASCI), characterized as telogen effluvium (TE). (a) Clinical photograph of the frontal scalp of a 57-year-old female showing diffuse thinning and decreased hair density with visible short, regrowing hairs at the hairline. (b) Trichoscopic image (magnified view) of the scalp showing upright regrowing hairs alongside vacant follicular ostia (yellowish dots), which represent empty follicles in the telogen phase. (c) Photomicrograph of shed hairs highlighting terminal hair shafts with tapered tips. (d) Clinical photograph showing clumps of shed hairs with bulbous, club-shaped roots characteristic of telogen hair follicles. Collectively, these images illustrate the typical progression and diagnostic features of post-viral telogen effluvium, including the synchronization of the hair cycle into the shedding phase and subsequent early regrowth. The presentation is relevant for dermatology education regarding secondary hair loss following systemic inflammatory stress or 'cytokine storms' associated with COVID-19.

This composite of four images demonstrates clinical and diagnostic findings of Hair Loss After SARS-CoV-2 Infection (HLASCI), characterized as telogen effluvium (TE). (a) Clinical photograph of the frontal scalp of a 57-year-old female showing diffuse thinning and decreased hair density with visible short, regrowing hairs at the hairline. (b) Trichoscopic image (magnified view) of the scalp showing upright regrowing hairs alongside vacant follicular ostia (yellowish dots), which represent empty follicles in the telogen phase. (c) Photomicrograph of shed hairs highlighting terminal hair shafts with tapered tips. (d) Clinical photograph showing clumps of shed hairs with bulbous, club-shaped roots characteristic of telogen hair follicles. Collectively, these images illustrate the typical progression and diagnostic features of post-viral telogen effluvium, including the synchronization of the hair cycle into the shedding phase and subsequent early regrowth. The presentation is relevant for dermatology education regarding secondary hair loss following systemic inflammatory stress or 'cytokine storms' associated with COVID-19.

Imaging modality: Clinical photography; macroscopic close-up of hair fragments collected from the scalp to illustrate anagen effluvium. Primary subject: Hair shafts showing abrupt shedding during the anagen phase. Specimen: Hair sample (scalp) arranged on a blue background for contrast. Perspective: Macroscopic, top-down view focusing on hair shaft morphology. Anatomical location: Scalp hair shafts as the source of the specimens. In terms of technique, high-resolution digital photography was used with diffuse lighting to minimize glare; no staining or contrast agents were applied. Magnification: Macro level (approximately 2–5x) to reveal hair shaft integrity and cuticle; acquisition parameters not provided. Observed features: Dark, bundled hair shafts with varying lengths, some with abrupt ends and frayed cuticles; minimal to no root visible. The sample demonstrates a rapid shedding pattern typical of anagen effluvium. The image documents anagen effluvium—a rapid loss of growing hair often linked to chemotherapy or toxin exposure. Notable features include uniform shedding of anagen hairs with preserved follicular openings and minimal inflammation on the specimen level. Diagnostic significance: Supports diagnosis of drug-induced hair loss and distinguishes from telogen effluvium or alopecia areata. Differential considerations: Telogen effluvium, chemotherapy-related damage, radiation-induced hair loss. Clinical correlation: Useful in dermatology, oncology, and trichology to assess severity, monitor response to cytotoxic therapy, and guide counseling.

Imaging modality: Clinical photography; macroscopic close-up of hair fragments collected from the scalp to illustrate anagen effluvium. Primary subject: Hair shafts showing abrupt shedding during the anagen phase. Specimen: Hair sample (scalp) arranged on a blue background for contrast. Perspective: Macroscopic, top-down view focusing on hair shaft morphology. Anatomical location: Scalp hair shafts as the source of the specimens. In terms of technique, high-resolution digital photography was used with diffuse lighting to minimize glare; no staining or contrast agents were applied. Magnification: Macro level (approximately 2–5x) to reveal hair shaft integrity and cuticle; acquisition parameters not provided. Observed features: Dark, bundled hair shafts with varying lengths, some with abrupt ends and frayed cuticles; minimal to no root visible. The sample demonstrates a rapid shedding pattern typical of anagen effluvium. The image documents anagen effluvium—a rapid loss of growing hair often linked to chemotherapy or toxin exposure. Notable features include uniform shedding of anagen hairs with preserved follicular openings and minimal inflammation on the specimen level. Diagnostic significance: Supports diagnosis of drug-induced hair loss and distinguishes from telogen effluvium or alopecia areata. Differential considerations: Telogen effluvium, chemotherapy-related damage, radiation-induced hair loss. Clinical correlation: Useful in dermatology, oncology, and trichology to assess severity, monitor response to cytotoxic therapy, and guide counseling.

This composite clinical photograph illustrates the 'acute telogen effluvium triad' following resolution, specifically in a patient post-weight loss. Image A (frontal view) demonstrates a 'frontal fringe' composed of short, regrowing hairs along the anterior hairline. Image B (lateral view) shows bitemporal rarefaction, characterized by a visible decrease in hair density and thinning of hair shafts in the temporal region, making the scalp more prominent. Image C (posterior view) displays an 'occipital fringe,' where hair regrowth is evident through varying hair lengths and thicknesses in the occipital region. Collectively, these images highlight the characteristic clinical signs of hair recovery after a telogen effluvium event. The material is intended for intermediate to advanced medical learners in dermatology, demonstrating the differential diagnosis between active hair loss and clinical signs of recovery/regrowth.

This composite clinical photograph illustrates the 'acute telogen effluvium triad' following resolution, specifically in a patient post-weight loss. Image A (frontal view) demonstrates a 'frontal fringe' composed of short, regrowing hairs along the anterior hairline. Image B (lateral view) shows bitemporal rarefaction, characterized by a visible decrease in hair density and thinning of hair shafts in the temporal region, making the scalp more prominent. Image C (posterior view) displays an 'occipital fringe,' where hair regrowth is evident through varying hair lengths and thicknesses in the occipital region. Collectively, these images highlight the characteristic clinical signs of hair recovery after a telogen effluvium event. The material is intended for intermediate to advanced medical learners in dermatology, demonstrating the differential diagnosis between active hair loss and clinical signs of recovery/regrowth.

This clinical photograph provides a superior view of the human scalp, demonstrating the clinical presentation of telogen effluvium during the recovery phase. The patient exhibits dark, terminal hair coverage across the majority of the scalp. While hair density has significantly improved, visible thinning remains prominent at the vertex and mid-scalp regions, where the underlying scalp skin is partially visible through the hair shafts. This diffuse thinning pattern is characteristic of systemic stress-induced hair loss, such as that following severe viral infection or hospitalization. The image illustrates the gradual process of hair follicle re-entry into the anagen phase, showing substantial regrowth and volume restoration compared to acute stages of alopecia. This visual is an important educational resource for dermatology and internal medicine, highlighting the natural history and favorable prognosis of post-inflammatory telogen effluvium.

This clinical photograph provides a superior view of the human scalp, demonstrating the clinical presentation of telogen effluvium during the recovery phase. The patient exhibits dark, terminal hair coverage across the majority of the scalp. While hair density has significantly improved, visible thinning remains prominent at the vertex and mid-scalp regions, where the underlying scalp skin is partially visible through the hair shafts. This diffuse thinning pattern is characteristic of systemic stress-induced hair loss, such as that following severe viral infection or hospitalization. The image illustrates the gradual process of hair follicle re-entry into the anagen phase, showing substantial regrowth and volume restoration compared to acute stages of alopecia. This visual is an important educational resource for dermatology and internal medicine, highlighting the natural history and favorable prognosis of post-inflammatory telogen effluvium.

Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Loading Image
Now I have everything needed for a thorough response.

Telogen Effluvium (TE)

Definition

Telogen effluvium is an acute or chronic diffuse, non-scarring hair loss caused by a premature or excessive shift of hair follicles from the anagen (growth) phase into the telogen (resting/shedding) phase. The result is an abnormal increase in club hair shedding, typically involving the entire scalp. - Fitzpatrick's Dermatology, p. 1537

Hair Cycle - Background

Under normal conditions:
  • A full scalp contains approximately 100,000 hair follicles
  • About 10% are in telogen at any given time
  • Normal daily loss = 100-150 hairs/day
  • In TE, daily loss rises to 150-400+ hairs/day

Pathophysiology: Five Mechanisms (Kligman's Classification)

MechanismDescriptionExample
Immediate anagen releaseAbrupt, premature conversion of anagen → telogenFebrile illness, childbirth, surgery
Delayed anagen releaseProlonged anagen (as in pregnancy), mass release after trigger resolvesPostpartum TE, 2-3 months after delivery
Short anagenIntrinsically shortened anagen phase; more hairs cycling into telogen constantlyChronic TE, androgenetic alopecia
Immediate telogen releasePremature exit from telogen to initiate anagenTopical minoxidil (transient early shedding)
Delayed telogen releaseProlonged telogen; synchronous delayed sheddingSeasonal shedding
  • Andrews' Diseases of the Skin, p. 870

Etiology and Triggers

Physiological

  • Postpartum (telogen gravidarum): Most widely recognized form. Anagen rate rises to ~94% during pregnancy; telogen rate increases to ~25% at 6 weeks postpartum. Shedding peaks 2-3 months after delivery.
  • Neonatal TE: Physiologic shedding in infants begins within 4 months of birth; telogen counts can reach 60-80%. Self-resolves by 6 months.

Medical / Systemic

  • Febrile illness: High fever stresses matrix cells and causes early anagen release. Post-COVID-19 TE is a well-recognized modern example.
  • Major surgery (including rhytidectomy, which can cause localized TE)
  • Thyroid disease: Hypothyroidism is the most established association - more often causes chronic diffuse telogen hair loss (CDTHL) than acute TE. Hair regrowth begins ~8 weeks after thyroid hormone replacement.
  • Iron deficiency (low ferritin/saturation - serves as a marker of overall nutritional status)
  • Renal dialysis with secondary hypervitaminosis A
  • Allergic contact dermatitis to hair dyes

Nutritional

  • Crash dieting / severe calorie restriction: Weight loss of ~12-25 kg over 3 weeks to 3 months can raise telogen counts to 25-50%.
  • Protein deficiency, iron deficiency, other micronutrient deficits

Drugs (Drug-induced TE)

Aminosalicylic acid, amphetamines, bromocriptine, captopril, carbamazepine, cimetidine, coumarin, danazol, enalapril, etretinate, levodopa, lithium carbonate, metoprolol, metyrapone, pramipexole, propranolol, pyridostigmine, trimethadione

Psychological

  • Severe emotional or psychological stress/trauma
  • Trichodynia (scalp pain/dysesthesia) is a common associated symptom and may coexist with depression, anxiety, or obsessive personality traits.
  • Andrews' Diseases of the Skin, p. 870-871

Anagen vs. Telogen Hair - Key Morphology

Anagen hair (left) has a pigmented bulb surrounded by a gelatinous root sheath. Telogen hair (right) has a non-pigmented, club-shaped bulb with no root sheath.
Fig: Anagen hair (left) - pigmented bulb with root sheath. Telogen hair (right) - non-pigmented club bulb, no sheath. - Andrews' Diseases of the Skin, Fig. 33.3

Clinical Features

  • Diffuse hair shedding across the entire scalp (not patchy)
  • Hair lost "at the root" - each shed hair shows a depigmented, club-shaped bulb with no sheath
  • Bitemporal recession is frequently noted, especially in chronic TE
  • Shedding typically begins 3-5 months after the precipitating event
  • The scalp itself appears normal - no erythema, scaling, or scarring
  • Patients may complain of hair blocking the shower drain or filling bags of shed hair

Clinical Images

Post-COVID telogen effluvium: (a) frontal thinning with short regrowing hairs, (b) trichoscopic view showing vacant follicles and regrowing hairs, (c) terminal hairs with tapered tips, (d) shed hairs with bulbous club-shaped roots
Post-viral TE (post-COVID): diffuse thinning, vacant follicular ostia, and characteristic club-shaped shed hairs
Acute telogen effluvium triad during recovery after weight loss: frontal fringe (A), bitemporal rarefaction (B), occipital fringe (C) of regrowing hairs
Recovery phase: "frontal fringe" and "occipital fringe" of new regrowing hairs are characteristic signs of resolving TE

Diagnosis

1. Pull Test

  • Grasp ~40 hairs firmly, apply a slow, firm pull
  • Normal: 0-4 club hairs dislodged
  • Abnormal: >4-6 club hairs (on an unshampooed scalp); >2-3 on a freshly shampooed scalp
  • Result varies by phase of TE (active vs. resolving)

2. Clip Test

  • 25-30 hairs cut just above the scalp surface and mounted
  • Telogen/indeterminate hairs appear short and of small diameter

3. Trichogram

  • 50 hairs plucked with a Kelly clamp
  • Provides anagen:telogen ratio
  • Telogen counts of 64-87% reported in neonatal TE

4. Scalp Biopsy (4 mm punch, horizontal sections)

  • 25-50 hairs normally present
  • >12-15% of terminal follicles in telogen = significant anagen-to-telogen shift
  • Distinguishes from androgenetic alopecia (miniaturization + variable shaft diameter) and trichotillomania (pigment casts, trichomalacia, catagen hairs)

5. Laboratory Workup (for prolonged or unclear cases)

  • Serum ferritin and iron saturation
  • Thyroid function tests (TSH, free T4)
  • CBC, metabolic panel
  • Nutritional markers if indicated
  • Andrews' Diseases of the Skin, p. 870-871

Differential Diagnosis

ConditionDistinguishing Features
Androgenetic alopeciaPatterned distribution; miniaturization on biopsy
Diffuse alopecia areataPersonal/family hx of AA; nail changes; body hair loss
Central centrifugal cicatricial alopeciaVertex scarring; women of African descent
Frontal fibrosing alopeciaBand-like frontotemporal scarring; eyebrow loss
Traction alopeciaHistory of tight braiding/tension
Hypotrichosis simplexEarly childhood onset; progressive; no skin/nail changes
  • Fitzpatrick's Dermatology, Table 85-1

Chronic Telogen Effluvium (CTE)

CTE is an idiopathic variant first characterized by Whiting in a cohort of 355 patients (346 women, 9 men):
  • Affects women predominantly in the 4th-6th decade
  • Abrupt onset with large amounts of shed hair; fluctuating long course (>6 months to years)
  • Associated with bitemporal recession
  • Patients often had intrinsically denser-than-average hair before onset, capable of growing very long hair in childhood (suggesting intrinsically prolonged anagen)
  • Pathophysiology: shortened anagen phase rather than acute trigger
  • 5% minoxidil solution may help in this form
  • Fitzpatrick's Dermatology, p. 1538; Andrews' Diseases of the Skin, p. 871

Management

Acute / Self-Limiting TE

  • No specific treatment is required in most cases
  • The condition resolves spontaneously within 3-6 months once the trigger resolves
  • If drug-induced: discontinue the offending agent
  • If papulosquamous scalp disease is present (e.g., seborrheic dermatitis): treat the underlying scalp condition

Nutritional Correction

  • Correct identified deficiencies (iron, protein, vitamins)
  • Encourage a balanced, varied diet
  • Investigate sources of blood loss (menstrual, GI) if iron is low
  • Note: iron replacement alone did not resolve TE in one study - likely a marker for broader nutritional status

Thyroid Disease

  • Thyroid hormone replacement in hypothyroidism → hair regrowth observed by ~8 weeks

Chronic TE

  • 5% topical minoxidil (may help by shortening telogen to trigger anagen entry)
  • Address any reversible underlying factors

Patient Counseling

  • Prognosis is excellent when a clear precipitating event is identified
  • Reassure patients that the follicles are intact and hair will regrow
  • Trichodynia is common and may need separate attention if significant

Summary Table: Acute vs. Chronic TE

FeatureAcute TEChronic TE (CTE)
Duration<6 months>6 months, fluctuating
TriggerIdentifiable (illness, surgery, delivery)Idiopathic
DemographicsAny age, genderWomen, 4th-6th decade
MechanismPremature anagen releaseShortened anagen phase
Pull testDiffusely positivePositive at vertex/occiput
TreatmentTreat cause; reassure5% minoxidil
PrognosisExcellent, full regrowthFluctuating; may persist

Sources: Fitzpatrick's Dermatology (9780071837781), Andrews' Diseases of the Skin (9780323547536)

Create a clinical reference PDF on telogen effluvium diagnosis and management

Reading File
Reading File
Running Command

mkdir -p /tmp/workspace/telogen-effluvium && ls /tmp/workspace/telogen-effluvium/

Writing File

~/telogen-effluvium/generate_pdf.py


from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether, ListFlowable, ListItem, PageBreak
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch, mm
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus.flowables import Flowable
import reportlab.rl_config

OUTPUT = "/tmp/workspace/telogen-effluvium/Telogen_Effluvium_Clinical_Reference.pdf"

# ── Colour palette ────────────────────────────────────────────────────────────
C_NAVY      = colors.HexColor("#1B3A5C")   # header / title bar
C_TEAL      = colors.HexColor("#1A7B8C")   # section heading bar
C_TEAL_LITE = colors.HexColor("#E8F5F7")   # section heading bar fill (light)
C_ACCENT    = colors.HexColor("#D4A843")   # gold accent line
C_RED       = colors.HexColor("#C0392B")   # alert / warning
C_GREEN     = colors.HexColor("#27AE60")   # positive/good
C_AMBER     = colors.HexColor("#E67E22")   # caution
C_BG_GREY   = colors.HexColor("#F4F6F8")   # table alt row
C_BG_BLUE   = colors.HexColor("#EBF4F8")   # info box
C_TEXT      = colors.HexColor("#2C3E50")   # body text
C_WHITE     = colors.white
C_HEADER_TXT= colors.HexColor("#E0EEF3")

# ── Page setup ─────────────────────────────────────────────────────────────────
PAGE_W, PAGE_H = A4
L_MARGIN = 18 * mm
R_MARGIN = 18 * mm
T_MARGIN = 20 * mm
B_MARGIN = 20 * mm

# ── Styles ─────────────────────────────────────────────────────────────────────
base = getSampleStyleSheet()

def make_style(name, parent="Normal", **kw):
    s = ParagraphStyle(name, parent=base[parent])
    for k, v in kw.items():
        setattr(s, k, v)
    return s

sTitle       = make_style("sTitle",      "Title",
                           fontName="Helvetica-Bold", fontSize=22,
                           textColor=C_WHITE, alignment=TA_CENTER,
                           spaceAfter=2, spaceBefore=0, leading=26)
sSubtitle    = make_style("sSubtitle",   "Normal",
                           fontName="Helvetica", fontSize=10,
                           textColor=C_HEADER_TXT, alignment=TA_CENTER,
                           spaceAfter=0, leading=14)
sSectionHdr  = make_style("sSectionHdr", "Normal",
                           fontName="Helvetica-Bold", fontSize=11,
                           textColor=C_WHITE, alignment=TA_LEFT,
                           spaceBefore=10, spaceAfter=4, leading=16)
sSubHdr      = make_style("sSubHdr",     "Normal",
                           fontName="Helvetica-Bold", fontSize=9.5,
                           textColor=C_NAVY, alignment=TA_LEFT,
                           spaceBefore=6, spaceAfter=2, leading=13)
sBody        = make_style("sBody",       "Normal",
                           fontName="Helvetica", fontSize=8.5,
                           textColor=C_TEXT, alignment=TA_JUSTIFY,
                           spaceAfter=4, leading=12)
sBodyBold    = make_style("sBodyBold",   "Normal",
                           fontName="Helvetica-Bold", fontSize=8.5,
                           textColor=C_TEXT, alignment=TA_LEFT,
                           spaceAfter=2, leading=12)
sBullet      = make_style("sBullet",     "Normal",
                           fontName="Helvetica", fontSize=8.2,
                           textColor=C_TEXT, alignment=TA_LEFT,
                           leftIndent=10, spaceAfter=2, leading=12)
sTableHdr    = make_style("sTableHdr",   "Normal",
                           fontName="Helvetica-Bold", fontSize=8,
                           textColor=C_WHITE, alignment=TA_CENTER,
                           leading=11)
sTableCell   = make_style("sTableCell",  "Normal",
                           fontName="Helvetica", fontSize=8,
                           textColor=C_TEXT, alignment=TA_LEFT,
                           leading=11)
sTableCellC  = make_style("sTableCellC", "Normal",
                           fontName="Helvetica", fontSize=8,
                           textColor=C_TEXT, alignment=TA_CENTER,
                           leading=11)
sTableCellB  = make_style("sTableCellB", "Normal",
                           fontName="Helvetica-Bold", fontSize=8,
                           textColor=C_TEXT, alignment=TA_LEFT,
                           leading=11)
sAlertRed    = make_style("sAlertRed",   "Normal",
                           fontName="Helvetica-Bold", fontSize=8.5,
                           textColor=C_RED, alignment=TA_LEFT,
                           spaceAfter=2, leading=12)
sFooter      = make_style("sFooter",     "Normal",
                           fontName="Helvetica", fontSize=7,
                           textColor=colors.HexColor("#7F8C8D"),
                           alignment=TA_CENTER, leading=10)
sCaption     = make_style("sCaption",    "Normal",
                           fontName="Helvetica-Oblique", fontSize=7.5,
                           textColor=colors.HexColor("#5D6D7E"),
                           alignment=TA_CENTER, spaceAfter=4, leading=11)
sDrug        = make_style("sDrug",       "Normal",
                           fontName="Helvetica", fontSize=8,
                           textColor=C_TEXT, alignment=TA_LEFT,
                           spaceAfter=2, leading=12)

# ── Helper flowables ────────────────────────────────────────────────────────────
def HR(color=C_ACCENT, width=1.2):
    return HRFlowable(width="100%", thickness=width, color=color, spaceAfter=4, spaceBefore=2)

def section_header(text):
    """Teal background bar with white text used for each major section."""
    tbl = Table([[Paragraph(text, sSectionHdr)]], colWidths=[PAGE_W - L_MARGIN - R_MARGIN])
    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (-1, -1), C_TEAL),
        ("LEFTPADDING",  (0, 0), (-1, -1), 8),
        ("RIGHTPADDING", (0, 0), (-1, -1), 8),
        ("TOPPADDING",   (0, 0), (-1, -1), 5),
        ("BOTTOMPADDING",(0, 0), (-1, -1), 5),
        ("ROUNDEDCORNERS", [4, 4, 4, 4]),
    ]))
    return tbl

def info_box(text, bg=C_BG_BLUE, border=C_TEAL):
    """Coloured info box."""
    tbl = Table([[Paragraph(text, sBody)]], colWidths=[PAGE_W - L_MARGIN - R_MARGIN])
    tbl.setStyle(TableStyle([
        ("BACKGROUND",   (0, 0), (-1, -1), bg),
        ("BOX",          (0, 0), (-1, -1), 1, border),
        ("LEFTPADDING",  (0, 0), (-1, -1), 10),
        ("RIGHTPADDING", (0, 0), (-1, -1), 10),
        ("TOPPADDING",   (0, 0), (-1, -1), 6),
        ("BOTTOMPADDING",(0, 0), (-1, -1), 6),
    ]))
    return tbl

def alert_box(text, bg=colors.HexColor("#FDEDEC"), border=C_RED):
    tbl = Table([[Paragraph(text, sAlertRed)]], colWidths=[PAGE_W - L_MARGIN - R_MARGIN])
    tbl.setStyle(TableStyle([
        ("BACKGROUND",   (0, 0), (-1, -1), bg),
        ("BOX",          (0, 0), (-1, -1), 1, border),
        ("LEFTPADDING",  (0, 0), (-1, -1), 10),
        ("RIGHTPADDING", (0, 0), (-1, -1), 10),
        ("TOPPADDING",   (0, 0), (-1, -1), 6),
        ("BOTTOMPADDING",(0, 0), (-1, -1), 6),
    ]))
    return tbl

def success_box(text, bg=colors.HexColor("#EAFAF1"), border=C_GREEN):
    tbl = Table([[Paragraph(text, sBody)]], colWidths=[PAGE_W - L_MARGIN - R_MARGIN])
    tbl.setStyle(TableStyle([
        ("BACKGROUND",   (0, 0), (-1, -1), bg),
        ("BOX",          (0, 0), (-1, -1), 1, border),
        ("LEFTPADDING",  (0, 0), (-1, -1), 10),
        ("RIGHTPADDING", (0, 0), (-1, -1), 10),
        ("TOPPADDING",   (0, 0), (-1, -1), 6),
        ("BOTTOMPADDING",(0, 0), (-1, -1), 6),
    ]))
    return tbl

def TC(text, style=None, bold=False):
    if style is None:
        style = sTableCellB if bold else sTableCell
    return Paragraph(text, style)

def TH(text):
    return Paragraph(text, sTableHdr)

def build_table(headers, rows, col_widths, alt=True, hdr_color=C_NAVY):
    data = [[TH(h) for h in headers]] + [[TC(c) for c in row] for row in rows]
    style = [
        ("BACKGROUND",    (0, 0), (-1, 0),  hdr_color),
        ("ROWBACKGROUNDS",(0, 1), (-1, -1), [C_WHITE, C_BG_GREY] if alt else [C_WHITE]),
        ("GRID",          (0, 0), (-1, -1), 0.4, colors.HexColor("#BDC3C7")),
        ("VALIGN",        (0, 0), (-1, -1), "TOP"),
        ("LEFTPADDING",   (0, 0), (-1, -1), 5),
        ("RIGHTPADDING",  (0, 0), (-1, -1), 5),
        ("TOPPADDING",    (0, 0), (-1, -1), 4),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 4),
    ]
    t = Table(data, colWidths=col_widths)
    t.setStyle(TableStyle(style))
    return t

# ── Header / Footer callbacks ──────────────────────────────────────────────────
def on_first_page(canvas, doc):
    _draw_header(canvas, doc, first=True)
    _draw_footer(canvas, doc)

def on_later_pages(canvas, doc):
    _draw_header(canvas, doc, first=False)
    _draw_footer(canvas, doc)

def _draw_header(canvas, doc, first=False):
    canvas.saveState()
    if first:
        # Full navy title banner
        banner_h = 58
        canvas.setFillColor(C_NAVY)
        canvas.rect(0, PAGE_H - banner_h, PAGE_W, banner_h, fill=1, stroke=0)
        # Gold accent stripe
        canvas.setFillColor(C_ACCENT)
        canvas.rect(0, PAGE_H - banner_h - 3, PAGE_W, 3, fill=1, stroke=0)
    else:
        # Compact repeat header
        hdr_h = 22
        canvas.setFillColor(C_NAVY)
        canvas.rect(0, PAGE_H - hdr_h, PAGE_W, hdr_h, fill=1, stroke=0)
        canvas.setFillColor(C_ACCENT)
        canvas.rect(0, PAGE_H - hdr_h - 2, PAGE_W, 2, fill=1, stroke=0)
        canvas.setFont("Helvetica-Bold", 9)
        canvas.setFillColor(C_WHITE)
        canvas.drawString(L_MARGIN, PAGE_H - 15, "TELOGEN EFFLUVIUM — Clinical Reference")
        canvas.setFont("Helvetica", 8)
        canvas.setFillColor(C_HEADER_TXT)
        canvas.drawRightString(PAGE_W - R_MARGIN, PAGE_H - 15, f"Page {doc.page}")
    canvas.restoreState()

def _draw_footer(canvas, doc):
    canvas.saveState()
    canvas.setFillColor(colors.HexColor("#ECF0F1"))
    canvas.rect(0, 0, PAGE_W, 16, fill=1, stroke=0)
    canvas.setFillColor(C_ACCENT)
    canvas.rect(0, 16, PAGE_W, 1, fill=1, stroke=0)
    canvas.setFont("Helvetica", 6.5)
    canvas.setFillColor(colors.HexColor("#7F8C8D"))
    canvas.drawString(L_MARGIN, 5, "Sources: Fitzpatrick's Dermatology (9780071837781) | Andrews' Diseases of the Skin (9780323547536) | Dermatology 2-Volume Set 5e (9780702082252)")
    canvas.drawRightString(PAGE_W - R_MARGIN, 5, "For clinical use — verify with current guidelines")
    canvas.restoreState()

# ── Build document ─────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    leftMargin=L_MARGIN,
    rightMargin=R_MARGIN,
    topMargin=T_MARGIN + 45,   # extra top for banner
    bottomMargin=B_MARGIN + 16,
    title="Telogen Effluvium — Clinical Reference",
    author="Orris Medical AI",
    subject="Dermatology — Hair Loss",
)

story = []
SP = Spacer(1, 5)
SP8 = Spacer(1, 8)

# ═══════════════════════════════════════════════════════
# TITLE SECTION  (drawn in canvas; here we just add a spacer)
# ═══════════════════════════════════════════════════════
# We draw the title text directly in the first-page callback
# via a custom Flowable so it sits inside the banner
class TitleFlowable(Flowable):
    def __init__(self):
        Flowable.__init__(self)
        self.width  = PAGE_W - L_MARGIN - R_MARGIN
        self.height = 0  # zero height — rendered above in canvas callback

    def draw(self):
        pass   # actual drawing done in on_first_page

story.append(TitleFlowable())

# We add explicit title paragraphs as the very first story items,
# but place them INSIDE a table so they render nicely in the banner space.
# Actually simpler: just push them to a spacer + paragraphs aligned to top margin.
# The on_first_page callback draws the navy banner behind them.

# Because reportlab draws canvas decorations behind story items, we push
# the title text using normal paragraphs but with navy-background table so
# they visually merge with the canvas banner.
title_block = Table([
    [Paragraph("TELOGEN EFFLUVIUM", sTitle)],
    [Paragraph("Clinical Reference Guide &nbsp;|&nbsp; Diagnosis &amp; Management", sSubtitle)],
    [Paragraph("Dermatology &nbsp;·&nbsp; August 2026", sSubtitle)],
], colWidths=[PAGE_W - L_MARGIN - R_MARGIN])
title_block.setStyle(TableStyle([
    ("BACKGROUND",    (0,0),(-1,-1), C_NAVY),
    ("TOPPADDING",    (0,0),(-1,-1), 4),
    ("BOTTOMPADDING", (0,0),(-1,-1), 4),
    ("LEFTPADDING",   (0,0),(-1,-1), 0),
    ("RIGHTPADDING",  (0,0),(-1,-1), 0),
]))
story.append(title_block)
story.append(Spacer(1, 10))

# ═══════════════════════════════════════════════════════
# 1 — DEFINITION & OVERVIEW
# ═══════════════════════════════════════════════════════
story.append(section_header("1.  DEFINITION & OVERVIEW"))
story.append(SP)
story.append(Paragraph(
    "<b>Telogen effluvium (TE)</b> is an acute or chronic diffuse, <b>non-scarring alopecia</b> caused by a premature or "
    "excessive shift of hair follicles from the <b>anagen</b> (growth) phase into the <b>telogen</b> (resting/shedding) phase, "
    "resulting in abnormal club-hair shedding across the entire scalp.",
    sBody))
story.append(SP)

# Key numbers box
story.append(info_box(
    "<b>Key numbers:</b>&nbsp; Normal scalp ~ 100,000 follicles &nbsp;|&nbsp; ~10% normally in telogen &nbsp;|&nbsp; "
    "Normal daily loss: 100–150 hairs &nbsp;|&nbsp; TE daily loss: 150–400+ hairs"))
story.append(SP8)

# ═══════════════════════════════════════════════════════
# 2 — PATHOPHYSIOLOGY
# ═══════════════════════════════════════════════════════
story.append(section_header("2.  PATHOPHYSIOLOGY — Five Mechanisms (Kligman)"))
story.append(SP)

path_data = [
    ["Mechanism", "Description", "Classic Example"],
    ["Immediate anagen release", "Abrupt premature conversion of anagen → telogen", "Febrile illness, surgery, childbirth"],
    ["Delayed anagen release",   "Prolonged anagen (e.g. pregnancy), mass release after trigger resolves", "Postpartum TE — shedding 2–3 months after delivery"],
    ["Short anagen",             "Intrinsically shortened anagen; more hairs cycling into telogen constantly", "Chronic TE, androgenetic alopecia"],
    ["Immediate telogen release","Premature exit from telogen to initiate anagen", "Topical minoxidil (transient early shedding)"],
    ["Delayed telogen release",  "Prolonged telogen; synchronous delayed shedding", "Seasonal shedding"],
]
story.append(build_table(path_data[0], [r for r in path_data[1:]], [85, 200, 190]))
story.append(SP8)

# ═══════════════════════════════════════════════════════
# 3 — ETIOLOGY & TRIGGERS
# ═══════════════════════════════════════════════════════
story.append(section_header("3.  ETIOLOGY & COMMON TRIGGERS"))
story.append(SP)

story.append(Paragraph("<b>A. Physiological</b>", sSubHdr))
phys = [
    ["Postpartum (Telogen Gravidarum)", "Most widely recognised TE. Anagen rate peaks ~94% in pregnancy; telogen rises ~25% by 6 weeks postpartum. Shedding peaks 2–3 months post-delivery."],
    ["Neonatal TE", "Telogen counts 60–80%; begins within 4 months of birth; resolves spontaneously by 6 months."],
]
story.append(build_table(["Trigger", "Notes"], phys, [130, 345]))
story.append(SP)

story.append(Paragraph("<b>B. Medical / Systemic</b>", sSubHdr))
med = [
    ["Febrile illness / sepsis",   "High fever stresses matrix cells → early anagen release. Post-COVID-19 TE is a current well-recognised example."],
    ["Major surgery",              "Surgery itself or accompanying factors (fever, anaesthesia, hormonal/cytokine changes, nutritional shifts). Rhytidectomy can cause localised TE."],
    ["Hypothyroidism",             "Well-established association. More often causes chronic diffuse telogen hair loss (CDTHL). Hair regrowth begins ~8 weeks after thyroid hormone replacement."],
    ["Iron deficiency",            "Low ferritin / iron saturation. Iron replacement alone may not resolve TE — likely a marker of overall nutritional status."],
    ["Other",                      "Renal dialysis with secondary hypervitaminosis A; allergic contact dermatitis to hair dyes; hyperthyroidism (less clear association)."],
]
story.append(build_table(["Trigger", "Notes"], med, [130, 345]))
story.append(SP)

story.append(Paragraph("<b>C. Nutritional</b>", sSubHdr))
nutr = [
    ["Crash diet / severe calorie restriction", "Weight loss ~12–25 kg over 3 weeks–3 months → telogen counts rise to 25–50%. Classic example shown in Fig 33.4 of Andrews'."],
    ["Protein deficiency",                      "Inadequate dietary protein reduces hair matrix cell proliferation."],
    ["Micronutrient deficiencies",              "Iron, zinc, biotin, vitamin D — assess and correct where identified."],
]
story.append(build_table(["Trigger", "Notes"], nutr, [175, 300]))
story.append(SP)

story.append(Paragraph("<b>D. Drug-induced TE</b>", sSubHdr))
story.append(Paragraph(
    "Aminosalicylic acid, amphetamines, bromocriptine, captopril, carbamazepine, cimetidine, "
    "coumarin, danazol, enalapril, etretinate, levodopa, lithium carbonate, metoprolol, metyrapone, "
    "pramipexole, propranolol, pyridostigmine, trimethadione.", sDrug))
story.append(alert_box("Drug-induced TE: Discontinue the offending agent — this is usually curative."))
story.append(SP8)

# ═══════════════════════════════════════════════════════
# 4 — CLINICAL FEATURES
# ═══════════════════════════════════════════════════════
story.append(section_header("4.  CLINICAL FEATURES"))
story.append(SP)

clin_data = [
    ["Feature", "Detail"],
    ["Pattern",                "Diffuse shedding across entire scalp — NOT patchy"],
    ["Timing",                 "Typically begins 3–5 months after precipitating event"],
    ["Shed hair morphology",   "Depigmented, club-shaped bulb; no root sheath (telogen club hair)"],
    ["Scalp appearance",       "Normal — no erythema, scaling, or scarring"],
    ["Bitemporal recession",   "Frequently noted, especially in chronic TE"],
    ["Trichodynia",            "Scalp pain/dysaesthesia — common; may coexist with anxiety or depression"],
    ["Severity",               "Patient may notice hair blocking shower drain; clumps of shed hair"],
    ["Duration",               "Acute TE: resolves within 3–6 months. Chronic TE: >6 months, fluctuating"],
]
story.append(build_table(clin_data[0], [r for r in clin_data[1:]], [150, 325]))
story.append(SP8)

# ═══════════════════════════════════════════════════════
# 5 — DIAGNOSIS
# ═══════════════════════════════════════════════════════
story.append(section_header("5.  DIAGNOSTIC APPROACH"))
story.append(SP)

story.append(Paragraph("<b>5.1  Clinical Tests</b>", sSubHdr))
diag_data = [
    ["Test", "Method", "Interpretation"],
    ["Pull Test",
     "Grasp ~40 hairs, apply slow firm traction",
     ">4–6 club hairs = abnormal (unshampooed scalp)\n>2–3 club hairs = abnormal (freshly shampooed scalp)"],
    ["Clip Test",
     "Cut 25–30 hairs just above scalp surface, mount",
     "Short, small-diameter hairs = indeterminate/telogen. Many such hairs in TE or pattern alopecia"],
    ["Trichogram",
     "Pluck 50 hairs with rubber-padded Kelly clamp",
     "Provides anagen:telogen ratio. Neonatal TE: telogen ~60–80%"],
    ["Hair Collection Count",
     "Patient collects all shed hairs for 24 h (bed, brush, shower)",
     ">100 hairs/day sustained over time = significant shedding"],
]
story.append(build_table(diag_data[0], [r for r in diag_data[1:]], [75, 165, 235]))
story.append(SP)

story.append(Paragraph("<b>5.2  Scalp Biopsy (4 mm punch, horizontal/transverse sections)</b>", sSubHdr))
bx_data = [
    ["Finding", "Significance"],
    [">12–15% terminal follicles in telogen", "Significant anagen-to-telogen shift — supports TE diagnosis"],
    ["Miniaturisation + variable shaft diameter", "Androgenetic alopecia (key differential)"],
    ["Pigment casts, trichomalacia, catagen hairs", "Traction alopecia / trichotillomania"],
    ["Normal follicle count in transverse section", "25–50 follicles expected per 4 mm punch"],
]
story.append(build_table(bx_data[0], [r for r in bx_data[1:]], [220, 255]))
story.append(SP)

story.append(Paragraph("<b>5.3  Laboratory Investigations</b>", sSubHdr))
lab_data = [
    ["Test", "Rationale"],
    ["Serum ferritin + iron saturation", "Iron deficiency — also a marker of overall nutritional status"],
    ["TSH ± free T4", "Hypothyroidism (most common thyroid cause); hyperthyroidism less clearly linked"],
    ["FBC / CBC",     "Anaemia, infection markers"],
    ["Metabolic panel", "Renal function, liver function"],
    ["Hormonal panel (if indicated)", "DHEAS, testosterone, prolactin — consider in women with signs of hyperandrogenaemia"],
    ["25-OH Vitamin D, zinc, B12", "Micronutrient deficiencies in prolonged or unexplained TE"],
]
story.append(build_table(lab_data[0], [r for r in lab_data[1:]], [175, 300]))
story.append(SP8)

# ═══════════════════════════════════════════════════════
# 6 — DIFFERENTIAL DIAGNOSIS
# ═══════════════════════════════════════════════════════
story.append(section_header("6.  DIFFERENTIAL DIAGNOSIS"))
story.append(SP)

diff_data = [
    ["Condition", "Key Distinguishing Features", "Biopsy Clue"],
    ["Androgenetic alopecia",         "Patterned (frontoparietal) distribution; miniaturisation",            "Miniaturised follicles; variable shaft diameter"],
    ["Diffuse alopecia areata",       "Personal/family hx of AA; nail changes (pitting); body hair loss",   "Peribulbar lymphocytic infiltrate ('swarm of bees')"],
    ["Central centrifugal cicatricial alopecia", "Vertex scarring; women of African descent; progressive", "Scarring; perifollicular fibrosis"],
    ["Frontal fibrosing alopecia",    "Band-like frontotemporal recession; eyebrow loss; perifollicular erythema", "Lymphocytic scarring alopecia"],
    ["Traction alopecia",             "History of tight braiding/tension; frontoparietal margin", "Increased catagen/telogen; no miniaturisation"],
    ["Tinea capitis",                 "Children; scaling; broken-off hairs; KOH positive",                  "Fungal hyphae"],
    ["Secondary syphilis",            "'Moth-eaten' patchy loss; systemic signs; RPR positive",              "Perivascular/lichenoid infiltrate"],
]
story.append(build_table(diff_data[0], [r for r in diff_data[1:]], [130, 215, 130]))
story.append(SP8)

# ═══════════════════════════════════════════════════════
# 7 — CHRONIC TELOGEN EFFLUVIUM
# ═══════════════════════════════════════════════════════
story.append(section_header("7.  CHRONIC TELOGEN EFFLUVIUM (CTE)"))
story.append(SP)
story.append(info_box(
    "<b>Definition:</b> Idiopathic diffuse club-hair loss lasting >6 months with fluctuating course. "
    "Described by Whiting in 355 patients (346 women, 9 men), predominantly aged 30–60 years."))
story.append(SP)

cte_data = [
    ["Feature", "Acute TE", "Chronic TE (CTE)"],
    ["Duration",          "<6 months, self-limiting",      ">6 months; fluctuating, may persist years"],
    ["Trigger",           "Identifiable precipitant",       "Idiopathic; no clear trigger"],
    ["Demographics",      "Any age, any gender",            "Women, 4th–6th decade predominantly"],
    ["Mechanism",         "Premature anagen release",       "Shortened anagen phase"],
    ["Hair density before onset", "Normal",                 "Often above average — very long hair in childhood"],
    ["Pull test",         "Diffusely positive scalp-wide",  "Positive at vertex and occiput"],
    ["Bitemporal recession", "Less prominent",              "Frequently marked"],
    ["Treatment",         "Treat cause; reassure",          "5% topical minoxidil; correct modifiable factors"],
    ["Prognosis",         "Excellent — full regrowth",      "Variable; may improve with minoxidil"],
]
hdr = cte_data[0]
rows = cte_data[1:]
# Build manually for coloured middle column
data_p = [[TH(h) for h in hdr]]
for r in rows:
    data_p.append([TC(r[0], sTableCellB), TC(r[1]), TC(r[2])])
cte_tbl = Table(data_p, colWidths=[130, 185, 160])
cte_tbl.setStyle(TableStyle([
    ("BACKGROUND",    (0, 0), (-1, 0),  C_NAVY),
    ("BACKGROUND",    (1, 1), (1, -1),  colors.HexColor("#EBF5FB")),
    ("BACKGROUND",    (2, 1), (2, -1),  colors.HexColor("#FEF9E7")),
    ("ROWBACKGROUNDS",(0, 1), (0, -1),  [C_WHITE, C_BG_GREY]),
    ("GRID",          (0, 0), (-1, -1), 0.4, colors.HexColor("#BDC3C7")),
    ("VALIGN",        (0, 0), (-1, -1), "TOP"),
    ("LEFTPADDING",   (0, 0), (-1, -1), 5),
    ("RIGHTPADDING",  (0, 0), (-1, -1), 5),
    ("TOPPADDING",    (0, 0), (-1, -1), 4),
    ("BOTTOMPADDING", (0, 0), (-1, -1), 4),
]))
story.append(cte_tbl)
story.append(SP8)

# ═══════════════════════════════════════════════════════
# 8 — MANAGEMENT
# ═══════════════════════════════════════════════════════
story.append(section_header("8.  MANAGEMENT"))
story.append(SP)

story.append(Paragraph("8.1  General Principles", sSubHdr))
story.append(success_box(
    "<b>Key principle:</b> No specific therapy is required for most cases of acute TE. "
    "The majority resolve spontaneously within 3–6 months once the precipitating trigger resolves. "
    "Follicles remain intact — full hair regrowth is expected."))
story.append(SP)

mgmt_data = [
    ["Scenario", "Management"],
    ["Drug-induced TE",           "Discontinue offending drug — usually curative. Hair regrowth in 3–6 months."],
    ["Nutritional deficiency",    "Correct identified deficiency. Encourage balanced diet. Investigate blood loss (menstrual, GI). Note: iron replacement alone may not resolve TE."],
    ["Postpartum TE",             "Reassurance — self-limiting. Full regrowth expected within 6–12 months post-delivery."],
    ["Hypothyroidism",            "Thyroid hormone replacement. Expect hair regrowth from ~8 weeks post-treatment."],
    ["Papulosquamous scalp disease", "Treat underlying condition (seborrhoeic dermatitis, psoriasis) — may precipitate TE."],
    ["Chronic TE (idiopathic)",   "5% topical minoxidil solution — may shorten telogen and trigger anagen. Address all modifiable factors."],
    ["Neonatal TE",               "No treatment. Spontaneous resolution by 6 months of age."],
]
story.append(build_table(mgmt_data[0], [r for r in mgmt_data[1:]], [145, 330]))
story.append(SP)

story.append(Paragraph("8.2  Patient Counselling Points", sSubHdr))
counsel = [
    "Follicles are intact and will regrow — TE does not cause permanent hair loss.",
    "Shedding peaks 3–5 months after the trigger, not immediately after it.",
    "Recovery is often slower than expected — allow 6–12 months after trigger resolution.",
    "Trichodynia (scalp tenderness) is common and does not indicate disease severity.",
    "Avoid unnecessary hair dye products or tight hairstyles during recovery.",
    "A balanced, protein-rich diet supports optimal hair re-growth.",
]
for pt in counsel:
    story.append(Paragraph(f"• {pt}", sBullet))
story.append(SP8)

# ═══════════════════════════════════════════════════════
# 9 — DIAGNOSTIC ALGORITHM
# ═══════════════════════════════════════════════════════
story.append(section_header("9.  DIAGNOSTIC ALGORITHM — Diffuse Hair Loss"))
story.append(SP)

algo_steps = [
    ("STEP 1", "History",
     "Duration of shedding | Precipitating event (illness, surgery, delivery, diet, drugs, stress) | "
     "Timing: 3–5 month lag after trigger | Drug history | Nutritional habits | Family history | Menstrual history"),
    ("STEP 2", "Examination",
     "Pull test (>4–6 club hairs = positive) | Scalp inspection (scarring? scaling? erythema?) | "
     "Distribution (diffuse vs patterned) | Nail changes | Body hair | Thyroid exam"),
    ("STEP 3", "Initial Labs",
     "Serum ferritin + iron saturation | TSH | FBC | If indicated: hormonal screen, metabolic panel, vitamin D, zinc"),
    ("STEP 4", "Trichoscopy (if available)",
     "Vacant follicular ostia (yellow dots) | Upright regrowing hairs | Diversity of hair shaft diameter"),
    ("STEP 5", "Scalp Biopsy (if diagnosis unclear)",
     "Horizontal sections | >12–15% terminal follicles in telogen confirms TE | Exclude scarring alopecias"),
    ("STEP 6", "Diagnosis & Management",
     "Acute TE with identifiable trigger → treat cause + reassure | Chronic TE (>6 months, idiopathic) → "
     "5% minoxidil + correct modifiable factors | Refer dermatology if uncertain or refractory"),
]

for step, title, desc in algo_steps:
    row = Table([[
        Paragraph(step, make_style(f"algo_{step}", "Normal",
                                   fontName="Helvetica-Bold", fontSize=8, textColor=C_WHITE,
                                   alignment=TA_CENTER, leading=11)),
        Paragraph(f"<b>{title}:</b> {desc}", sBody)
    ]], colWidths=[45, PAGE_W - L_MARGIN - R_MARGIN - 55])
    row.setStyle(TableStyle([
        ("BACKGROUND",   (0, 0), (0, 0), C_TEAL),
        ("BACKGROUND",   (1, 0), (1, 0), C_BG_BLUE),
        ("BOX",          (0, 0), (-1, -1), 0.5, C_TEAL),
        ("VALIGN",       (0, 0), (-1, -1), "MIDDLE"),
        ("LEFTPADDING",  (0, 0), (-1, -1), 6),
        ("RIGHTPADDING", (0, 0), (-1, -1), 6),
        ("TOPPADDING",   (0, 0), (-1, -1), 5),
        ("BOTTOMPADDING",(0, 0), (-1, -1), 5),
    ]))
    story.append(row)
    story.append(Spacer(1, 2))

story.append(SP8)

# ═══════════════════════════════════════════════════════
# 10 — PROGNOSIS
# ═══════════════════════════════════════════════════════
story.append(section_header("10.  PROGNOSIS"))
story.append(SP)
story.append(success_box(
    "<b>Overall prognosis is excellent when a clear precipitating event is identified.</b> "
    "Full hair regrowth is the norm for acute TE. Neonatal TE always resolves by 6 months. "
    "Chronic idiopathic TE has a fluctuating course but is non-scarring and responds partially "
    "to 5% minoxidil. Female pattern hair loss must be excluded before diagnosing CTE."))
story.append(SP)

prog_data = [
    ["Type of TE", "Expected Outcome", "Timeframe"],
    ["Postpartum",              "Full regrowth",           "6–12 months post-delivery"],
    ["Post-febrile illness",    "Full regrowth",           "3–6 months after recovery"],
    ["Drug-induced",            "Full regrowth",           "3–6 months after stopping drug"],
    ["Post-surgical",           "Full regrowth",           "3–6 months post-operatively"],
    ["Nutritional/dietary",     "Full regrowth",           "After nutritional correction — 3–6 months"],
    ["Hypothyroid",             "Full regrowth",           "Begins ~8 weeks after treatment"],
    ["Neonatal",                "Full regrowth — always",  "By 6 months of age"],
    ["Chronic TE (idiopathic)", "Partial/variable",        "Fluctuating; may require long-term minoxidil"],
]
story.append(build_table(prog_data[0], [r for r in prog_data[1:]], [145, 200, 130]))
story.append(SP8)

# ═══════════════════════════════════════════════════════
# 11 — QUICK REFERENCE CARD
# ═══════════════════════════════════════════════════════
story.append(section_header("11.  QUICK REFERENCE — At a Glance"))
story.append(SP)

qr_left = [
    ("<b>Diagnose TE when:</b>", None),
    ("• Diffuse shedding, 3–5 months after trigger", sBody),
    ("• Pull test >4–6 club hairs positive", sBody),
    ("• Club-shaped, non-pigmented bulb on shed hair", sBody),
    ("• Normal scalp — no scarring, no erythema", sBody),
    ("• Ferritin, TSH normal (or abnormal — explains TE)", sBody),
    ("", None),
    ("<b>Exclude before diagnosing TE:</b>", None),
    ("• Androgenetic alopecia (patterned, miniaturisation)", sBody),
    ("• Alopecia areata (patches, nail changes)", sBody),
    ("• Scarring alopecia (permanent loss risk)", sBody),
    ("• Tinea capitis in children", sBody),
]
qr_right = [
    ("<b>Immediate action:</b>", None),
    ("• Identify and remove/treat the trigger", sBody),
    ("• Check ferritin + TSH in all cases", sBody),
    ("• Reassure — follicles intact, hair WILL regrow", sBody),
    ("", None),
    ("<b>Refer to Dermatology if:</b>", None),
    ("• Diagnosis unclear after workup", sBody),
    ("• Shedding >12 months without resolution", sBody),
    ("• Scalp biopsy required", sBody),
    ("• Suspected scarring alopecia", sBody),
    ("• Minoxidil not tolerated or ineffective", sBody),
]

def qr_paras(items):
    out = []
    for text, style in items:
        if style is None:
            out.append(Paragraph(text, sSubHdr if text else sBody))
        else:
            out.append(Paragraph(text, style))
    return out

qr_tbl = Table([[qr_paras(qr_left), qr_paras(qr_right)]],
               colWidths=[(PAGE_W - L_MARGIN - R_MARGIN) / 2 - 4,
                          (PAGE_W - L_MARGIN - R_MARGIN) / 2 - 4])
qr_tbl.setStyle(TableStyle([
    ("BACKGROUND",   (0, 0), (0, 0), colors.HexColor("#EBF4F8")),
    ("BACKGROUND",   (1, 0), (1, 0), colors.HexColor("#EAFAF1")),
    ("BOX",          (0, 0), (0, 0), 0.6, C_TEAL),
    ("BOX",          (1, 0), (1, 0), 0.6, C_GREEN),
    ("VALIGN",       (0, 0), (-1, -1), "TOP"),
    ("LEFTPADDING",  (0, 0), (-1, -1), 10),
    ("RIGHTPADDING", (0, 0), (-1, -1), 10),
    ("TOPPADDING",   (0, 0), (-1, -1), 8),
    ("BOTTOMPADDING",(0, 0), (-1, -1), 8),
]))
story.append(qr_tbl)
story.append(SP8)
story.append(HR())
story.append(Paragraph(
    "Sources: Fitzpatrick's Dermatology (9780071837781) | Andrews' Diseases of the Skin (9780323547536) | "
    "Dermatology 2-Volume Set 5e (9780702082252) | Compiled by Orris Medical AI, August 2026",
    sFooter))

# ── Build ──────────────────────────────────────────────────────────────────────
doc.build(story, onFirstPage=on_first_page, onLaterPages=on_later_pages)
print(f"PDF written to: {OUTPUT}")
Running Command

cd /tmp/workspace/telogen-effluvium && python generate_pdf.py 2>&1

Running Command

ls -lh /tmp/workspace/telogen-effluvium/Telogen_Effluvium_Clinical_Reference.pdf

Your clinical reference PDF is ready:

Telogen Effluvium Clinical Reference

PDF Document · PDF


Here is what the PDF contains across 11 structured sections:
SectionContent
1. Definition & OverviewCore definition, key numbers (follicle count, normal vs TE shedding rates)
2. PathophysiologyKligman's 5 mechanisms with examples (colour-coded table)
3. Etiology & TriggersPhysiological, medical/systemic, nutritional, drug-induced (full drug list)
4. Clinical FeaturesPattern, timing, shed hair morphology, trichodynia
5. Diagnostic ApproachPull test, clip test, trichogram, biopsy criteria, full lab panel
6. Differential Diagnosis7 conditions with distinguishing features and biopsy clues
7. Chronic TE (CTE)Acute vs chronic comparison table
8. ManagementPer-scenario management table + 6-point patient counselling guide
9. Diagnostic Algorithm6-step step-by-step clinical workflow
10. PrognosisExpected outcomes and timeframes by TE type
11. Quick Reference CardTwo-column at-a-glance summary (diagnose when / immediate action)
Formatted with a navy/teal clinical theme, colour-coded info boxes, alternating-row tables, and page headers/footers for easy printing. Sources are cited from Fitzpatrick's Dermatology and Andrews' Diseases of the Skin throughout.
This is a shared conversation. Sign in to Orris to start your own chat.