User feedback: the exam steps were too generic (e.g. "Shoulder abduction
— 5/5 bilaterally" never explained what 5/5 means or HOW to test it).
The guide needs to serve as a teaching tool, not just a checkbox list.
Three changes:
1. GRADING SCALES reference card (new). Collapsible panel at the top of
each system showing the relevant scales:
- Neuro: MRC strength (0-5), DTR (0-4+), Plantar response
- MSK: Scoliometer ATR, Beighton hypermobility score
Each scale shows the grade AND its clinical meaning in a compact
table. No more orphan "5/5 bilaterally" without definition.
2. Per-component SIGNIFICANCE + PEARL fields (optional). Adolescent
neuro components enriched with:
- Significance: one-line clinical relevance (what this component is
actually for — what pathologies it detects)
- Teaching pearl: a Hutchison/Bates/Nelson-style tip that helps the
learner see past the mechanics to the reasoning
Visually distinct — pearl gets a warm amber accent, significance is
a crosshair icon under the name.
3. Method strings REWRITTEN for every adolescent strength step. Before:
"Shoulder abduction — 5/5 bilaterally". After: "Patient abducts both
arms to 90°. Examiner pushes down on each arm just above the elbow
while patient resists. Compare sides. — Holds against full resistance
— MRC 5/5 bilaterally". Same treatment for all 14 strength steps,
all 8 DTR steps, and tone/pronator-drift.
UI redesign:
- Accent bars on cards (cyan for MSK, purple for neuro) for visual
anchor
- Numbered step circles instead of "1." prefix
- HOW / NORMAL label badges on each step
- Watch-for block with red left-border for red-flag grouping
- System-level header with icon (bone for MSK, brain for neuro)
Other age groups (newborn through school-age) keep the old data shape
(steps without pearls) — they still render correctly, just without the
pearl/significance blocks. Enriching them is an incremental follow-up.
960 lines
79 KiB
JavaScript
960 lines
79 KiB
JavaScript
// ============================================================
|
||
// PHYSICAL EXAM GUIDE — step-by-step OSCE reference + report generator
|
||
// ============================================================
|
||
// Sources for the exam content:
|
||
// - Bates' Guide to Physical Examination, 13th edition (technique)
|
||
// - Nelson Textbook of Pediatrics, 22nd edition (age-specific content)
|
||
// - Hutchison's Clinical Methods, 25th edition (systematic approach)
|
||
// - Developmental reflex timing: Fenichel Clinical Pediatric Neurology, 8th ed
|
||
//
|
||
// Data model:
|
||
// PE_DATA[ageGroup][system] = { overview, components: [{ name, steps: [{label, method, normal}], abnormalHints }] }
|
||
// Each step has its own Normal / Abnormal / Skip toggle so the physician
|
||
// ticks the exam off step-by-step and flags specific abnormal findings.
|
||
// Report generation (POST /api/generate-pe-narrative) receives the flat
|
||
// step array and produces a Technique + Findings narrative.
|
||
// ============================================================
|
||
|
||
(function () {
|
||
|
||
// ────────────────────────────────────────────────────────────
|
||
// GRADING SCALES — universal reference shown at top of each system
|
||
// ────────────────────────────────────────────────────────────
|
||
var SCALES = {
|
||
mrc: {
|
||
title: 'MRC strength grade (0–5)',
|
||
icon: 'fa-hand-fist',
|
||
rows: [
|
||
['5', 'Normal power — holds against full resistance'],
|
||
['4', 'Reduced — moves against gravity + some resistance'],
|
||
['3', 'Moves against gravity only (no added resistance)'],
|
||
['2', 'Full range with gravity eliminated (horizontal plane)'],
|
||
['1', 'Flicker / trace contraction, no joint movement'],
|
||
['0', 'No contraction']
|
||
]
|
||
},
|
||
dtr: {
|
||
title: 'Deep-tendon reflex grade (0–4+)',
|
||
icon: 'fa-circle-dot',
|
||
rows: [
|
||
['0', 'Absent'],
|
||
['1+', 'Hypoactive — trace, only with reinforcement'],
|
||
['2+', 'Normal'],
|
||
['3+', 'Brisk — may still be normal in anxious patients'],
|
||
['4+', 'Hyperactive with sustained clonus — always abnormal']
|
||
]
|
||
},
|
||
plantar: {
|
||
title: 'Plantar response (Babinski)',
|
||
icon: 'fa-shoe-prints',
|
||
rows: [
|
||
['Down-going', 'Normal in anyone ≥ 2 years'],
|
||
['Up-going', 'Normal < 2 years; abnormal after — UMN lesion'],
|
||
['Asymmetric', 'Always abnormal at any age']
|
||
]
|
||
},
|
||
beighton: {
|
||
title: 'Beighton hypermobility score (0–9)',
|
||
icon: 'fa-hands',
|
||
rows: [
|
||
['≤ 3', 'Normal flexibility'],
|
||
['4', 'Borderline — consider in context'],
|
||
['≥ 5', 'Hypermobility spectrum; screen for hEDS if other features present']
|
||
]
|
||
},
|
||
atr: {
|
||
title: 'Scoliometer — angle of trunk rotation',
|
||
icon: 'fa-ruler',
|
||
rows: [
|
||
['< 5°', 'Normal, no follow-up'],
|
||
['5–6°', 'Borderline — re-check at each visit'],
|
||
['≥ 7°', 'Refer for PA/lateral spine x-ray + orthopedic evaluation']
|
||
]
|
||
}
|
||
};
|
||
// Which scales are relevant per system
|
||
var SYSTEM_SCALES = {
|
||
msk: ['atr', 'beighton'],
|
||
neuro: ['mrc', 'dtr', 'plantar']
|
||
};
|
||
|
||
// ────────────────────────────────────────────────────────────
|
||
// DATA
|
||
// ────────────────────────────────────────────────────────────
|
||
var PE_DATA = {
|
||
|
||
newborn: {
|
||
label: 'Newborn (0–28 days)',
|
||
msk: {
|
||
overview: 'Exam done warm, quiet, undressed. Focus: birth injury, DDH, congenital anomaly. All steps symmetric.',
|
||
components: [
|
||
{ name: 'Resting posture', steps: [
|
||
{ label: 'Observe posture', method: 'Place supine and undisturbed for 30s', normal: 'Symmetric flexion at hips, knees, elbows' },
|
||
{ label: 'Hand position', method: 'Inspect resting hands', normal: 'Loosely fisted; opens intermittently' },
|
||
{ label: 'Symmetry', method: 'Compare left vs right side at rest', normal: 'Mirror-image posture' }
|
||
], abnormalHints: ['Frog-leg (hypotonia)', 'Asymmetric arm (brachial plexus/clavicle fx)', 'Opisthotonos (CNS)', 'Persistent fisting with thumb in palm'] },
|
||
|
||
{ name: 'Clavicles', steps: [
|
||
{ label: 'Palpate right clavicle', method: 'Trace from sternoclavicular joint to acromion with index finger', normal: 'Smooth, continuous, no step-off' },
|
||
{ label: 'Palpate left clavicle', method: 'Same technique on left side', normal: 'Smooth, continuous' },
|
||
{ label: 'Crepitus check', method: 'Light pressure along length of clavicle while gently abducting arm', normal: 'No crepitus, no pain response' }
|
||
], abnormalHints: ['Palpable step-off or callus (fracture — LGA, shoulder dystocia)', 'Asymmetric Moro on affected side'] },
|
||
|
||
{ name: 'Hips — DDH screen', steps: [
|
||
{ label: 'Thigh/gluteal folds', method: 'Undress completely; compare skin-fold symmetry', normal: 'Symmetric thigh and gluteal folds' },
|
||
{ label: 'Abduction', method: 'Flex hips 90°, abduct simultaneously', normal: 'Both hips abduct to ≥75° symmetrically' },
|
||
{ label: 'Barlow maneuver', method: 'Thumb on medial thigh, flex hip 90°, adduct, apply gentle posterior pressure', normal: 'No clunk or movement felt (negative)' },
|
||
{ label: 'Ortolani maneuver', method: 'From Barlow position: abduct and lift with fingers on greater trochanter', normal: 'No clunk as hip returns (negative)' },
|
||
{ label: 'Galeazzi sign', method: 'Knees flexed together with feet on table; compare knee heights', normal: 'Knees level — no leg-length discrepancy' }
|
||
], abnormalHints: ['Palpable Ortolani clunk (dislocated, reducible)', 'Barlow clunk (dislocatable)', 'Limited abduction', 'Positive Galeazzi (shortened femur)'] },
|
||
|
||
{ name: 'Spine and back', steps: [
|
||
{ label: 'Position prone', method: 'Turn infant prone, support chest', normal: 'Tolerates position, lifts head briefly' },
|
||
{ label: 'Palpate midline', method: 'Run finger from C-spine to coccyx', normal: 'Straight midline, no step-offs or gaps' },
|
||
{ label: 'Sacral inspection', method: 'Inspect sacral dimple if present; measure depth, distance from anus', normal: 'No dimple, or dimple <5mm deep and <2.5cm from anus' },
|
||
{ label: 'Cutaneous markers', method: 'Inspect midline skin from neck to coccyx', normal: 'No hair tuft, hemangioma, lipoma, or sinus tract' }
|
||
], abnormalHints: ['Deep sacral dimple (>5mm) or >2.5cm from anus — imaging', 'Hair tuft, hemangioma, lipoma (occult dysraphism)', 'Palpable defect'] },
|
||
|
||
{ name: 'Upper extremities', steps: [
|
||
{ label: 'Spontaneous movement', method: 'Observe both arms for 30s', normal: 'Symmetric antigravity movement' },
|
||
{ label: 'Digits', method: 'Count and inspect fingers both hands', normal: '5 digits each, no webbing or duplication' },
|
||
{ label: 'Palmar creases', method: 'Inspect palmar creases', normal: 'Normal triradiate creases' }
|
||
], abnormalHints: ['Erb/Klumpke palsy (paucity of movement)', 'Polydactyly, syndactyly', 'Single transverse (simian) palmar crease'] },
|
||
|
||
{ name: 'Lower extremities / feet', steps: [
|
||
{ label: 'Hip and knee range', method: 'Gently flex, extend, internally/externally rotate each', normal: 'Full symmetric range, no contracture' },
|
||
{ label: 'Foot alignment', method: 'Inspect resting foot position', normal: 'Midline or mildly adducted forefoot' },
|
||
{ label: 'Passive correction', method: 'Gently attempt to bring foot to neutral', normal: 'Fully correctable to neutral' },
|
||
{ label: 'Stroke test', method: 'Stroke lateral border of foot', normal: 'Foot dorsiflexes and everts reflexively' }
|
||
], abnormalHints: ['Rigid clubfoot (non-correctable talipes equinovarus)', 'Fixed metatarsus adductus', 'Rocker-bottom foot (trisomy 18)', 'Calcaneovalgus'] }
|
||
]
|
||
},
|
||
neuro: {
|
||
overview: 'Primitive reflexes present and symmetric. Tone assessed passively and actively. Full exam 3–5 min on a quiet, fed infant.',
|
||
components: [
|
||
{ name: 'Alertness and behavior', steps: [
|
||
{ label: 'State cycling', method: 'Observe over 1–2 min for alert periods', normal: 'Alert periods with spontaneous eye opening' },
|
||
{ label: 'Response to voice', method: 'Speak softly near ear', normal: 'Quiets to voice or turns toward sound' },
|
||
{ label: 'Consolability', method: 'If crying, attempt to soothe with swaddling or voice', normal: 'Consolable within 1–2 min' }
|
||
], abnormalHints: ['Lethargy', 'Jitteriness not stopped by passive flexion', 'Irritability unrelieved by feeding'] },
|
||
|
||
{ name: 'Cranial nerves', steps: [
|
||
{ label: 'CN II — pupil response', method: 'Shine light in each eye', normal: 'Pupils equal, reactive to light, direct and consensual' },
|
||
{ label: 'CN II — blink to light', method: 'Bright light in the line of sight', normal: 'Reflex blink' },
|
||
{ label: 'CN VII — facial symmetry at rest', method: 'Observe resting face', normal: 'Symmetric nasolabial folds' },
|
||
{ label: 'CN VII — facial symmetry with cry', method: 'Note face during a cry', normal: 'Symmetric grimace' },
|
||
{ label: 'CN IX, X, XII — suck and swallow', method: 'Offer clean gloved finger, pacifier, or during feed', normal: 'Strong coordinated suck-swallow, no choking' }
|
||
], abnormalHints: ['Asymmetric face (CN VII injury — usually forceps)', 'Poor suck or uncoordinated swallow', 'Fixed or unequal pupil'] },
|
||
|
||
{ name: 'Tone — passive', steps: [
|
||
{ label: 'Pull-to-sit', method: 'Grasp hands/wrists, pull smoothly to sit', normal: 'Brief head lag at term; not dramatic' },
|
||
{ label: 'Ventral suspension', method: 'Suspend prone over hand at chest', normal: 'Head briefly lifts to horizontal; extremities flexed' },
|
||
{ label: 'Arm recoil', method: 'Extend both arms fully at elbows, release', normal: 'Rapid return to flexion' },
|
||
{ label: 'Popliteal angle', method: 'Hip flexed 90°, extend knee maximally', normal: '≤110°' }
|
||
], abnormalHints: ['Marked head lag (hypotonia)', 'Slip-through on vertical suspension', 'Hypertonia / scissoring', 'Floppy limbs with no recoil'] },
|
||
|
||
{ name: 'Spontaneous movement', steps: [
|
||
{ label: 'Observe limbs', method: 'Undisturbed over 1 min, note movement', normal: 'Symmetric antigravity movement of all 4 limbs' },
|
||
{ label: 'Quality of movement', method: 'Note smoothness vs jitteriness', normal: 'Smooth, mildly variable movements' }
|
||
], abnormalHints: ['Paucity of movement in one limb', 'Coarse jitteriness', 'Clonic jerks', 'Tonic posturing'] },
|
||
|
||
{ name: 'Primitive reflexes', steps: [
|
||
{ label: 'Moro', method: 'Support head; allow 30° head drop or loud clap', normal: 'Symmetric arm abduction then flexion, often cry' },
|
||
{ label: 'Rooting', method: 'Stroke cheek at corner of mouth', normal: 'Turns head toward stroke and opens mouth' },
|
||
{ label: 'Palmar grasp', method: 'Press into palm with finger', normal: 'Strong, symmetric finger flexion' },
|
||
{ label: 'Plantar grasp', method: 'Press ball of foot below toes', normal: 'Toes flex around finger symmetrically' },
|
||
{ label: 'Stepping', method: 'Hold upright with feet touching surface', normal: 'Alternating stepping movements' },
|
||
{ label: 'Tonic neck (fencing)', method: 'Turn head to one side with infant supine', normal: 'Same-side arm extends, opposite flexes (not obligate)' },
|
||
{ label: 'Galant', method: 'Stroke paravertebrally from shoulder to buttock, one side', normal: 'Trunk curves toward stroked side' }
|
||
], abnormalHints: ['Absent or asymmetric Moro — CNS injury, brachial plexus, clavicle fx', 'Absent grasps — CNS depression', 'Obligate tonic neck is abnormal'] },
|
||
|
||
{ name: 'Babinski (plantar response)', steps: [
|
||
{ label: 'Stroke lateral sole', method: 'Firm stroke from heel toward toes along lateral plantar border', normal: 'Up-going great toe with fanning (normal in newborn)' },
|
||
{ label: 'Symmetry check', method: 'Repeat opposite foot', normal: 'Symmetric response' }
|
||
], abnormalHints: ['Asymmetric response is always abnormal'] }
|
||
]
|
||
}
|
||
},
|
||
|
||
infant: {
|
||
label: 'Infant (1–12 months)',
|
||
msk: {
|
||
overview: 'Continued DDH screen through 6 months. Watch motor progression and symmetry of tone/movement.',
|
||
components: [
|
||
{ name: 'Hips — continued DDH screen', steps: [
|
||
{ label: 'Thigh-fold symmetry', method: 'Inspect with infant supine, thighs flexed', normal: 'Symmetric folds' },
|
||
{ label: 'Barlow/Ortolani (through 3mo)', method: 'As in newborn — thumb medial, flex 90°, adduct+push then abduct+lift', normal: 'Negative bilaterally' },
|
||
{ label: 'Abduction (any age)', method: 'Flex 90°, abduct simultaneously', normal: '≥70° symmetric abduction' },
|
||
{ label: 'Galeazzi', method: 'Knees flexed feet flat on exam table', normal: 'Knees equal height' }
|
||
], abnormalHints: ['Clunk on Barlow/Ortolani (<3mo)', 'Limited abduction', 'Asymmetric folds', 'Positive Galeazzi'] },
|
||
|
||
{ name: 'Gross-motor milestones (age-appropriate)', steps: [
|
||
{ label: 'Head control', method: 'Prone, pull-to-sit, held upright', normal: 'Age-appropriate: 2mo lifts head 45°; 4mo no head lag' },
|
||
{ label: 'Rolling', method: 'Observe on flat surface', normal: 'Rolls back-to-front by 5–6mo' },
|
||
{ label: 'Sitting', method: 'Place in sitting position', normal: 'Tripod sit by 6mo; sits without support by 7–8mo' },
|
||
{ label: 'Standing', method: 'Support under arms', normal: 'Bears weight by 6mo; pulls to stand by 9mo' }
|
||
], abnormalHints: ['Milestone delay by ≥2mo', 'Loss of previously attained milestone', 'Asymmetric use of limbs'] },
|
||
|
||
{ name: 'Spine', steps: [
|
||
{ label: 'Palpate seated', method: 'Run finger along spine with infant sitting or held upright', normal: 'Midline, no step-offs' },
|
||
{ label: 'Back curvature', method: 'Inspect sitting and lying', normal: 'Physiologic gentle kyphosis in early infancy; lumbar lordosis as sitting develops' }
|
||
], abnormalHints: ['Fixed kyphoscoliosis', 'Sacral dimple with cutaneous marker', 'Step-off'] },
|
||
|
||
{ name: 'Extremities', steps: [
|
||
{ label: 'Passive range', method: 'Through each major joint', normal: 'Full symmetric range' },
|
||
{ label: 'Joint inspection', method: 'Inspect for swelling, warmth, effusion', normal: 'No swelling, warmth, or effusion' },
|
||
{ label: 'Feet alignment', method: 'Observe standing if pulling up, else passive positioning', normal: 'Correctable or aligned feet; flexible' }
|
||
], abnormalHints: ['Joint swelling/warmth (septic vs reactive arthritis)', 'Rigid clubfoot', 'Persistent asymmetric tone'] }
|
||
]
|
||
},
|
||
neuro: {
|
||
overview: 'Primitive reflexes fading on schedule; protective reflexes emerging; gross motor and tone interlinked.',
|
||
components: [
|
||
{ name: 'Alertness and social engagement', steps: [
|
||
{ label: 'Social smile', method: 'Face-to-face interaction', normal: 'Social smile by 6–8 weeks' },
|
||
{ label: 'Tracking', method: 'Move object across visual field', normal: '180° horizontal tracking by 3mo' },
|
||
{ label: 'Engagement', method: 'Face-to-face, voice, toys', normal: 'Age-appropriate reciprocal interaction' }
|
||
], abnormalHints: ['No social smile by 3mo', 'Absent tracking past 3mo', 'Poor engagement (developmental concern)'] },
|
||
|
||
{ name: 'Cranial nerves', steps: [
|
||
{ label: 'Pupils', method: 'Light response each eye', normal: 'Equal reactive' },
|
||
{ label: 'Eye alignment', method: 'Inspect with gaze forward and in all directions', normal: 'No strabismus past 4mo' },
|
||
{ label: 'Facial symmetry', method: 'Observe smile and cry', normal: 'Symmetric' },
|
||
{ label: 'Suck and swallow', method: 'Observe feeding', normal: 'Coordinated, no choking' }
|
||
], abnormalHints: ['Persistent nystagmus', 'Strabismus past 4mo', 'Asymmetric face'] },
|
||
|
||
{ name: 'Tone', steps: [
|
||
{ label: 'Pull-to-sit', method: 'Gently pull wrists/hands', normal: 'No head lag by 4mo' },
|
||
{ label: 'Ventral suspension', method: 'Support prone, observe', normal: 'Head above horizontal, extremities actively flexed (age-dependent)' },
|
||
{ label: 'Vertical suspension', method: 'Support under arms, lift', normal: 'Does not slip through hands' }
|
||
], abnormalHints: ['Persistent head lag past 4mo (hypotonia)', 'Hypertonia / scissoring (UMN)', 'Slip-through on vertical suspension'] },
|
||
|
||
{ name: 'Primitive reflex integration', steps: [
|
||
{ label: 'Moro', method: 'Head drop or clap', normal: 'Absent by 6mo' },
|
||
{ label: 'Palmar grasp', method: 'Press into palm', normal: 'Integrated by 5–6mo; replaced by voluntary grasp' },
|
||
{ label: 'Tonic neck', method: 'Turn head to side', normal: 'Absent by 6mo' },
|
||
{ label: 'Rooting', method: 'Stroke cheek', normal: 'Absent by 3–4mo' }
|
||
], abnormalHints: ['Persistence of any primitive reflex past 6mo warrants eval (CP, CNS injury)'] },
|
||
|
||
{ name: 'Protective and postural reflexes', steps: [
|
||
{ label: 'Parachute', method: 'Held prone, tilt head downward suddenly', normal: 'Symmetric arm extension protectively by 9mo (emerges 6–9mo)' },
|
||
{ label: 'Lateral propping', method: 'Seated infant, gentle tilt to one side', normal: 'Arm extends to catch by 6–7mo' },
|
||
{ label: 'Landau', method: 'Suspend prone', normal: 'Extends head, spine, legs by 6mo' }
|
||
], abnormalHints: ['Absent parachute after 12mo (concerning)', 'Asymmetric lateral propping', 'Absent Landau'] }
|
||
]
|
||
}
|
||
},
|
||
|
||
toddler: {
|
||
label: 'Toddler (1–3 years)',
|
||
msk: {
|
||
overview: 'Gait, physiologic alignment changes, in-toeing, joint range. Cooperation unpredictable — use play.',
|
||
components: [
|
||
{ name: 'Gait', steps: [
|
||
{ label: 'Base of support', method: 'Have child walk ~10 feet', normal: 'Wide-based initially, narrowing by 2y' },
|
||
{ label: 'Heel-strike', method: 'Observe foot contact pattern', normal: 'Heel-strike developing by 18mo, consistent by 2y' },
|
||
{ label: 'Arm swing', method: 'Observe reciprocal arm swing', normal: 'Reciprocal arm swing by 18mo' },
|
||
{ label: 'Symmetry', method: 'Watch both sides in stance and swing', normal: 'Symmetric stride length and cadence' }
|
||
], abnormalHints: ['Toe-walking past 2y (idiopathic vs CP vs DMD)', 'Limp (Legg-Calvé-Perthes, transient synovitis, trauma)', 'Wide-based ataxia'] },
|
||
|
||
{ name: 'Knee alignment', steps: [
|
||
{ label: 'Stand feet together', method: 'Feet/medial malleoli touching; inspect knees', normal: 'Genu varum resolving by 18–24mo; mild genu valgum common by 2–3y' },
|
||
{ label: 'Intercondylar or intermalleolar distance', method: 'Measure if alignment appears abnormal', normal: '<5cm intercondylar (varum) or <8cm intermalleolar (valgum)' },
|
||
{ label: 'Symmetry', method: 'Compare sides', normal: 'Symmetric' }
|
||
], abnormalHints: ['Persistent varum past 2y', 'Severe valgum >8cm', 'Unilateral (Blount disease, rickets)'] },
|
||
|
||
{ name: 'Feet alignment', steps: [
|
||
{ label: 'In-toeing / out-toeing', method: 'Observe foot angle during gait', normal: 'Mild in-toeing common (tibial torsion, femoral anteversion)' },
|
||
{ label: 'Arch during stance', method: 'Stand flat, then on tiptoes', normal: 'Flexible flat foot that forms arch on tiptoe' },
|
||
{ label: 'Heel alignment', method: 'View from behind standing', normal: 'Neutral or mildly valgus heel' }
|
||
], abnormalHints: ['Rigid flat foot (tarsal coalition)', 'Fixed metatarsus adductus', 'Severe in-toeing >15°'] },
|
||
|
||
{ name: 'Joint range', steps: [
|
||
{ label: 'Hips', method: 'Flex, abduct, rotate each hip', normal: 'Full symmetric range, no pain' },
|
||
{ label: 'Knees', method: 'Flex, extend; palpate for effusion', normal: 'Full range, no effusion, stable' },
|
||
{ label: 'Ankles', method: 'Dorsiflex, plantarflex, invert, evert', normal: 'Full range' },
|
||
{ label: 'Shoulders, elbows, wrists', method: 'Through full range each', normal: 'Full symmetric range' }
|
||
], abnormalHints: ['Joint effusion (septic vs reactive)', 'Guarded or painful motion', 'Asymmetric limitation'] },
|
||
|
||
{ name: 'Spine', steps: [
|
||
{ label: 'Inspect standing', method: 'View spine from behind', normal: 'Midline, no prominent curve' },
|
||
{ label: 'Palpate midline', method: 'Run finger along spinous processes', normal: 'Midline, no step-off, no tenderness' },
|
||
{ label: 'Shoulder/hip symmetry', method: 'Compare shoulder and hip heights', normal: 'Symmetric' }
|
||
], abnormalHints: ['Fixed scoliosis', 'Abnormal kyphosis', 'Asymmetric shoulder/hip', 'Midline tenderness'] }
|
||
]
|
||
},
|
||
neuro: {
|
||
overview: 'Shifting to adult-pattern exam. Primitive reflexes should be absent. Use play-based techniques.',
|
||
components: [
|
||
{ name: 'Mental status and language', steps: [
|
||
{ label: 'Engagement', method: 'Interaction with examiner/parent', normal: 'Alert, interactive, age-appropriate' },
|
||
{ label: 'Language — expressive', method: 'Note spontaneous utterances', normal: '1y: 1–3 words; 2y: 2-word phrases; 3y: short sentences' },
|
||
{ label: 'Language — receptive', method: 'Ask to point to body parts or follow simple commands', normal: 'Follows age-appropriate commands' }
|
||
], abnormalHints: ['Language regression (autism, epileptic encephalopathy)', 'Poor engagement', 'No 2-word phrases by 2y'] },
|
||
|
||
{ name: 'Cranial nerves', steps: [
|
||
{ label: 'CN II — pupil response', method: 'Shine light each eye', normal: 'Pupils equal reactive' },
|
||
{ label: 'CN III, IV, VI — EOM', method: 'Follow toy in H pattern', normal: 'Full smooth tracking, no strabismus' },
|
||
{ label: 'CN V — facial sensation', method: 'Light touch on forehead, cheek, jaw', normal: 'Responds to touch, symmetric' },
|
||
{ label: 'CN VII — face', method: 'Elicit smile, watch eye closure during cry', normal: 'Symmetric face' },
|
||
{ label: 'CN IX, X, XII — mouth', method: 'Say "ahh"; stick out tongue', normal: 'Palate rises symmetrically; tongue midline' }
|
||
], abnormalHints: ['Strabismus', 'Facial asymmetry', 'Tongue deviation', 'Absent palate elevation'] },
|
||
|
||
{ name: 'Motor — tone and bulk', steps: [
|
||
{ label: 'Passive tone', method: 'Move each limb through full range', normal: 'Normal resistance throughout' },
|
||
{ label: 'Bulk inspection', method: 'Inspect muscle bulk of thighs, calves, glutes', normal: 'Symmetric, age-appropriate bulk' },
|
||
{ label: 'Contracture check', method: 'Test for heel-cord tightness, hamstring tightness', normal: 'No contractures' }
|
||
], abnormalHints: ['Spasticity (especially catch in ankles)', 'Hypotonia', 'Calf pseudo-hypertrophy (DMD)'] },
|
||
|
||
{ name: 'Motor — functional strength', steps: [
|
||
{ label: 'Rising from floor', method: 'Place flat on back; ask to stand up', normal: 'Rises without using hands to push off thighs (no Gowers)' },
|
||
{ label: 'Climbing stairs', method: 'Observe or history', normal: 'Climbs holding rail' },
|
||
{ label: 'Squatting/getting up', method: 'Encourage via play', normal: 'Squats and rises without help' }
|
||
], abnormalHints: ['Gowers sign (proximal weakness — DMD)', 'Unable to climb stairs at age expected', 'Calf pain on walking (myositis)'] },
|
||
|
||
{ name: 'Deep tendon reflexes', steps: [
|
||
{ label: 'Patellar', method: 'Sitting or supine with distraction (toy)', normal: '2+ symmetric' },
|
||
{ label: 'Biceps', method: 'Arm at rest, strike thumb on tendon', normal: '2+ symmetric' },
|
||
{ label: 'Achilles', method: 'With distraction', normal: '2+ symmetric' }
|
||
], abnormalHints: ['Hyperreflexia or clonus (UMN, CP)', 'Absent reflexes (LMN, neuropathy)', 'Asymmetry'] },
|
||
|
||
{ name: 'Coordination and gait', steps: [
|
||
{ label: 'Run', method: 'Watch run ~10 feet', normal: 'Runs with reciprocal arm swing by 2y' },
|
||
{ label: 'Stairs', method: 'Observe', normal: 'Climbs with rail' },
|
||
{ label: 'Kick ball', method: 'Place ball; observe kick', normal: 'Kicks by 2y' },
|
||
{ label: 'Ataxia check', method: 'Watch for fluency of movement', normal: 'Smooth, no tremor' }
|
||
], abnormalHints: ['Ataxic gait', 'Intention tremor', 'Clumsiness beyond age'] },
|
||
|
||
{ name: 'Plantar response', steps: [
|
||
{ label: 'Stroke lateral sole', method: 'Firm stroke from heel to toes', normal: 'Down-going great toe (plantar flexion) by age 2' }
|
||
], abnormalHints: ['Up-going toe after age 2 = UMN sign (Babinski positive)'] }
|
||
]
|
||
}
|
||
},
|
||
|
||
preschool: {
|
||
label: 'Preschool (3–5 years)',
|
||
msk: {
|
||
overview: 'Functional gait maneuvers, scoliosis screen, resolving physiologic alignment.',
|
||
components: [
|
||
{ name: 'Gait — multiple patterns', steps: [
|
||
{ label: 'Normal gait', method: 'Walk ~15 feet barefoot', normal: 'Symmetric, smooth, reciprocal arm swing' },
|
||
{ label: 'Heel walking', method: 'Walk on heels only', normal: 'Able by 4y' },
|
||
{ label: 'Toe walking', method: 'Walk on toes only', normal: 'Able by 4y' },
|
||
{ label: 'Tandem walking', method: 'Heel-to-toe along a line for 5 steps', normal: 'Able by 4y with minimal deviation' },
|
||
{ label: 'Hopping', method: 'Hop on one foot', normal: '3–5 hops on preferred foot by 4y' }
|
||
], abnormalHints: ['Persistent toe-walking', 'Asymmetric stance/stride', 'Difficulty with any pattern'] },
|
||
|
||
{ name: 'Alignment', steps: [
|
||
{ label: 'Knee alignment', method: 'Stand feet together', normal: 'Mild residual valgus resolving; neutral by 6–7y' },
|
||
{ label: 'Foot arch', method: 'Standing, then tiptoe', normal: 'Arch forms on tiptoe (flexible flat foot)' },
|
||
{ label: 'Heel position', method: 'View from behind standing', normal: 'Neutral or mild valgus' }
|
||
], abnormalHints: ['Persistent unilateral varum', 'Rigid flat foot (no arch on tiptoe)', 'Pes cavus'] },
|
||
|
||
{ name: 'Scoliosis screen (Adam forward-bend)', steps: [
|
||
{ label: 'Position', method: 'Feet together, bend forward at waist, arms hanging, palms together', normal: 'Arms and head relaxed' },
|
||
{ label: 'View from behind', method: 'Examiner at same height; look along back', normal: 'Symmetric paraspinal contour' },
|
||
{ label: 'View from side', method: 'Side view for kyphosis', normal: 'Smooth thoracic curve' }
|
||
], abnormalHints: ['Rib hump (thoracic scoliosis)', 'Lumbar prominence', 'Asymmetric scapular height'] },
|
||
|
||
{ name: 'Joint range and stability', steps: [
|
||
{ label: 'Active range', method: 'Ask to perform full range at hips, knees, ankles, shoulders, elbows, wrists', normal: 'Full symmetric range, no pain' },
|
||
{ label: 'Knee stability', method: 'Palpate for effusion; assess stability if complaint', normal: 'Stable, no effusion' },
|
||
{ label: 'Carrying angle (elbows)', method: 'Arms at sides, palms forward', normal: 'Normal valgus carrying angle' }
|
||
], abnormalHints: ['Joint hypermobility (Beighton score)', 'Effusion', 'Pain with motion', 'Valgus >15°'] },
|
||
|
||
{ name: 'Feet', steps: [
|
||
{ label: 'Standing inspection', method: 'View from front and behind', normal: 'Symmetric feet, neutral heel, flexible flat feet common' },
|
||
{ label: 'Tiptoe', method: 'Stand on tiptoes', normal: 'Arch forms, symmetric' },
|
||
{ label: 'Pes planus vs cavus', method: 'Note arch height', normal: 'Flexible flat foot or mild arch' }
|
||
], abnormalHints: ['Rigid flat foot', 'Pes cavus (Charcot-Marie-Tooth)', 'Pain'] }
|
||
]
|
||
},
|
||
neuro: {
|
||
overview: 'Formal pediatric neuro exam now feasible — most 4- and 5-year-olds cooperate with structured testing.',
|
||
components: [
|
||
{ name: 'Mental status and language', steps: [
|
||
{ label: 'Orientation (age-appropriate)', method: 'Ask name, age, where you are', normal: 'Knows name and age by 3y; location by 4–5y' },
|
||
{ label: 'Speech intelligibility', method: 'Listen to spontaneous speech', normal: 'Strangers understand by 4y' },
|
||
{ label: 'Receptive language', method: '2- and 3-step commands', normal: 'Follows 3-step commands by 4–5y' }
|
||
], abnormalHints: ['Dysarthria', 'Expressive or receptive language delay', 'Inattention'] },
|
||
|
||
{ name: 'Cranial nerves (II–XII)', steps: [
|
||
{ label: 'CN II — visual acuity', method: 'HOTV chart or pictures at 10ft, each eye', normal: '20/30 or better by 4y; 20/25 by 5y' },
|
||
{ label: 'CN II — visual fields', method: 'Confrontation with toys from periphery', normal: 'Full fields' },
|
||
{ label: 'CN II — pupils', method: 'Light response each eye', normal: 'PERRL' },
|
||
{ label: 'CN III, IV, VI — EOM', method: 'Follow toy in H pattern; include convergence', normal: 'Full EOM, convergence present' },
|
||
{ label: 'CN V — sensation', method: 'Light touch forehead, cheek, jaw each side', normal: 'Intact, symmetric' },
|
||
{ label: 'CN V — motor', method: 'Clench teeth, palpate masseter', normal: 'Symmetric strong bulk' },
|
||
{ label: 'CN VII — face', method: 'Smile, wrinkle forehead, close eyes, puff cheeks', normal: 'Symmetric movement of all regions' },
|
||
{ label: 'CN VIII — hearing', method: 'Finger rub each ear or whispered words', normal: 'Intact bilaterally' },
|
||
{ label: 'CN IX, X — palate', method: 'Open mouth, say "ahh"', normal: 'Palate rises symmetrically, uvula midline' },
|
||
{ label: 'CN XI — SCM/trapezius', method: 'Shrug shoulders, turn head against resistance', normal: 'Symmetric strength' },
|
||
{ label: 'CN XII — tongue', method: 'Stick tongue out, move side to side', normal: 'Midline, no atrophy, full movement' }
|
||
], abnormalHints: ['Strabismus (amblyopia risk)', 'Facial weakness', 'Tongue deviation/fasciculations', 'Uvula off-midline'] },
|
||
|
||
{ name: 'Motor — tone, bulk, strength', steps: [
|
||
{ label: 'Tone inspection', method: 'Passive range all four limbs', normal: 'Normal tone throughout' },
|
||
{ label: 'Bulk inspection', method: 'Observe muscle bulk symmetry', normal: 'Symmetric, age-appropriate' },
|
||
{ label: 'Strength — shoulder abduction', method: 'Arms out, push down against resistance', normal: '5/5 bilaterally' },
|
||
{ label: 'Strength — elbow flexion', method: 'Flex elbow against resistance', normal: '5/5 bilaterally' },
|
||
{ label: 'Strength — grip', method: 'Squeeze examiner\'s fingers', normal: '5/5 symmetric' },
|
||
{ label: 'Strength — hip flexion', method: 'Lift leg off table against resistance', normal: '5/5 bilaterally' },
|
||
{ label: 'Strength — knee extension', method: 'Straighten knee against resistance', normal: '5/5 bilaterally' },
|
||
{ label: 'Strength — dorsiflexion', method: 'Pull toes up against resistance', normal: '5/5 bilaterally' }
|
||
], abnormalHints: ['Focal weakness', 'Gowers sign', 'Pseudohypertrophy (DMD)', 'Atrophy'] },
|
||
|
||
{ name: 'Deep tendon reflexes', steps: [
|
||
{ label: 'Biceps', method: 'Thumb on biceps tendon, strike', normal: '2+ symmetric' },
|
||
{ label: 'Patellar', method: 'Knees hanging, strike patellar tendon', normal: '2+ symmetric' },
|
||
{ label: 'Achilles', method: 'Slight dorsiflexion, strike Achilles tendon', normal: '2+ symmetric' },
|
||
{ label: 'Plantar response', method: 'Stroke lateral sole heel-to-toes', normal: 'Down-going great toe' }
|
||
], abnormalHints: ['Hyperreflexia or clonus (UMN)', 'Hyporeflexia (LMN)', 'Up-going plantar (Babinski — abnormal past 2y)', 'Asymmetry'] },
|
||
|
||
{ name: 'Coordination', steps: [
|
||
{ label: 'Finger-to-nose', method: 'Touch examiner\'s finger then own nose, repeat', normal: 'Smooth, no dysmetria' },
|
||
{ label: 'Heel-to-shin', method: 'Run heel down opposite shin', normal: 'Smooth bilaterally' },
|
||
{ label: 'Rapid alternating movements', method: 'Tap palm with opposite hand alternating palm/back', normal: 'Rhythmic, symmetric' },
|
||
{ label: 'Tandem walk', method: 'Heel-to-toe for 5 steps', normal: 'Minimal deviation' }
|
||
], abnormalHints: ['Dysmetria', 'Dysdiadochokinesia', 'Intention tremor', 'Ataxic tandem'] },
|
||
|
||
{ name: 'Sensory', steps: [
|
||
{ label: 'Light touch — hands', method: 'Cotton wisp on palm/dorsum, eyes closed', normal: 'Feels each touch' },
|
||
{ label: 'Light touch — feet', method: 'Same on dorsum of foot bilaterally', normal: 'Feels each touch' }
|
||
], abnormalHints: ['Focal sensory loss', 'Stocking-glove loss'] },
|
||
|
||
{ name: 'Gait and Romberg', steps: [
|
||
{ label: 'Normal gait', method: 'Walk ~20 feet', normal: 'Smooth, symmetric' },
|
||
{ label: 'Heel walk', method: 'Walk on heels', normal: 'Able without difficulty' },
|
||
{ label: 'Toe walk', method: 'Walk on toes', normal: 'Able without difficulty' },
|
||
{ label: 'Tandem', method: 'Heel-to-toe', normal: 'Intact' },
|
||
{ label: 'Romberg (5y+)', method: 'Feet together, eyes closed, stand 10s', normal: 'Stable without sway' }
|
||
], abnormalHints: ['Ataxic gait (cerebellar)', 'Romberg positive (dorsal column)', 'Circumduction (UMN)'] }
|
||
]
|
||
}
|
||
},
|
||
|
||
school: {
|
||
label: 'School-age (6–11 years)',
|
||
msk: {
|
||
overview: 'Scoliosis screening peri-puberty, sports overuse injuries, resolving alignment.',
|
||
components: [
|
||
{ name: 'Scoliosis screen (forward-bend + scoliometer)', steps: [
|
||
{ label: 'Standing inspection', method: 'Shoulders and iliac crest heights', normal: 'Symmetric shoulder and pelvic heights' },
|
||
{ label: 'Forward bend (Adam test)', method: 'Feet together, bend forward at waist, arms hanging palms together', normal: 'Symmetric paraspinal contour' },
|
||
{ label: 'Rib hump', method: 'View tangentially from behind at level of curve', normal: 'No rib hump' },
|
||
{ label: 'Lumbar prominence', method: 'Same view at lumbar level', normal: 'No prominence' },
|
||
{ label: 'Scoliometer (if available)', method: 'Place scoliometer across rib hump, read angle of trunk rotation', normal: 'ATR < 5°; ≥7° → refer' }
|
||
], abnormalHints: ['Rib hump', 'ATR ≥7°', 'Asymmetric shoulders or pelvis', 'Decompensation (plumb line offset)'] },
|
||
|
||
{ name: 'Back and spine', steps: [
|
||
{ label: 'Posture inspection', method: 'Standing, view front/back/side', normal: 'Normal spinal curves; plumb line centered' },
|
||
{ label: 'Palpate spinous processes', method: 'From C2 to S1', normal: 'No tenderness, no step-off' },
|
||
{ label: 'Range of motion', method: 'Flex, extend, lateral bend, rotate', normal: 'Full painless range' }
|
||
], abnormalHints: ['Midline tenderness', 'Step-off (spondylolisthesis)', 'Limited motion with pain'] },
|
||
|
||
{ name: 'Alignment', steps: [
|
||
{ label: 'Knees', method: 'Feet together, inspect', normal: 'Neutral alignment by 6–7y' },
|
||
{ label: 'Feet', method: 'Stand, then tiptoes', normal: 'Medial arch present, symmetric' },
|
||
{ label: 'Leg lengths', method: 'Supine, measure ASIS to medial malleolus if asymmetric', normal: 'Equal within 1cm' }
|
||
], abnormalHints: ['Residual valgum', 'Pes cavus', 'Leg-length discrepancy >1cm'] },
|
||
|
||
{ name: 'Joint stability and sports exam (if active)', steps: [
|
||
{ label: 'Active range all joints', method: 'Through full range', normal: 'Full symmetric range, no pain or crepitus' },
|
||
{ label: 'Knee — Lachman (if sports-active)', method: 'Knee 20° flexion, stabilize femur, pull tibia forward', normal: 'Firm endpoint, no laxity' },
|
||
{ label: 'Knee — McMurray', method: 'Flexed knee, rotate tibia while extending', normal: 'No pain or click' },
|
||
{ label: 'Shoulder — impingement (Neer/Hawkins)', method: 'Passive shoulder flexion with arm in internal rotation', normal: 'No pain' },
|
||
{ label: 'Ankle stability', method: 'Anterior drawer and talar tilt', normal: 'No laxity' }
|
||
], abnormalHints: ['ACL laxity (positive Lachman)', 'Meniscal click', 'Shoulder impingement', 'Ankle instability'] },
|
||
|
||
{ name: 'Gait and functional movement', steps: [
|
||
{ label: 'Normal gait', method: 'Walk 20 feet', normal: 'Smooth, symmetric' },
|
||
{ label: 'Single-leg stance', method: 'Stand on one foot 10s each side', normal: 'Stable without Trendelenburg drop' },
|
||
{ label: 'Squat', method: 'Full squat and rise', normal: 'Full squat without pain or asymmetry' },
|
||
{ label: 'Hop on one foot', method: '5 hops each side', normal: 'Able and symmetric' }
|
||
], abnormalHints: ['Trendelenburg sign (hip abductor weakness)', 'Antalgic gait', 'Asymmetric squat', 'Pain with hop'] }
|
||
]
|
||
},
|
||
neuro: {
|
||
overview: 'Adult-pattern six-component exam: mental status, CN, motor, reflexes, sensory, coordination/gait.',
|
||
components: [
|
||
{ name: 'Mental status', steps: [
|
||
{ label: 'Orientation', method: 'Name, age, school, city, day of week', normal: 'Oriented x 4' },
|
||
{ label: 'Attention', method: 'Count backward from 20; days of week backward', normal: 'Intact' },
|
||
{ label: '3-item recall', method: 'Ball-flag-tree; ask at 3 and 5 min', normal: '3/3 recall at 5 min' },
|
||
{ label: 'Language', method: 'Name common objects; repeat a sentence', normal: 'Fluent, no paraphasia' }
|
||
], abnormalHints: ['Inattention (ADHD features)', 'Memory deficits', 'Word-finding difficulty', 'Perseveration'] },
|
||
|
||
{ name: 'Cranial nerves (II–XII)', steps: [
|
||
{ label: 'CN II — acuity', method: 'Snellen at 20ft each eye with corrective lenses if worn', normal: '20/20 or baseline' },
|
||
{ label: 'CN II — fields', method: 'Confrontation, 4 quadrants each eye', normal: 'Full fields' },
|
||
{ label: 'CN II — fundoscopy (if indicated)', method: 'Direct ophthalmoscopy — disc, vessels, macula', normal: 'Sharp disc, normal cup-disc ratio, no papilledema' },
|
||
{ label: 'CN II, III — pupils', method: 'Direct and consensual light, accommodation', normal: 'PERRLA' },
|
||
{ label: 'CN III, IV, VI — EOM', method: 'Follow finger in H pattern; convergence', normal: 'Full EOM, no nystagmus, convergence intact' },
|
||
{ label: 'CN V — sensation', method: 'Light touch V1 (forehead), V2 (cheek), V3 (jaw) each side', normal: 'Intact, symmetric' },
|
||
{ label: 'CN V — motor', method: 'Clench teeth, palpate masseter/temporalis; jaw opening', normal: 'Symmetric strength' },
|
||
{ label: 'CN VII', method: 'Raise eyebrows, close eyes tight, smile/show teeth, puff cheeks', normal: 'Symmetric movement, all regions' },
|
||
{ label: 'CN VIII', method: 'Finger rub each ear; Weber/Rinne if deficit', normal: 'Hears bilaterally' },
|
||
{ label: 'CN IX, X', method: 'Palate elevation with "ahh"; uvula midline; voice quality', normal: 'Symmetric elevation, uvula midline, normal voice' },
|
||
{ label: 'CN XI', method: 'Shrug shoulders against resistance; head turn against resistance', normal: '5/5 SCM and trapezius' },
|
||
{ label: 'CN XII', method: 'Stick tongue out; side-to-side', normal: 'Midline, no atrophy or fasciculations' }
|
||
], abnormalHints: ['Papilledema (increased ICP)', 'Focal cranial nerve deficit — any warrants workup', 'Tongue fasciculations (LMN/MND)'] },
|
||
|
||
{ name: 'Motor — bulk, tone, strength', steps: [
|
||
{ label: 'Bulk inspection', method: 'Shoulders, thighs, calves, intrinsic hand muscles', normal: 'Symmetric, no atrophy' },
|
||
{ label: 'Tone', method: 'Passive range at elbows, wrists, knees, ankles', normal: 'Normal resistance throughout' },
|
||
{ label: 'Strength — deltoids', method: 'Shoulder abduction against resistance', normal: '5/5 bilaterally' },
|
||
{ label: 'Strength — biceps', method: 'Elbow flexion against resistance', normal: '5/5' },
|
||
{ label: 'Strength — triceps', method: 'Elbow extension against resistance', normal: '5/5' },
|
||
{ label: 'Strength — grip', method: 'Squeeze 2 fingers', normal: '5/5 symmetric' },
|
||
{ label: 'Strength — finger abduction', method: 'Spread fingers against resistance', normal: '5/5' },
|
||
{ label: 'Strength — hip flexion', method: 'Lift leg supine against resistance', normal: '5/5' },
|
||
{ label: 'Strength — knee extension', method: 'Straighten knee against resistance', normal: '5/5' },
|
||
{ label: 'Strength — dorsiflexion', method: 'Pull toes up against resistance', normal: '5/5' },
|
||
{ label: 'Strength — plantarflexion', method: 'Push foot down against resistance', normal: '5/5' }
|
||
], abnormalHints: ['Focal weakness (localize)', 'Spasticity (UMN)', 'Atrophy', 'Fasciculations'] },
|
||
|
||
{ name: 'Deep tendon reflexes', steps: [
|
||
{ label: 'Biceps (C5-C6)', method: 'Thumb on tendon, strike', normal: '2+ symmetric' },
|
||
{ label: 'Triceps (C7-C8)', method: 'Strike triceps tendon', normal: '2+ symmetric' },
|
||
{ label: 'Brachioradialis (C5-C6)', method: 'Strike distal radius', normal: '2+ symmetric' },
|
||
{ label: 'Patellar (L3-L4)', method: 'Knees hanging, strike tendon', normal: '2+ symmetric' },
|
||
{ label: 'Achilles (S1)', method: 'Slight dorsiflexion, strike tendon', normal: '2+ symmetric' },
|
||
{ label: 'Plantar response', method: 'Stroke lateral sole heel-to-toes', normal: 'Down-going bilaterally' },
|
||
{ label: 'Clonus', method: 'Rapid dorsiflexion at ankle', normal: 'No sustained clonus' }
|
||
], abnormalHints: ['Hyperreflexia with clonus (UMN: stroke, MS, cord lesion)', 'Hyporeflexia (LMN, neuropathy, myopathy)', 'Asymmetry', 'Up-going Babinski', 'Sustained clonus'] },
|
||
|
||
{ name: 'Sensory', steps: [
|
||
{ label: 'Light touch — upper', method: 'Cotton wisp dorsum of hands, eyes closed', normal: 'Intact, symmetric' },
|
||
{ label: 'Light touch — lower', method: 'Same on dorsum of feet', normal: 'Intact, symmetric' },
|
||
{ label: 'Pain — upper', method: 'Broken Q-tip or pin on hands', normal: 'Intact, symmetric' },
|
||
{ label: 'Pain — lower', method: 'Same on feet', normal: 'Intact, symmetric' },
|
||
{ label: 'Vibration', method: '128 Hz tuning fork at distal IP joint of great toes', normal: 'Feels vibration; counts down seconds' },
|
||
{ label: 'Proprioception', method: 'Move great toe up/down with eyes closed', normal: 'Identifies direction correctly' }
|
||
], abnormalHints: ['Dermatomal loss (nerve root)', 'Stocking-glove (neuropathy)', 'Loss of vibration/proprioception (dorsal column — B12, tabes, MS)'] },
|
||
|
||
{ name: 'Coordination', steps: [
|
||
{ label: 'Finger-nose-finger', method: 'Touch examiner finger then own nose, examiner moves target', normal: 'Smooth, accurate, no dysmetria' },
|
||
{ label: 'Heel-to-shin', method: 'Supine: heel down opposite shin', normal: 'Smooth, on-target' },
|
||
{ label: 'Rapid alternating movements', method: 'Supinate/pronate hand on knee rapidly', normal: 'Rhythmic, symmetric' },
|
||
{ label: 'Fine motor', method: 'Finger tapping (thumb to each finger in sequence)', normal: 'Rhythmic, accurate' }
|
||
], abnormalHints: ['Dysmetria (past-pointing, overshoot)', 'Intention tremor', 'Dysdiadochokinesia'] },
|
||
|
||
{ name: 'Gait and Romberg', steps: [
|
||
{ label: 'Normal gait', method: 'Walk 20 feet', normal: 'Narrow-based, smooth, reciprocal arm swing' },
|
||
{ label: 'Heel walk', method: 'Walk on heels', normal: 'Able without difficulty' },
|
||
{ label: 'Toe walk', method: 'Walk on toes', normal: 'Able without difficulty' },
|
||
{ label: 'Tandem', method: 'Heel-to-toe along a line', normal: 'Minimal deviation, 10+ steps' },
|
||
{ label: 'Romberg', method: 'Feet together, eyes closed, 30s', normal: 'Stable without fall or significant sway' }
|
||
], abnormalHints: ['Wide-based (cerebellar)', 'Steppage (peripheral neuropathy)', 'Scissoring (UMN)', 'Romberg positive (dorsal column)', 'Circumduction'] }
|
||
]
|
||
}
|
||
},
|
||
|
||
adolescent: {
|
||
label: 'Adolescent (12–21 years)',
|
||
msk: {
|
||
overview: 'Sports-related injuries, adolescent scoliosis, apophyseal overuse, hypermobility screening.',
|
||
components: [
|
||
{ name: 'Scoliosis screen', steps: [
|
||
{ label: 'Standing inspection', method: 'Patient undressed to waist (keep privacy); compare shoulders, iliac crests, scapular heights', normal: 'Symmetric shoulders and pelvis' },
|
||
{ label: 'Forward bend (Adam)', method: 'Feet together, bend forward, arms hanging palms together', normal: 'Symmetric paraspinal contour' },
|
||
{ label: 'Scoliometer', method: 'Place across thoracic and lumbar regions at maximum prominence', normal: 'ATR <5°; 5–6° monitor; ≥7° refer' },
|
||
{ label: 'Plumb line check', method: 'Drop plumb from C7; note where it falls', normal: 'Passes through gluteal cleft (compensated)' },
|
||
{ label: 'Leg lengths', method: 'Supine; ASIS to medial malleolus each side', normal: 'Within 1cm' }
|
||
], abnormalHints: ['Rib/lumbar hump', 'ATR ≥7°', 'Decompensation (plumb off gluteal cleft)', 'Leg-length discrepancy driving apparent curve'] },
|
||
|
||
{ name: 'Back pain evaluation (if complaint)', steps: [
|
||
{ label: 'Inspect and palpate', method: 'Spinous processes, paraspinal muscles, SI joints', normal: 'Non-tender' },
|
||
{ label: 'Range of motion', method: 'Flex, extend, lateral bend, rotate', normal: 'Full painless range' },
|
||
{ label: 'Single-leg hyperextension (stork)', method: 'Stand on one foot, extend back — each side', normal: 'No pain (negative for spondylolysis)' },
|
||
{ label: 'Straight-leg raise', method: 'Supine, lift straight leg to 70°+', normal: 'No radicular pain to 70°' },
|
||
{ label: 'SI joint tests', method: 'FABER, SI compression', normal: 'No pain' }
|
||
], abnormalHints: ['Spondylolysis (positive stork test)', 'Radicular pain (disc herniation)', 'SI joint pathology', 'Inflammatory back pain pattern'] },
|
||
|
||
{ name: 'Joint stability — sports-specific', steps: [
|
||
{ label: 'Knee — Lachman', method: 'Knee 20° flexion, stabilize femur, pull tibia anteriorly', normal: 'Firm endpoint, no laxity (ACL intact)' },
|
||
{ label: 'Knee — anterior drawer', method: 'Knee 90°, pull tibia forward', normal: 'No excess anterior translation' },
|
||
{ label: 'Knee — varus/valgus stress', method: 'Stress at 0 and 30° flexion', normal: 'No gap opening (LCL/MCL intact)' },
|
||
{ label: 'Knee — McMurray', method: 'Flex, rotate tibia while extending', normal: 'No pain or click' },
|
||
{ label: 'Shoulder — apprehension', method: 'Abduct and externally rotate', normal: 'No apprehension' },
|
||
{ label: 'Shoulder — Neer/Hawkins', method: 'Passive flexion with internal rotation', normal: 'No pain' },
|
||
{ label: 'Ankle — anterior drawer', method: 'Pull heel forward with tibia stabilized', normal: 'No laxity' },
|
||
{ label: 'Ankle — talar tilt', method: 'Invert heel with tibia stabilized', normal: 'No excess tilt' }
|
||
], abnormalHints: ['ACL/PCL tear', 'MCL/LCL laxity', 'Meniscal injury', 'Shoulder instability/impingement', 'Ankle ligament laxity'] },
|
||
|
||
{ name: 'Apophysitis and overuse screen', steps: [
|
||
{ label: 'Tibial tubercle', method: 'Palpate with knee flexed', normal: 'Non-tender' },
|
||
{ label: 'Calcaneal apophysis', method: 'Palpate posterior calcaneus', normal: 'Non-tender' },
|
||
{ label: 'Iliac apophyses', method: 'Palpate ASIS, AIIS, iliac crest', normal: 'Non-tender' },
|
||
{ label: 'Rotator cuff', method: 'Empty-can (Jobe) test', normal: 'No pain or weakness' }
|
||
], abnormalHints: ['Osgood-Schlatter (tibial tubercle tender)', 'Sever (calcaneal tender)', 'Iliac apophysitis', 'Rotator cuff tendinopathy'] },
|
||
|
||
{ name: 'Hypermobility screen (Beighton)', steps: [
|
||
{ label: 'Fifth finger extension', method: 'Passive extension of fifth MCP to >90°', normal: 'No hyperextension (1 pt each side if positive)' },
|
||
{ label: 'Thumb to forearm', method: 'Passive flexion of thumb to touch forearm', normal: 'Does not reach (1 pt each side if positive)' },
|
||
{ label: 'Elbow hyperextension', method: 'Hyperextension >10°', normal: 'No hyperextension (1 pt each side if positive)' },
|
||
{ label: 'Knee hyperextension', method: 'Hyperextension >10°', normal: 'No hyperextension (1 pt each side if positive)' },
|
||
{ label: 'Palms to floor', method: 'Feet together, bend forward, palms flat on floor with knees straight', normal: 'Cannot reach (1 pt if positive)' }
|
||
], abnormalHints: ['Beighton ≥5/9 suggests hypermobility spectrum (hEDS workup if with other features)'] },
|
||
|
||
{ name: 'Alignment and gait', steps: [
|
||
{ label: 'Standing alignment', method: 'View knees, feet', normal: 'Neutral alignment, medial arch' },
|
||
{ label: 'Normal gait', method: 'Walk 20 feet', normal: 'Symmetric, smooth' },
|
||
{ label: 'Functional movements', method: 'Squat, single-leg stance, hop', normal: 'Full symmetric function' }
|
||
], abnormalHints: ['Antalgic gait', 'Trendelenburg', 'Asymmetric squat'] }
|
||
]
|
||
},
|
||
neuro: {
|
||
overview: 'Full adult-pattern neuro exam across six pillars: mental status, cranial nerves, motor, reflexes, sensory, coordination/gait. In adolescents, screen concussion sequelae if sports-active; frontal release signs must be absent.',
|
||
components: [
|
||
{ name: 'Mental status',
|
||
significance: 'Detects cognitive change (concussion, substance use, mood disorder, rare neurodegenerative disease).',
|
||
pearl: 'Attention precedes memory. A patient who can\'t attend (serial 7s, months backward) will fail memory even with intact hippocampus — distinguish before calling it a memory problem.',
|
||
steps: [
|
||
{ label: 'Orientation', method: 'Name, age, date, location, situation', normal: 'Oriented x 4' },
|
||
{ label: 'Attention', method: 'Count backward from 100 by 7s (serial 7s) or months of year backward', normal: 'Intact' },
|
||
{ label: 'Short-term memory', method: '3-item registration and recall at 5 min', normal: '3/3 recall' },
|
||
{ label: 'Language', method: 'Object naming; sentence repetition; reading; writing', normal: 'Fluent, no paraphasia, comprehends written and spoken' },
|
||
{ label: 'Executive function', method: 'Similarities (apple/orange); interpret proverb', normal: 'Abstract, age-appropriate' }
|
||
], abnormalHints: ['Post-concussion cognitive changes', 'Mood or personality changes', 'Subtle executive dysfunction', 'Word-finding difficulty'] },
|
||
|
||
{ name: 'Cranial nerves (II–XII, full formal exam)',
|
||
significance: 'Localises brainstem, base-of-skull, and specific nerve pathology. Subtle deficits (RAPD, mild facial weakness, Horner) are easily missed — exam discipline matters.',
|
||
pearl: 'The fastest screen for a CN deficit is asking the patient to speak, smile, look around, and swallow water. What\'s preserved in everyday function tells you what\'s likely intact — then examine formally to confirm and to catch the subtle.',
|
||
steps: [
|
||
{ label: 'CN I (if indicated)', method: 'Coffee or cinnamon each nostril separately', normal: 'Identifies both' },
|
||
{ label: 'CN II — acuity', method: 'Snellen at 20ft each eye; corrective lenses if worn', normal: '20/20 or baseline' },
|
||
{ label: 'CN II — fields', method: 'Confrontation, 4 quadrants each eye', normal: 'Full fields' },
|
||
{ label: 'CN II — fundoscopy', method: 'Direct ophthalmoscopy — disc, vessels, macula', normal: 'Sharp disc, normal cup/disc, no papilledema' },
|
||
{ label: 'CN II, III — pupils', method: 'Direct, consensual, swinging flashlight, accommodation', normal: 'PERRLA, no RAPD' },
|
||
{ label: 'CN III, IV, VI — EOM', method: 'H pattern, convergence, note nystagmus or ptosis', normal: 'Full conjugate movement, no nystagmus, convergence intact' },
|
||
{ label: 'CN V — sensation', method: 'Light touch V1, V2, V3 each side', normal: 'Intact, symmetric' },
|
||
{ label: 'CN V — motor', method: 'Clench jaw, palpate masseter/temporalis; lateral jaw movement', normal: 'Symmetric strength and bulk' },
|
||
{ label: 'CN V — corneal reflex (if indicated)', method: 'Cotton wisp to cornea', normal: 'Blinks bilaterally' },
|
||
{ label: 'CN VII', method: 'Wrinkle forehead, close eyes against resistance, smile/bare teeth, puff cheeks', normal: 'Symmetric all four movements' },
|
||
{ label: 'CN VIII — hearing', method: 'Finger rub each ear; Weber (midline) + Rinne (air > bone) if deficit', normal: 'Equal bilaterally' },
|
||
{ label: 'CN IX, X', method: 'Palate elevation with "ahh"; uvula midline; voice; gag (if indicated)', normal: 'Symmetric palate, uvula midline, normal voice' },
|
||
{ label: 'CN XI', method: 'Shoulder shrug and head turn against resistance', normal: '5/5 SCM and trapezius bilaterally' },
|
||
{ label: 'CN XII', method: 'Tongue protrusion, side to side; inspect for fasciculations/atrophy', normal: 'Midline, no atrophy or fasciculations, full movement' }
|
||
], abnormalHints: ['Any focal cranial nerve deficit', 'Papilledema', 'RAPD', 'Nystagmus', 'Facial asymmetry', 'Tongue deviation'] },
|
||
|
||
{ name: 'Motor — bulk, tone, strength',
|
||
significance: 'Localises lesion to UMN vs LMN vs muscle vs junction. Pattern of weakness (proximal vs distal, symmetric vs focal) narrows differential.',
|
||
pearl: 'Pronator drift is the most sensitive screen for subtle UMN weakness — a normal-feeling arm that drifts down with eyes closed still has corticospinal tract dysfunction. Always do it even when formal strength is 5/5.',
|
||
steps: [
|
||
{ label: 'Bulk inspection', method: 'Inspect shoulders, biceps, thighs, calves, dorsal interossei (between metacarpals) of hands.', normal: 'Symmetric bulk; no atrophy, no pseudohypertrophy' },
|
||
{ label: 'Tone — upper', method: 'Passive flex-extend elbow and pronate-supinate wrist at slow then quick speeds. Then pronator drift: arms outstretched, palms up, eyes closed for 10 s.', normal: 'Smooth passive range; no drift, no pronation of the outstretched hand' },
|
||
{ label: 'Tone — lower', method: 'Passive knee flexion-extension; quick ankle dorsiflexion to check for catch. Heel-slap test: roll thigh and watch for ankle swing.', normal: 'Normal resistance, no catch, symmetric' },
|
||
{ label: 'Strength — deltoid (C5)', method: 'Patient abducts both arms to 90°. Examiner pushes down on each arm just above the elbow while patient resists. Compare sides.', normal: 'Holds against full resistance — MRC 5/5 bilaterally' },
|
||
{ label: 'Strength — biceps (C5–C6)', method: 'Elbow flexed 90°, supinated. Examiner grasps wrist and pulls to extend while patient resists.', normal: 'Holds against full resistance — 5/5' },
|
||
{ label: 'Strength — triceps (C7)', method: 'Elbow flexed 90°. Examiner pushes wrist toward shoulder while patient extends against resistance.', normal: 'Extends against full resistance — 5/5' },
|
||
{ label: 'Strength — wrist extension (C6–C7)', method: 'Patient makes fist, extends wrist. Examiner pushes down on knuckles while patient holds wrist up.', normal: 'Holds against full resistance — 5/5' },
|
||
{ label: 'Strength — finger flexion / grip (C8)', method: 'Patient grips two of examiner\'s crossed fingers as hard as possible. Compare sides.', normal: 'Strong symmetric grip — 5/5' },
|
||
{ label: 'Strength — finger abduction (T1)', method: 'Patient spreads fingers wide. Examiner squeezes index and little fingers together while patient resists.', normal: 'Holds fingers apart — 5/5' },
|
||
{ label: 'Strength — hip flexion (L2–L3)', method: 'Supine. Patient lifts straight leg 30° off table. Examiner pushes down on thigh just above knee while patient resists.', normal: 'Holds thigh up against full resistance — 5/5' },
|
||
{ label: 'Strength — knee extension (L3–L4)', method: 'Sitting, knee 90°. Patient straightens knee while examiner pushes distal shin down.', normal: 'Extends against full resistance — 5/5' },
|
||
{ label: 'Strength — ankle dorsiflexion (L4–L5)', method: 'Patient pulls toes and foot up toward shin. Examiner pushes foot down at the dorsum.', normal: 'Holds dorsiflexion against full resistance — 5/5; preserved heel-walk' },
|
||
{ label: 'Strength — great toe extension (L5)', method: 'Patient extends great toe up while examiner pushes it down with thumb.', normal: 'Holds against full resistance — 5/5 (classic L5 test)' },
|
||
{ label: 'Strength — ankle plantarflexion (S1)', method: 'Patient pushes foot down against examiner\'s hand at the ball. OR ask patient to toe-walk 10 steps (more sensitive — unilateral plantarflexion weakness shows immediately).', normal: 'Full power; toe-walks symmetrically — 5/5' }
|
||
], abnormalHints: ['Focal weakness → localise by myotome', 'Pronator drift (subtle UMN, always check even with 5/5)', 'Spasticity / catch (UMN)', 'Atrophy (LMN, disuse)', 'Fasciculations (MND, ALS)', 'Pseudohypertrophy of calves (DMD in a young male)'] },
|
||
|
||
{ name: 'Deep tendon reflexes',
|
||
significance: 'Reflex pattern (increased, decreased, asymmetric) localises UMN vs LMN vs root vs peripheral nerve. Inexpensive and fast, but asymmetry is the most informative finding.',
|
||
pearl: 'A reinforced reflex is still a reflex. If you can\'t elicit it initially, use Jendrassik (teeth clench or pull interlocked fingers apart) to boost — absent reflexes without reinforcement aren\'t truly absent.',
|
||
steps: [
|
||
{ label: 'Biceps (C5–C6)', method: 'Patient\'s arm relaxed across lap. Examiner places thumb firmly on biceps tendon at the cubital fossa, strikes thumb with reflex hammer. Compare both sides sequentially.', normal: '2+ symmetric — visible contraction of biceps, slight elbow flexion' },
|
||
{ label: 'Brachioradialis (C5–C6)', method: 'Arm relaxed. Strike the distal radius about 3 cm proximal to the wrist, on its radial (thumb) side.', normal: '2+ symmetric — elbow flexion and slight forearm supination' },
|
||
{ label: 'Triceps (C7)', method: 'Support the patient\'s arm at the wrist with elbow at 90°. Strike the triceps tendon just above the olecranon.', normal: '2+ symmetric — triceps contraction, slight elbow extension' },
|
||
{ label: 'Finger flexors — Hoffmann sign', method: 'Grasp the middle finger\'s distal phalanx, flick it downward quickly and release. Watch the thumb and index finger.', normal: 'Negative — no thumb flexion, no index flexion (positive = corticospinal tract dysfunction)' },
|
||
{ label: 'Patellar (L3–L4)', method: 'Patient sits with knees hanging freely off the table. Strike the patellar tendon just below the patella.', normal: '2+ symmetric — quadriceps contraction with knee extension' },
|
||
{ label: 'Achilles (S1)', method: 'Patient\'s knee slightly flexed and leg externally rotated, or kneeling on a chair. Slightly dorsiflex the foot and strike the Achilles tendon.', normal: '2+ symmetric — plantar flexion of the foot' },
|
||
{ label: 'Plantar response (Babinski)', method: 'Stroke the lateral aspect of the sole firmly from the heel toward the little toe, then curve across the ball of the foot.', normal: 'Toes flex downward (plantar flexion, "down-going") bilaterally in anyone ≥ 2 years' },
|
||
{ label: 'Ankle clonus', method: 'Knee slightly bent. Support the shin with one hand, quickly and sharply dorsiflex the foot with the other, hold in dorsiflexion.', normal: '≤ 3 non-sustained beats is acceptable; sustained rhythmic oscillation = pathological clonus (UMN)' }
|
||
], abnormalHints: ['Hyperreflexia + sustained clonus = UMN (MS, myelopathy, cord lesion, stroke)', 'Symmetric hyporeflexia = peripheral polyneuropathy, GBS, myopathy, hypothyroid, B12 deficiency', 'Asymmetric hyporeflexia = radiculopathy at that segment', 'Hoffmann positive = corticospinal tract dysfunction at cervical cord or above', 'Up-going Babinski after age 2 = UMN (always abnormal)'] },
|
||
|
||
{ name: 'Sensory', steps: [
|
||
{ label: 'Light touch — upper', method: 'Cotton wisp, dorsum of hands, eyes closed', normal: 'Intact, symmetric' },
|
||
{ label: 'Light touch — lower', method: 'Dorsum of feet', normal: 'Intact, symmetric' },
|
||
{ label: 'Pain — upper', method: 'Broken Q-tip sharp end, hands', normal: 'Intact, symmetric' },
|
||
{ label: 'Pain — lower', method: 'Same on feet', normal: 'Intact, symmetric' },
|
||
{ label: 'Temperature (if indicated)', method: 'Cold tuning fork each area', normal: 'Intact' },
|
||
{ label: 'Vibration', method: '128 Hz tuning fork at distal IP of great toes; count seconds to fade', normal: 'Feels vibration; appropriate duration' },
|
||
{ label: 'Proprioception', method: 'Move great toe up/down with eyes closed', normal: 'Identifies direction correctly' },
|
||
{ label: 'Two-point discrimination (if indicated)', method: 'Blunt calipers on fingertip', normal: '<5mm on fingertip' },
|
||
{ label: 'Stereognosis (if indicated)', method: 'Identify coin/key in hand with eyes closed', normal: 'Correct identification' }
|
||
], abnormalHints: ['Dermatomal loss (nerve root)', 'Stocking-glove loss (length-dependent neuropathy)', 'Dorsal column loss (B12, tabes, MS — positive Romberg, vibration loss)', 'Cortical deficit (astereognosis, impaired 2-pt)'] },
|
||
|
||
{ name: 'Coordination', steps: [
|
||
{ label: 'Finger-nose-finger', method: 'Alternate examiner\'s finger and own nose; examiner moves target', normal: 'Smooth, accurate bilaterally' },
|
||
{ label: 'Heel-to-shin', method: 'Supine: heel down opposite shin and back', normal: 'Smooth, accurate' },
|
||
{ label: 'Rapid alternating (Dysdiadochokinesis)', method: 'Supinate/pronate hand rapidly on thigh', normal: 'Rhythmic, symmetric' },
|
||
{ label: 'Finger tapping', method: 'Thumb to each finger in sequence rapidly', normal: 'Rhythmic, smooth, symmetric' }
|
||
], abnormalHints: ['Dysmetria (cerebellar)', 'Intention tremor', 'Dysdiadochokinesia', 'Decomposed movement'] },
|
||
|
||
{ name: 'Gait and Romberg', steps: [
|
||
{ label: 'Normal gait', method: 'Walk 20 feet', normal: 'Narrow-based, smooth, reciprocal arm swing' },
|
||
{ label: 'Heel walk', method: 'Walk on heels only', normal: 'Able without difficulty' },
|
||
{ label: 'Toe walk', method: 'Walk on toes only', normal: 'Able without difficulty' },
|
||
{ label: 'Tandem', method: 'Heel-to-toe along a line, 10+ steps', normal: 'Minimal deviation' },
|
||
{ label: 'Romberg', method: 'Feet together, eyes open then closed, 30s', normal: 'Stable — no significant sway or fall with eyes closed' },
|
||
{ label: 'Single-leg stance', method: '10s each side, eyes open', normal: 'Stable without drift' }
|
||
], abnormalHints: ['Ataxic (wide-based — cerebellar)', 'Steppage (peripheral neuropathy / foot drop)', 'Circumduction (UMN hemiparesis)', 'Scissoring', 'Romberg positive (dorsal column)'] },
|
||
|
||
{ name: 'Frontal release / primitive reflexes', steps: [
|
||
{ label: 'Grasp reflex', method: 'Stroke palm', normal: 'Absent' },
|
||
{ label: 'Snout reflex', method: 'Tap upper lip', normal: 'No lip pucker' },
|
||
{ label: 'Glabellar tap', method: 'Tap between eyebrows — should habituate after 3–4 taps', normal: 'Habituates (no sustained blink)' },
|
||
{ label: 'Palmomental', method: 'Stroke thenar eminence', normal: 'No ipsilateral chin twitch' }
|
||
], abnormalHints: ['Presence suggests frontal lobe pathology, neurodegenerative disease, or severe TBI — rare in adolescence but relevant in post-concussion workup'] }
|
||
]
|
||
}
|
||
}
|
||
};
|
||
|
||
// ────────────────────────────────────────────────────────────
|
||
// STATE + RENDER
|
||
// ────────────────────────────────────────────────────────────
|
||
var _inited = false;
|
||
// state keyed as 'system-componentIdx-stepIdx' → { label, method, normal, status, note }
|
||
var state = {};
|
||
var currentSystem = 'msk';
|
||
var currentAgeGroup = '';
|
||
|
||
document.addEventListener('tabChanged', function (e) {
|
||
if (e.detail.tab !== 'peguide' || _inited) return;
|
||
_inited = true;
|
||
init();
|
||
});
|
||
|
||
function init() {
|
||
var ageSelect = document.getElementById('pe-age-group');
|
||
var content = document.getElementById('pe-content');
|
||
var actions = document.getElementById('pe-actions');
|
||
|
||
ageSelect.addEventListener('change', function () {
|
||
currentAgeGroup = ageSelect.value;
|
||
state = {};
|
||
document.getElementById('pe-output').classList.add('hidden');
|
||
if (!currentAgeGroup || !PE_DATA[currentAgeGroup]) {
|
||
content.innerHTML = '<p style="text-align:center;color:#9ca3af;padding:40px;">Select an age group above.</p>';
|
||
actions.style.display = 'none';
|
||
return;
|
||
}
|
||
renderSystem();
|
||
actions.style.display = 'flex';
|
||
});
|
||
|
||
document.querySelectorAll('[data-pesystem]').forEach(function (btn) {
|
||
btn.addEventListener('click', function () {
|
||
document.querySelectorAll('[data-pesystem]').forEach(function (b) { b.classList.remove('active'); });
|
||
btn.classList.add('active');
|
||
currentSystem = btn.dataset.pesystem;
|
||
state = {};
|
||
document.getElementById('pe-output').classList.add('hidden');
|
||
if (currentAgeGroup) renderSystem();
|
||
});
|
||
});
|
||
|
||
document.getElementById('pe-all-normal').addEventListener('click', setAllNormal);
|
||
document.getElementById('pe-all-clear').addEventListener('click', clearAll);
|
||
document.getElementById('pe-generate-btn').addEventListener('click', generate);
|
||
}
|
||
|
||
function renderSystem() {
|
||
var content = document.getElementById('pe-content');
|
||
var group = PE_DATA[currentAgeGroup];
|
||
if (!group || !group[currentSystem]) {
|
||
content.innerHTML = '<p style="text-align:center;color:#9ca3af;padding:40px;">No data for this combination.</p>';
|
||
return;
|
||
}
|
||
var section = group[currentSystem];
|
||
var accent = currentSystem === 'msk' ? '#0891b2' : '#7c3aed'; // cyan for MSK, purple for neuro
|
||
var accentTint = currentSystem === 'msk' ? '#ecfeff' : '#f5f3ff';
|
||
var html = '';
|
||
|
||
// ─ Overview banner ─
|
||
html += '<div class="card" style="margin-bottom:14px;border-left:4px solid ' + accent + ';">';
|
||
html += ' <div class="card-header" style="border:0;padding:14px 16px 6px;"><h3 style="margin:0;font-size:16px;color:' + accent + ';"><i class="fas fa-' + (currentSystem === 'msk' ? 'bone' : 'brain') + '"></i> ' + esc(group.label) + ' — ' + (currentSystem === 'msk' ? 'Musculoskeletal' : 'Neurologic') + '</h3></div>';
|
||
html += ' <div style="padding:0 16px 14px;font-size:13px;line-height:1.65;color:var(--g700);">' + esc(section.overview) + '</div>';
|
||
html += '</div>';
|
||
|
||
// ─ Grading scales reference (collapsible) ─
|
||
var scaleKeys = SYSTEM_SCALES[currentSystem] || [];
|
||
if (scaleKeys.length) {
|
||
html += '<details class="card" style="margin-bottom:14px;background:' + accentTint + ';border:1px solid ' + accent + '33;">';
|
||
html += ' <summary style="padding:10px 16px;cursor:pointer;font-weight:600;font-size:13px;color:' + accent + ';list-style:none;display:flex;align-items:center;gap:8px;"><i class="fas fa-book-medical"></i> Grading scales & reference <span style="font-weight:400;color:var(--g500);font-size:11px;">(click to expand)</span></summary>';
|
||
html += ' <div style="padding:0 16px 14px;display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:14px;">';
|
||
scaleKeys.forEach(function (sk) {
|
||
var sc = SCALES[sk]; if (!sc) return;
|
||
html += '<div style="background:#fff;border:1px solid var(--g200);border-radius:8px;padding:10px 12px;">';
|
||
html += ' <div style="font-weight:600;font-size:12px;color:var(--g800);margin-bottom:6px;"><i class="fas ' + sc.icon + '" style="color:' + accent + ';margin-right:6px;"></i>' + esc(sc.title) + '</div>';
|
||
html += ' <table style="width:100%;font-size:11px;line-height:1.5;border-collapse:collapse;">';
|
||
sc.rows.forEach(function (row) {
|
||
html += '<tr><td style="padding:2px 0;white-space:nowrap;color:' + accent + ';font-weight:600;font-family:ui-monospace,monospace;">' + esc(row[0]) + '</td><td style="padding:2px 0 2px 10px;color:var(--g700);">' + esc(row[1]) + '</td></tr>';
|
||
});
|
||
html += ' </table>';
|
||
html += '</div>';
|
||
});
|
||
html += ' </div>';
|
||
html += '</details>';
|
||
}
|
||
|
||
// ─ Components ─
|
||
section.components.forEach(function (c, ci) {
|
||
html += '<div class="card" style="margin-bottom:12px;border-left:3px solid ' + accent + ';">';
|
||
|
||
// Header
|
||
html += ' <div style="padding:12px 16px 8px;display:flex;align-items:center;justify-content:space-between;gap:10px;">';
|
||
html += ' <h3 style="margin:0;font-size:15px;color:var(--g800);">' + esc(c.name) + '</h3>';
|
||
html += ' <span style="font-size:10px;font-weight:600;padding:3px 8px;border-radius:10px;background:' + accent + '22;color:' + accent + ';text-transform:uppercase;letter-spacing:0.5px;white-space:nowrap;">' + c.steps.length + ' steps</span>';
|
||
html += ' </div>';
|
||
|
||
// Significance line
|
||
if (c.significance) {
|
||
html += ' <div style="padding:0 16px 6px;font-size:12px;color:var(--g600);line-height:1.55;"><i class="fas fa-bullseye" style="color:' + accent + ';margin-right:6px;font-size:11px;"></i>' + esc(c.significance) + '</div>';
|
||
}
|
||
|
||
// Teaching pearl
|
||
if (c.pearl) {
|
||
html += ' <div style="margin:6px 16px 10px;padding:10px 12px;background:#fef7e7;border-left:3px solid #f59e0b;border-radius:0 6px 6px 0;font-size:12px;line-height:1.6;color:#78350f;"><i class="fas fa-lightbulb" style="color:#f59e0b;margin-right:6px;"></i><em>' + esc(c.pearl) + '</em></div>';
|
||
}
|
||
|
||
// Steps
|
||
html += ' <div style="padding:4px 12px 10px;">';
|
||
c.steps.forEach(function (s, si) {
|
||
var key = currentSystem + '-' + ci + '-' + si;
|
||
if (!state[key]) state[key] = { component: c.name, label: s.label, method: s.method, normal: s.normal, status: null, note: '' };
|
||
var st = state[key].status;
|
||
var rowBg = st === 'normal' ? '#ecfdf5' : st === 'abnormal' ? '#fef2f2' : 'transparent';
|
||
var rowBorder = st === 'normal' ? '#a7f3d0' : st === 'abnormal' ? '#fecaca' : 'var(--g200)';
|
||
html += '<div class="pe-step" data-pe-key="' + key + '" style="padding:10px 12px;border:1px solid ' + rowBorder + ';border-radius:8px;margin-bottom:6px;background:' + rowBg + ';transition:background 0.12s,border-color 0.12s;">';
|
||
html += ' <div style="display:flex;align-items:flex-start;gap:10px;">';
|
||
html += ' <div style="flex-shrink:0;width:22px;height:22px;border-radius:50%;background:' + accent + '22;color:' + accent + ';font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center;line-height:1;">' + (si + 1) + '</div>';
|
||
html += ' <div style="flex:1;min-width:0;">';
|
||
html += ' <div style="font-weight:600;font-size:13px;color:var(--g800);">' + esc(s.label) + '</div>';
|
||
html += ' <div style="font-size:12px;color:var(--g600);margin-top:3px;line-height:1.55;"><span style="color:var(--g500);font-weight:600;text-transform:uppercase;letter-spacing:0.5px;font-size:10px;">How</span> ' + esc(s.method) + '</div>';
|
||
html += ' <div style="font-size:12px;color:var(--g600);margin-top:2px;line-height:1.55;"><span style="color:#059669;font-weight:600;text-transform:uppercase;letter-spacing:0.5px;font-size:10px;">Normal</span> ' + esc(s.normal) + '</div>';
|
||
html += ' </div>';
|
||
html += ' <div style="display:flex;gap:3px;flex-shrink:0;">';
|
||
html += ' <button class="visit-status-btn ' + (st === 'normal' ? 'done' : '') + '" data-pe-status="normal" data-pe-key="' + key + '" title="Normal">✓</button>';
|
||
html += ' <button class="visit-status-btn ' + (st === 'abnormal' ? 'refused' : '') + '" data-pe-status="abnormal" data-pe-key="' + key + '" title="Abnormal">✗</button>';
|
||
html += ' <button class="visit-status-btn ' + (st === null ? 'not-due' : '') + '" data-pe-status="skip" data-pe-key="' + key + '" title="Skip">—</button>';
|
||
html += ' </div>';
|
||
html += ' </div>';
|
||
html += ' <div class="pe-abnormal-detail" style="margin-top:8px;' + (st === 'abnormal' ? '' : 'display:none;') + '">';
|
||
html += ' <input type="text" class="pe-note" data-pe-key="' + key + '" placeholder="Describe the abnormal finding (e.g., 4/5 strength, left pronator drift)" value="' + esc(state[key].note || '') + '" style="width:100%;padding:6px 10px;font-size:12px;border:1px solid #fecaca;border-radius:6px;background:#fff;">';
|
||
html += ' </div>';
|
||
html += '</div>';
|
||
});
|
||
html += ' </div>';
|
||
|
||
// Watch-for
|
||
if (c.abnormalHints && c.abnormalHints.length) {
|
||
html += '<div style="margin:0 12px 12px;padding:10px 12px;background:#fef2f2;border-left:3px solid #ef4444;border-radius:0 6px 6px 0;font-size:11px;line-height:1.7;color:#7f1d1d;">';
|
||
html += '<div style="font-weight:600;text-transform:uppercase;letter-spacing:0.5px;color:#991b1b;margin-bottom:4px;font-size:10px;"><i class="fas fa-triangle-exclamation"></i> Watch for</div>';
|
||
html += c.abnormalHints.map(esc).join(' · ');
|
||
html += '</div>';
|
||
}
|
||
|
||
html += '</div>';
|
||
});
|
||
|
||
content.innerHTML = html;
|
||
|
||
content.querySelectorAll('[data-pe-status]').forEach(function (btn) {
|
||
btn.addEventListener('click', function () { handleStatus(btn); });
|
||
});
|
||
content.querySelectorAll('.pe-note').forEach(function (inp) {
|
||
inp.addEventListener('input', function () {
|
||
var key = inp.dataset.peKey;
|
||
if (state[key]) state[key].note = inp.value;
|
||
});
|
||
});
|
||
}
|
||
|
||
function handleStatus(btn) {
|
||
var key = btn.dataset.peKey;
|
||
var status = btn.dataset.peStatus;
|
||
if (!state[key]) return;
|
||
state[key].status = (status === 'skip') ? null : status;
|
||
var row = btn.closest('.pe-step');
|
||
if (row) {
|
||
var s = state[key].status;
|
||
row.style.background = s === 'normal' ? '#ecfdf5' : s === 'abnormal' ? '#fef2f2' : 'transparent';
|
||
row.style.borderColor = s === 'normal' ? '#a7f3d0' : s === 'abnormal' ? '#fecaca' : 'var(--g200)';
|
||
row.querySelectorAll('[data-pe-status]').forEach(function (b) {
|
||
b.classList.remove('done', 'refused', 'not-due');
|
||
if (b.dataset.peStatus === 'normal' && state[key].status === 'normal') b.classList.add('done');
|
||
if (b.dataset.peStatus === 'abnormal' && state[key].status === 'abnormal') b.classList.add('refused');
|
||
if (b.dataset.peStatus === 'skip' && state[key].status === null) b.classList.add('not-due');
|
||
});
|
||
var detail = row.querySelector('.pe-abnormal-detail');
|
||
if (detail) detail.style.display = (state[key].status === 'abnormal') ? '' : 'none';
|
||
}
|
||
}
|
||
|
||
function setAllNormal() {
|
||
Object.keys(state).forEach(function (k) { if (k.indexOf(currentSystem + '-') === 0) state[k].status = 'normal'; });
|
||
renderSystem();
|
||
}
|
||
function clearAll() {
|
||
Object.keys(state).forEach(function (k) { if (k.indexOf(currentSystem + '-') === 0) { state[k].status = null; state[k].note = ''; } });
|
||
renderSystem();
|
||
}
|
||
|
||
function generate() {
|
||
if (!currentAgeGroup || !PE_DATA[currentAgeGroup]) return;
|
||
var steps = Object.keys(state)
|
||
.filter(function (k) { return k.indexOf(currentSystem + '-') === 0; })
|
||
.map(function (k) { return state[k]; });
|
||
|
||
var assessed = steps.filter(function (s) { return s.status !== null; });
|
||
if (assessed.length === 0) { showToast('Mark at least one step Normal or Abnormal', 'error'); return; }
|
||
|
||
var btn = document.getElementById('pe-generate-btn');
|
||
btn.disabled = true; btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Generating...';
|
||
|
||
var modelSel = document.querySelector('#peguide-tab .tab-model-select');
|
||
var model = modelSel ? modelSel.value : '';
|
||
var format = document.getElementById('pe-format').value;
|
||
|
||
fetch('/api/generate-pe-narrative', {
|
||
method: 'POST',
|
||
headers: getAuthHeaders(),
|
||
body: JSON.stringify({
|
||
steps: steps,
|
||
ageGroup: PE_DATA[currentAgeGroup].label,
|
||
system: currentSystem,
|
||
patientAge: document.getElementById('pe-age').value,
|
||
patientGender: document.getElementById('pe-gender').value,
|
||
model: model,
|
||
format: format
|
||
})
|
||
})
|
||
.then(function (r) { return r.json(); })
|
||
.then(function (data) {
|
||
if (!data.success) { showToast(data.error || 'Generation failed', 'error'); return; }
|
||
var out = document.getElementById('pe-output');
|
||
out.classList.remove('hidden');
|
||
document.getElementById('pe-narrative-text').textContent = data.narrative;
|
||
var tag = document.getElementById('pe-model-tag');
|
||
if (tag) tag.textContent = data.model || '';
|
||
var bar = document.getElementById('pe-summary-bar');
|
||
if (bar && data.summary) {
|
||
bar.classList.remove('hidden');
|
||
bar.innerHTML = '<span style="color:#10b981;">' + data.summary.normal + ' normal</span> · <span style="color:#ef4444;">' + data.summary.abnormal + ' abnormal</span> · <span style="color:#9ca3af;">' + data.summary.notAssessed + ' skipped</span>';
|
||
}
|
||
})
|
||
.catch(function (err) { console.error('[PEGuide] generate error', err); showToast('Request failed', 'error'); })
|
||
.finally(function () {
|
||
btn.disabled = false; btn.innerHTML = '<i class="fas fa-wand-magic-sparkles"></i> Generate Exam Report';
|
||
});
|
||
}
|
||
|
||
function esc(s) {
|
||
if (s == null) return '';
|
||
return String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||
}
|
||
|
||
})();
|