pediatric-ai-scribe-v3/public/js/calculators.js
Daniel ddf9ca805b feat: C — extract Bedside reference into ES modules
Split the Bedside clinical reference section out of calculators.js
(~1220 lines) into 20 focused ES modules under public/js/bedside/.
Each module owns one clinical topic (cardiac, seizure, sepsis, burns,
etc.) and exports an init() wired up by bedside/index.js. Shared
helpers live in shared.js and also set window._EM for back-compat
with the 4 remaining call sites in calculators.js.

Load order: classic defer calculators.js first, then module script
bedside/index.js. Handlers bind at DOM-ready; runtime _EM lookups
resolve after both are evaluated.

Makes bedside content editable per-section, shrinks calculators.js
from 4111 to 2891 lines, and keeps the existing Playwright smoke
suite (e2e/tests/bedside-smoke.spec.js) as the behavioral contract.
2026-04-20 23:19:50 +02:00

2891 lines
232 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ============================================================
// CALCULATORS.JS — Pediatric clinical calculators
// ============================================================
(function() {
var _inited = false;
document.addEventListener('tabChanged', function(e) {
if (e.detail.tab !== 'calculators' || _inited) return;
_inited = true;
initCalculators();
});
// ── Flexible age parser ─────────────────────────────────────────────
// Accepts: "3y", "3 years", "29m", "29 months", "2y5m", "2 years 5 months",
// "15d", "15 days", "3y 2m 10d", "36" (months), "3.5 years", etc.
// Returns age in months (may be fractional), or null if unparseable.
function parseAgeMonths(input) {
if (input == null) return null;
var s = String(input).toLowerCase().trim();
if (!s) return null;
// Plain number with no unit: if >= 24 assume years, else months. Matches
// common shorthand ("36" for 3y, "6" for 6 months).
if (/^[\d.]+$/.test(s)) {
var n = parseFloat(s);
if (isNaN(n)) return null;
return n >= 24 ? n : n; // keep as months; user can add unit if they meant years
}
var total = 0;
var matched = false;
// Use (?![a-z]) instead of \b so "2y5m" terminates "y" correctly.
// Order matters: longest-first alternations (years before yrs before y, etc.).
var my = s.match(/([\d.]+)\s*(?:years|year|yrs|yr|y)(?![a-z])/);
if (my) { total += parseFloat(my[1]) * 12; matched = true; }
var mm = s.match(/([\d.]+)\s*(?:months|month|mos|mo|m)(?![a-z])/);
if (mm) { total += parseFloat(mm[1]); matched = true; }
var mw = s.match(/([\d.]+)\s*(?:weeks|week|wks|wk|w)(?![a-z])/);
if (mw) { total += parseFloat(mw[1]) * 7 / 30.4375; matched = true; }
var md = s.match(/([\d.]+)\s*(?:days|day|d)(?![a-z])/);
if (md) { total += parseFloat(md[1]) / 30.4375; matched = true; }
return matched ? total : null;
}
function formatParsedAge(months) {
if (months < 1) {
var d = Math.round(months * 30.4375);
return '= ' + d + ' day' + (d === 1 ? '' : 's') + ' (' + months.toFixed(2) + ' mo)';
}
if (months < 24) {
return '= ' + (Math.round(months * 10) / 10) + ' months';
}
var yr = Math.floor(months / 12);
var mo = Math.round(months - yr * 12);
if (mo === 12) { yr += 1; mo = 0; }
return '= ' + yr + ' yr' + (mo ? ' ' + mo + ' mo' : '') + ' (' + Math.round(months) + ' mo total)';
}
// Expose for debugging / other modules
window._parseAgeMonths = parseAgeMonths;
function initCalculators() {
// ── Top-level pill navigation (scoped to .calc-nav-pill only) ──
document.querySelectorAll('.calc-nav-pill').forEach(function(pill) {
pill.addEventListener('click', function() {
document.querySelectorAll('.calc-nav-pill').forEach(function(p) { p.classList.remove('active'); });
document.querySelectorAll('.calc-panel').forEach(function(p) { p.classList.add('hidden'); });
pill.classList.add('active');
var panel = document.getElementById('calc-' + pill.dataset.calc);
if (panel) panel.classList.remove('hidden');
});
});
// ═══════════════════════════════════════════════════════════
// BP PERCENTILE — BCM/Rosner Quantile Spline Regression
// AAP 2017 classification with exact percentile computation
// ═══════════════════════════════════════════════════════════
// Height LMS parameters (218 entries, index 0 = month 24 / age 2y, index 217 = month 241)
var _htLMS_F_L=[1.07244896,1.051272912,1.041951175,1.012592236,0.970541909,0.921129988,0.868221392,0.81454413,0.761957977,0.711660228,0.664323379,0.620285102,0.57955631,0.54198094,0.511429832,0.482799937,0.455521041,0.429150288,0.403351725,0.377878239,0.352555862,0.327270297,0.301955463,0.276583851,0.251158446,0.225705996,0.20027145,0.174913356,0.149700081,0.12470671,0.100012514,0.075698881,0.051847635,0.02853967,0.005853853,-0.016133871,-0.037351181,-0.057729947,-0.077206672,-0.09572283,-0.113225128,-0.129665689,-0.145002179,-0.159197885,-0.172221748,-0.184048358,-0.194660215,-0.204030559,-0.212174408,-0.219069129,-0.224722166,-0.229140412,-0.232335686,-0.234324563,-0.235128195,-0.234772114,-0.233286033,-0.230703633,-0.227062344,-0.222403111,-0.216770161,-0.210210748,-0.202774891,-0.194515104,-0.185486099,-0.175744476,-0.165348396,-0.15435722,-0.142831123,-0.130830669,-0.118416354,-0.105648092,-0.092584657,-0.079283065,-0.065797888,-0.0521805,-0.03847825,-0.024733545,-0.010982868,0.002744306,0.016426655,0.030052231,0.043619747,0.05713988,0.070636605,0.08414848,0.097729873,0.111452039,0.125404005,0.13969316,0.154445482,0.169805275,0.185934346,0.203010488,0.2212252,0.240780542,0.261885086,0.284748919,0.309577733,0.336566048,0.365889711,0.397699038,0.432104409,0.46917993,0.508943272,0.551354277,0.596307363,0.643626542,0.693062173,0.744289752,0.79691098,0.85045728,0.904395871,0.958138449,1.011054559,1.062474568,1.111727029,1.158135105,1.201050821,1.239852328,1.274006058,1.303044695,1.326605954,1.344443447,1.356437773,1.362602695,1.363085725,1.358162799,1.348227142,1.333772923,1.315374704,1.293664024,1.269304678,1.242968236,1.21531127,1.186955477,1.158471522,1.130367088,1.103079209,1.076970655,1.052329922,1.029374161,1.008254396,0.989062282,0.971837799,0.95657215,0.94324228,0.931767062,0.922058291,0.914012643,0.907516917,0.902452436,0.898698641,0.896143482,0.894659668,0.89413892,0.894475371,0.895569834,0.897330209,0.899671635,0.902516442,0.905793969,0.909440266,0.913397733,0.91761471,0.922045055,0.926647697,0.931386217,0.93622842,0.941145943,0.94611388,0.95111043,0.956116576,0.961115792,0.966093766,0.971038162,0.975938391,0.980785418,0.985571579,0.99029042,0.994936555,0.999505539,1.003993753,1.0083983,1.012716921,1.016947912,1.021090055,1.025142554,1.029104983,1.032977233,1.036759475,1.040452117,1.044055774,1.047571238,1.050999451,1.054341482,1.057598512,1.060771808,1.063862715,1.066872639,1.069803036,1.072655401,1.075431258,1.078132156,1.080759655,1.083315329,1.085800751,1.088217496,1.090567133,1.092851222,1.095071313,1.097228939,1.099325619,1.101362852,1.103342119,1.105264876,1.107132561,1.108046193];
var _htLMS_F_M=[84.97555512,85.3973169,86.29026318,87.15714182,87.9960184,88.8055115,89.58476689,90.33341722,91.0515436,91.7396352,92.39854429,93.02945392,93.63382278,94.21335709,94.79643239,95.37391918,95.94692677,96.51644912,97.08337211,97.6484807,98.21246579,98.77593069,99.33939735,99.9033122,100.4680516,101.033927,101.6011898,102.1700358,102.7406094,103.3130077,103.8872839,104.4634511,105.0414853,105.6213287,106.2028921,106.7860583,107.3706841,107.9566031,108.5436278,109.1315521,109.7201531,110.3091934,110.8984228,111.4875806,112.0763967,112.6645943,113.2518902,113.8380006,114.4226317,115.0054978,115.5863089,116.1647782,116.7406221,117.3135622,117.8833259,118.4496481,119.0122722,119.5709513,120.1254495,120.6755427,121.22102,121.7616844,122.2973542,122.827864,123.3530652,123.8728276,124.38704,124.8956114,125.398472,125.895574,126.3868929,126.8724284,127.3522056,127.8262759,128.2947187,128.757642,129.2151839,129.6675143,130.1148354,130.5573839,130.995432,131.4292887,131.8593015,132.2858574,132.7093845,133.1303527,133.5492749,133.9667073,134.3832499,134.7995463,135.2162826,135.634186,136.0540223,136.4765925,136.9027281,137.3332846,137.7691339,138.2111552,138.6602228,139.1171933,139.5828898,140.0580848,140.5434787,141.0396832,141.5471945,142.0663731,142.59742,143.1403553,143.6949981,144.2609497,144.8375809,145.4240246,146.0191748,146.621692,147.2300177,147.8423918,148.4568879,149.0714413,149.6838943,150.2920328,150.8936469,151.4865636,152.0686985,152.6380955,153.1929631,153.7317031,154.2529332,154.755501,155.2384904,155.7012216,156.1432438,156.564323,156.9644258,157.3436995,157.7024507,158.0411233,158.3602756,158.6605588,158.9426964,159.2074654,159.455679,159.688172,159.9057871,160.1093647,160.299733,160.4776996,160.6440526,160.7995428,160.9448916,161.0807857,161.2078755,161.3267744,161.4380593,161.5422726,161.639917,161.7314645,161.8173534,161.8979913,161.9737558,162.0449969,162.1120386,162.17518,162.2346979,162.2908474,162.343864,162.3939652,162.4413513,162.4862071,162.5287029,162.5689958,162.6072309,162.6435418,162.6780519,162.7108751,162.7421168,162.7718741,162.8002371,162.8272889,162.8531067,162.8777619,162.9013208,162.9238449,162.9453912,162.9660131,162.9857599,163.0046776,163.0228094,163.0401953,163.0568727,163.0728768,163.0882404,163.1029943,163.1171673,163.1307866,163.1438776,163.1564644,163.1685697,163.1802146,163.1914194,163.202203,163.2125835,163.2225779,163.2322024,163.2414722,163.2504019,163.2590052,163.2672954,163.2752848,163.2829854,163.2904086,163.297565,163.304465,163.3111185,163.3175349,163.3237231,163.3296918,163.3354491,163.338251];
var _htLMS_F_S=[0.040791394,0.040859727,0.041142161,0.041349399,0.041500428,0.041610508,0.041691761,0.04175368,0.041803562,0.041846882,0.041887626,0.041928568,0.041971514,0.042017509,0.042104522,0.042199507,0.042300333,0.042405225,0.042512706,0.042621565,0.042730809,0.042839638,0.042947412,0.043053626,0.043157889,0.043259907,0.043359463,0.043456406,0.043550638,0.043642107,0.043730791,0.043816701,0.043899867,0.043980337,0.044058171,0.04413344,0.044206218,0.044276588,0.044344632,0.044410436,0.044474084,0.044535662,0.044595254,0.044652942,0.044708809,0.044762936,0.044815402,0.044866288,0.044915672,0.044963636,0.045010259,0.045055624,0.045099817,0.045142924,0.045185036,0.045226249,0.045266662,0.045306383,0.045345524,0.045384203,0.045422551,0.045460702,0.045498803,0.045537012,0.045575495,0.045614432,0.045654016,0.04569445,0.045735953,0.045778759,0.045823114,0.04586928,0.045917535,0.045968169,0.04602149,0.046077818,0.046137487,0.046200842,0.04626824,0.046340046,0.046416629,0.046498361,0.046585611,0.046678741,0.046778099,0.04688401,0.046996769,0.047116633,0.047243801,0.047378413,0.047520521,0.047670085,0.047826946,0.04799081,0.048161228,0.04833757,0.048519011,0.048704503,0.048892759,0.049082239,0.049271137,0.049457371,0.049638596,0.049812203,0.049975355,0.050125012,0.050257992,0.050371024,0.050460835,0.050524236,0.050558224,0.050560083,0.050527494,0.050458634,0.050352269,0.050207825,0.050025434,0.049805967,0.049551023,0.049262895,0.048944504,0.048599314,0.048231224,0.047844442,0.047443362,0.04703243,0.046616026,0.046198356,0.04578335,0.045374597,0.044975281,0.044588148,0.044215488,0.043859135,0.04352048,0.043200497,0.042899776,0.042618565,0.042356812,0.042114211,0.041890247,0.04168424,0.041495379,0.041322765,0.041165437,0.041022401,0.040892651,0.040775193,0.040669052,0.040573288,0.040487005,0.040409354,0.040339537,0.040276811,0.040220488,0.040169932,0.040124562,0.040083845,0.040047295,0.040014473,0.03998498,0.039958458,0.039934584,0.039913066,0.039893644,0.039876087,0.039860185,0.039845754,0.039832629,0.039820663,0.039809725,0.0397997,0.039790485,0.039781991,0.039774136,0.03976685,0.03976007,0.039753741,0.039747815,0.039742249,0.039737004,0.039732048,0.039727352,0.03972289,0.03971864,0.039714581,0.039710697,0.039706971,0.039703391,0.039699945,0.039696623,0.039693415,0.039690313,0.039687311,0.039684402,0.039681581,0.039678842,0.039676182,0.039673596,0.039671082,0.039668635,0.039666254,0.039663936,0.039661679,0.039659481,0.039657339,0.039655252,0.039653218,0.039651237,0.039649306,0.039647424,0.039645591,0.039643804,0.039642063,0.039640367,0.039638715,0.039637105,0.039636316];
var _htLMS_M_L=[0.941523967,1.00720807,0.837251351,0.681492975,0.538779654,0.407697153,0.286762453,0.174489485,0.069444521,-0.029720564,-0.124251789,-0.215288396,-0.30385434,-0.390918369,-0.254801167,-0.125654535,-0.00316735,0.11291221,0.222754969,0.326530126,0.42436156,0.516353108,0.602595306,0.683170764,0.758158406,0.827636736,0.891686306,0.95039153,1.003830006,1.05213569,1.0953669,1.133652119,1.167104213,1.195845353,1.220004233,1.239715856,1.255121285,1.266367398,1.273606657,1.276996893,1.276701119,1.272887366,1.265728536,1.255402281,1.242090871,1.225981067,1.207263978,1.186140222,1.162796198,1.137442868,1.110286487,1.081536236,1.05140374,1.020102497,0.987847213,0.954853043,0.921334742,0.887505723,0.85357703,0.819756239,0.786246296,0.753244292,0.720940222,0.689515708,0.659142731,0.629997853,0.602203984,0.575908038,0.55123134,0.528279901,0.507143576,0.487895344,0.470590753,0.455267507,0.441945241,0.430625458,0.421291648,0.413909588,0.408427813,0.404778262,0.402877077,0.402625561,0.40391127,0.406609232,0.410583274,0.415687443,0.421767514,0.428662551,0.436206531,0.44423,0.45256176,0.461030578,0.469466904,0.477704608,0.48558272,0.492947182,0.499652617,0.505564115,0.510559047,0.514528903,0.517381177,0.519041285,0.519454524,0.518588072,0.516433004,0.513006312,0.508352901,0.502547502,0.495696454,0.487939275,0.479449924,0.470437652,0.461147305,0.451858946,0.442886661,0.434576385,0.427302633,0.421464027,0.417477538,0.415771438,0.416777012,0.420919142,0.428606007,0.440218167,0.456097443,0.476536014,0.501766234,0.531951655,0.567179725,0.607456565,0.652704121,0.702759868,0.757379106,0.816239713,0.878947416,0.945053486,1.014046108,1.085383319,1.158487278,1.232768816,1.307628899,1.382473225,1.456720479,1.529810247,1.601219573,1.670433444,1.736995571,1.800483802,1.860518777,1.916765525,1.968934444,2.016781776,2.060109658,2.098765817,2.132642948,2.16167779,2.185849904,2.205180153,2.219728869,2.2295937,2.234907144,2.235833767,2.232567138,2.2253265,2.214353232,2.199905902,2.182262864,2.161704969,2.138524662,2.113023423,2.085490286,2.0562195,2.025496648,1.993598182,1.960789092,1.927320937,1.89343024,1.859337259,1.825245107,1.791339209,1.757787065,1.724738292,1.692324905,1.660661815,1.629847495,1.599964788,1.571081817,1.543252982,1.516519998,1.490912963,1.466451429,1.44314546,1.420996665,1.399999187,1.380140651,1.361403047,1.343763564,1.327195355,1.311668242,1.297149359,1.283603728,1.270994782,1.25928483,1.248435461,1.23840791,1.229163362,1.220663228,1.212869374,1.20574431,1.199251356,1.19335477,1.188019859,1.183213059,1.178901998,1.175055543,1.171643828,1.16863827,1.167279219];
var _htLMS_M_M=[86.45220101,86.86160934,87.65247282,88.42326434,89.17549228,89.91040853,90.62907762,91.33242379,92.02127167,92.69637946,93.35846546,94.00822923,94.64636981,95.27359106,95.91474929,96.54734328,97.17191309,97.78897727,98.3990283,99.00254338,99.599977,100.191764,100.7783198,101.3600411,101.9373058,102.5104735,103.0798852,103.645864,104.208713,104.7687256,105.3261638,105.8812823,106.4343146,106.9854769,107.534968,108.0829695,108.6296457,109.1751441,109.7195954,110.2631136,110.8057967,111.3477265,111.8889694,112.4295761,112.9695827,113.5090108,114.0478678,114.5861486,115.1238315,115.6608862,116.1972691,116.732925,117.2677879,117.8017819,118.3348215,118.8668123,119.397652,119.9272309,120.455433,120.9821362,121.5072136,122.0305342,122.5519634,123.0713645,123.588599,124.1035312,124.6160161,125.1259182,125.6331012,126.1374319,126.6387804,127.1370217,127.6320362,128.1237104,128.6119383,129.096622,129.5776723,130.0550101,130.5285669,130.9982857,131.4641218,131.9260439,132.3840348,132.838092,133.2882291,133.7344759,134.1768801,134.6155076,135.0504433,135.4817925,135.9096813,136.3342577,136.7556923,137.1741794,137.5899378,138.0032114,138.4142703,138.8234114,139.2309592,139.6372663,140.042714,140.4477127,140.8527022,141.2581515,141.6645592,142.072452,142.4823852,142.8949403,143.3107241,143.7303663,144.1545167,144.5838414,145.0190192,145.4607359,145.9096784,146.3665278,146.8319513,147.3065929,147.7910635,148.2859294,148.7917006,149.3088178,149.8376391,150.3784267,150.9313331,151.4963887,152.0734897,152.6623878,153.2626819,153.8738124,154.495058,155.1255365,155.7642086,156.4098858,157.0612415,157.7168289,158.3750929,159.034399,159.6930501,160.3493168,161.0014586,161.6477515,162.2865119,162.9161202,163.535045,164.1418486,164.7352199,165.3139755,165.8770715,166.4236087,166.9528354,167.4641466,167.9570814,168.4313175,168.8866644,169.3230548,169.7405351,170.139255,170.5194567,170.881464,171.2256717,171.5525345,171.8625576,172.1562865,172.4342983,172.6971935,172.9455898,173.180112,173.4013896,173.6100518,173.8067179,173.9919998,174.1664951,174.3307855,174.4854344,174.6309856,174.7679617,174.8968634,175.0181691,175.1323345,175.2397926,175.340954,175.4362071,175.5259191,175.6104358,175.690083,175.7651671,175.8359757,175.9027788,175.9658293,176.0253641,176.081605,176.1347593,176.1850208,176.2325707,176.2775781,176.3202008,176.3605864,176.3988725,176.4351874,176.469651,176.5023751,176.533464,176.5630153,176.5911197,176.6178621,176.6433219,176.6675729,176.6906844,176.712721,176.733743,176.753807,176.7729657,176.7912687,176.8087622,176.8254895,176.8414914,176.8492322];
var _htLMS_M_S=[0.040321528,0.040395626,0.040577525,0.040723122,0.040833194,0.040909059,0.040952433,0.04096533,0.040949976,0.040908737,0.040844062,0.040758431,0.040654312,0.04053412,0.040572876,0.04061691,0.040666414,0.040721467,0.040782045,0.040848042,0.040919281,0.040995524,0.041076485,0.041161838,0.041251224,0.041344257,0.041440534,0.041539635,0.041641136,0.041744602,0.041849607,0.041955723,0.042062532,0.042169628,0.042276619,0.042383129,0.042488804,0.042593311,0.042696342,0.042797615,0.042896877,0.042993904,0.043088503,0.043180513,0.043269806,0.043356287,0.043439893,0.043520597,0.043598407,0.043673359,0.043745523,0.043815003,0.043881929,0.043946461,0.044008785,0.044069112,0.044127675,0.044184725,0.044240532,0.044295379,0.044349559,0.044403374,0.04445713,0.044511135,0.044565693,0.044621104,0.044677662,0.044735646,0.044795322,0.044856941,0.04492073,0.044986899,0.045055632,0.045127088,0.045201399,0.045278671,0.045358979,0.045442372,0.045528869,0.045618459,0.045711105,0.045806742,0.045905281,0.046006604,0.046110573,0.046217028,0.04632579,0.046436662,0.04654943,0.046663871,0.046779748,0.046896817,0.047014827,0.047133525,0.047252654,0.047371961,0.047491194,0.047610108,0.047728463,0.04784603,0.047962592,0.048077942,0.048191889,0.048304259,0.048414893,0.048523648,0.048630402,0.04873505,0.048837504,0.048937694,0.049035564,0.049131073,0.049224189,0.049314887,0.049403145,0.049488934,0.049572216,0.049652935,0.049731004,0.0498063,0.04987865,0.049947823,0.050013518,0.050075353,0.050132858,0.050185471,0.050232532,0.050273285,0.050306885,0.050332406,0.05034886,0.050355216,0.050350423,0.050333444,0.050303283,0.050259018,0.050199837,0.050125062,0.05003418,0.049926861,0.049802977,0.04966261,0.049506051,0.049333801,0.049146553,0.04894519,0.048730749,0.048504404,0.048267442,0.04802123,0.047767192,0.047506783,0.047241456,0.04697265,0.046701759,0.046430122,0.046159004,0.045889585,0.045622955,0.045360101,0.045101913,0.044849174,0.044602566,0.044362674,0.044129985,0.043904897,0.043687723,0.043478698,0.043277987,0.043085685,0.042901835,0.042726424,0.042559396,0.042400652,0.042250063,0.042107465,0.041972676,0.041845488,0.041725679,0.041613015,0.041507249,0.041408129,0.041315398,0.041228796,0.04114806,0.041072931,0.04100315,0.040938463,0.040878617,0.040823368,0.040772475,0.040725706,0.040682834,0.04064364,0.040607913,0.040575448,0.040546051,0.040519532,0.040495713,0.040474421,0.040455493,0.040438773,0.040424111,0.040411366,0.040400405,0.040391101,0.040383334,0.04037699,0.040371962,0.040368149,0.040365456,0.040363795,0.04036308,0.040363233,0.040364179,0.04036585,0.04036818,0.040369574];
// BP Rosner spline coefficients (99 percentiles x 13 coefficients)
var _bpCoeff_F_SYS=[
[-7.4855,-1.2252,1.2643,-6.8797,20.4744,0.7114,-0.0066,-0.0667,0.3564,-0.0012,0.5278,-0.6927,0.1388],
[8.4462,-0.9598,0.9046,-5.1098,15.1548,0.5919,-0.0029,-0.065,0.2495,-0.003,0.4421,-0.5724,0.0997],
[26.6223,-1.1479,1.2134,-8.4665,28.0408,0.475,0.0001,-0.0643,0.2062,-0.023,0.5561,-0.7467,0.185],
[31.8947,-0.867,1.1693,-8.2932,26.0849,0.4251,-0.0002,-0.0535,0.1718,-0.008,0.3954,-0.5402,0.1473],
[30.9472,-1.1288,1.5926,-11.7371,34.5934,0.4578,-0.0019,-0.0341,0.1144,-0.0167,0.6897,-1.0025,0.3867],
[23.152,-1.1368,1.751,-13.8556,41.2104,0.527,-0.0048,-0.0149,0.0623,0.0062,0.4347,-0.6509,0.2798],
[19.3036,-0.923,1.6566,-14.2294,42.9522,0.5494,-0.0062,-0.0051,0.0555,0.0242,0.1295,-0.1986,0.0876],
[20.0191,-1.0378,1.6928,-13.6476,40.8615,0.5596,-0.0071,0.0146,-0.03,0.0135,0.1632,-0.2423,0.1013],
[21.6515,-0.9745,1.5964,-13.0096,38.8309,0.5462,-0.0063,0.0087,-0.0183,0.0093,0.2644,-0.3848,0.1477],
[22.6952,-0.8665,1.4799,-11.8203,34.2277,0.537,-0.0066,0.0176,-0.0648,0.0046,0.3226,-0.4689,0.1811],
[23.1615,-0.8132,1.4422,-11.8893,34.8542,0.5329,-0.0063,0.013,-0.0367,0.008,0.34,-0.5072,0.2171],
[27.9,-0.8288,1.4257,-11.5803,33.7393,0.4995,-0.0049,0.0013,0.0117,-0.0014,0.4954,-0.7333,0.3051],
[34.8678,-0.801,1.429,-11.2835,32.3656,0.4469,-0.0037,-0.0037,0.0274,-0.0004,0.3936,-0.5873,0.251],
[37.7557,-0.9638,1.5603,-11.545,31.5671,0.4392,-0.0035,0.0024,-0.0164,-0.0087,0.395,-0.575,0.2238],
[39.9509,-1.0185,1.6189,-11.6485,31.009,0.4284,-0.0032,0.0051,-0.0452,-0.0101,0.3516,-0.5073,0.1906],
[40.8576,-0.9313,1.5386,-11.5031,31.8413,0.418,-0.0029,0.0019,-0.0291,-0.0081,0.3507,-0.5094,0.1968],
[42.1455,-0.9104,1.5356,-11.4411,31.5567,0.4098,-0.0029,0.0038,-0.0368,-0.006,0.2848,-0.4155,0.1642],
[44.0009,-1.0103,1.6565,-11.8711,31.8672,0.4038,-0.0026,0.0007,-0.0172,-0.0017,0.1877,-0.2802,0.1211],
[42.9483,-0.9479,1.6532,-12.4439,34.3937,0.4097,-0.0029,0.0023,-0.0231,-0.0003,0.1892,-0.2761,0.1077],
[43.4489,-0.9355,1.5751,-11.4463,30.9525,0.4076,-0.0027,0,-0.0199,0.0013,0.1619,-0.2376,0.0949],
[42.0432,-0.9668,1.5892,-11.2769,29.6658,0.4235,-0.003,0.0009,-0.0194,0.0051,0.1181,-0.1781,0.0784],
[43.3921,-0.9251,1.5125,-10.669,27.8566,0.4122,-0.0025,-0.0008,-0.0269,-0.0003,0.178,-0.2571,0.0962],
[43.1823,-0.9153,1.5502,-11.2058,29.7148,0.4154,-0.0028,0.0025,-0.0386,0.0053,0.0679,-0.0977,0.0352],
[43.5111,-0.8427,1.4724,-10.8634,29.5168,0.4107,-0.0027,0.0019,-0.0416,-0.0023,0.1644,-0.2282,0.0711],
[44.8115,-0.9195,1.5496,-10.7815,27.8384,0.4087,-0.003,0.012,-0.0908,-0.0063,0.1451,-0.1957,0.053],
[45.1153,-0.8419,1.4685,-10.4821,27.7389,0.404,-0.003,0.0148,-0.1094,-0.0047,0.1524,-0.2131,0.0715],
[45.0184,-0.9109,1.4637,-9.8769,25.3956,0.4124,-0.0031,0.0163,-0.1196,-0.0095,0.2128,-0.3015,0.1084],
[46.8396,-0.9336,1.4913,-10.0409,25.5791,0.4004,-0.0025,0.0087,-0.0854,-0.0083,0.207,-0.2945,0.1065],
[46.3627,-1.0691,1.6403,-10.8997,27.3749,0.4156,-0.003,0.0128,-0.0892,-0.006,0.1891,-0.2783,0.1168],
[46.056,-1.0253,1.6174,-10.8914,27.6133,0.4169,-0.0032,0.0134,-0.0831,-0.0015,0.1168,-0.1751,0.0794],
[45.8707,-1.0687,1.6929,-11.5282,29.3823,0.4234,-0.0035,0.0189,-0.1052,-0.002,0.0549,-0.0766,0.0279],
[46.225,-1.0493,1.6305,-11.0002,28.295,0.4212,-0.0032,0.015,-0.0892,0.001,0.0192,-0.0279,0.014],
[49.7043,-1.1168,1.6687,-10.6909,26.5418,0.4005,-0.0027,0.0175,-0.1166,-0.0029,-0.0064,0.0124,-0.0056],
[52.501,-1.2283,1.7174,-10.288,24.6009,0.39,-0.0025,0.0229,-0.1413,-0.0055,-0.0773,0.1151,-0.0428],
[52.638,-1.2668,1.7982,-10.7251,24.8323,0.393,-0.0027,0.0233,-0.1352,-0.0037,-0.1218,0.1797,-0.0678],
[52.9451,-1.2987,1.8214,-10.8739,25.4383,0.3952,-0.0028,0.0249,-0.1365,-0.0026,-0.1753,0.2588,-0.1002],
[51.6977,-1.2275,1.7723,-10.6355,24.5465,0.4024,-0.0032,0.0273,-0.1377,0.0023,-0.2334,0.3428,-0.1327],
[51.5803,-1.1856,1.7323,-10.549,24.7169,0.4027,-0.0033,0.029,-0.1504,0.004,-0.2752,0.4081,-0.1658],
[52.5542,-1.1951,1.7357,-10.3953,23.5706,0.3978,-0.0032,0.0312,-0.1661,0.0005,-0.2249,0.34,-0.1482],
[54.7146,-1.2604,1.8028,-10.773,24.4075,0.3869,-0.0029,0.0332,-0.1862,-0.002,-0.2181,0.3306,-0.1449],
[56.735,-1.199,1.8011,-11.3328,26.8609,0.3684,-0.0025,0.0319,-0.1874,0.0002,-0.2443,0.3686,-0.1611],
[57.7385,-1.2515,1.8588,-11.3519,25.8098,0.3657,-0.0024,0.0287,-0.1704,-0.0009,-0.2306,0.3502,-0.1567],
[57.7098,-1.257,1.9037,-11.8077,27.0173,0.3677,-0.0024,0.0271,-0.1572,-0.0012,-0.1965,0.298,-0.1324],
[58.0736,-1.2363,1.9353,-12.317,28.6066,0.3643,-0.0024,0.0253,-0.1507,0.002,-0.178,0.2641,-0.1092],
[62.0223,-1.2128,1.9237,-12.157,27.903,0.3343,-0.0016,0.0242,-0.1555,-0.0004,-0.21,0.315,-0.136],
[62.1221,-1.1404,1.8555,-11.839,27.3698,0.3308,-0.0017,0.026,-0.1685,-0.0024,-0.1452,0.2208,-0.0993],
[62.7962,-1.113,1.8421,-11.7266,26.7715,0.3253,-0.0016,0.0282,-0.1884,-0.0019,-0.1808,0.2766,-0.1276],
[61.7073,-1.2183,1.9323,-12.0462,26.8742,0.3435,-0.0022,0.0321,-0.2009,-0.0018,-0.1943,0.2958,-0.1342],
[61.7636,-1.1885,1.9597,-12.4946,27.9124,0.342,-0.0022,0.0308,-0.1956,0.003,-0.234,0.3493,-0.149],
[63.7493,-1.2055,1.96,-12.5069,28.0089,0.3283,-0.0012,0.0195,-0.1595,-0.002,-0.1708,0.2634,-0.1258],
[62.2586,-1.077,1.8646,-12.2702,27.8184,0.3328,-0.0012,0.0137,-0.1292,-0.0024,-0.0705,0.1151,-0.0646],
[64.2911,-1.0805,1.8431,-11.8647,26.3816,0.3191,-0.0007,0.0088,-0.1057,-0.007,-0.0325,0.0621,-0.0471],
[68.9778,-1.2187,1.888,-11.2553,23.9127,0.294,0.0003,0.0053,-0.0991,-0.0123,-0.0668,0.1121,-0.0648],
[70.4806,-1.165,1.8218,-10.7395,22.4622,0.2801,0.0009,0.0001,-0.0853,-0.0136,-0.0702,0.1225,-0.0781],
[70.6109,-1.1182,1.8262,-11.2854,24.8046,0.2768,0.001,-0.0007,-0.084,-0.01,-0.1092,0.1806,-0.1041],
[69.8975,-1.1611,1.8731,-11.7046,26.3452,0.287,0.0007,0.0018,-0.0954,-0.0067,-0.1524,0.2386,-0.1185],
[69.191,-1.1401,1.9015,-12.217,27.9129,0.2928,0.0003,0.0055,-0.111,-0.0035,-0.2103,0.3262,-0.1586],
[69.9619,-1.1195,1.8816,-11.9235,26.817,0.2873,0.0005,0.0046,-0.1118,-0.0053,-0.1918,0.3015,-0.1525],
[68.3161,-1.0128,1.7759,-11.6001,26.6764,0.2951,0.0003,0.0028,-0.1008,-0.0022,-0.2321,0.3639,-0.1831],
[68.0555,-0.9162,1.6469,-10.7107,24.2868,0.2927,0.0006,-0.0014,-0.0813,-0.0004,-0.236,0.3707,-0.1882],
[65.6124,-0.7989,1.5036,-9.8072,21.9786,0.3055,0.0004,-0.0054,-0.0567,-0.0017,-0.1403,0.2328,-0.1369],
[65.1636,-0.7707,1.457,-9.5828,21.8374,0.3086,0.0005,-0.0086,-0.0391,-0.0024,-0.0941,0.1647,-0.109],
[66.6766,-0.913,1.5894,-9.8498,21.1477,0.3073,0.0008,-0.0116,-0.029,-0.0052,-0.0645,0.1189,-0.0865],
[65.4537,-0.895,1.5329,-9.3616,19.7235,0.3178,0.0007,-0.0136,-0.0176,-0.0044,-0.0173,0.0444,-0.0479],
[64.8596,-0.9404,1.6229,-9.8355,19.8054,0.3274,0.0002,-0.0077,-0.0396,-0.006,0.0077,0.0094,-0.0359],
[64.7808,-0.935,1.5826,-9.392,18.2771,0.3302,0.0002,-0.0082,-0.0324,-0.009,0.0629,-0.0712,-0.0032],
[65.5762,-0.9693,1.558,-8.833,16.6679,0.3289,0.0003,-0.009,-0.0304,-0.0092,0.0526,-0.0599,-0.0011],
[64.0451,-1.1203,1.7205,-9.4755,16.9051,0.3537,-0.0007,0.0019,-0.0701,-0.0041,-0.1202,0.1997,-0.1156],
[66.825,-1.1964,1.8333,-10.0226,17.9273,0.3397,-0.0006,0.0056,-0.0822,-0.0081,-0.1245,0.2047,-0.1138],
[65.6846,-1.2525,1.9018,-10.459,18.6882,0.3537,-0.0009,0.0036,-0.066,-0.0057,-0.113,0.1831,-0.0985],
[65.3052,-1.2617,1.9135,-10.5223,18.771,0.3604,-0.0013,0.0085,-0.0848,-0.0046,-0.1438,0.2265,-0.112],
[64.899,-1.2245,1.8584,-10.1192,17.7416,0.3641,-0.0016,0.0138,-0.1073,-0.0048,-0.1372,0.2161,-0.1063],
[65.3578,-1.2248,1.8289,-9.7674,16.8046,0.3627,-0.0014,0.0124,-0.1066,-0.0057,-0.1576,0.2502,-0.1263],
[64.5514,-1.1783,1.7442,-9.4075,16.9106,0.3687,-0.0013,0.0091,-0.0924,-0.0076,-0.0787,0.1365,-0.0847],
[66.0885,-1.1878,1.7936,-9.5264,16.3425,0.3605,-0.0016,0.0179,-0.1274,-0.0072,-0.185,0.2994,-0.1608],
[67.302,-1.1912,1.725,-8.4639,12.8607,0.3551,-0.0016,0.0212,-0.1358,-0.0076,-0.2055,0.3238,-0.1601],
[69.6151,-1.1726,1.7606,-8.9219,14.4437,0.3387,-0.0015,0.026,-0.1521,-0.0094,-0.1704,0.2659,-0.1257],
[70.5901,-1.2426,1.8162,-8.921,13.7988,0.3388,-0.0016,0.0283,-0.1619,-0.016,-0.066,0.1157,-0.069],
[74.0399,-1.3696,1.9736,-9.9705,16.4081,0.322,-0.001,0.0261,-0.1607,-0.0211,0.054,-0.068,0.017],
[78.1837,-1.4118,1.9659,-9.2285,13.6521,0.2962,-0.0004,0.0279,-0.176,-0.0236,0.0265,-0.035,0.0171],
[77.8733,-1.5496,2.1217,-10.0164,15.085,0.3117,-0.0013,0.041,-0.234,-0.0167,-0.141,0.2059,-0.0717],
[78.6258,-1.5819,2.1292,-10.2662,16.5876,0.311,-0.0011,0.0374,-0.2191,-0.0181,-0.0881,0.1294,-0.044],
[78.1114,-1.6551,2.2258,-11.1197,18.7127,0.3231,-0.0016,0.0421,-0.2369,-0.0174,-0.0626,0.0903,-0.0264],
[79.7562,-1.6836,2.2862,-11.9207,21.9312,0.3146,-0.0013,0.038,-0.2147,-0.0164,-0.0397,0.0537,-0.0083],
[81.1825,-1.7413,2.3012,-11.7683,21.4169,0.3106,-0.0011,0.0381,-0.2099,-0.0197,0.0394,-0.07,0.0551],
[82.4317,-1.7326,2.3369,-11.7377,20.8323,0.3043,-0.0014,0.0468,-0.2545,-0.0145,-0.1069,0.1451,-0.0329],
[83.4279,-1.7479,2.3341,-12.1336,23.8773,0.3009,-0.0009,0.0394,-0.2205,-0.0159,-0.0384,0.039,0.0189],
[87.5318,-1.8801,2.4042,-11.8201,21.5,0.2804,0,0.0344,-0.215,-0.0208,-0.0131,0.0053,0.0276],
[91.5471,-1.9424,2.5247,-12.4507,21.7964,0.2576,0.0005,0.0374,-0.2444,-0.0294,-0.0119,0.0227,-0.01],
[92.4497,-1.8508,2.5523,-13.6421,26.226,0.2495,0,0.0494,-0.305,-0.0184,-0.1813,0.2673,-0.1041],
[92.8328,-1.7523,2.5128,-13.17,23.6191,0.2436,0.0005,0.0322,-0.2188,-0.0162,-0.1657,0.2435,-0.0938],
[100.346,-1.9852,2.7015,-12.334,16.8429,0.2061,0.0016,0.0236,-0.1616,-0.0093,-0.4796,0.6954,-0.2616],
[106.8231,-1.8617,2.4704,-10.3756,11.994,0.1537,0.0038,0.0071,-0.1169,-0.0192,-0.4992,0.7439,-0.3113],
[111.3953,-1.9833,2.5967,-11.4122,16.0199,0.1324,0.0046,0.0068,-0.1417,-0.0242,-0.6418,0.9712,-0.431],
[117.6411,-2.0964,2.6981,-11.2572,13.4182,0.0991,0.0053,0.0132,-0.1836,-0.0338,-0.4799,0.719,-0.3037],
[121.3735,-2.3828,2.9534,-12.2263,14.8292,0.0974,0.0055,0.0085,-0.1487,-0.0205,-0.6271,0.9041,-0.3313],
[115.9126,-2.5317,3.2788,-15.2093,22.0287,0.1601,0.0028,0.0231,-0.181,0.0006,-0.7258,1.0194,-0.3341],
[125.5877,-1.6743,2.6055,-13.4481,23.2621,0.0405,0.006,-0.0009,-0.0707,0.0296,-1.1873,1.6794,-0.5743],
[135.675,-1.8473,2.0605,-8.0487,16.9201,-0.0112,0.0136,-0.0896,0.1678,-0.0337,0.3359,-0.5938,0.4196]
];
var _bpCoeff_F_DIA=[
[36.3363,-0.4513,-0.2328,28.8499,-129.833,-0.0182,0.0007,0.0464,-0.2691,-0.0622,-0.2979,0.6276,-0.5522],
[30.6534,-1.0645,-0.5369,30.836,-125.69,0.1058,0.0021,0.039,-0.2859,-0.0568,-0.8988,1.5116,-0.9035],
[46.6521,-0.8427,-0.8134,29.0051,-109.524,-0.0091,0.0049,0.0484,-0.379,-0.0684,-0.6066,1.0179,-0.5945],
[34.7995,-1.0943,-0.5132,24.8976,-93.9462,0.1143,0.0006,0.0856,-0.4757,-0.03,-0.9349,1.424,-0.6362],
[15.9095,-0.3518,-0.6484,19.5391,-72.0796,0.2253,-0.0045,0.1041,-0.5073,0.007,-1.3455,2.0777,-0.9953],
[12.8878,-0.0974,-1.0427,20.0319,-66.1203,0.2379,-0.002,0.0402,-0.2008,-0.0112,-0.4679,0.7618,-0.4226],
[3.2759,-0.1741,-0.7763,16.2511,-53.8662,0.3223,-0.0044,0.0485,-0.2089,-0.0061,-0.2448,0.4092,-0.2385],
[12.846,-0.0649,-0.8792,16.2183,-50.693,0.2474,-0.0022,0.0311,-0.123,-0.0255,0.239,-0.3265,0.1012],
[12.8668,0.1716,-1.0619,16.2814,-49.2028,0.2361,-0.002,0.0293,-0.1263,-0.0322,0.5303,-0.7561,0.2762],
[9.112,0.1408,-1.0811,16.1015,-48.0962,0.2737,-0.0032,0.0416,-0.1676,-0.0278,0.5837,-0.8523,0.3437],
[11.7225,-0.2667,-0.674,14.1978,-45.5872,0.284,-0.0034,0.0505,-0.203,-0.0368,0.5673,-0.8255,0.3314],
[19.5753,-0.4609,-0.4453,12.7133,-41.9359,0.2384,-0.002,0.0503,-0.2232,-0.0503,0.7475,-1.0987,0.4581],
[21.1297,-0.7489,-0.2784,12.1653,-40.6521,0.2491,-0.0015,0.0462,-0.2201,-0.0415,0.5736,-0.8537,0.3742],
[17.5087,-0.5589,-0.5804,13.6135,-42.3595,0.2699,-0.0017,0.0438,-0.2286,-0.0325,0.5451,-0.8138,0.3581],
[19.125,-0.6931,-0.358,11.3984,-35.5973,0.2679,-0.0009,0.0341,-0.1992,-0.0272,0.3386,-0.5034,0.2204],
[12.3312,-0.7307,-0.2314,9.1993,-27.9046,0.3246,-0.002,0.0272,-0.1474,-0.0218,0.4218,-0.6267,0.2695],
[8.7933,-0.5755,-0.2574,8.5358,-26.1118,0.3473,-0.0031,0.0313,-0.1447,-0.0249,0.4514,-0.6549,0.2572],
[6.8234,-0.7262,-0.0687,7.7821,-26.4927,0.3781,-0.0044,0.0462,-0.203,-0.0214,0.2612,-0.3714,0.1375],
[6.5708,-0.6226,-0.1738,8.0763,-26.5849,0.3759,-0.0041,0.0378,-0.1688,-0.0223,0.3339,-0.475,0.1725],
[12.4952,-0.781,0.0532,6.8239,-24.2698,0.3431,-0.0032,0.0368,-0.1732,-0.0262,0.1513,-0.1909,0.0331],
[16.8254,-0.4175,-0.2206,7.4894,-23.9702,0.2885,-0.0021,0.0295,-0.1608,-0.0154,-0.0241,0.0763,-0.095],
[17.8811,-0.4367,-0.1266,7.0389,-24.15,0.2868,-0.0028,0.0392,-0.1928,-0.0081,-0.278,0.4577,-0.2641],
[16.5734,-0.2666,-0.2542,7.0108,-22.3832,0.2899,-0.0032,0.0387,-0.1806,-0.0041,-0.2653,0.436,-0.2519],
[19.9011,-0.2317,-0.3427,7.6601,-23.4789,0.2636,-0.002,0.0303,-0.1519,-0.0146,-0.0788,0.162,-0.1394],
[21.7218,-0.2625,-0.2345,6.6903,-20.9185,0.2553,-0.0023,0.0347,-0.1547,-0.023,0.0302,0.0052,-0.0801],
[21.9955,-0.4947,-0.0505,6.3827,-21.7936,0.2719,-0.0028,0.0392,-0.1593,-0.0334,0.1394,-0.1536,-0.0152],
[25.2014,-0.5716,0.0877,5.7268,-21.1119,0.2566,-0.0032,0.0512,-0.2028,-0.0358,0.0855,-0.0747,-0.0456],
[24.9355,-0.6578,0.231,4.6551,-18.8514,0.2671,-0.0039,0.0592,-0.2224,-0.0268,-0.0489,0.114,-0.1096],
[23.5259,-0.5069,0.1119,4.7744,-18.0734,0.2698,-0.004,0.0557,-0.2087,-0.0263,0.0265,0.0098,-0.0803],
[22.6538,-0.3685,-0.0683,5.5225,-18.8175,0.2682,-0.0033,0.0439,-0.1629,-0.0299,0.2232,-0.2808,0.039],
[25.1343,-0.4732,0.0854,3.9605,-13.912,0.2571,-0.0028,0.0398,-0.1488,-0.038,0.4146,-0.5644,0.1571],
[26.0776,-0.4748,0.0973,4.2405,-15.6978,0.2526,-0.0028,0.0409,-0.1485,-0.0398,0.4214,-0.5758,0.1652],
[27.7828,-0.4017,0.07,4.258,-15.4754,0.2367,-0.0027,0.0432,-0.1635,-0.035,0.3149,-0.4222,0.1074],
[33.321,-0.5491,0.2782,3.9722,-17.4641,0.2081,-0.0028,0.0559,-0.2079,-0.0453,0.3091,-0.4165,0.114],
[34.8309,-0.6942,0.426,3.3318,-16.8497,0.2081,-0.003,0.0647,-0.2508,-0.0416,0.1445,-0.1779,0.0236],
[37.5926,-0.6443,0.3677,3.4067,-16.42,0.1823,-0.0015,0.0474,-0.1947,-0.0411,0.2234,-0.2936,0.0668],
[39.4412,-0.5625,0.2263,4.2984,-18.3087,0.1635,-0.0003,0.0348,-0.1585,-0.0452,0.3142,-0.4246,0.1158],
[40.6765,-0.6234,0.3141,3.8208,-17.9457,0.1599,-0.0002,0.0372,-0.1782,-0.041,0.1452,-0.1684,-0.0017],
[38.5263,-0.6294,0.3817,3.0897,-16.2418,0.1784,-0.0007,0.0354,-0.1608,-0.0439,0.2718,-0.3597,0.0853],
[38.8799,-0.7551,0.4856,2.734,-15.7989,0.186,-0.0008,0.037,-0.1615,-0.0449,0.292,-0.3993,0.1186],
[41.2743,-0.9011,0.6699,2.2512,-16.8137,0.1795,-0.0009,0.042,-0.1746,-0.0484,0.2216,-0.293,0.0726],
[42.2558,-1.0062,0.7158,2.6789,-19.1943,0.1817,-0.0009,0.0441,-0.1858,-0.0468,0.0978,-0.112,0.002],
[40.2612,-0.9872,0.7444,1.7973,-16.1566,0.1974,-0.0012,0.0445,-0.1857,-0.0476,0.1203,-0.1402,0.0055],
[43.6457,-1.0069,0.734,1.9082,-15.776,0.1751,-0.0005,0.0411,-0.1774,-0.054,0.2098,-0.2758,0.0684],
[37.4261,-1.0061,0.8119,0.7582,-12.6239,0.2262,-0.0023,0.0517,-0.2087,-0.0439,0.0866,-0.0919,-0.0122],
[39.6219,-1.2657,1.1924,-1.7105,-7.6258,0.228,-0.0027,0.0582,-0.2341,-0.047,-0.0208,0.0811,-0.1069],
[40.843,-1.2324,1.2238,-1.9885,-7.0689,0.2204,-0.0032,0.0673,-0.2749,-0.0429,-0.1374,0.2503,-0.1721],
[43.5592,-1.2444,1.2281,-1.7233,-8.2869,0.2012,-0.0024,0.0607,-0.2564,-0.0432,-0.1732,0.3033,-0.1943],
[44.6015,-1.2557,1.2143,-1.1069,-11.0077,0.197,-0.0025,0.062,-0.2557,-0.0368,-0.2817,0.4521,-0.2374],
[43.431,-1.4836,1.4844,-2.8301,-7.691,0.2221,-0.0031,0.0664,-0.2718,-0.0343,-0.3518,0.5529,-0.2744],
[40.2503,-1.5293,1.5113,-3.3498,-5.9574,0.2524,-0.0038,0.0674,-0.2644,-0.0307,-0.3766,0.5899,-0.2912],
[38.7912,-1.4248,1.4482,-3.6476,-4.2826,0.2581,-0.0037,0.0597,-0.2243,-0.033,-0.308,0.4967,-0.266],
[43.1602,-1.3762,1.3057,-2.4967,-6.1669,0.2217,-0.0018,0.0357,-0.1265,-0.0409,-0.031,0.0745,-0.0711],
[44.7535,-1.2714,1.1636,-1.6742,-7.0124,0.2031,-0.0006,0.0171,-0.0429,-0.0436,0.1573,-0.2169,0.0706],
[44.9528,-1.1354,1.0103,-0.6896,-9.5126,0.1953,-0.0005,0.0153,-0.0298,-0.0404,0.1044,-0.1372,0.0343],
[39.8113,-0.9011,0.8911,-1.1437,-6.6547,0.2237,-0.002,0.0227,-0.0406,-0.0358,0.093,-0.1099,0.0051],
[37.8989,-1.0051,1.0055,-1.5428,-6.9588,0.2482,-0.0029,0.031,-0.0735,-0.0328,-0.0609,0.1319,-0.119],
[35.1924,-0.8104,0.8253,-0.5962,-9.35,0.2601,-0.0037,0.0368,-0.0925,-0.0269,-0.1549,0.2764,-0.1888],
[35.6873,-0.7372,0.8448,-1.3541,-6.8503,0.254,-0.0041,0.0431,-0.1168,-0.023,-0.2589,0.4332,-0.2593],
[32.6133,-0.5491,0.7277,-1.3961,-5.5317,0.2691,-0.0053,0.0532,-0.1439,-0.0153,-0.3595,0.5813,-0.3205],
[34.8437,-0.4711,0.6905,-1.4542,-4.7991,0.2492,-0.0052,0.0579,-0.1655,-0.0189,-0.3396,0.557,-0.3175],
[35.5381,-0.4317,0.6593,-1.2682,-5.2622,0.2433,-0.0053,0.063,-0.1896,-0.0217,-0.3173,0.5302,-0.316],
[36.1777,-0.4466,0.641,-0.9947,-5.8087,0.2409,-0.0052,0.0631,-0.1933,-0.022,-0.1927,0.3323,-0.2121],
[41.2921,-0.4612,0.5856,-0.5033,-6.0372,0.2021,-0.0034,0.0497,-0.1573,-0.0331,0.0525,-0.035,-0.0513],
[43.0646,-0.3308,0.3256,1.3124,-9.9318,0.1798,-0.0016,0.0281,-0.0904,-0.0459,0.3232,-0.4202,0.0842],
[44.3551,-0.1948,0.1835,1.9859,-10.8501,0.1628,-0.0011,0.0241,-0.0832,-0.0524,0.5032,-0.684,0.19],
[41.152,0.0212,-0.0243,2.9817,-12.3905,0.1771,-0.0019,0.0273,-0.0838,-0.047,0.5514,-0.7673,0.2434],
[40.7747,0.1804,-0.1901,4.1333,-15.4608,0.1742,-0.0025,0.0343,-0.0976,-0.0441,0.5815,-0.8266,0.2933],
[42.6723,0.2057,-0.2093,4.492,-16.8094,0.1599,-0.0024,0.0353,-0.0956,-0.0449,0.6759,-0.9819,0.3834],
[44.4726,0.1842,-0.1287,4.2111,-17.151,0.1485,-0.0024,0.0365,-0.0871,-0.036,0.5025,-0.7363,0.2978],
[44.4307,0.0412,0.0455,3.5578,-17.0706,0.1602,-0.0031,0.0461,-0.1195,-0.0272,0.2636,-0.3881,0.1611],
[46.146,-0.1944,0.3303,2.0667,-14.4506,0.1634,-0.0032,0.0504,-0.1357,-0.0212,0.0591,-0.0927,0.0497],
[48.5522,-0.2845,0.4266,2.1896,-16.3502,0.1537,-0.0035,0.0626,-0.1955,-0.0152,-0.2111,0.308,-0.1179],
[47.5272,-0.3843,0.5027,1.5489,-14.8051,0.1683,-0.0032,0.0566,-0.179,-0.0162,-0.1752,0.2648,-0.1172],
[42.3688,-0.2544,0.359,1.5821,-13.3586,0.2003,-0.0031,0.0394,-0.1,-0.023,0.1762,-0.2505,0.0889],
[40.419,-0.1244,0.2024,2.2651,-13.8723,0.2085,-0.0028,0.0242,-0.027,-0.0263,0.4803,-0.717,0.3102],
[41.2786,-0.4001,0.5512,0.3246,-9.9661,0.2234,-0.0037,0.0333,-0.0397,-0.0258,0.411,-0.6274,0.2957],
[44.5475,-0.4095,0.5884,0.3313,-11.0779,0.202,-0.0036,0.0417,-0.0815,-0.024,0.2501,-0.3889,0.1968],
[48.1433,-0.5054,0.6845,0.6598,-14.3615,0.1854,-0.0038,0.0599,-0.1887,-0.0266,0.0236,-0.0355,0.0216],
[36.6027,-0.2846,0.4948,0.5126,-11.9027,0.2648,-0.0058,0.0611,-0.1823,-0.0318,0.3126,-0.4516,0.177],
[32.668,-0.2953,0.5385,-0.5236,-7.6933,0.2977,-0.0064,0.0584,-0.1674,-0.0333,0.4917,-0.7205,0.2953],
[34.2675,-0.3725,0.6712,-1.4456,-4.71,0.2927,-0.0065,0.0568,-0.1384,-0.0262,0.4807,-0.7367,0.354],
[34.5736,-0.5184,0.8798,-2.5558,-3.2479,0.3039,-0.0074,0.0666,-0.1528,-0.013,0.1827,-0.311,0.2009],
[38.2705,-0.8498,1.178,-3.1281,-5.8888,0.2993,-0.0068,0.0702,-0.2122,-0.0147,-0.202,0.2993,-0.1195],
[27.2619,-0.709,1.1524,-4.729,0.3025,0.3797,-0.0092,0.0796,-0.2446,-0.0222,0.1254,-0.163,0.0363],
[30.6429,-0.6031,1.1239,-5.8827,7.3287,0.3476,-0.0081,0.0684,-0.2186,-0.027,0.4252,-0.6274,0.2628],
[38.2584,-0.5815,1.057,-5.5212,7.7327,0.2884,-0.0057,0.0424,-0.1141,-0.0255,0.4732,-0.7143,0.3218],
[34.2063,-0.6992,1.3687,-7.5293,9.9367,0.33,-0.0072,0.0412,-0.0552,-0.0037,0.0265,-0.062,0.0645],
[28.3761,-0.5032,1.1656,-6.5035,7.3478,0.3702,-0.009,0.0557,-0.0992,0.0012,-0.2162,0.3295,-0.1511],
[31.5473,-0.191,0.8482,-4.995,5.5448,0.333,-0.0093,0.0772,-0.2338,-0.0012,-0.3665,0.5893,-0.3214],
[28.0599,-0.1241,0.7701,-4.7329,5.1931,0.3597,-0.0102,0.0796,-0.2161,-0.0098,0.0298,-0.0073,-0.0557],
[23.6587,0.3036,0.2722,-3.1305,5.7577,0.3693,-0.0097,0.0627,-0.1368,-0.0164,0.4595,-0.6438,0.21],
[30.6936,0.0131,0.6061,-3.5047,1.8377,0.3406,-0.0098,0.0776,-0.195,-0.0166,0.1956,-0.2534,0.0492],
[36.2121,-0.1094,0.7833,-3.9736,0.5351,0.3083,-0.0089,0.0774,-0.1975,-0.0148,0.091,-0.0977,-0.0189],
[42.9427,-0.2087,1.2659,-7.7504,8.427,0.2634,-0.0082,0.0706,-0.1836,0.0138,-0.4419,0.6751,-0.3217],
[35.6163,-0.3308,1.3791,-8.3941,8.0466,0.3365,-0.0098,0.0787,-0.2043,-0.0005,-0.1455,0.2492,-0.1613],
[52.6206,0.342,0.8903,-5.8391,3.6866,0.1778,-0.0082,0.0886,-0.2524,0.0117,-0.5949,0.9156,-0.4441],
[73.797,-0.1315,1.1805,-3.1333,-12.7158,0.0592,-0.0043,0.0809,-0.2789,-0.052,0.1674,-0.2079,0.0315],
[106.9205,-0.8638,1.9387,-5.949,-7.0235,-0.131,0.0011,0.064,-0.2761,-0.1211,0.5938,-0.7577,0.1352]
];
var _bpCoeff_M_SYS=[
[-15.1614,0.1585,0.7927,-16.2445,64.9588,0.7016,-0.0159,0.0803,-0.1501,0.0109,0.1002,-0.1603,0.0565],
[7.1181,0.1808,0.1658,-8.1838,41.4072,0.5512,-0.0095,0.054,-0.1228,0.0057,0.0042,0.0299,-0.0661],
[16.6833,-0.0164,0.2766,-6.0204,29.5897,0.5,-0.0072,0.037,-0.0808,-0.0092,0.0673,-0.0993,0.0246],
[4.2312,0.3344,0.0389,-4.8857,26.2991,0.583,-0.0104,0.0473,-0.0885,0.0009,0.0958,-0.155,0.0586],
[7.5365,-0.0042,0.4065,-5.8405,25.1459,0.5865,-0.0109,0.0523,-0.0938,0.001,0.0934,-0.1598,0.0738],
[9.1488,-0.3319,0.8441,-9.4288,35.3411,0.6019,-0.0121,0.0661,-0.1243,-0.0028,0.105,-0.187,0.0975],
[8.942,-0.0756,0.7374,-10.0163,38.7888,0.5921,-0.0126,0.0712,-0.1373,0.013,0.076,-0.1417,0.0814],
[7.6195,0.0671,0.6085,-8.8982,34.0775,0.5961,-0.0127,0.0706,-0.1365,0.0147,0.0961,-0.1812,0.1062],
[4.7191,0.0248,0.8039,-10.5118,37.6146,0.6241,-0.014,0.074,-0.1321,0.0285,0.0747,-0.1503,0.0994],
[-3.7807,0.2569,0.5926,-10.5763,40.4022,0.6754,-0.0144,0.0649,-0.1065,0.0265,0.1273,-0.2395,0.1377],
[-4.3588,0.5128,0.4441,-11.0057,43.9366,0.6643,-0.0141,0.0598,-0.0914,0.0297,0.1526,-0.2899,0.1703],
[0.9793,0.277,0.5168,-10.2491,40.6962,0.6426,-0.0127,0.0539,-0.0858,0.0133,0.1639,-0.2987,0.1604],
[4.1744,0.2919,0.5211,-10.2719,41.0334,0.6197,-0.0121,0.0528,-0.0869,0.0122,0.1661,-0.3033,0.1633],
[6.8468,0.1938,0.5369,-9.8873,39.859,0.6088,-0.0115,0.0517,-0.0889,0.0046,0.1768,-0.321,0.1715],
[11.1461,0.2378,0.3678,-8.151,35.8557,0.5761,-0.01,0.044,-0.0795,-0.0007,0.1778,-0.321,0.1698],
[12.4221,0.276,0.2488,-6.8316,31.9031,0.5662,-0.0092,0.0391,-0.073,-0.0089,0.2003,-0.3583,0.1859],
[10.6386,0.5028,0.0451,-6.0581,30.8189,0.5675,-0.0093,0.0395,-0.0789,-0.0048,0.1885,-0.3309,0.1625],
[11.895,0.4259,0.0403,-5.1913,27.4155,0.5654,-0.0088,0.0351,-0.0686,-0.0151,0.216,-0.3783,0.1854],
[15.6199,0.2947,0.1255,-4.8706,25.2474,0.5485,-0.0083,0.0349,-0.0709,-0.0153,0.1958,-0.3402,0.1631],
[19.1961,0.2043,0.1214,-4.058,22.8341,0.5297,-0.0074,0.031,-0.0656,-0.025,0.2093,-0.3615,0.171],
[24.9014,0.1164,0.1324,-3.0351,18.7307,0.4951,-0.0063,0.0283,-0.0649,-0.0265,0.1862,-0.3184,0.1463],
[27.7411,-0.0002,0.251,-3.251,17.9354,0.4835,-0.0062,0.0313,-0.073,-0.026,0.1667,-0.2835,0.1289],
[26.5408,-0.0132,0.3133,-3.6487,17.7499,0.4961,-0.0068,0.0361,-0.0837,-0.0188,0.1384,-0.2306,0.0976],
[24.9608,0.0679,0.2933,-3.7963,17.8167,0.5066,-0.0077,0.043,-0.0991,-0.0102,0.1136,-0.1873,0.0762],
[30.7628,-0.0404,0.3473,-3.514,16.9902,0.4711,-0.0065,0.0402,-0.0991,-0.0135,0.1043,-0.172,0.0705],
[32.9166,-0.0712,0.3957,-3.9,17.9467,0.4584,-0.0062,0.0397,-0.0994,-0.0111,0.0905,-0.1473,0.0576],
[35.8384,-0.154,0.4647,-4.0996,18.2022,0.4447,-0.0061,0.0445,-0.1155,-0.0116,0.0725,-0.1148,0.0406],
[35.8936,-0.2601,0.5885,-4.4079,17.6393,0.4551,-0.0069,0.0522,-0.1317,-0.0062,0.042,-0.0594,0.0107],
[35.6599,-0.2948,0.6396,-4.5403,17.3049,0.4616,-0.0074,0.0559,-0.1397,-0.0065,0.0482,-0.0732,0.0217],
[34.2326,-0.3816,0.7322,-4.795,17.0262,0.4801,-0.0079,0.0573,-0.1393,-0.0049,0.0527,-0.0851,0.0332],
[38.436,-0.518,0.8471,-5.2375,18.6249,0.4592,-0.0074,0.0594,-0.1493,-0.0109,0.0578,-0.0961,0.042],
[37.4759,-0.3108,0.6669,-4.487,17.3228,0.4543,-0.0072,0.0558,-0.1401,-0.0071,0.0668,-0.1148,0.0546],
[38.2626,-0.2565,0.595,-3.8813,15.733,0.4471,-0.0072,0.0565,-0.1436,-0.0047,0.058,-0.0993,0.0468],
[40.1654,-0.373,0.7286,-4.669,17.4341,0.4421,-0.0071,0.0576,-0.1469,-0.0005,0.0365,-0.0612,0.0272],
[42.9794,-0.5548,0.8878,-5.2907,18.8227,0.4348,-0.0069,0.0595,-0.1514,-0.0022,0.033,-0.0585,0.0309],
[45.6449,-0.6118,0.8823,-5.0487,18.8985,0.4196,-0.0061,0.0555,-0.1462,-0.0051,0.0381,-0.069,0.0387],
[46.6551,-0.5689,0.866,-5.0611,19.3856,0.41,-0.0059,0.0537,-0.1435,-0.0027,0.039,-0.0728,0.0431],
[47.5003,-0.5697,0.8793,-5.203,19.8144,0.4057,-0.0059,0.0563,-0.1527,-0.0019,0.0291,-0.0538,0.0314],
[45.403,-0.5065,0.8608,-5.5153,21.0092,0.4195,-0.0064,0.0585,-0.1569,0.0032,0.0197,-0.0361,0.0204],
[44.8971,-0.395,0.8017,-5.6222,21.9379,0.4168,-0.0064,0.0554,-0.147,0.0027,0.0376,-0.069,0.0382],
[47.5247,-0.4291,0.8436,-5.8317,22.6883,0.3999,-0.0058,0.0527,-0.1421,0.0015,0.0382,-0.0702,0.0389],
[46.463,-0.3679,0.8717,-6.4206,23.9766,0.4049,-0.006,0.0518,-0.1372,0.0093,0.0233,-0.0445,0.0258],
[43.9842,-0.1919,0.792,-6.7209,25.4109,0.4126,-0.0063,0.0508,-0.1325,0.0119,0.037,-0.0693,0.0383],
[43.2939,-0.2722,0.8627,-7.0319,25.6372,0.4253,-0.0066,0.052,-0.1346,0.0151,0.022,-0.0414,0.0222],
[44.9267,-0.3058,0.9029,-7.1291,25.4723,0.4173,-0.0066,0.054,-0.1396,0.0166,0.008,-0.0161,0.0087],
[45.3659,-0.1577,0.7596,-6.3854,23.8924,0.4047,-0.006,0.0477,-0.1258,0.015,0.0245,-0.0444,0.0212],
[45.5821,-0.0245,0.5923,-5.4731,22.294,0.3963,-0.0056,0.046,-0.1251,0.0164,0.0239,-0.0431,0.0201],
[47.1433,-0.0461,0.591,-5.2852,21.7529,0.3877,-0.0053,0.0449,-0.1222,0.0153,0.0223,-0.0412,0.0208],
[51.495,-0.1432,0.644,-5.3385,21.775,0.3619,-0.0042,0.0417,-0.1223,0.0089,0.0218,-0.0369,0.0143],
[49.2507,-0.0452,0.5634,-5.0092,21.3118,0.3735,-0.0044,0.0403,-0.1176,0.0104,0.0345,-0.0607,0.0278],
[48.723,-0.0088,0.5464,-5.0086,21.4246,0.3773,-0.0046,0.0403,-0.114,0.0144,0.0211,-0.0365,0.0147],
[46.2919,0.137,0.4328,-4.7097,21.0581,0.387,-0.0047,0.0368,-0.1041,0.0171,0.0335,-0.0595,0.027],
[47.5969,0.1489,0.3829,-4.2807,20.076,0.3772,-0.0039,0.0315,-0.0941,0.0134,0.0397,-0.0681,0.0283],
[48.5103,0.1248,0.3886,-4.0219,19.1219,0.3741,-0.0039,0.0318,-0.0943,0.0115,0.0417,-0.0714,0.03],
[47.0617,0.2003,0.3427,-3.9935,19.2648,0.3815,-0.0041,0.0313,-0.0915,0.0121,0.0505,-0.0878,0.0394],
[47.9002,0.1572,0.3732,-3.8154,17.8605,0.3802,-0.0041,0.032,-0.0944,0.0113,0.0408,-0.067,0.024],
[49.115,0.0782,0.4887,-4.5668,19.8764,0.3783,-0.0042,0.0339,-0.0974,0.0137,0.0304,-0.0508,0.019],
[49.9451,0.1037,0.4323,-3.9989,18.2108,0.3716,-0.0039,0.0318,-0.0942,0.0126,0.0354,-0.0602,0.0246],
[50.1287,0.2012,0.3324,-3.2058,15.608,0.3664,-0.0039,0.0327,-0.0981,0.0177,0.0133,-0.0189,0.0001],
[49.51,0.1993,0.3903,-3.8043,17.1157,0.3729,-0.0042,0.0344,-0.1008,0.0221,0.0041,-0.0038,-0.0061],
[47.0301,0.2961,0.3665,-3.9702,17.4284,0.3864,-0.0047,0.0328,-0.0906,0.0207,0.0246,-0.0408,0.0138],
[46.9571,0.2268,0.4324,-4.3249,18.4933,0.3932,-0.0048,0.0332,-0.0914,0.0225,0.0162,-0.0255,0.0051],
[45.7187,0.319,0.3143,-3.5355,16.3535,0.3986,-0.0048,0.0327,-0.0905,0.0195,0.039,-0.0672,0.0285],
[46.6338,0.3294,0.3122,-3.6994,16.9404,0.3928,-0.0047,0.0327,-0.0892,0.02,0.0422,-0.0754,0.036],
[46.796,0.2184,0.4173,-4.2913,18.3125,0.4005,-0.0048,0.0316,-0.0843,0.0138,0.0632,-0.1146,0.0591],
[45.6059,0.2609,0.3536,-3.7119,16.4744,0.409,-0.005,0.0313,-0.0814,0.0161,0.0671,-0.1239,0.0669],
[46.2843,0.1969,0.384,-3.6001,15.9912,0.4103,-0.005,0.0321,-0.0828,0.0153,0.0735,-0.139,0.08],
[42.7066,0.3391,0.2772,-3.5789,16.5957,0.4304,-0.0057,0.0333,-0.0798,0.0158,0.0981,-0.1852,0.1067],
[42.8015,0.3061,0.3293,-3.7417,16.4765,0.4348,-0.0061,0.0357,-0.0812,0.0203,0.0909,-0.1775,0.1098],
[44.6588,0.3589,0.2756,-3.1211,14.5181,0.4196,-0.0059,0.0374,-0.0881,0.0175,0.0943,-0.1832,0.1126],
[45.4978,0.2369,0.3198,-2.8753,12.9699,0.4238,-0.0058,0.0377,-0.09,0.0126,0.0997,-0.1911,0.1148],
[44.3791,0.247,0.2747,-2.2776,10.7861,0.4342,-0.0061,0.0387,-0.0918,0.0106,0.1113,-0.2121,0.1265],
[44.5213,0.3308,0.2335,-2.5761,12.6357,0.4295,-0.006,0.0393,-0.0953,0.015,0.1005,-0.192,0.1141],
[43.3339,0.3496,0.2289,-2.6952,12.6151,0.4397,-0.0064,0.0411,-0.0987,0.0118,0.1138,-0.2135,0.1223],
[45.7745,0.2806,0.323,-3.0124,12.5836,0.4279,-0.0062,0.0429,-0.1061,0.0132,0.0996,-0.1888,0.1104],
[46.2858,0.2501,0.3239,-2.6897,11.1237,0.4274,-0.0059,0.0399,-0.1008,0.0086,0.1214,-0.2293,0.1336],
[47.1461,0.0565,0.3804,-1.9028,7.5777,0.4368,-0.0058,0.0399,-0.1016,-0.0042,0.1495,-0.2777,0.1579],
[49.8411,-0.0213,0.4353,-2.2574,9.0572,0.4224,-0.0051,0.0374,-0.0989,-0.0067,0.1499,-0.2787,0.1591],
[54.41,-0.2754,0.6713,-3.3139,10.8614,0.4065,-0.0045,0.0392,-0.1059,-0.0134,0.1536,-0.2881,0.1687],
[59.0571,-0.3916,0.714,-3.2563,11.6335,0.3792,-0.0031,0.0313,-0.0925,-0.0235,0.1848,-0.3462,0.2023],
[61.5501,-0.4923,0.8257,-3.7049,12.2735,0.3688,-0.0028,0.0301,-0.0892,-0.0258,0.1974,-0.3735,0.2231],
[62.0991,-0.5602,0.8523,-3.3702,9.855,0.371,-0.0025,0.0277,-0.085,-0.0253,0.1895,-0.3572,0.2113],
[63.7402,-0.7486,1.0333,-4.0639,10.5288,0.3743,-0.0026,0.0296,-0.0853,-0.0264,0.1907,-0.3647,0.2234],
[63.1912,-0.7684,1.0572,-4.1343,10.1666,0.3825,-0.0028,0.0301,-0.0846,-0.0226,0.1752,-0.3347,0.204],
[65.29,-0.9003,1.2109,-4.7056,10.0344,0.3789,-0.0031,0.0353,-0.0982,-0.0171,0.1415,-0.2745,0.173],
[69.7586,-0.9059,1.1421,-3.8514,8.3464,0.3466,-0.0015,0.0272,-0.0852,-0.0254,0.1633,-0.3147,0.1963],
[68.7204,-0.7413,1.161,-4.8929,11.4709,0.347,-0.0023,0.0323,-0.0945,-0.0166,0.1384,-0.2677,0.1676],
[70.0709,-0.7105,1.1845,-4.9763,11.0263,0.3366,-0.0017,0.0271,-0.0857,-0.0132,0.1197,-0.2317,0.1451],
[71.2247,-0.6095,1.0475,-4.2244,9.2028,0.3239,-0.0008,0.022,-0.0796,-0.0212,0.1383,-0.2581,0.1496],
[71.0728,-0.5897,0.954,-3.2255,5.828,0.3275,-0.0005,0.0181,-0.0707,-0.02,0.1457,-0.2721,0.1573],
[70.0217,-0.3531,0.6571,-1.1748,0.806,0.3265,-0.0006,0.0201,-0.0785,-0.0091,0.1053,-0.1976,0.115],
[70.5203,-0.3866,0.7711,-1.2734,-1.0004,0.3319,-0.0017,0.0287,-0.092,0.009,0.0424,-0.0915,0.0678],
[76.3547,-0.7212,0.9341,-1.3303,-1.6526,0.314,-0.0002,0.0247,-0.0938,-0.0122,0.0896,-0.174,0.1101],
[90.6025,-1.3557,1.1746,0.1551,-7.729,0.2521,0.0034,0.0132,-0.0881,-0.0357,0.0885,-0.1674,0.1033],
[102.6662,-1.2263,0.8589,3.2534,-15.7885,0.1576,0.0072,-0.0076,-0.0516,-0.0325,0.0706,-0.1432,0.1009],
[102.9154,-1.5899,1.4523,-0.5061,-7.5933,0.1871,0.0055,0.002,-0.0596,-0.0411,0.1113,-0.2264,0.1604],
[125.2207,-3.3398,2.9466,-5.4863,-1.908,0.1438,0.0076,0.0111,-0.0959,-0.1006,0.1222,-0.2249,0.1376],
[125.8697,-3.2997,3.1051,-7.3155,3.4281,0.1505,0.0067,0.0193,-0.1148,-0.0879,0.0819,-0.1569,0.1076],
[99.6314,-2.8535,3.065,-6.4997,-4.9829,0.3473,-0.001,0.0499,-0.1346,-0.0354,-0.0379,0.0681,-0.0284]
];
var _bpCoeff_M_DIA=[
[-13.567,-1.1325,-1.7078,28.8607,-81.1719,0.4118,0.0003,-0.0263,0.0507,-0.0087,-0.1202,0.2977,-0.2691],
[-43.7777,1.9512,-3.8763,28.8717,-57.6407,0.4741,-0.0029,-0.0496,0.1518,-0.0191,0.1992,-0.2879,0.0508],
[-35.5221,1.6542,-3.2001,22.4882,-41.299,0.4425,-0.0025,-0.0428,0.1269,-0.0674,0.3133,-0.465,0.1062],
[-25.9772,2.0924,-3.8188,24.4956,-38.8551,0.3556,0.0003,-0.0543,0.1499,-0.0796,0.4423,-0.7299,0.2906],
[-16.9931,2.2497,-3.7873,23.1323,-35.1791,0.2916,0.0006,-0.0481,0.1416,-0.0641,0.3962,-0.6572,0.2638],
[-19.6683,2.3137,-3.7117,22.8638,-35.7152,0.3203,-0.0015,-0.0388,0.1406,-0.0689,0.4499,-0.7699,0.3469],
[-33.2858,2.7679,-4.0941,22.3138,-27.6548,0.3986,-0.0021,-0.0592,0.2053,-0.0938,0.6243,-1.0803,0.5056],
[-42.522,3.0229,-4.2155,22.1584,-27.6854,0.4632,-0.0051,-0.0392,0.1567,-0.0631,0.512,-0.8671,0.3759],
[-34.2517,2.7721,-3.6109,17.4453,-15.4161,0.4233,-0.0055,-0.0269,0.1286,-0.0371,0.366,-0.6077,0.2427],
[-42.4833,3.1554,-3.8233,16.9605,-12.0012,0.466,-0.0072,-0.0191,0.1105,-0.0294,0.3572,-0.5855,0.2225],
[-54.4375,3.0764,-3.5785,15.2542,-9.8518,0.569,-0.0112,-0.0014,0.0879,-0.034,0.4004,-0.6627,0.2631],
[-38.5925,2.3768,-3.1326,15.4931,-14.1216,0.5015,-0.0094,0.0059,0.0528,-0.0475,0.355,-0.5818,0.2245],
[-40.8119,2.5241,-3.3547,16.1453,-12.993,0.5119,-0.0092,0.0039,0.0554,-0.0504,0.3968,-0.6637,0.2771],
[-46.3014,2.6717,-3.5156,16.4588,-11.9729,0.5495,-0.0106,0.0106,0.0468,-0.0493,0.4299,-0.7314,0.3246],
[-47.6314,2.9586,-3.758,16.7192,-10.3567,0.5434,-0.0102,0.0067,0.0518,-0.0595,0.4837,-0.8241,0.3686],
[-41.6665,2.9392,-3.8754,17.5857,-10.8233,0.4983,-0.0073,-0.0149,0.0964,-0.0817,0.5737,-0.987,0.4563],
[-45.7369,2.9396,-3.8633,17.231,-10.561,0.5321,-0.008,-0.0146,0.1016,-0.0765,0.5824,-1.0084,0.4748],
[-51.929,2.9378,-3.7832,15.9238,-7.0752,0.586,-0.0101,-0.0013,0.0747,-0.0647,0.5498,-0.9515,0.4469],
[-45.8559,3.0516,-3.9216,17.0729,-10.1336,0.5356,-0.0086,-0.0063,0.0786,-0.0616,0.5196,-0.8956,0.415],
[-39.5605,2.8551,-3.5847,14.9465,-5.3128,0.5025,-0.0082,-0.003,0.0687,-0.0683,0.5134,-0.8848,0.4109],
[-33.7657,2.9223,-3.533,14.1257,-2.6863,0.4575,-0.0075,-0.0012,0.0596,-0.0664,0.4876,-0.8388,0.3872],
[-32.281,2.6018,-3.2278,12.8399,-0.8793,0.472,-0.0081,0.0063,0.0419,-0.062,0.4496,-0.7751,0.3605],
[-31.5797,2.3929,-2.9101,11.2038,1.5782,0.4845,-0.0091,0.0143,0.0265,-0.0586,0.4152,-0.712,0.3258],
[-32.2816,2.6349,-3.0487,11.5875,0.5188,0.4779,-0.0097,0.0203,0.0104,-0.044,0.3694,-0.6297,0.2818],
[-25.44,2.7183,-3.2535,13.5284,-4.0414,0.421,-0.007,0.0038,0.0396,-0.0469,0.3676,-0.6261,0.2792],
[-22.8873,2.5652,-3.2543,13.672,-3.1603,0.4141,-0.0056,-0.0066,0.0583,-0.0566,0.3787,-0.6382,0.2747],
[-20.7911,2.6849,-3.4699,14.9131,-5.2628,0.3921,-0.0042,-0.015,0.0686,-0.0663,0.3974,-0.6642,0.2789],
[-18.557,2.4292,-3.0989,12.2737,1.0228,0.3937,-0.0045,-0.0121,0.0655,-0.073,0.4005,-0.667,0.277],
[-17.5306,2.5085,-3.1093,11.7413,3.3022,0.3838,-0.0047,-0.009,0.0598,-0.0637,0.3744,-0.6243,0.2595],
[-14.3488,2.3673,-3.0068,11.4653,3.7471,0.3712,-0.004,-0.0129,0.0679,-0.0681,0.3759,-0.6244,0.2561],
[-16.6395,2.3516,-2.9622,11.2382,3.1551,0.3924,-0.0047,-0.0114,0.0678,-0.0675,0.3777,-0.6258,0.2543],
[-10.6475,2.2971,-2.8656,10.1755,7.4446,0.3509,-0.0034,-0.0169,0.0752,-0.0763,0.3958,-0.6548,0.2643],
[-10.0847,2.4662,-2.9361,10.2311,6.9534,0.3368,-0.0033,-0.0182,0.08,-0.073,0.3922,-0.6484,0.2607],
[-9.646,2.4037,-2.8587,10.171,5.6614,0.3398,-0.0036,-0.0141,0.0709,-0.0667,0.3688,-0.6116,0.2487],
[-5.5,2.2058,-2.7946,11.4006,-0.0691,0.3246,-0.003,-0.0129,0.0635,-0.0713,0.3492,-0.5757,0.231],
[-3.1184,2.0845,-2.7566,11.9122,-2.7527,0.3161,-0.0025,-0.0137,0.0596,-0.0779,0.347,-0.5661,0.2186],
[-1.8889,1.938,-2.5612,10.5284,0.4557,0.3178,-0.0027,-0.01,0.0505,-0.0868,0.3703,-0.6072,0.2401],
[1.3652,1.8159,-2.5509,11.3987,-2.5982,0.3031,-0.002,-0.0117,0.0496,-0.095,0.3856,-0.6354,0.2568],
[4.1129,1.8155,-2.5332,11.0415,-0.7368,0.2849,-0.0018,-0.0081,0.038,-0.0883,0.364,-0.6035,0.2493],
[1.4862,1.9999,-2.7504,12.2222,-3.4789,0.295,-0.0018,-0.0113,0.0461,-0.0881,0.3736,-0.6168,0.2503],
[-2.474,2.0859,-2.8319,12.5224,-3.8212,0.3229,-0.0028,-0.0094,0.0487,-0.086,0.392,-0.6551,0.2772],
[-0.415,1.9078,-2.6838,12.7489,-6.852,0.3217,-0.0029,-0.0082,0.0472,-0.0801,0.3635,-0.6077,0.2576],
[-0.0497,1.8113,-2.6253,12.8018,-7.7129,0.3277,-0.0029,-0.0071,0.0414,-0.0794,0.3497,-0.5807,0.2402],
[-1.5833,1.7827,-2.6894,13.4925,-9.1732,0.3439,-0.003,-0.0061,0.0371,-0.0845,0.3665,-0.6098,0.2548],
[1.209,1.7298,-2.6076,12.8518,-6.9268,0.3277,-0.0027,-0.0052,0.0323,-0.087,0.3703,-0.6203,0.2656],
[1.2834,1.6318,-2.5106,12.1368,-4.9164,0.335,-0.0025,-0.0086,0.0415,-0.0924,0.386,-0.6467,0.2773],
[-0.4438,1.6936,-2.4801,11.7414,-4.8147,0.3463,-0.0031,-0.0075,0.0435,-0.0895,0.3834,-0.6422,0.2749],
[-0.2325,1.613,-2.4272,12.1673,-8.1046,0.3529,-0.0033,-0.0065,0.0434,-0.0851,0.3606,-0.6019,0.2545],
[-2.1989,1.6982,-2.4926,12.7697,-10.7769,0.3643,-0.0037,-0.0061,0.0459,-0.0859,0.3821,-0.6441,0.2821],
[-0.8411,1.6919,-2.4301,12.0592,-8.667,0.3572,-0.004,-0.0005,0.0305,-0.0865,0.3748,-0.6317,0.2776],
[0.1678,1.6387,-2.3829,11.423,-6.0839,0.3552,-0.0038,-0.0004,0.0275,-0.0933,0.3894,-0.6552,0.2867],
[0.8079,1.7778,-2.4652,11.0582,-4.0097,0.3404,-0.0029,-0.0096,0.0477,-0.0928,0.4036,-0.6792,0.2963],
[-1.1219,1.8103,-2.4361,10.7708,-4.1791,0.3561,-0.0036,-0.0078,0.0484,-0.0819,0.3736,-0.6278,0.2717],
[-4.8133,1.8058,-2.331,9.8828,-2.9487,0.3871,-0.0049,-0.0019,0.0409,-0.0736,0.3513,-0.5879,0.2503],
[-8.1979,2.0298,-2.494,10.6089,-5.3076,0.4011,-0.0058,0.0028,0.0321,-0.0692,0.3504,-0.5851,0.247],
[-6.752,2.0613,-2.4814,10.131,-3.6573,0.3884,-0.0055,0.0002,0.0371,-0.0753,0.3769,-0.6294,0.2655],
[-3.566,1.8329,-2.2802,9.0883,-0.4962,0.3807,-0.005,-0.0007,0.0371,-0.081,0.3819,-0.6401,0.2738],
[1.0387,1.7975,-2.2844,9.2486,-0.6268,0.3494,-0.0037,-0.0064,0.0437,-0.0821,0.3621,-0.6004,0.2472],
[1.6962,1.5592,-2.1909,9.9497,-4.5187,0.3625,-0.0033,-0.0098,0.0505,-0.0904,0.364,-0.5976,0.2383],
[1.7174,1.6924,-2.3499,11.1189,-8.075,0.3556,-0.0029,-0.0144,0.0602,-0.0871,0.3514,-0.5716,0.2195],
[-1.1808,1.896,-2.4788,11.4555,-8.5302,0.3668,-0.0036,-0.0124,0.0586,-0.0775,0.3326,-0.5377,0.2006],
[-1.9286,1.8974,-2.4107,10.6569,-6.2357,0.3747,-0.0042,-0.0079,0.0509,-0.0731,0.3224,-0.5217,0.1951],
[-0.6762,1.6316,-2.0498,8.2301,-0.4293,0.3859,-0.0052,0.0017,0.0314,-0.0748,0.3067,-0.4907,0.1753],
[0.0177,1.3931,-1.7224,6.2104,3.67,0.398,-0.006,0.0074,0.0231,-0.0781,0.3064,-0.4907,0.1763],
[1.8242,1.4415,-1.8531,7.4867,0.3209,0.381,-0.0045,-0.0055,0.0517,-0.0808,0.3148,-0.504,0.181],
[3.3864,1.5296,-1.8957,8.1805,-2.714,0.3667,-0.0046,-0.0044,0.0516,-0.0669,0.2582,-0.4028,0.1272],
[1.4518,1.5557,-2.0588,9.891,-7.5275,0.3836,-0.0047,-0.0045,0.0515,-0.0676,0.2556,-0.3964,0.1218],
[-0.2228,1.7851,-2.3148,11.3445,-10.9345,0.3835,-0.0048,-0.0063,0.0572,-0.0663,0.2738,-0.4312,0.1425],
[-1.2686,1.848,-2.3626,11.0795,-8.9995,0.3885,-0.0049,-0.0053,0.0531,-0.0765,0.3143,-0.5003,0.1745],
[-1.1771,1.9498,-2.33,9.7844,-3.6954,0.382,-0.0052,-0.0022,0.0473,-0.0778,0.3354,-0.5421,0.202],
[-1.5905,1.9246,-2.2012,8.7588,-1.7051,0.39,-0.0063,0.0071,0.0279,-0.0723,0.315,-0.5067,0.1847],
[1.3907,1.7403,-1.9434,6.9646,2.6064,0.3789,-0.006,0.0072,0.0262,-0.0787,0.3279,-0.5282,0.1939],
[5.7059,1.724,-1.9265,7.7741,-2.061,0.3493,-0.0054,0.0068,0.0244,-0.0694,0.282,-0.4467,0.1515],
[12.6597,1.3459,-1.7148,8.837,-8.9553,0.3265,-0.0048,0.0144,-0.0045,-0.065,0.1958,-0.2892,0.0669],
[14.3993,1.3957,-1.9442,11.1527,-15.7051,0.3118,-0.0037,0.0089,-0.0004,-0.0745,0.2201,-0.3286,0.0822],
[17.6818,1.388,-1.9866,11.7883,-17.7697,0.2899,-0.0031,0.0095,-0.0089,-0.0708,0.1938,-0.2807,0.056],
[11.917,1.6817,-2.3045,13.3873,-21.1645,0.3206,-0.0046,0.0186,-0.0278,-0.0691,0.2114,-0.3145,0.0776],
[9.2777,1.6967,-2.2055,11.4045,-13.2029,0.3418,-0.0056,0.0253,-0.0412,-0.0758,0.2487,-0.3832,0.1165],
[5.8584,1.6874,-2.0515,9.5688,-8.1664,0.3719,-0.0073,0.0382,-0.0675,-0.0715,0.2508,-0.3923,0.1289],
[9.3245,1.5374,-1.8954,9.7989,-11.7858,0.3581,-0.0073,0.0413,-0.0754,-0.063,0.2057,-0.3147,0.0928],
[16.2286,1.2597,-1.7964,11.1013,-18.2966,0.3267,-0.0058,0.0385,-0.0835,-0.0656,0.1577,-0.2201,0.0326],
[15.2268,1.0841,-1.7857,12.168,-22.5467,0.3504,-0.0059,0.0373,-0.0777,-0.0718,0.1751,-0.253,0.0528],
[10.4724,1.4733,-2.2295,13.8392,-23.1801,0.3634,-0.0056,0.0276,-0.0497,-0.0848,0.2636,-0.4153,0.1436],
[5.2365,1.5165,-2.1802,12.4214,-17.9441,0.4039,-0.0071,0.0317,-0.0486,-0.0919,0.3179,-0.5147,0.1988],
[10.1259,1.4465,-1.9666,11.6878,-19.1724,0.3722,-0.0063,0.0273,-0.0379,-0.0743,0.2451,-0.3873,0.1349],
[8.7996,1.6042,-2.2123,13.8638,-26.1613,0.3767,-0.006,0.0209,-0.0216,-0.0624,0.2044,-0.3117,0.0907],
[7.3808,1.9753,-2.5467,14.6551,-24.7762,0.366,-0.0058,0.0184,-0.0173,-0.0685,0.2633,-0.4213,0.1535],
[8.2409,1.8093,-1.8703,8.5537,-10.4574,0.3742,-0.008,0.033,-0.0361,-0.0481,0.1904,-0.2951,0.0924],
[16.3443,1.4613,-1.5844,8.5531,-13.7014,0.3376,-0.0067,0.028,-0.0305,-0.0421,0.1473,-0.2208,0.0564],
[13.6814,1.7899,-2.0949,11.8906,-20.3017,0.3408,-0.0062,0.0239,-0.0268,-0.0499,0.1898,-0.2958,0.0953],
[-2.2305,2.0458,-2.0636,8.7608,-9.0684,0.4491,-0.0095,0.0277,-0.0118,-0.0522,0.2641,-0.4295,0.1659],
[7.1024,1.4245,-1.2884,5.4006,-5.1633,0.4266,-0.0107,0.0507,-0.0701,-0.0223,0.0801,-0.0982,-0.0105],
[22.5224,1.2411,-1.1587,5.4827,-6.229,0.3231,-0.008,0.0497,-0.0852,-0.035,0.0837,-0.1047,-0.0066],
[7.1688,2.0574,-2.1429,8.7073,-6.973,0.3913,-0.0079,0.0285,-0.027,-0.0746,0.3209,-0.5246,0.2072],
[10.9219,1.7121,-1.5447,6.0756,-5.588,0.3914,-0.0095,0.0458,-0.0634,-0.034,0.1515,-0.2269,0.0567],
[0.0292,1.3826,-1.5163,7.1831,-10.5716,0.5124,-0.0137,0.0821,-0.1555,-0.0443,0.1613,-0.2416,0.0645],
[-7.4708,1.924,-1.6304,5.8484,-7.4136,0.5394,-0.0152,0.0752,-0.1166,-0.0193,0.205,-0.3492,0.1599],
[17.4158,1.6902,-1.3304,3.6898,3.0431,0.3737,-0.0096,0.0478,-0.0772,-0.0183,0.131,-0.2054,0.0662],
[-2.725,3.8134,-2.3052,3.5243,8.0191,0.4042,-0.0133,0.0238,0.0586,0.0627,0.0422,-0.052,-0.018]
];
function calcHeightPctile(age, sex, heightCm) {
var idx = Math.max(0, Math.min(217, Math.round(age * 12) - 24));
var L, M, S;
if (sex === 'female') { L = _htLMS_F_L[idx]; M = _htLMS_F_M[idx]; S = _htLMS_F_S[idx]; }
else { L = _htLMS_M_L[idx]; M = _htLMS_M_M[idx]; S = _htLMS_M_S[idx]; }
var z = (Math.pow(heightCm / M, L) - 1) / (L * S);
return { z: z, percentile: normalCDF(z) * 100 };
}
function computeBPPercentile(age, sex, heightCm, bpType, bpValue) {
var t1, t2, t3, t4, t5, ta1, ta2, ta3, ta4, ta5, tb1, tb2, tb3, tb4, tb5, w;
if (sex === 'female') {
t1=106.7; t2=140.7; t3=154.0; t4=160.5; t5=168.9;
ta1=5.00; ta2=10.70; ta3=13.16; ta4=14.51; ta5=17.33;
tb1=6.701; tb2=16.438; tb3=46.80; tb4=84.46; tb5=203.608;
w = (age - 10) * (heightCm - 147);
} else {
t1=107.8; t2=140.0; t3=154.5; t4=166.4; t5=179.1;
ta1=5.06; ta2=10.79; ta3=13.22; ta4=14.51; ta5=17.30;
tb1=-15; tb2=8.9; tb3=50.375; tb4=112.684; tb5=250.04;
w = (age - 10) * (heightCm - 150);
}
var x = heightCm, y = age;
// Height restricted cubic splines
var x2a = Math.max(0, x - t1); var x2b = Math.max(0, x - t4); var x2c = Math.max(0, x - t5);
var x2 = Math.pow(x2a,3) - Math.pow(x2b,3)*(t5-t1)/(t5-t4) + Math.pow(x2c,3)*(t4-t1)/(t5-t4);
var x3a = Math.max(0, x - t2);
var x3 = Math.pow(x3a,3) - Math.pow(x2b,3)*(t5-t2)/(t5-t4) + Math.pow(x2c,3)*(t4-t2)/(t5-t4);
var x4a = Math.max(0, x - t3);
var x4 = Math.pow(x4a,3) - Math.pow(x2b,3)*(t5-t3)/(t5-t4) + Math.pow(x2c,3)*(t4-t3)/(t5-t4);
var x2s = x2/100, x3s = x3/100, x4s = x4/100;
// Age restricted cubic splines
var y2a = Math.max(0, y - ta1); var y2b = Math.max(0, y - ta4); var y2c = Math.max(0, y - ta5);
var y2 = Math.pow(y2a,3) - Math.pow(y2b,3)*(ta5-ta1)/(ta5-ta4) + Math.pow(y2c,3)*(ta4-ta1)/(ta5-ta4);
var y3a = Math.max(0, y - ta2);
var y3 = Math.pow(y3a,3) - Math.pow(y2b,3)*(ta5-ta2)/(ta5-ta4) + Math.pow(y2c,3)*(ta4-ta2)/(ta5-ta4);
var y4a = Math.max(0, y - ta3);
var y4 = Math.pow(y4a,3) - Math.pow(y2b,3)*(ta5-ta3)/(ta5-ta4) + Math.pow(y2c,3)*(ta4-ta3)/(ta5-ta4);
var y2s = y2/100, y3s = y3/100, y4s = y4/100;
// Interaction restricted cubic splines
var w2a = Math.max(0, w - tb1); var w2b = Math.max(0, w - tb4); var w2c = Math.max(0, w - tb5);
var w2 = Math.pow(w2a,3) - Math.pow(w2b,3)*(tb5-tb1)/(tb5-tb4) + Math.pow(w2c,3)*(tb4-tb1)/(tb5-tb4);
var w3a = Math.max(0, w - tb2);
var w3 = Math.pow(w3a,3) - Math.pow(w2b,3)*(tb5-tb2)/(tb5-tb4) + Math.pow(w2c,3)*(tb4-tb2)/(tb5-tb4);
var w4a = Math.max(0, w - tb3);
var w4 = Math.pow(w4a,3) - Math.pow(w2b,3)*(tb5-tb3)/(tb5-tb4) + Math.pow(w2c,3)*(tb4-tb3)/(tb5-tb4);
var w2s = w2/10000, w3s = w3/10000, w4s = w4/10000;
// Select coefficient array
var coeff;
if (sex === 'female') coeff = (bpType === 'sys') ? _bpCoeff_F_SYS : _bpCoeff_F_DIA;
else coeff = (bpType === 'sys') ? _bpCoeff_M_SYS : _bpCoeff_M_DIA;
// Compute predicted BP at each percentile and find closest match
var fxsys = new Array(99);
for (var i = 0; i < 99; i++) {
fxsys[i] = coeff[i][0] + coeff[i][5]*x + coeff[i][6]*x2s + coeff[i][7]*x3s + coeff[i][8]*x4s
+ coeff[i][1]*y + coeff[i][2]*y2s + coeff[i][3]*y3s + coeff[i][4]*y4s
+ coeff[i][9]*w + coeff[i][10]*w2s + coeff[i][11]*w3s + coeff[i][12]*w4s;
}
var minDiff = Infinity, percentile = 50;
for (var i = 0; i < 99; i++) {
var diff = Math.abs(bpValue - fxsys[i]);
if (diff < minDiff) { minDiff = diff; percentile = i + 1; }
}
return { percentile: percentile, predicted: fxsys };
}
function classifyBPFromPercentiles(age, sysPctile, diaPctile, sys, dia) {
var sysClass, diaClass;
if (age >= 13) {
// Ages >= 13: use absolute thresholds per AAP 2017
if (sys >= 140) sysClass = 'stage2';
else if (sys >= 130) sysClass = 'stage1';
else if (sys >= 120) sysClass = 'elevated';
else sysClass = 'normal';
if (dia >= 90) diaClass = 'stage2';
else if (dia >= 80) diaClass = 'stage1';
else diaClass = 'normal';
} else {
// Ages 1-<13: use percentile thresholds
if (sysPctile >= 95 + 12 || sys >= 140) sysClass = 'stage2';
else if (sysPctile >= 95 || sys >= 130) sysClass = 'stage1';
else if (sysPctile >= 90 || sys >= 120) sysClass = 'elevated';
else sysClass = 'normal';
if (diaPctile >= 95 + 12 || dia >= 90) diaClass = 'stage2';
else if (diaPctile >= 95 || dia >= 80) diaClass = 'stage1';
else if (diaPctile >= 90) diaClass = 'elevated';
else diaClass = 'normal';
}
var levels = { normal: 0, elevated: 1, stage1: 2, stage2: 3 };
var overall = levels[sysClass] >= levels[diaClass] ? sysClass : diaClass;
return { sysClass: sysClass, diaClass: diaClass, classification: overall };
}
var classLabels = {
normal: { text: 'Normal', color: '#10b981', bg: '#d1fae5' },
elevated: { text: 'Elevated', color: '#f59e0b', bg: '#fef3c7' },
stage1: { text: 'Stage 1 Hypertension', color: '#f97316', bg: '#ffedd5' },
stage2: { text: 'Stage 2 Hypertension', color: '#ef4444', bg: '#fee2e2' }
};
document.getElementById('btn-calc-bp').addEventListener('click', function() {
var age = parseFloat(document.getElementById('bp-age').value);
var sex = document.getElementById('bp-sex').value;
var sys = parseFloat(document.getElementById('bp-systolic').value);
var dia = parseFloat(document.getElementById('bp-diastolic').value);
var heightCm = parseFloat(document.getElementById('bp-height').value);
if (!age || !sex || !sys || !dia || !heightCm) { showToast('Fill in all fields including height', 'error'); return; }
if (age < 1 || age > 17) { showToast('Age must be 1-17 years', 'error'); return; }
var htResult = calcHeightPctile(age, sex, heightCm);
var sysResult = computeBPPercentile(age, sex, heightCm, 'sys', sys);
var diaResult = computeBPPercentile(age, sex, heightCm, 'dia', dia);
var bpClass = classifyBPFromPercentiles(age, sysResult.percentile, diaResult.percentile, sys, dia);
// Get 50th, 90th, 95th predicted values for display
var sys50 = sysResult.predicted[49].toFixed(0), sys90 = sysResult.predicted[89].toFixed(0), sys95 = sysResult.predicted[94].toFixed(0);
var dia50 = diaResult.predicted[49].toFixed(0), dia90 = diaResult.predicted[89].toFixed(0), dia95 = diaResult.predicted[94].toFixed(0);
var cl = classLabels[bpClass.classification];
var resultDiv = document.getElementById('bp-result');
resultDiv.classList.remove('hidden');
resultDiv.innerHTML =
'<div class="calc-result-header" style="background:' + cl.bg + ';border-color:' + cl.color + ';">' +
'<div style="font-size:18px;font-weight:700;color:' + cl.color + ';">' + cl.text + '</div>' +
'<div style="font-size:13px;color:var(--g600);margin-top:4px;">' + sys + '/' + dia + ' mmHg &mdash; ' + age + ' year old ' + sex + ', ' + heightCm + ' cm</div>' +
'</div>' +
'<div class="calc-result-grid">' +
'<div class="calc-result-item">' +
'<div class="calc-result-label">Systolic</div>' +
'<div class="calc-result-value">' + sysResult.percentile + '<span style="font-size:12px;">th %ile</span></div>' +
'<div class="calc-result-sub" style="color:' + classLabels[bpClass.sysClass].color + ';">' + classLabels[bpClass.sysClass].text + '</div>' +
'</div>' +
'<div class="calc-result-item">' +
'<div class="calc-result-label">Diastolic</div>' +
'<div class="calc-result-value">' + diaResult.percentile + '<span style="font-size:12px;">th %ile</span></div>' +
'<div class="calc-result-sub" style="color:' + classLabels[bpClass.diaClass].color + ';">' + classLabels[bpClass.diaClass].text + '</div>' +
'</div>' +
'<div class="calc-result-item">' +
'<div class="calc-result-label">Height</div>' +
'<div class="calc-result-value">' + Math.round(htResult.percentile) + '<span style="font-size:12px;">th %ile</span></div>' +
'<div class="calc-result-sub">Z = ' + htResult.z.toFixed(2) + '</div>' +
'</div>' +
'<div class="calc-result-item">' +
'<div class="calc-result-label">Reference (50th %ile)</div>' +
'<div class="calc-result-value" style="font-size:16px;">' + sys50 + '/' + dia50 + '</div>' +
'<div class="calc-result-sub">90th: ' + sys90 + '/' + dia90 + ' &bull; 95th: ' + sys95 + '/' + dia95 + '</div>' +
'</div>' +
'</div>' +
'<p style="font-size:11px;color:var(--g400);margin:12px 0 0;">BCM/Rosner quantile regression percentiles adjusted to patient height. AAP 2017 classification.</p>';
// Generate BP curves across ages 1-17 for this sex/height
renderBPChart(age, sex, heightCm, sys, dia);
});
function renderBPChart(patientAge, sex, heightCm, patientSys, patientDia) {
if (typeof Chart === 'undefined') return;
var container = document.getElementById('bp-chart-container');
if (!container) return;
container.classList.remove('hidden');
if (_chartInstances['bp-chart-canvas']) { _chartInstances['bp-chart-canvas'].destroy(); _chartInstances['bp-chart-canvas'] = null; }
// Generate percentile curves across ages 1-17
var sys50 = [], sys90 = [], sys95 = [], dia50 = [], dia90 = [], dia95 = [];
for (var a = 1; a <= 17; a++) {
var sr = computeBPPercentile(a, sex, heightCm, 'sys', 100);
var dr = computeBPPercentile(a, sex, heightCm, 'dia', 60);
sys50.push({x:a, y:Math.round(sr.predicted[49])}); sys90.push({x:a, y:Math.round(sr.predicted[89])}); sys95.push({x:a, y:Math.round(sr.predicted[94])});
dia50.push({x:a, y:Math.round(dr.predicted[49])}); dia90.push({x:a, y:Math.round(dr.predicted[89])}); dia95.push({x:a, y:Math.round(dr.predicted[94])});
}
var datasets = [
{ label: 'SBP 95th', data: sys95, borderColor: 'rgba(239,68,68,0.7)', borderWidth: 2, borderDash: [4,4], pointRadius: 0, fill: false, tension: 0.3 },
{ label: 'SBP 90th', data: sys90, borderColor: 'rgba(249,115,22,0.6)', borderWidth: 1.5, borderDash: [3,3], pointRadius: 0, fill: false, tension: 0.3 },
{ label: 'SBP 50th', data: sys50, borderColor: 'rgba(16,185,129,0.8)', borderWidth: 2, pointRadius: 0, fill: false, tension: 0.3 },
{ label: 'DBP 95th', data: dia95, borderColor: 'rgba(239,68,68,0.4)', borderWidth: 1.5, borderDash: [4,4], pointRadius: 0, fill: false, tension: 0.3 },
{ label: 'DBP 90th', data: dia90, borderColor: 'rgba(249,115,22,0.3)', borderWidth: 1, borderDash: [3,3], pointRadius: 0, fill: false, tension: 0.3 },
{ label: 'DBP 50th', data: dia50, borderColor: 'rgba(16,185,129,0.4)', borderWidth: 1.5, pointRadius: 0, fill: false, tension: 0.3 },
{ label: 'Patient SBP', data: [{x:patientAge, y:patientSys}], backgroundColor: '#2563eb', borderColor: '#1d4ed8', pointRadius: 8, pointHoverRadius: 10, showLine: false, type: 'scatter', order: 0 },
{ label: 'Patient DBP', data: [{x:patientAge, y:patientDia}], backgroundColor: '#7c3aed', borderColor: '#6d28d9', pointRadius: 8, pointHoverRadius: 10, pointStyle: 'triangle', showLine: false, type: 'scatter', order: 0 }
];
_chartInstances['bp-chart-canvas'] = new Chart(document.getElementById('bp-chart-canvas'), {
type: 'line',
data: { datasets: datasets },
options: {
responsive: true, maintainAspectRatio: true, aspectRatio: 1.6,
animation: { duration: 300 },
scales: {
x: { type: 'linear', title: { display: true, text: 'Age (years)', font: { size: 12, weight: 'bold' } }, min: 1, max: 17, ticks: { stepSize: 1 }, grid: { color: 'rgba(0,0,0,0.05)' } },
y: { title: { display: true, text: 'Blood Pressure (mmHg)', font: { size: 12, weight: 'bold' } }, min: 30, grid: { color: 'rgba(0,0,0,0.05)' } }
},
plugins: {
legend: { display: true, position: 'bottom', labels: { font: { size: 10 }, usePointStyle: true } },
tooltip: {
callbacks: {
label: function(ctx) {
if (ctx.dataset.label.indexOf('Patient') !== -1) return ctx.dataset.label + ': ' + ctx.parsed.y + ' mmHg';
return ctx.dataset.label + ': ' + ctx.parsed.y + ' mmHg at age ' + ctx.parsed.x;
}
}
}
}
}
});
}
document.getElementById('btn-clear-bp').addEventListener('click', function() {
['bp-age', 'bp-sex', 'bp-height', 'bp-systolic', 'bp-diastolic'].forEach(function(id) {
var el = document.getElementById(id); if (el) el.value = '';
});
document.getElementById('bp-result').classList.add('hidden');
var bpc = document.getElementById('bp-chart-container'); if (bpc) bpc.classList.add('hidden');
});
// ═══════════════════════════════════════════════════════════
// BMI PERCENTILE — CDC 2000
// ═══════════════════════════════════════════════════════════
// CDC BMI-for-Age 24-240mo (every 3 months, from CDC bmiagerev.csv)
var bmiLMS = {male:{24:{L:-1.982374,M:16.5478,S:0.080127},30:{L:-1.642107,M:16.2497,S:0.075499},36:{L:-1.419991,M:16.0003,S:0.072634},42:{L:-1.438165,M:15.7941,S:0.071495},48:{L:-1.714869,M:15.6282,S:0.071889},54:{L:-2.155348,M:15.5026,S:0.073491},60:{L:-2.615166,M:15.4191,S:0.075992},66:{L:-2.981797,M:15.3795,S:0.079211},72:{L:-3.211705,M:15.3835,S:0.083048},78:{L:-3.314769,M:15.429,S:0.0874},84:{L:-3.323189,M:15.5129,S:0.092131},90:{L:-3.270455,M:15.6317,S:0.097082},96:{L:-3.183058,M:15.7823,S:0.102091},102:{L:-3.079383,M:15.9617,S:0.107013},108:{L:-2.971148,M:16.1671,S:0.111721},114:{L:-2.865311,M:16.3961,S:0.116113},120:{L:-2.765648,M:16.6461,S:0.120112},126:{L:-2.673903,M:16.9151,S:0.123664},132:{L:-2.59056,M:17.2009,S:0.126735},138:{L:-2.51532,M:17.5014,S:0.129309},144:{L:-2.447426,M:17.8146,S:0.131389},150:{L:-2.385858,M:18.1387,S:0.132991},156:{L:-2.329457,M:18.4718,S:0.134141},162:{L:-2.277017,M:18.812,S:0.13488},168:{L:-2.227362,M:19.1576,S:0.135251},174:{L:-2.179426,M:19.5067,S:0.135309},180:{L:-2.132345,M:19.8577,S:0.13511},186:{L:-2.085574,M:20.2086,S:0.134718},192:{L:-2.039015,M:20.5576,S:0.134198},198:{L:-1.99315,M:20.9029,S:0.13362},204:{L:-1.949135,M:21.2425,S:0.133057},210:{L:-1.908831,M:21.5742,S:0.132585},216:{L:-1.87467,M:21.8959,S:0.132286},222:{L:-1.849323,M:22.2054,S:0.132249},228:{L:-1.835138,M:22.5007,S:0.132566},234:{L:-1.833401,M:22.7799,S:0.133339},240:{L:-1.843581,M:23.0414,S:0.134675}},female:{24:{L:-1.024497,M:16.388,S:0.085026},30:{L:-1.534542,M:16.0059,S:0.080932},36:{L:-2.096829,M:15.6992,S:0.078605},42:{L:-2.618733,M:15.4647,S:0.077904},48:{L:-3.018522,M:15.2985,S:0.078713},54:{L:-3.2593,M:15.1961,S:0.080904},60:{L:-3.350078,M:15.1519,S:0.0843},66:{L:-3.325522,M:15.1606,S:0.08868},72:{L:-3.225607,M:15.2169,S:0.093803},78:{L:-3.084291,M:15.3161,S:0.099427},84:{L:-2.926187,M:15.4536,S:0.105325},90:{L:-2.76731,M:15.6252,S:0.111295},96:{L:-2.617192,M:15.827,S:0.117159},102:{L:-2.480952,M:16.0552,S:0.122771},108:{L:-2.360921,M:16.3061,S:0.128014},114:{L:-2.257782,M:16.5763,S:0.132797},120:{L:-2.171296,M:16.8623,S:0.137057},126:{L:-2.100749,M:17.161,S:0.140754},132:{L:-2.045235,M:17.4691,S:0.143868},138:{L:-2.003802,M:17.7836,S:0.146399},144:{L:-1.975521,M:18.1015,S:0.148361},150:{L:-1.95952,M:18.42,S:0.149783},156:{L:-1.954978,M:18.7364,S:0.150705},162:{L:-1.9611,M:19.0481,S:0.151176},168:{L:-1.977074,M:19.3526,S:0.151256},174:{L:-2.002014,M:19.6475,S:0.15101},180:{L:-2.034893,M:19.9306,S:0.150512},186:{L:-2.07446,M:20.1998,S:0.149843},192:{L:-2.119157,M:20.4533,S:0.14909},198:{L:-2.167045,M:20.6891,S:0.148349},204:{L:-2.215738,M:20.9058,S:0.147723},210:{L:-2.262382,M:21.1016,S:0.147323},216:{L:-2.303688,M:21.2753,S:0.147269},222:{L:-2.336038,M:21.4255,S:0.147689},228:{L:-2.355678,M:21.5508,S:0.148724},234:{L:-2.35898,M:21.6501,S:0.150521},240:{L:-2.342797,M:21.7219,S:0.153241}}};
function calcBMIPercentile(bmi, L, M, S) {
// Z-score from LMS: Z = ((BMI/M)^L - 1) / (L * S)
var z;
if (Math.abs(L) < 0.001) {
z = Math.log(bmi / M) / S;
} else {
z = (Math.pow(bmi / M, L) - 1) / (L * S);
}
// Convert Z to percentile using standard normal CDF approximation
var p = normalCDF(z);
return { z: z, percentile: Math.round(p * 10000) / 100 };
}
function normalCDF(z) {
var a1=0.254829592, a2=-0.284496736, a3=1.421413741, a4=-1.453152027, a5=1.061405429, p=0.3275911;
var sign = z < 0 ? -1 : 1;
z = Math.abs(z) / Math.sqrt(2);
var t = 1 / (1 + p * z);
var y = 1 - (((((a5*t+a4)*t)+a3)*t+a2)*t+a1)*t*Math.exp(-z*z);
return 0.5 * (1 + sign * y);
}
// ═══════════════════════════════════════════════════════════
// CHART.JS GROWTH CURVE RENDERING
// ═══════════════════════════════════════════════════════════
// Inverse LMS: given Z-score, return measurement value
function valueFromLMS(L, M, S, z) {
if (Math.abs(L) < 0.001) return M * Math.exp(S * z);
return M * Math.pow(1 + L * S * z, 1 / L);
}
// 7-line reference set: 3, 10, 25, 50, 75, 90, 97.
// Drops 5th and 95th (they crowded the 3rd/10th and 90th/97th labels
// on mobile without adding clinical value — 3rd/97th are the
// abnormal-threshold lines, the inner percentiles give the trend).
var PERCENTILE_LINES = [
{ p: 3, z: -1.88079, color: 'rgba(220,38,38,0.9)', dash: [6,4], width: 1.4 }, // red
{ p: 10, z: -1.28155, color: 'rgba(234,88,12,0.9)', dash: [], width: 1.2 }, // orange
{ p: 25, z: -0.67449, color: 'rgba(202,138,4,0.85)', dash: [], width: 1.1 }, // amber
{ p: 50, z: 0, color: 'rgba(22,163,74,0.95)', dash: [], width: 2.4 }, // green (center)
{ p: 75, z: 0.67449, color: 'rgba(37,99,235,0.85)', dash: [], width: 1.1 }, // blue
{ p: 90, z: 1.28155, color: 'rgba(124,58,237,0.9)', dash: [], width: 1.2 }, // violet
{ p: 97, z: 1.88079, color: 'rgba(219,39,119,0.9)', dash: [6,4], width: 1.4 } // pink
];
function generatePercentileCurves(lmsTable, percentileLines) {
var ages = Object.keys(lmsTable).map(Number).sort(function(a,b){return a-b;});
var datasets = [];
percentileLines.forEach(function(pl, idx) {
var points = [];
ages.forEach(function(age) {
var lms = lmsTable[age];
var val = valueFromLMS(lms.L, lms.M, lms.S, pl.z);
if (isFinite(val) && val > 0) points.push({ x: age, y: Math.round(val * 100) / 100 });
});
datasets.push({
label: pl.p + 'th',
data: points,
borderColor: pl.color,
borderWidth: pl.width,
borderDash: pl.dash,
pointRadius: 0,
pointHoverRadius: 0,
fill: false,
tension: 0.4,
order: 10
});
});
// Fill bands between symmetric percentile pairs.
// Indexes: 3=0, 10=1, 25=2, 50=3, 75=4, 90=5, 97=6
var fills = [
{ outer: 0, inner: 6, color: 'rgba(220,38,38,0.04)' }, // 3rd-97th (widest)
{ outer: 1, inner: 5, color: 'rgba(234,88,12,0.04)' }, // 10th-90th
{ outer: 2, inner: 4, color: 'rgba(163,163,163,0.05)' } // 25th-75th (IQR)
];
fills.forEach(function(f) {
if (datasets[f.outer] && datasets[f.inner]) {
datasets[f.outer].fill = { target: f.inner, above: f.color, below: f.color };
}
});
return datasets;
}
var _chartInstances = {};
// Chart.js plugin — labels each percentile curve at its right edge,
// spreads labels bidirectionally so top (97/95/90) and bottom (3/5/10)
// clusters both breathe, draws a thin leader from each label to the
// actual curve position when nudged, then repaints the patient dot
// ON TOP so it's never obscured by a label.
var percentileLabelPlugin = {
id: 'percentileLabels',
afterDatasetsDraw: function(chart) {
var ctx = chart.ctx;
var font = '700 11px -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif';
var MIN_GAP = 15;
// Collect percentile-line labels with native screen positions
var items = [];
chart.data.datasets.forEach(function(ds, i) {
if (!ds.label || !/^\d+th$/.test(ds.label)) return;
var meta = chart.getDatasetMeta(i);
if (!meta || meta.hidden || !meta.data || !meta.data.length) return;
var last = meta.data[meta.data.length - 1];
if (!last) return;
items.push({ label: ds.label, color: ds.borderColor, x: last.x, nativeY: last.y, targetY: last.y });
});
// Top to bottom (ascending canvas Y)
items.sort(function(a, b) { return a.nativeY - b.nativeY; });
// Forward pass — push items DOWN when crowded by item above
for (var k = 1; k < items.length; k++) {
if (items[k].targetY - items[k - 1].targetY < MIN_GAP) {
items[k].targetY = items[k - 1].targetY + MIN_GAP;
}
}
// Backward pass — pull items UP when still crowded by item below
for (var j = items.length - 2; j >= 0; j--) {
if (items[j + 1].targetY - items[j].targetY < MIN_GAP) {
items[j].targetY = items[j + 1].targetY - MIN_GAP;
}
}
// Clamp to chart area so nothing clips top/bottom
var area = chart.chartArea;
if (area) {
items.forEach(function(it) {
if (it.targetY < area.top + 6) it.targetY = area.top + 6;
if (it.targetY > area.bottom - 6) it.targetY = area.bottom - 6;
});
}
// Draw leader + label
items.forEach(function(it) {
var stroke = typeof it.color === 'string' ? it.color : '#555';
var m = stroke.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
if (m) stroke = 'rgb(' + m[1] + ',' + m[2] + ',' + m[3] + ')';
ctx.save();
// Leader — only if the label was nudged away from its native Y
if (Math.abs(it.targetY - it.nativeY) > 2) {
ctx.strokeStyle = stroke;
ctx.globalAlpha = 0.55;
ctx.lineWidth = 0.8;
ctx.beginPath();
ctx.moveTo(it.x, it.nativeY);
ctx.lineTo(it.x + 4, it.targetY);
ctx.stroke();
ctx.globalAlpha = 1;
}
// Label with white halo
ctx.font = font;
ctx.textAlign = 'left';
ctx.textBaseline = 'middle';
ctx.lineWidth = 3;
ctx.strokeStyle = 'rgba(255,255,255,0.92)';
ctx.strokeText(it.label, it.x + 5, it.targetY);
ctx.fillStyle = stroke;
ctx.fillText(it.label, it.x + 5, it.targetY);
ctx.restore();
});
// Repaint the patient dot ON TOP of the labels so it's never
// covered by a nearby percentile label.
chart.data.datasets.forEach(function(ds, i) {
if (ds.label !== 'Patient') return;
var meta = chart.getDatasetMeta(i);
if (!meta || !meta.data || !meta.data.length) return;
var pt = meta.data[0];
if (!pt) return;
ctx.save();
ctx.beginPath();
ctx.arc(pt.x, pt.y, 5, 0, Math.PI * 2);
ctx.fillStyle = '#2563eb';
ctx.fill();
ctx.lineWidth = 1.8;
ctx.strokeStyle = '#ffffff';
ctx.stroke();
ctx.restore();
});
}
};
function renderGrowthChart(canvasId, containerId, lmsTable, patientX, patientY, xLabel, yLabel, extraDatasets) {
if (typeof Chart === 'undefined') return; // Chart.js not loaded yet
var container = document.getElementById(containerId);
if (!container) return;
container.classList.remove('hidden');
if (_chartInstances[canvasId]) { _chartInstances[canvasId].destroy(); _chartInstances[canvasId] = null; }
var datasets = generatePercentileCurves(lmsTable, PERCENTILE_LINES);
// Patient data point — drawn on top of every curve. White ring so
// it reads cleanly even when it lands directly on a colored line.
datasets.push({
label: 'Patient',
data: [{ x: patientX, y: patientY }],
backgroundColor: '#2563eb',
borderColor: '#ffffff',
borderWidth: 1.8,
pointRadius: 5,
pointHoverRadius: 7,
pointStyle: 'circle',
showLine: false,
type: 'scatter',
order: -1
});
if (extraDatasets) extraDatasets.forEach(function(d) { datasets.push(d); });
_chartInstances[canvasId] = new Chart(document.getElementById(canvasId), {
type: 'line',
data: { datasets: datasets },
plugins: [percentileLabelPlugin],
options: {
responsive: true,
maintainAspectRatio: true,
aspectRatio: 1.6,
animation: { duration: 300 },
// Leave ~28px of padding on the right so the percentile labels
// ("50th", "95th", ...) drawn past the last data point are not
// clipped by the canvas edge.
layout: { padding: { right: 30 } },
scales: {
x: {
type: 'linear',
title: { display: true, text: xLabel, font: { size: 12, weight: 'bold' } },
grid: { color: 'rgba(0,0,0,0.05)' }
},
y: {
title: { display: true, text: yLabel, font: { size: 12, weight: 'bold' } },
grid: { color: 'rgba(0,0,0,0.05)' }
}
},
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
label: function(ctx) {
if (ctx.dataset.label === 'Patient') return 'Patient: ' + ctx.parsed.y.toFixed(1) + ' ' + yLabel.split('(').pop().replace(')', '');
return ctx.dataset.label + ': ' + ctx.parsed.y.toFixed(1);
}
}
}
}
}
});
}
// Mid-parental height calculation
function calcMidParentalHeight(motherHt, fatherHt, sex) {
if (!motherHt || !fatherHt) return null;
var mph = sex === 'male' ? (motherHt + fatherHt + 13) / 2 : (motherHt + fatherHt - 13) / 2;
return { target: mph, low: mph - 8.5, high: mph + 8.5 };
}
// Extended BMI classification per CDC 2022
// Uses % of 95th percentile for severe obesity staging
function classifyBMI(percentile, bmi, lms) {
// Calculate 95th percentile BMI from LMS
var p95z = 1.645; // Z for 95th percentile
var bmi95;
if (Math.abs(lms.L) < 0.001) bmi95 = lms.M * Math.exp(lms.S * p95z);
else bmi95 = lms.M * Math.pow(1 + lms.L * lms.S * p95z, 1 / lms.L);
var pctOf95 = (bmi / bmi95) * 100;
if (percentile >= 95) {
if (pctOf95 >= 140) return { text: 'Class 3 Severe Obesity', color: '#7f1d1d', bg: '#fecaca', pctOf95: pctOf95, bmi95: bmi95 };
if (pctOf95 >= 120) return { text: 'Class 2 Severe Obesity', color: '#dc2626', bg: '#fee2e2', pctOf95: pctOf95, bmi95: bmi95 };
return { text: 'Obese (Class 1)', color: '#ef4444', bg: '#fee2e2', pctOf95: pctOf95, bmi95: bmi95 };
}
if (percentile >= 85) return { text: 'Overweight', color: '#f97316', bg: '#ffedd5', pctOf95: pctOf95, bmi95: bmi95 };
if (percentile >= 5) return { text: 'Healthy Weight', color: '#10b981', bg: '#d1fae5', pctOf95: pctOf95, bmi95: bmi95 };
return { text: 'Underweight', color: '#f59e0b', bg: '#fef3c7', pctOf95: pctOf95, bmi95: bmi95 };
}
document.getElementById('btn-calc-bmi').addEventListener('click', function() {
var ageYr = parseFloat(document.getElementById('bmi-age-yr').value) || 0;
var ageMo = parseInt(document.getElementById('bmi-age-mo').value) || 0;
var age = ageYr + ageMo / 12;
var sex = document.getElementById('bmi-sex').value;
var weight = parseFloat(document.getElementById('bmi-weight').value);
var height = parseFloat(document.getElementById('bmi-height').value);
if (!age || !sex || !weight || !height) { showToast('Fill in all fields', 'error'); return; }
if (age < 2 || age > 20) { showToast('Age must be 2-20 years', 'error'); return; }
var bmi = weight / Math.pow(height / 100, 2);
var ageMonths = Math.round(age * 12);
if (ageMonths < 24) ageMonths = 24;
if (ageMonths > 240) ageMonths = 240;
var lms = interpolateLMS(bmiLMS[sex], ageMonths);
if (!lms) { showToast('Invalid age/sex', 'error'); return; }
var result = calcBMIPercentile(bmi, lms.L, lms.M, lms.S);
var cl = classifyBMI(result.percentile, bmi, lms);
var extendedInfo = '';
if (result.percentile >= 85) {
extendedInfo = '<div class="calc-result-item"><div class="calc-result-label">% of 95th</div><div class="calc-result-value" style="font-size:16px;">' + cl.pctOf95.toFixed(0) + '%</div><div class="calc-result-sub">95th = ' + cl.bmi95.toFixed(1) + ' kg/m&sup2;</div></div>';
}
var resultDiv = document.getElementById('bmi-result');
resultDiv.classList.remove('hidden');
resultDiv.innerHTML =
'<div class="calc-result-header" style="background:' + cl.bg + ';border-color:' + cl.color + ';">' +
'<div style="font-size:18px;font-weight:700;color:' + cl.color + ';">' + cl.text + '</div>' +
'<div style="font-size:13px;color:var(--g600);margin-top:4px;">BMI ' + bmi.toFixed(1) + ' kg/m&sup2; &mdash; ' + result.percentile + 'th percentile' + (cl.pctOf95 && result.percentile >= 95 ? ' (' + cl.pctOf95.toFixed(0) + '% of 95th)' : '') + '</div>' +
'</div>' +
'<div class="calc-result-grid">' +
'<div class="calc-result-item"><div class="calc-result-label">BMI</div><div class="calc-result-value">' + bmi.toFixed(1) + '</div><div class="calc-result-sub">kg/m&sup2;</div></div>' +
'<div class="calc-result-item"><div class="calc-result-label">Percentile</div><div class="calc-result-value">' + result.percentile + '<span style="font-size:12px;">th</span></div></div>' +
'<div class="calc-result-item"><div class="calc-result-label">Z-Score</div><div class="calc-result-value" style="font-size:16px;">' + result.z.toFixed(2) + '</div></div>' +
extendedInfo +
'</div>';
var bmiYears = {}; Object.keys(bmiLMS[sex]).forEach(function(k) { bmiYears[+(k/12).toFixed(1)] = bmiLMS[sex][k]; });
renderGrowthChart('bmi-chart-canvas', 'bmi-chart-container', bmiYears, +(ageMonths/12).toFixed(1), bmi, 'Age (years)', 'BMI (kg/m2)');
});
document.getElementById('btn-clear-bmi').addEventListener('click', function() {
['bmi-age-yr', 'bmi-sex', 'bmi-weight', 'bmi-height'].forEach(function(id) {
var el = document.getElementById(id); if (el) el.value = '';
});
document.getElementById('bmi-result').classList.add('hidden');
});
// ═══════════════════════════════════════════════════════════
// BODY SURFACE AREA — Mosteller
// ═══════════════════════════════════════════════════════════
document.getElementById('btn-calc-bsa').addEventListener('click', function() {
var weight = parseFloat(document.getElementById('bsa-weight').value);
var height = parseFloat(document.getElementById('bsa-height').value);
if (!weight || !height) { showToast('Enter weight and height', 'error'); return; }
var bsa = Math.sqrt(height * weight / 3600);
var resultDiv = document.getElementById('bsa-result');
resultDiv.classList.remove('hidden');
resultDiv.innerHTML =
'<div class="calc-result-header" style="background:#e0f2fe;border-color:#0ea5e9;">' +
'<div style="font-size:18px;font-weight:700;color:#0369a1;">BSA: ' + bsa.toFixed(3) + ' m&sup2;</div>' +
'<div style="font-size:13px;color:var(--g600);margin-top:4px;">' + weight + ' kg, ' + height + ' cm (Mosteller formula)</div>' +
'</div>';
});
document.getElementById('btn-clear-bsa').addEventListener('click', function() {
['bsa-weight', 'bsa-height'].forEach(function(id) {
var el = document.getElementById(id); if (el) el.value = '';
});
document.getElementById('bsa-result').classList.add('hidden');
});
// ═══════════════════════════════════════════════════════════
// WEIGHT-BASED DOSING
// ═══════════════════════════════════════════════════════════
document.getElementById('btn-calc-dose').addEventListener('click', function() {
var weight = parseFloat(document.getElementById('dose-weight').value);
var dosePerKg = parseFloat(document.getElementById('dose-per-kg').value);
var freq = parseInt(document.getElementById('dose-freq').value);
var maxDose = parseFloat(document.getElementById('dose-max').value) || 0;
var conc = parseFloat(document.getElementById('dose-conc').value) || 0;
if (!weight || !dosePerKg) { showToast('Enter weight and dose', 'error'); return; }
var singleDose = weight * dosePerKg;
var capped = false;
if (maxDose > 0 && singleDose > maxDose) { singleDose = maxDose; capped = true; }
var dailyDose = singleDose * freq;
var rows = '<div class="calc-result-item"><div class="calc-result-label">Single Dose</div><div class="calc-result-value">' + singleDose.toFixed(1) + ' <span style="font-size:12px;">mg</span></div>'
+ (capped ? '<div class="calc-result-sub" style="color:var(--red);">Capped at max ' + maxDose + ' mg</div>' : '') + '</div>'
+ '<div class="calc-result-item"><div class="calc-result-label">Daily Total</div><div class="calc-result-value">' + dailyDose.toFixed(1) + ' <span style="font-size:12px;">mg/day</span></div>'
+ '<div class="calc-result-sub">' + singleDose.toFixed(1) + ' mg x ' + freq + '/day</div></div>';
if (conc > 0) {
var vol = singleDose / conc;
rows += '<div class="calc-result-item"><div class="calc-result-label">Volume per Dose</div><div class="calc-result-value">' + vol.toFixed(1) + ' <span style="font-size:12px;">mL</span></div>'
+ '<div class="calc-result-sub">at ' + conc + ' mg/mL</div></div>';
}
var resultDiv = document.getElementById('dose-result');
resultDiv.classList.remove('hidden');
resultDiv.innerHTML =
'<div class="calc-result-header" style="background:#ede9fe;border-color:#7c3aed;">' +
'<div style="font-size:18px;font-weight:700;color:#6d28d9;">' + singleDose.toFixed(1) + ' mg per dose</div>' +
'<div style="font-size:13px;color:var(--g600);margin-top:4px;">' + weight + ' kg x ' + dosePerKg + ' mg/kg' + (capped ? ' (max ' + maxDose + ' mg)' : '') + '</div>' +
'</div>' +
'<div class="calc-result-grid">' + rows + '</div>' +
'<p style="font-size:11px;color:var(--g400);margin:12px 0 0;">Always verify dosing against your formulary and institutional guidelines.</p>';
});
document.getElementById('btn-clear-dose').addEventListener('click', function() {
['dose-weight', 'dose-per-kg', 'dose-max', 'dose-conc'].forEach(function(id) {
var el = document.getElementById(id); if (el) el.value = '';
});
document.getElementById('dose-freq').value = '1';
document.getElementById('dose-result').classList.add('hidden');
});
// ═══════════════════════════════════════════════════════════
// GROWTH CHARTS — WHO 0-2y / CDC 2-20y + Fenton Preterm
// ═══════════════════════════════════════════════════════════
var currentGrowthType = 'wfa';
// WHO Weight-for-Age 0-60mo (monthly, from WHO Anthro daily LMS)
var wfaLMS = {male:{0:{L:0.3487,M:3.3464,S:0.14602},1:{L:0.2303,M:4.4525,S:0.13413},2:{L:0.1969,M:5.5714,S:0.12382},3:{L:0.174,M:6.369,S:0.11732},4:{L:0.1551,M:7.0069,S:0.11313},5:{L:0.1396,M:7.5077,S:0.11081},6:{L:0.1256,M:7.9389,S:0.10957},7:{L:0.1134,M:8.2963,S:0.10902},8:{L:0.1019,M:8.62,S:0.10882},9:{L:0.0917,M:8.9019,S:0.10881},10:{L:0.0821,M:9.1618,S:0.1089},11:{L:0.0729,M:9.4136,S:0.10906},12:{L:0.0645,M:9.646,S:0.10925},13:{L:0.0563,M:9.8772,S:0.10949},14:{L:0.0487,M:10.0944,S:0.10976},15:{L:0.0412,M:10.3139,S:0.11008},16:{L:0.0343,M:10.5228,S:0.11041},17:{L:0.0276,M:10.7289,S:0.11078},18:{L:0.021,M:10.9393,S:0.1112},19:{L:0.0149,M:11.1409,S:0.11163},20:{L:0.0087,M:11.3478,S:0.11212},21:{L:0.0029,M:11.5474,S:0.11261},22:{L:-0.0029,M:11.7528,S:0.11315},23:{L:-0.0083,M:11.951,S:0.11369},24:{L:-0.0136,M:12.1482,S:0.11425},25:{L:-0.0189,M:12.3506,S:0.11485},26:{L:-0.0239,M:12.5442,S:0.11544},27:{L:-0.0289,M:12.7413,S:0.11604},28:{L:-0.0337,M:12.9288,S:0.11663},29:{L:-0.0385,M:13.1188,S:0.11723},30:{L:-0.0431,M:13.2993,S:0.11781},31:{L:-0.0477,M:13.4824,S:0.1184},32:{L:-0.052,M:13.6567,S:0.11896},33:{L:-0.0563,M:13.8285,S:0.11952},34:{L:-0.0607,M:14.0038,S:0.12008},35:{L:-0.0648,M:14.1719,S:0.12062},36:{L:-0.0689,M:14.3443,S:0.12116},37:{L:-0.0729,M:14.5102,S:0.12168},38:{L:-0.0769,M:14.6811,S:0.12221},39:{L:-0.0808,M:14.8462,S:0.12271},40:{L:-0.0846,M:15.0167,S:0.12323},41:{L:-0.0883,M:15.1816,S:0.12373},42:{L:-0.092,M:15.3465,S:0.12424},43:{L:-0.0957,M:15.5168,S:0.12478},44:{L:-0.0992,M:15.6815,S:0.12531},45:{L:-0.1028,M:15.8514,S:0.12587},46:{L:-0.1063,M:16.0156,S:0.12642},47:{L:-0.1098,M:16.1851,S:0.12701},48:{L:-0.1131,M:16.3489,S:0.12759},49:{L:-0.1164,M:16.5126,S:0.12818},50:{L:-0.1198,M:16.6818,S:0.12881},51:{L:-0.123,M:16.8454,S:0.12942},52:{L:-0.1263,M:17.0145,S:0.13006},53:{L:-0.1294,M:17.1782,S:0.13068},54:{L:-0.1326,M:17.3473,S:0.13133},55:{L:-0.1356,M:17.5107,S:0.13196},56:{L:-0.1387,M:17.674,S:0.1326},57:{L:-0.1417,M:17.8425,S:0.13325},58:{L:-0.1447,M:18.0053,S:0.13389},59:{L:-0.1477,M:18.1732,S:0.13454},60:{L:-0.1506,M:18.3352,S:0.13517}},female:{0:{L:0.3809,M:3.2322,S:0.14171},1:{L:0.1727,M:4.1716,S:0.13738},2:{L:0.0959,M:5.1315,S:0.12998},3:{L:0.0407,M:5.8393,S:0.12622},4:{L:-0.0053,M:6.428,S:0.12401},5:{L:-0.0428,M:6.8959,S:0.12274},6:{L:-0.0759,M:7.3016,S:0.12204},7:{L:-0.1039,M:7.6416,S:0.12178},8:{L:-0.1292,M:7.9534,S:0.12181},9:{L:-0.1507,M:8.2259,S:0.12199},10:{L:-0.1698,M:8.4769,S:0.12222},11:{L:-0.1873,M:8.7207,S:0.12247},12:{L:-0.2022,M:8.9462,S:0.12267},13:{L:-0.216,M:9.1722,S:0.12283},14:{L:-0.2277,M:9.3861,S:0.12294},15:{L:-0.2385,M:9.6038,S:0.12299},16:{L:-0.2478,M:9.8124,S:0.12303},17:{L:-0.2561,M:10.0196,S:0.12305},18:{L:-0.2637,M:10.2324,S:0.12309},19:{L:-0.2702,M:10.4372,S:0.12315},20:{L:-0.2763,M:10.6481,S:0.12324},21:{L:-0.2814,M:10.8521,S:0.12335},22:{L:-0.2862,M:11.0633,S:0.12351},23:{L:-0.2903,M:11.2684,S:0.12369},24:{L:-0.294,M:11.4741,S:0.12389},25:{L:-0.2975,M:11.6868,S:0.12414},26:{L:-0.3005,M:11.8922,S:0.12441},27:{L:-0.3033,M:12.1028,S:0.12472},28:{L:-0.3057,M:12.3042,S:0.12506},29:{L:-0.308,M:12.5093,S:0.12545},30:{L:-0.3101,M:12.7047,S:0.12587},31:{L:-0.312,M:12.9033,S:0.12634},32:{L:-0.3138,M:13.093,S:0.12683},33:{L:-0.3155,M:13.2809,S:0.12736},34:{L:-0.3171,M:13.4739,S:0.12794},35:{L:-0.3186,M:13.6599,S:0.12854},36:{L:-0.3201,M:13.8518,S:0.1292},37:{L:-0.3216,M:14.0373,S:0.12987},38:{L:-0.323,M:14.2288,S:0.1306},39:{L:-0.3243,M:14.4136,S:0.13134},40:{L:-0.3257,M:14.6041,S:0.13214},41:{L:-0.327,M:14.7877,S:0.13294},42:{L:-0.3283,M:14.9704,S:0.13375},43:{L:-0.3296,M:15.1584,S:0.13461},44:{L:-0.3309,M:15.3395,S:0.13544},45:{L:-0.3322,M:15.5259,S:0.13631},46:{L:-0.3335,M:15.7056,S:0.13715},47:{L:-0.3348,M:15.8908,S:0.13801},48:{L:-0.3361,M:16.0697,S:0.13884},49:{L:-0.3374,M:16.2485,S:0.13967},50:{L:-0.3387,M:16.433,S:0.14051},51:{L:-0.34,M:16.6114,S:0.14132},52:{L:-0.3414,M:16.7957,S:0.14214},53:{L:-0.3427,M:16.9737,S:0.14292},54:{L:-0.344,M:17.1573,S:0.14372},55:{L:-0.3453,M:17.3344,S:0.14448},56:{L:-0.3466,M:17.5107,S:0.14524},57:{L:-0.3479,M:17.692,S:0.146},58:{L:-0.3492,M:17.8664,S:0.14674},59:{L:-0.3505,M:18.0456,S:0.14749},60:{L:-0.3518,M:18.2179,S:0.14821}}};
// CDC Weight-for-Age 24-240mo (every 6 months)
var cdcWfaLMS = {male:{24:{L:-0.216501,M:12.7415,S:0.108166},30:{L:-0.397568,M:13.5609,S:0.109378},36:{L:-0.62132,M:14.4026,S:0.111875},42:{L:-0.804515,M:15.3194,S:0.115493},48:{L:-0.915242,M:16.3168,S:0.119955},54:{L:-0.969633,M:17.3791,S:0.124879},60:{L:-1.000454,M:18.4859,S:0.129879},66:{L:-1.035044,M:19.6214,S:0.134676},72:{L:-1.087471,M:20.7777,S:0.139143},78:{L:-1.158132,M:21.9564,S:0.14331},84:{L:-1.236497,M:23.1674,S:0.147337},90:{L:-1.306268,M:24.4265,S:0.151472},96:{L:-1.351813,M:25.7526,S:0.155974},102:{L:-1.363458,M:27.1649,S:0.161026},108:{L:-1.339405,M:28.6813,S:0.166659},114:{L:-1.284375,M:30.3177,S:0.172729},120:{L:-1.206688,M:32.088,S:0.178929},126:{L:-1.115543,M:34.0036,S:0.184847},132:{L:-1.019277,M:36.0726,S:0.19003},138:{L:-0.92467,M:38.2978,S:0.194053},144:{L:-0.836962,M:40.6744,S:0.196592},150:{L:-0.760274,M:43.1883,S:0.197464},156:{L:-0.698166,M:45.8134,S:0.196662},162:{L:-0.654143,M:48.5111,S:0.194344},168:{L:-0.631877,M:51.231,S:0.190808},174:{L:-0.634919,M:53.9126,S:0.186442},180:{L:-0.665609,M:56.491,S:0.181666},186:{L:-0.723218,M:58.9029,S:0.176887},192:{L:-0.801993,M:61.0954,S:0.172459},198:{L:-0.890436,M:63.0323,S:0.168655},204:{L:-0.973245,M:64.6996,S:0.16564},210:{L:-1.035402,M:66.1075,S:0.163439},216:{L:-1.066224,M:67.2899,S:0.161923},222:{L:-1.061342,M:68.3,S:0.16087},228:{L:-1.023292,M:69.1947,S:0.160138},234:{L:-0.964377,M:69.9987,S:0.160007},240:{L:-0.916488,M:70.5976,S:0.161477}},female:{24:{L:-0.752207,M:12.1346,S:0.10774},30:{L:-0.914719,M:13.0436,S:0.113023},36:{L:-1.024471,M:13.9411,S:0.119492},42:{L:-1.107022,M:14.8812,S:0.125973},48:{L:-1.17703,M:15.8782,S:0.131802},54:{L:-1.238331,M:16.9283,S:0.136811},60:{L:-1.287692,M:18.0231,S:0.141191},66:{L:-1.318993,M:19.1583,S:0.145317},72:{L:-1.326764,M:20.3364,S:0.14959},78:{L:-1.308487,M:21.5675,S:0.154326},84:{L:-1.265549,M:22.868,S:0.159693},90:{L:-1.202884,M:24.2579,S:0.165689},96:{L:-1.127684,M:25.757,S:0.172147},102:{L:-1.047847,M:27.382,S:0.178774},108:{L:-0.970686,M:29.1429,S:0.185201},114:{L:-0.902198,M:31.0403,S:0.191041},120:{L:-0.846873,M:33.0639,S:0.195947},126:{L:-0.807873,M:35.1918,S:0.199648},132:{L:-0.787374,M:37.3909,S:0.201971},138:{L:-0.786904,M:39.6191,S:0.202848},144:{L:-0.8076,M:41.828,S:0.202299},150:{L:-0.850307,M:43.9661,S:0.200419},156:{L:-0.915514,M:45.9837,S:0.197363},162:{L:-1.003051,M:47.8366,S:0.19333},168:{L:-1.111606,M:49.4908,S:0.18856},174:{L:-1.238005,M:50.9254,S:0.183328},180:{L:-1.376478,M:52.1357,S:0.177947},186:{L:-1.518156,M:53.1333,S:0.172761},192:{L:-1.651248,M:53.9454,S:0.168125},198:{L:-1.762241,M:54.6122,S:0.164368},204:{L:-1.838092,M:55.1822,S:0.161753},210:{L:-1.868977,M:55.7062,S:0.160423},216:{L:-1.850946,M:56.2297,S:0.16037},222:{L:-1.787979,M:56.7803,S:0.161399},228:{L:-1.693267,M:57.3518,S:0.163138},234:{L:-1.589533,M:57.8833,S:0.165088},240:{L:-1.513362,M:58.219,S:0.166645}}};
// WHO Length/Height-for-Age 0-60mo (monthly)
var lfaLMS = {male:{0:{L:1.0,M:49.8842,S:0.03795},1:{L:1.0,M:54.6645,S:0.03559},2:{L:1.0,M:58.4384,S:0.03423},3:{L:1.0,M:61.4013,S:0.03329},4:{L:1.0,M:63.9041,S:0.03257},5:{L:1.0,M:65.8912,S:0.03204},6:{L:1.0,M:67.6435,S:0.03165},7:{L:1.0,M:69.1615,S:0.03139},8:{L:1.0,M:70.6224,S:0.03124},9:{L:1.0,M:71.9714,S:0.03117},10:{L:1.0,M:73.2653,S:0.03118},11:{L:1.0,M:74.5464,S:0.03125},12:{L:1.0,M:75.7391,S:0.03137},13:{L:1.0,M:76.9304,S:0.03154},14:{L:1.0,M:78.0451,S:0.03174},15:{L:1.0,M:79.1613,S:0.03197},16:{L:1.0,M:80.2113,S:0.03222},17:{L:1.0,M:81.234,S:0.03249},18:{L:1.0,M:82.2628,S:0.03279},19:{L:1.0,M:83.2318,S:0.0331},20:{L:1.0,M:84.2074,S:0.03342},21:{L:1.0,M:85.1291,S:0.03375},22:{L:1.0,M:86.0589,S:0.0341},23:{L:1.0,M:86.9392,S:0.03445},24:{L:1.0,M:87.8018,S:0.03479},25:{L:1.0,M:87.9737,S:0.03542},26:{L:1.0,M:88.7964,S:0.03576},27:{L:1.0,M:89.6247,S:0.0361},28:{L:1.0,M:90.4056,S:0.03642},29:{L:1.0,M:91.1906,S:0.03674},30:{L:1.0,M:91.9297,S:0.03704},31:{L:1.0,M:92.6735,S:0.03733},32:{L:1.0,M:93.3753,S:0.03761},33:{L:1.0,M:94.0612,S:0.03787},34:{L:1.0,M:94.7559,S:0.03812},35:{L:1.0,M:95.4168,S:0.03836},36:{L:1.0,M:96.0889,S:0.03858},37:{L:1.0,M:96.7298,S:0.03879},38:{L:1.0,M:97.3827,S:0.039},39:{L:1.0,M:98.006,S:0.03919},40:{L:1.0,M:98.6412,S:0.03937},41:{L:1.0,M:99.2471,S:0.03954},42:{L:1.0,M:99.8441,S:0.0397},43:{L:1.0,M:100.4522,S:0.03986},44:{L:1.0,M:101.0326,S:0.04002},45:{L:1.0,M:101.6246,S:0.04017},46:{L:1.0,M:102.191,S:0.04031},47:{L:1.0,M:102.7706,S:0.04045},48:{L:1.0,M:103.3273,S:0.04059},49:{L:1.0,M:103.8806,S:0.04073},50:{L:1.0,M:104.4496,S:0.04086},51:{L:1.0,M:104.9984,S:0.041},52:{L:1.0,M:105.5641,S:0.04113},53:{L:1.0,M:106.1104,S:0.04126},54:{L:1.0,M:106.6736,S:0.04139},55:{L:1.0,M:107.2176,S:0.04152},56:{L:1.0,M:107.7607,S:0.04165},57:{L:1.0,M:108.3209,S:0.04177},58:{L:1.0,M:108.8621,S:0.0419},59:{L:1.0,M:109.4203,S:0.04202},60:{L:1.0,M:109.9593,S:0.04214}},female:{0:{L:1.0,M:49.1477,S:0.0379},1:{L:1.0,M:53.6326,S:0.03641},2:{L:1.0,M:57.0796,S:0.03568},3:{L:1.0,M:59.7773,S:0.0352},4:{L:1.0,M:62.1071,S:0.03486},5:{L:1.0,M:64.019,S:0.03463},6:{L:1.0,M:65.751,S:0.03448},7:{L:1.0,M:67.2842,S:0.03441},8:{L:1.0,M:68.7732,S:0.0344},9:{L:1.0,M:70.1463,S:0.03444},10:{L:1.0,M:71.4656,S:0.03452},11:{L:1.0,M:72.7788,S:0.03464},12:{L:1.0,M:74.0049,S:0.03479},13:{L:1.0,M:75.2297,S:0.03496},14:{L:1.0,M:76.377,S:0.03514},15:{L:1.0,M:77.5258,S:0.03534},16:{L:1.0,M:78.6055,S:0.03555},17:{L:1.0,M:79.6559,S:0.03576},18:{L:1.0,M:80.7121,S:0.03598},19:{L:1.0,M:81.708,S:0.0362},20:{L:1.0,M:82.7116,S:0.03643},21:{L:1.0,M:83.6595,S:0.03665},22:{L:1.0,M:84.6154,S:0.03689},23:{L:1.0,M:85.5184,S:0.03711},24:{L:1.0,M:86.4008,S:0.03733},25:{L:1.0,M:86.5922,S:0.03786},26:{L:1.0,M:87.4358,S:0.03808},27:{L:1.0,M:88.2881,S:0.0383},28:{L:1.0,M:89.0938,S:0.03851},29:{L:1.0,M:89.9072,S:0.03872},30:{L:1.0,M:90.6765,S:0.03893},31:{L:1.0,M:91.4539,S:0.03913},32:{L:1.0,M:92.1906,S:0.03933},33:{L:1.0,M:92.9135,S:0.03952},34:{L:1.0,M:93.6473,S:0.03971},35:{L:1.0,M:94.346,S:0.03989},36:{L:1.0,M:95.0572,S:0.04007},37:{L:1.0,M:95.7356,S:0.04024},38:{L:1.0,M:96.427,S:0.04041},39:{L:1.0,M:97.0871,S:0.04057},40:{L:1.0,M:97.7601,S:0.04074},41:{L:1.0,M:98.4028,S:0.04089},42:{L:1.0,M:99.0369,S:0.04105},43:{L:1.0,M:99.6834,S:0.0412},44:{L:1.0,M:100.3007,S:0.04135},45:{L:1.0,M:100.9301,S:0.0415},46:{L:1.0,M:101.5312,S:0.04164},47:{L:1.0,M:102.1446,S:0.04179},48:{L:1.0,M:102.7312,S:0.04193},49:{L:1.0,M:103.3113,S:0.04206},50:{L:1.0,M:103.9045,S:0.0422},51:{L:1.0,M:104.4727,S:0.04233},52:{L:1.0,M:105.0541,S:0.04247},53:{L:1.0,M:105.6114,S:0.04259},54:{L:1.0,M:106.1817,S:0.04272},55:{L:1.0,M:106.7284,S:0.04285},56:{L:1.0,M:107.2698,S:0.04297},57:{L:1.0,M:107.8238,S:0.0431},58:{L:1.0,M:108.3547,S:0.04322},59:{L:1.0,M:108.8981,S:0.04335},60:{L:1.0,M:109.4189,S:0.04346}}};
// CDC Stature-for-Age 24-240mo (every 6 months)
var cdcLfaLMS = {male:{24:{L:1.007208,M:86.8616,S:0.040396},30:{L:0.174489,M:91.3324,S:0.040965},36:{L:-0.390918,M:95.2736,S:0.040534},42:{L:0.32653,M:99.0025,S:0.040848},48:{L:0.827637,M:102.5105,S:0.041344},54:{L:1.133652,M:105.8813,S:0.041956},60:{L:1.266367,M:109.1751,S:0.042593},66:{L:1.255402,M:112.4296,S:0.043181},72:{L:1.137443,M:115.6609,S:0.043673},78:{L:0.954853,M:118.8668,S:0.044069},84:{L:0.753244,M:122.0305,S:0.044403},90:{L:0.575908,M:125.1259,S:0.044736},96:{L:0.455268,M:128.1237,S:0.045127},102:{L:0.404778,M:130.9983,S:0.045618},108:{L:0.415687,M:133.7345,S:0.046217},114:{L:0.461031,M:136.3343,S:0.046897},120:{L:0.505564,M:138.8234,S:0.04761},126:{L:0.518588,M:141.2582,S:0.048304},132:{L:0.487939,M:143.7304,S:0.048938},138:{L:0.434576,M:146.3665,S:0.049489},144:{L:0.420919,M:149.3088,S:0.049948},150:{L:0.531952,M:152.6624,S:0.050273},156:{L:0.81624,M:156.4099,S:0.050333},162:{L:1.232769,M:160.3493,S:0.049927},168:{L:1.670433,M:164.1418,S:0.048945},174:{L:2.016782,M:167.4641,S:0.047507},180:{L:2.20518,M:170.1393,S:0.04589},186:{L:2.225326,M:172.1563,S:0.044363},192:{L:2.113023,M:173.6101,S:0.043086},198:{L:1.927321,M:174.631,S:0.042107},204:{L:1.724738,M:175.341,S:0.041408},210:{L:1.543253,M:175.836,S:0.040938},216:{L:1.399999,M:176.185,S:0.040644},222:{L:1.297149,M:176.4352,S:0.040474},228:{L:1.229163,M:176.6179,S:0.040391},234:{L:1.18802,M:176.7538,S:0.040364},240:{L:1.167279,M:176.8492,S:0.04037}},female:{24:{L:1.051273,M:85.3973,S:0.04086},30:{L:0.814544,M:90.3334,S:0.041754},36:{L:0.541981,M:94.2134,S:0.042018},42:{L:0.377878,M:97.6485,S:0.042622},48:{L:0.225706,M:101.0339,S:0.04326},54:{L:0.075699,M:104.4635,S:0.043817},60:{L:-0.05773,M:107.9566,S:0.044277},66:{L:-0.159198,M:111.4876,S:0.044653},72:{L:-0.219069,M:115.0055,S:0.044964},78:{L:-0.234772,M:118.4496,S:0.045226},84:{L:-0.210211,M:121.7617,S:0.045461},90:{L:-0.154357,M:124.8956,S:0.045694},96:{L:-0.079283,M:127.8263,S:0.045968},102:{L:0.002744,M:130.5574,S:0.04634},108:{L:0.084148,M:133.1304,S:0.046884},114:{L:0.169805,M:135.6342,S:0.04767},120:{L:0.284749,M:138.2112,S:0.048705},126:{L:0.46918,M:141.0397,S:0.049812},132:{L:0.74429,M:144.2609,S:0.050524},138:{L:1.062475,M:147.8424,S:0.050208},144:{L:1.303045,M:151.4866,S:0.048599},150:{L:1.358163,M:154.7555,S:0.046198},156:{L:1.242968,M:157.3437,S:0.043859},162:{L:1.076971,M:159.2075,S:0.042114},168:{L:0.956572,M:160.4777,S:0.041022},174:{L:0.902452,M:161.3268,S:0.040409},180:{L:0.89557,M:161.898,S:0.040084},186:{L:0.913398,M:162.2908,S:0.039913},192:{L:0.941146,M:162.569,S:0.039821},198:{L:0.971038,M:162.7719,S:0.039767},204:{L:0.999506,M:162.9238,S:0.039732},210:{L:1.025143,M:163.0402,S:0.039707},216:{L:1.047571,M:163.1308,S:0.039687},222:{L:1.066873,M:163.2022,S:0.039671},228:{L:1.083315,M:163.259,S:0.039657},234:{L:1.097229,M:163.3045,S:0.039646},240:{L:1.108046,M:163.3383,S:0.039636}}};
// WHO Head Circumference 0-60mo (monthly)
var hcfaLMS = {male:{0:{L:1.0,M:34.4618,S:0.03686},1:{L:1.0,M:37.2435,S:0.03135},2:{L:1.0,M:39.1349,S:0.02997},3:{L:1.0,M:40.5008,S:0.02918},4:{L:1.0,M:41.6401,S:0.02868},5:{L:1.0,M:42.5524,S:0.02837},6:{L:1.0,M:43.3393,S:0.02817},7:{L:1.0,M:43.9791,S:0.02804},8:{L:1.0,M:44.5384,S:0.02796},9:{L:1.0,M:45.0007,S:0.02792},10:{L:1.0,M:45.4004,S:0.0279},11:{L:1.0,M:45.7593,S:0.02789},12:{L:1.0,M:46.0637,S:0.02789},13:{L:1.0,M:46.3421,S:0.02789},14:{L:1.0,M:46.5834,S:0.02791},15:{L:1.0,M:46.809,S:0.02792},16:{L:1.0,M:47.0088,S:0.02795},17:{L:1.0,M:47.1936,S:0.02797},18:{L:1.0,M:47.3718,S:0.028},19:{L:1.0,M:47.5341,S:0.02803},20:{L:1.0,M:47.6931,S:0.02806},21:{L:1.0,M:47.8399,S:0.0281},22:{L:1.0,M:47.985,S:0.02814},23:{L:1.0,M:48.1198,S:0.02817},24:{L:1.0,M:48.2494,S:0.02821},25:{L:1.0,M:48.378,S:0.02825},26:{L:1.0,M:48.4974,S:0.0283},27:{L:1.0,M:48.6158,S:0.02834},28:{L:1.0,M:48.7255,S:0.02838},29:{L:1.0,M:48.8341,S:0.02843},30:{L:1.0,M:48.9347,S:0.02847},31:{L:1.0,M:49.0341,S:0.02851},32:{L:1.0,M:49.126,S:0.02855},33:{L:1.0,M:49.214,S:0.02859},34:{L:1.0,M:49.3011,S:0.02863},35:{L:1.0,M:49.3818,S:0.02867},36:{L:1.0,M:49.4619,S:0.02871},37:{L:1.0,M:49.5362,S:0.02875},38:{L:1.0,M:49.6101,S:0.02878},39:{L:1.0,M:49.679,S:0.02882},40:{L:1.0,M:49.7476,S:0.02886},41:{L:1.0,M:49.8117,S:0.02889},42:{L:1.0,M:49.8737,S:0.02893},43:{L:1.0,M:49.9357,S:0.02896},44:{L:1.0,M:49.9938,S:0.02899},45:{L:1.0,M:50.0518,S:0.02903},46:{L:1.0,M:50.1062,S:0.02906},47:{L:1.0,M:50.1606,S:0.02909},48:{L:1.0,M:50.2115,S:0.02912},49:{L:1.0,M:50.261,S:0.02915},50:{L:1.0,M:50.3107,S:0.02918},51:{L:1.0,M:50.3573,S:0.02921},52:{L:1.0,M:50.4043,S:0.02924},53:{L:1.0,M:50.4485,S:0.02927},54:{L:1.0,M:50.4931,S:0.0293},55:{L:1.0,M:50.5353,S:0.02932},56:{L:1.0,M:50.5766,S:0.02935},57:{L:1.0,M:50.6184,S:0.02938},58:{L:1.0,M:50.6582,S:0.0294},59:{L:1.0,M:50.6986,S:0.02943},60:{L:1.0,M:50.7372,S:0.02945}},female:{0:{L:1.0,M:33.8787,S:0.03496},1:{L:1.0,M:36.5163,S:0.03211},2:{L:1.0,M:38.258,S:0.03168},3:{L:1.0,M:39.521,S:0.0314},4:{L:1.0,M:40.5895,S:0.03119},5:{L:1.0,M:41.454,S:0.03102},6:{L:1.0,M:42.2079,S:0.03087},7:{L:1.0,M:42.8278,S:0.03075},8:{L:1.0,M:43.3753,S:0.03063},9:{L:1.0,M:43.8309,S:0.03053},10:{L:1.0,M:44.2273,S:0.03044},11:{L:1.0,M:44.5865,S:0.03035},12:{L:1.0,M:44.894,S:0.03027},13:{L:1.0,M:45.1779,S:0.03019},14:{L:1.0,M:45.4255,S:0.03012},15:{L:1.0,M:45.6582,S:0.03005},16:{L:1.0,M:45.865,S:0.02999},17:{L:1.0,M:46.0571,S:0.02993},18:{L:1.0,M:46.2431,S:0.02987},19:{L:1.0,M:46.4135,S:0.02982},20:{L:1.0,M:46.5814,S:0.02977},21:{L:1.0,M:46.7375,S:0.02972},22:{L:1.0,M:46.8931,S:0.02967},23:{L:1.0,M:47.0388,S:0.02962},24:{L:1.0,M:47.1799,S:0.02958},25:{L:1.0,M:47.3207,S:0.02953},26:{L:1.0,M:47.452,S:0.02949},27:{L:1.0,M:47.5825,S:0.02945},28:{L:1.0,M:47.7035,S:0.02941},29:{L:1.0,M:47.8231,S:0.02937},30:{L:1.0,M:47.9336,S:0.02933},31:{L:1.0,M:48.0425,S:0.02929},32:{L:1.0,M:48.1432,S:0.02926},33:{L:1.0,M:48.2395,S:0.02922},34:{L:1.0,M:48.3347,S:0.02919},35:{L:1.0,M:48.423,S:0.02916},36:{L:1.0,M:48.5106,S:0.02912},37:{L:1.0,M:48.5921,S:0.02909},38:{L:1.0,M:48.6732,S:0.02906},39:{L:1.0,M:48.7487,S:0.02903},40:{L:1.0,M:48.824,S:0.029},41:{L:1.0,M:48.8942,S:0.02897},42:{L:1.0,M:48.9621,S:0.02894},43:{L:1.0,M:49.0298,S:0.02891},44:{L:1.0,M:49.0932,S:0.02888},45:{L:1.0,M:49.1566,S:0.02886},46:{L:1.0,M:49.2162,S:0.02883},47:{L:1.0,M:49.2759,S:0.0288},48:{L:1.0,M:49.3321,S:0.02878},49:{L:1.0,M:49.3869,S:0.02875},50:{L:1.0,M:49.4421,S:0.02873},51:{L:1.0,M:49.4942,S:0.0287},52:{L:1.0,M:49.5468,S:0.02868},53:{L:1.0,M:49.5966,S:0.02866},54:{L:1.0,M:49.647,S:0.02863},55:{L:1.0,M:49.6946,S:0.02861},56:{L:1.0,M:49.7413,S:0.02859},57:{L:1.0,M:49.7886,S:0.02856},58:{L:1.0,M:49.8335,S:0.02854},59:{L:1.0,M:49.8791,S:0.02852},60:{L:1.0,M:49.9225,S:0.0285}}};
// WHO Weight-for-Length 45-110cm (every 1cm)
var wflLMS = {male:{45:{L:-0.3521,M:2.441,S:0.09182},46:{L:-0.3521,M:2.6077,S:0.09124},47:{L:-0.3521,M:2.7755,S:0.09065},48:{L:-0.3521,M:2.948,S:0.09007},49:{L:-0.3521,M:3.1308,S:0.08948},50:{L:-0.3521,M:3.3278,S:0.0889},51:{L:-0.3521,M:3.5376,S:0.08831},52:{L:-0.3521,M:3.762,S:0.08771},53:{L:-0.3521,M:4.006,S:0.08711},54:{L:-0.3521,M:4.2693,S:0.08651},55:{L:-0.3521,M:4.5467,S:0.08592},56:{L:-0.3521,M:4.8338,S:0.08535},57:{L:-0.3521,M:5.1259,S:0.08481},58:{L:-0.3521,M:5.418,S:0.0843},59:{L:-0.3521,M:5.7074,S:0.08383},60:{L:-0.3521,M:5.9907,S:0.08342},61:{L:-0.3521,M:6.2632,S:0.08308},62:{L:-0.3521,M:6.5251,S:0.08279},63:{L:-0.3521,M:6.7786,S:0.08255},64:{L:-0.3521,M:7.0255,S:0.08236},65:{L:-0.3521,M:7.2666,S:0.08223},66:{L:-0.3521,M:7.5034,S:0.08215},67:{L:-0.3521,M:7.737,S:0.08212},68:{L:-0.3521,M:7.9674,S:0.08214},69:{L:-0.3521,M:8.1955,S:0.08219},70:{L:-0.3521,M:8.4227,S:0.08229},71:{L:-0.3521,M:8.648,S:0.08241},72:{L:-0.3521,M:8.8697,S:0.08254},73:{L:-0.3521,M:9.0865,S:0.08269},74:{L:-0.3521,M:9.2974,S:0.08283},75:{L:-0.3521,M:9.5032,S:0.08295},76:{L:-0.3521,M:9.7033,S:0.08307},77:{L:-0.3521,M:9.8963,S:0.08314},78:{L:-0.3521,M:10.0827,S:0.08318},79:{L:-0.3521,M:10.2649,S:0.08316},80:{L:-0.3521,M:10.4475,S:0.08308},81:{L:-0.3521,M:10.6352,S:0.08293},82:{L:-0.3521,M:10.8321,S:0.08273},83:{L:-0.3521,M:11.0415,S:0.08246},84:{L:-0.3521,M:11.2651,S:0.08215},85:{L:-0.3521,M:11.5007,S:0.08181},86:{L:-0.3521,M:11.7444,S:0.08145},87:{L:-0.3521,M:11.9916,S:0.08111},88:{L:-0.3521,M:12.2382,S:0.08082},89:{L:-0.3521,M:12.4815,S:0.08058},90:{L:-0.3521,M:12.7209,S:0.08041},91:{L:-0.3521,M:12.9569,S:0.0803},92:{L:-0.3521,M:13.191,S:0.08025},93:{L:-0.3521,M:13.4239,S:0.08026},94:{L:-0.3521,M:13.6572,S:0.08034},95:{L:-0.3521,M:13.8928,S:0.08047},96:{L:-0.3521,M:14.1325,S:0.08067},97:{L:-0.3521,M:14.3782,S:0.08092},98:{L:-0.3521,M:14.6316,S:0.08122},99:{L:-0.3521,M:14.8934,S:0.08157},100:{L:-0.3521,M:15.1637,S:0.08198},101:{L:-0.3521,M:15.4419,S:0.08243},102:{L:-0.3521,M:15.7276,S:0.08292},103:{L:-0.3521,M:16.0206,S:0.08343},104:{L:-0.3521,M:16.3204,S:0.08397},105:{L:-0.3521,M:16.6268,S:0.08453},106:{L:-0.3521,M:16.9401,S:0.0851},107:{L:-0.3521,M:17.2607,S:0.08568},108:{L:-0.3521,M:17.5885,S:0.08629},109:{L:-0.3521,M:17.9242,S:0.08691},110:{L:-0.3521,M:18.2689,S:0.08755}},female:{45:{L:-0.3833,M:2.4607,S:0.09029},46:{L:-0.3833,M:2.6306,S:0.09037},47:{L:-0.3833,M:2.8007,S:0.09044},48:{L:-0.3833,M:2.9741,S:0.09052},49:{L:-0.3833,M:3.156,S:0.0906},50:{L:-0.3833,M:3.3518,S:0.09068},51:{L:-0.3833,M:3.5636,S:0.09076},52:{L:-0.3833,M:3.7911,S:0.09085},53:{L:-0.3833,M:4.0332,S:0.09093},54:{L:-0.3833,M:4.2875,S:0.09102},55:{L:-0.3833,M:4.5498,S:0.0911},56:{L:-0.3833,M:4.8162,S:0.09118},57:{L:-0.3833,M:5.0837,S:0.09125},58:{L:-0.3833,M:5.3507,S:0.0913},59:{L:-0.3833,M:5.6151,S:0.09134},60:{L:-0.3833,M:5.8742,S:0.09136},61:{L:-0.3833,M:6.127,S:0.09137},62:{L:-0.3833,M:6.3738,S:0.09135},63:{L:-0.3833,M:6.6144,S:0.09131},64:{L:-0.3833,M:6.8501,S:0.09126},65:{L:-0.3833,M:7.0812,S:0.09119},66:{L:-0.3833,M:7.3076,S:0.0911},67:{L:-0.3833,M:7.5288,S:0.09101},68:{L:-0.3833,M:7.7448,S:0.0909},69:{L:-0.3833,M:7.9559,S:0.09079},70:{L:-0.3833,M:8.163,S:0.09068},71:{L:-0.3833,M:8.3666,S:0.09056},72:{L:-0.3833,M:8.5679,S:0.09043},73:{L:-0.3833,M:8.7661,S:0.09031},74:{L:-0.3833,M:8.9601,S:0.09018},75:{L:-0.3833,M:9.149,S:0.09005},76:{L:-0.3833,M:9.3337,S:0.08992},77:{L:-0.3833,M:9.5166,S:0.08979},78:{L:-0.3833,M:9.7015,S:0.08965},79:{L:-0.3833,M:9.8915,S:0.08952},80:{L:-0.3833,M:10.0891,S:0.0894},81:{L:-0.3833,M:10.2965,S:0.08928},82:{L:-0.3833,M:10.514,S:0.08918},83:{L:-0.3833,M:10.741,S:0.0891},84:{L:-0.3833,M:10.9767,S:0.08903},85:{L:-0.3833,M:11.2198,S:0.08898},86:{L:-0.3833,M:11.4684,S:0.08895},87:{L:-0.3833,M:11.7201,S:0.08895},88:{L:-0.3833,M:11.972,S:0.08896},89:{L:-0.3833,M:12.2229,S:0.089},90:{L:-0.3833,M:12.4723,S:0.08906},91:{L:-0.3833,M:12.7205,S:0.08913},92:{L:-0.3833,M:12.9681,S:0.08923},93:{L:-0.3833,M:13.2158,S:0.08934},94:{L:-0.3833,M:13.4643,S:0.08948},95:{L:-0.3833,M:13.7146,S:0.08963},96:{L:-0.3833,M:13.9676,S:0.08981},97:{L:-0.3833,M:14.2239,S:0.09},98:{L:-0.3833,M:14.4848,S:0.09021},99:{L:-0.3833,M:14.7519,S:0.09044},100:{L:-0.3833,M:15.0267,S:0.09069},101:{L:-0.3833,M:15.3108,S:0.09096},102:{L:-0.3833,M:15.6046,S:0.09125},103:{L:-0.3833,M:15.9087,S:0.09155},104:{L:-0.3833,M:16.2229,S:0.09186},105:{L:-0.3833,M:16.547,S:0.09219},106:{L:-0.3833,M:16.8814,S:0.09254},107:{L:-0.3833,M:17.2269,S:0.09289},108:{L:-0.3833,M:17.5839,S:0.09326},109:{L:-0.3833,M:17.9526,S:0.09363},110:{L:-0.3833,M:18.3324,S:0.09401}}};
// Fenton Preterm Growth LMS (GA 22-50 weeks) — Weight in grams
var fentonLMS = {
male: {
22:{L:0.21,M:496,S:0.17},24:{L:0.21,M:660,S:0.17},26:{L:0.21,M:870,S:0.16},
28:{L:0.20,M:1124,S:0.15},30:{L:0.18,M:1430,S:0.14},32:{L:0.15,M:1795,S:0.14},
34:{L:0.12,M:2230,S:0.13},36:{L:0.08,M:2710,S:0.13},38:{L:0.04,M:3195,S:0.12},
40:{L:0.01,M:3530,S:0.12},42:{L:-0.02,M:3820,S:0.12},44:{L:-0.04,M:4200,S:0.12},
46:{L:-0.06,M:4680,S:0.12},48:{L:-0.07,M:5200,S:0.12},50:{L:-0.08,M:5760,S:0.12}
},
female: {
22:{L:0.23,M:474,S:0.17},24:{L:0.22,M:610,S:0.17},26:{L:0.22,M:810,S:0.16},
28:{L:0.21,M:1040,S:0.15},30:{L:0.19,M:1330,S:0.14},32:{L:0.16,M:1680,S:0.14},
34:{L:0.12,M:2090,S:0.13},36:{L:0.08,M:2540,S:0.13},38:{L:0.04,M:3000,S:0.12},
40:{L:0.01,M:3340,S:0.12},42:{L:-0.02,M:3630,S:0.12},44:{L:-0.04,M:4010,S:0.12},
46:{L:-0.06,M:4470,S:0.12},48:{L:-0.07,M:4970,S:0.12},50:{L:-0.08,M:5510,S:0.12}
}
};
// Growth sub-pill navigation
document.querySelectorAll('[data-growth]').forEach(function(pill) {
pill.addEventListener('click', function() {
document.querySelectorAll('[data-growth]').forEach(function(p) { p.classList.remove('active'); });
pill.classList.add('active');
currentGrowthType = pill.dataset.growth;
var isFenton = currentGrowthType === 'fenton';
var isHC = currentGrowthType === 'hcfa';
var isWFL = currentGrowthType === 'wfl';
document.getElementById('growth-age-field').style.display = (isFenton || isWFL) ? 'none' : '';
document.getElementById('growth-ga-field').style.display = isFenton ? '' : 'none';
document.getElementById('growth-hc-field').style.display = isHC ? '' : 'none';
document.getElementById('growth-weight-field').style.display = isHC ? 'none' : '';
document.getElementById('growth-length-field').style.display = (currentGrowthType === 'wfa') ? 'none' : (isFenton ? 'none' : '');
var src = document.getElementById('growth-source-text');
if (isFenton) src.textContent = 'Fenton 2013 preterm growth charts (22-50 weeks GA). Weight in grams.';
else if (isHC) src.textContent = 'WHO head circumference-for-age (0-36 months).';
else if (isWFL) src.textContent = 'WHO weight-for-length (45-110 cm, 0-2 years).';
else src.textContent = 'WHO growth standards (0-2y) / CDC 2000 (2-20y).';
document.getElementById('growth-result').classList.add('hidden');
var chartContainer = document.getElementById('growth-chart-container');
if (chartContainer) chartContainer.classList.add('hidden');
if (_chartInstances['growth-chart-canvas']) { _chartInstances['growth-chart-canvas'].destroy(); _chartInstances['growth-chart-canvas'] = null; }
// Show MPH section only for LFA
var mphSection = document.getElementById('growth-mph-section');
if (mphSection) mphSection.style.display = (currentGrowthType === 'lfa') ? '' : 'none';
});
});
function interpolateLMS(lmsTable, val) {
var keys = Object.keys(lmsTable).map(Number).sort(function(a,b){return a-b;});
if (val <= keys[0]) return lmsTable[keys[0]];
if (val >= keys[keys.length-1]) return lmsTable[keys[keys.length-1]];
for (var i = 0; i < keys.length - 1; i++) {
if (val >= keys[i] && val <= keys[i+1]) {
var t = (val - keys[i]) / (keys[i+1] - keys[i]);
var a = lmsTable[keys[i]], b = lmsTable[keys[i+1]];
return { L: a.L + t*(b.L-a.L), M: a.M + t*(b.M-a.M), S: a.S + t*(b.S-a.S) };
}
}
return lmsTable[keys[0]];
}
function calcZFromLMS(value, L, M, S) {
if (Math.abs(L) < 0.001) return Math.log(value / M) / S;
return (Math.pow(value / M, L) - 1) / (L * S);
}
function renderGrowthResult(label, value, unit, z, percentile) {
var pctl = (Math.round(percentile * 100) / 100).toFixed(2);
var cl;
if (pctl >= 95 || pctl <= 5) cl = { color: '#f59e0b', bg: '#fef3c7', text: pctl <= 5 ? 'Below 5th percentile' : 'Above 95th percentile' };
else if (pctl >= 85 || pctl <= 15) cl = { color: '#f97316', bg: '#ffedd5', text: pctl + 'th percentile' };
else cl = { color: '#10b981', bg: '#d1fae5', text: pctl + 'th percentile' };
return '<div class="calc-result-header" style="background:' + cl.bg + ';border-color:' + cl.color + ';">' +
'<div style="font-size:18px;font-weight:700;color:' + cl.color + ';">' + cl.text + '</div>' +
'<div style="font-size:13px;color:var(--g600);margin-top:4px;">' + label + ': ' + value + ' ' + unit + '</div>' +
'</div>' +
'<div class="calc-result-grid">' +
'<div class="calc-result-item"><div class="calc-result-label">Percentile</div><div class="calc-result-value">' + pctl + '<span style="font-size:12px;">th</span></div></div>' +
'<div class="calc-result-item"><div class="calc-result-label">Z-Score</div><div class="calc-result-value" style="font-size:16px;">' + z.toFixed(2) + '</div></div>' +
'</div>';
}
document.getElementById('btn-calc-growth').addEventListener('click', function() {
var sex = document.getElementById('growth-sex').value;
if (!sex) { showToast('Select sex', 'error'); return; }
var resultDiv = document.getElementById('growth-result');
if (currentGrowthType === 'fenton') {
var ga = parseFloat(document.getElementById('growth-ga').value);
var wt = parseFloat(document.getElementById('growth-weight').value);
if (!ga || !wt) { showToast('Enter gestational age and weight', 'error'); return; }
var wtGrams = wt * 1000;
var lms = interpolateLMS(fentonLMS[sex], ga);
var z = calcZFromLMS(wtGrams, lms.L, lms.M, lms.S);
var p = normalCDF(z) * 100;
resultDiv.classList.remove('hidden');
resultDiv.innerHTML = renderGrowthResult('Weight at ' + ga + ' weeks GA', wt + ' kg (' + Math.round(wtGrams) + 'g)', '', z, p);
renderGrowthChart('growth-chart-canvas', 'growth-chart-container', fentonLMS[sex], ga, wtGrams, 'Gestational Age (weeks)', 'Weight (g)');
return;
}
var yrEl = document.getElementById('growth-age-yr');
var moEl = document.getElementById('growth-age-mo');
var dyEl = document.getElementById('growth-age-d');
var yrRaw = yrEl ? yrEl.value.trim() : '';
var moRaw = moEl ? moEl.value.trim() : '';
var dyRaw = dyEl ? dyEl.value.trim() : '';
// Treat blank fields as 0, but require at least ONE field to have any value.
// "0 days" (newborn at birth) is valid — explicit zero counts.
if (yrRaw === '' && moRaw === '' && dyRaw === '') {
showToast('Enter age (years, months, or days)', 'error'); return;
}
var yr = parseFloat(yrRaw) || 0;
var mo = parseFloat(moRaw) || 0;
var dy = parseFloat(dyRaw) || 0;
var age = yr * 12 + mo + dy / 30.4375; // age in months, fractional OK
if (age < 0) { showToast('Age cannot be negative', 'error'); return; }
if (currentGrowthType === 'wfa') {
var wt = parseFloat(document.getElementById('growth-weight').value);
if (!wt) { showToast('Enter weight', 'error'); return; }
// Use WHO for 0-60mo, CDC for >60mo
var wfaTable = (age > 24) ? cdcWfaLMS[sex] : wfaLMS[sex];
var wfaChartTable = (age > 24) ? cdcWfaLMS[sex] : wfaLMS[sex];
var lms = interpolateLMS(wfaTable, age);
var z = calcZFromLMS(wt, lms.L, lms.M, lms.S);
var p = normalCDF(z) * 100;
var src = (age > 24) ? 'CDC' : 'WHO';
resultDiv.classList.remove('hidden');
resultDiv.innerHTML = renderGrowthResult('Weight-for-Age (' + age + ' mo, ' + src + ')', wt, 'kg', z, p);
if (age > 24) {
var wfaYears = {}; Object.keys(wfaChartTable).forEach(function(k) { wfaYears[+(k/12).toFixed(2)] = wfaChartTable[k]; });
renderGrowthChart('growth-chart-canvas', 'growth-chart-container', wfaYears, +(age/12).toFixed(2), wt, 'Age (years)', 'Weight (kg)');
} else {
renderGrowthChart('growth-chart-canvas', 'growth-chart-container', wfaChartTable, age, wt, 'Age (months)', 'Weight (kg)');
}
}
else if (currentGrowthType === 'lfa') {
var len = parseFloat(document.getElementById('growth-length').value);
if (!len) { showToast('Enter length/height', 'error'); return; }
// Use WHO for 0-60mo, CDC for >60mo
var lfaTable = (age > 24) ? cdcLfaLMS[sex] : lfaLMS[sex];
var lms = interpolateLMS(lfaTable, age);
var z = calcZFromLMS(len, lms.L, lms.M, lms.S);
var p = normalCDF(z) * 100;
var src = (age > 24) ? 'CDC' : 'WHO';
resultDiv.classList.remove('hidden');
resultDiv.innerHTML = renderGrowthResult('Length/Height-for-Age (' + age + ' mo, ' + src + ')', len, 'cm', z, p);
// Mid-parental height
var mphDatasets = [];
var motherHt = parseFloat((document.getElementById('growth-mother-ht') || {}).value);
var fatherHt = parseFloat((document.getElementById('growth-father-ht') || {}).value);
var mph = calcMidParentalHeight(motherHt, fatherHt, sex);
if (mph) {
// Calculate what percentile the MPH corresponds to using adult height LMS (~18y = 216mo)
var adultLms = interpolateLMS(cdcLfaLMS[sex], 216);
var mphZ = calcZFromLMS(mph.target, adultLms.L, adultLms.M, adultLms.S);
var mphPctile = (Math.round(normalCDF(mphZ) * 10000) / 100).toFixed(2);
resultDiv.innerHTML += '<div style="margin-top:8px;padding:8px 12px;background:#ede9fe;border-radius:6px;font-size:13px;color:#6d28d9;"><strong>Mid-Parental Height:</strong> ' + mph.target.toFixed(1) + ' cm (' + mphPctile + 'th percentile) &mdash; target range: ' + mph.low.toFixed(1) + ' - ' + mph.high.toFixed(1) + ' cm</div>';
// MPH coordinates: use years if age > 24mo
var mphX1 = age > 24 ? 17 : 204;
var mphX2 = age > 24 ? 20 : 240;
mphDatasets.push({ label: 'MPH Range', data: [{x:mphX1,y:mph.low},{x:mphX2,y:mph.low}], borderColor:'rgba(139,92,246,0.3)', backgroundColor:'rgba(139,92,246,0.1)', fill:'+1', pointRadius:0, borderWidth:1, tension:0, order:5 });
mphDatasets.push({ label: 'MPH Upper', data: [{x:mphX1,y:mph.high},{x:mphX2,y:mph.high}], borderColor:'rgba(139,92,246,0.3)', fill:false, pointRadius:0, borderWidth:1, tension:0, order:5 });
mphDatasets.push({ label: 'MPH ' + mph.target.toFixed(0) + 'cm (' + mphPctile + 'th %ile)', data: [{x:mphX1,y:mph.target},{x:mphX2,y:mph.target}], borderColor:'rgba(139,92,246,0.8)', borderDash:[6,3], fill:false, pointRadius:3, pointHoverRadius:6, borderWidth:2, tension:0, order:5 });
}
if (age > 24) {
var lfaYears = {}; Object.keys(lfaTable).forEach(function(k) { lfaYears[+(k/12).toFixed(2)] = lfaTable[k]; });
renderGrowthChart('growth-chart-canvas', 'growth-chart-container', lfaYears, +(age/12).toFixed(2), len, 'Age (years)', 'Length/Height (cm)', mphDatasets);
} else {
renderGrowthChart('growth-chart-canvas', 'growth-chart-container', lfaTable, age, len, 'Age (months)', 'Length/Height (cm)', mphDatasets);
}
}
else if (currentGrowthType === 'hcfa') {
var hc = parseFloat(document.getElementById('growth-hc').value);
if (!hc) { showToast('Enter head circumference', 'error'); return; }
if (age > 60) { showToast('HC charts available 0-60 months only', 'error'); return; }
var lms = interpolateLMS(hcfaLMS[sex], age);
var z = calcZFromLMS(hc, lms.L, lms.M, lms.S);
var p = normalCDF(z) * 100;
resultDiv.classList.remove('hidden');
resultDiv.innerHTML = renderGrowthResult('Head Circumference (' + age + ' mo)', hc, 'cm', z, p);
if (age > 24) {
var hcYears = {}; Object.keys(hcfaLMS[sex]).forEach(function(k) { hcYears[+(k/12).toFixed(2)] = hcfaLMS[sex][k]; });
renderGrowthChart('growth-chart-canvas', 'growth-chart-container', hcYears, +(age/12).toFixed(2), hc, 'Age (years)', 'Head Circumference (cm)');
} else {
renderGrowthChart('growth-chart-canvas', 'growth-chart-container', hcfaLMS[sex], age, hc, 'Age (months)', 'Head Circumference (cm)');
}
}
else if (currentGrowthType === 'wfl') {
var wt = parseFloat(document.getElementById('growth-weight').value);
var len = parseFloat(document.getElementById('growth-length').value);
if (!wt || !len) { showToast('Enter weight and length', 'error'); return; }
// Use WHO Weight-for-Length if length is within 45-110cm range
if (len >= 45 && len <= 110 && wflLMS[sex]) {
var lms = interpolateLMS(wflLMS[sex], len);
var z = calcZFromLMS(wt, lms.L, lms.M, lms.S);
var p = normalCDF(z) * 100;
resultDiv.classList.remove('hidden');
resultDiv.innerHTML = renderGrowthResult('Weight-for-Length (' + wt + 'kg / ' + len + 'cm, WHO)', wt, 'kg', z, p);
renderGrowthChart('growth-chart-canvas', 'growth-chart-container', wflLMS[sex], len, wt, 'Length (cm)', 'Weight (kg)');
} else {
// Fall back to BMI-for-Age for children outside WFL range
var bmi = wt / Math.pow(len / 100, 2);
var ageMonths = Math.max(24, Math.min(240, Math.round(age)));
var lms = interpolateLMS(bmiLMS[sex], ageMonths);
var z = calcZFromLMS(bmi, lms.L, lms.M, lms.S);
var p = normalCDF(z) * 100;
resultDiv.classList.remove('hidden');
resultDiv.innerHTML = renderGrowthResult('Weight-for-Length (' + wt + 'kg / ' + len + 'cm, BMI proxy)', 'BMI ' + bmi.toFixed(1), 'kg/m2', z, p);
}
}
});
document.getElementById('btn-clear-growth').addEventListener('click', function() {
['growth-sex', 'growth-age-yr', 'growth-age-mo', 'growth-age-d', 'growth-ga', 'growth-weight', 'growth-length', 'growth-hc'].forEach(function(id) {
var el = document.getElementById(id); if (el) el.value = '';
});
var hint = document.getElementById('growth-age-parsed'); if (hint) hint.textContent = '';
document.getElementById('growth-result').classList.add('hidden');
});
// Live feedback as the age fields change
var ageHint = document.getElementById('growth-age-parsed');
function updateAgeHint() {
if (!ageHint) return;
var yrRaw = ((document.getElementById('growth-age-yr') || {}).value || '').trim();
var moRaw = ((document.getElementById('growth-age-mo') || {}).value || '').trim();
var dyRaw = ((document.getElementById('growth-age-d') || {}).value || '').trim();
if (yrRaw === '' && moRaw === '' && dyRaw === '') { ageHint.textContent = ''; return; }
var total = (parseFloat(yrRaw) || 0) * 12 + (parseFloat(moRaw) || 0) + (parseFloat(dyRaw) || 0) / 30.4375;
ageHint.style.color = 'var(--g500)';
ageHint.textContent = formatParsedAge(total);
}
['growth-age-yr', 'growth-age-mo', 'growth-age-d'].forEach(function(id) {
var el = document.getElementById(id);
if (el) el.addEventListener('input', updateAgeHint);
});
// ═══════════════════════════════════════════════════════════
// BILIRUBIN — AAP 2022 Phototherapy + Bhutani Nomogram
// ═══════════════════════════════════════════════════════════
// ── Bilirubin chart helpers ──
function generateThresholdCurve(table) {
var keys = Object.keys(table).map(Number).sort(function(a,b){return a-b;});
return keys.map(function(h) { return { x: h, y: table[h] }; });
}
function renderBiliChart(patientHours, patientTSB, curveDatasets) {
if (typeof Chart === 'undefined') return;
var container = document.getElementById('bili-chart-container');
if (!container) return;
container.classList.remove('hidden');
if (_chartInstances['bili-chart-canvas']) { _chartInstances['bili-chart-canvas'].destroy(); _chartInstances['bili-chart-canvas'] = null; }
var datasets = curveDatasets.map(function(ds) {
return Object.assign({ pointRadius: 0, pointHoverRadius: 0, tension: 0.3, order: 10 }, ds);
});
// Patient point
datasets.push({
label: 'Patient',
data: [{ x: patientHours, y: patientTSB }],
backgroundColor: '#2563eb',
borderColor: '#1d4ed8',
pointRadius: 8,
pointHoverRadius: 10,
showLine: false,
type: 'scatter',
order: 0
});
_chartInstances['bili-chart-canvas'] = new Chart(document.getElementById('bili-chart-canvas'), {
type: 'line',
data: { datasets: datasets },
options: {
responsive: true,
maintainAspectRatio: true,
aspectRatio: 1.6,
animation: { duration: 300 },
scales: {
x: { type: 'linear', title: { display: true, text: 'Age (hours)', font: { size: 12, weight: 'bold' } }, min: 12, max: 150, grid: { color: 'rgba(0,0,0,0.05)' } },
y: { title: { display: true, text: 'TSB (mg/dL)', font: { size: 12, weight: 'bold' } }, min: 0, grid: { color: 'rgba(0,0,0,0.05)' } }
},
plugins: {
legend: { display: true, position: 'bottom', labels: { font: { size: 11 }, usePointStyle: true, pointStyle: 'line' } },
tooltip: {
callbacks: {
label: function(ctx) {
if (ctx.dataset.label === 'Patient') return 'Patient: ' + ctx.parsed.y.toFixed(1) + ' mg/dL at ' + ctx.parsed.x + 'h';
return ctx.dataset.label + ': ' + ctx.parsed.y.toFixed(1) + ' mg/dL';
}
}
}
}
}
});
}
// AAP 2022 phototherapy thresholds (TSB in mg/dL) by hour of age
// Source: Kemper et al., Pediatrics 2022;150(3):e2022058859, Figures 2-3
// Values read from published nomogram curves at key time points
// NOTE: The AAP 2022 raised thresholds ~2 mg/dL above the 2004 guidelines
// AAP 2022 EXACT hour-by-hour phototherapy thresholds (extracted from PediTools API, validated against AAP nomograms)
// >= 38 weeks, no neurotoxicity risk factors
var photoThresholds38 = {12:10.1,13:10.3,14:10.5,15:10.7,16:10.8,17:11,18:11.2,19:11.4,20:11.6,21:11.7,22:11.9,23:12.1,24:12.3,25:12.4,26:12.6,27:12.8,28:12.9,29:13.1,30:13.3,31:13.4,32:13.6,33:13.8,34:13.9,35:14.1,36:14.2,37:14.4,38:14.5,39:14.7,40:14.8,41:15,42:15.1,43:15.3,44:15.4,45:15.6,46:15.7,47:15.8,48:16,49:16.1,50:16.2,51:16.4,52:16.5,53:16.6,54:16.8,55:16.9,56:17,57:17.1,58:17.3,59:17.4,60:17.5,61:17.6,62:17.7,63:17.8,64:17.9,65:18.1,66:18.2,67:18.3,68:18.4,69:18.5,70:18.6,71:18.7,72:18.8,73:18.9,74:19,75:19.1,76:19.2,77:19.3,78:19.4,79:19.5,80:19.5,81:19.6,82:19.7,83:19.8,84:19.9,85:20,86:20,87:20.1,88:20.2,89:20.3,90:20.3,91:20.4,92:20.5,93:20.6,94:20.6,95:20.7,96:20.7};
// >= 38 weeks, WITH neurotoxicity risk factors
var photoThresholds38risk = {12:8.5,13:8.6,14:8.8,15:9,16:9.2,17:9.4,18:9.5,19:9.7,20:9.9,21:10,22:10.2,23:10.4,24:10.5,25:10.7,26:10.8,27:11,28:11.2,29:11.3,30:11.5,31:11.6,32:11.8,33:11.9,34:12.1,35:12.2,36:12.4,37:12.5,38:12.7,39:12.8,40:12.9,41:13.1,42:13.2,43:13.3,44:13.5,45:13.6,46:13.7,47:13.9,48:14,49:14.1,50:14.2,51:14.4,52:14.5,53:14.6,54:14.7,55:14.8,56:14.9,57:15.1,58:15.2,59:15.3,60:15.4,61:15.5,62:15.6,63:15.7,64:15.8,65:15.9,66:16,67:16.1,68:16.2,69:16.3,70:16.4,71:16.5,72:16.6,73:16.6,74:16.7,75:16.8,76:16.9,77:17,78:17.1,79:17.1,80:17.2,81:17.3,82:17.4,83:17.4,84:17.5,85:17.6,86:17.6,87:17.7,88:17.8,89:17.8,90:17.9,91:18,92:18,93:18.1,94:18.1,95:18.2,96:18.2};
// 36-37 weeks, no neurotoxicity risk factors
var photoThresholds36 = {12:9,13:9.2,14:9.4,15:9.6,16:9.8,17:9.9,18:10.1,19:10.3,20:10.5,21:10.6,22:10.8,23:11,24:11.2,25:11.3,26:11.5,27:11.7,28:11.8,29:12,30:12.1,31:12.3,32:12.5,33:12.6,34:12.8,35:12.9,36:13.1,37:13.2,38:13.4,39:13.5,40:13.7,41:13.8,42:13.9,43:14.1,44:14.2,45:14.4,46:14.5,47:14.6,48:14.8,49:14.9,50:15,51:15.1,52:15.3,53:15.4,54:15.5,55:15.6,56:15.8,57:15.9,58:16,59:16.1,60:16.2,61:16.3,62:16.5,63:16.6,64:16.7,65:16.8,66:16.9,67:17,68:17.1,69:17.2,70:17.3,71:17.4,72:17.5,73:17.6,74:17.7,75:17.8,76:17.9,77:17.9,78:18,79:18.1,80:18.2,81:18.3,82:18.4,83:18.4,84:18.5,85:18.6,86:18.7,87:18.8,88:18.8,89:18.9,90:19,91:19,92:19.1,93:19.2,94:19.2,95:19.3,96:19.3};
// 36-37 weeks, WITH neurotoxicity risk factors
var photoThresholds36risk = {12:7.4,13:7.6,14:7.8,15:8,16:8.1,17:8.3,18:8.5,19:8.6,20:8.8,21:9,22:9.1,23:9.3,24:9.4,25:9.6,26:9.8,27:9.9,28:10.1,29:10.2,30:10.4,31:10.5,32:10.7,33:10.8,34:11,35:11.1,36:11.2,37:11.4,38:11.5,39:11.7,40:11.8,41:11.9,42:12.1,43:12.2,44:12.3,45:12.5,46:12.6,47:12.7,48:12.8,49:13,50:13.1,51:13.2,52:13.3,53:13.4,54:13.5,55:13.7,56:13.8,57:13.9,58:14,59:14.1,60:14.2,61:14.3,62:14.4,63:14.5,64:14.6,65:14.7,66:14.8,67:14.9,68:15,69:15.1,70:15.2,71:15.3,72:15.4,73:15.4,74:15.5,75:15.6,76:15.7,77:15.8,78:15.8,79:15.9,80:16,81:16.1,82:16.1,83:16.2,84:16.3,85:16.4,86:16.4,87:16.5,88:16.6,89:16.6,90:16.7,91:16.7,92:16.8,93:16.8,94:16.9,95:17,96:17};
// 35 weeks, no neurotoxicity risk factors
var photoThresholds35 = {12:8.5,13:8.7,14:8.9,15:9,16:9.2,17:9.4,18:9.6,19:9.8,20:9.9,21:10.1,22:10.3,23:10.4,24:10.6,25:10.8,26:10.9,27:11.1,28:11.3,29:11.4,30:11.6,31:11.7,32:11.9,33:12,34:12.2,35:12.3,36:12.5,37:12.6,38:12.8,39:12.9,40:13.1,41:13.2,42:13.4,43:13.5,44:13.6,45:13.8,46:13.9,47:14,48:14.2,49:14.3,50:14.4,51:14.5,52:14.7,53:14.8,54:14.9,55:15,56:15.1,57:15.3,58:15.4,59:15.5,60:15.6,61:15.7,62:15.8,63:15.9,64:16,65:16.1,66:16.2,67:16.3,68:16.4,69:16.5,70:16.6,71:16.7,72:16.8,73:16.9,74:17,75:17.1,76:17.2,77:17.3,78:17.4,79:17.5,80:17.5,81:17.6,82:17.7,83:17.8,84:17.8,85:17.9,86:18,87:18.1,88:18.1,89:18.2,90:18.3,91:18.3,92:18.4,93:18.5,94:18.5,95:18.6,96:18.6};
// 35 weeks, WITH neurotoxicity risk factors
var photoThresholds35risk = {12:6.9,13:7.1,14:7.2,15:7.4,16:7.6,17:7.7,18:7.9,19:8.1,20:8.2,21:8.4,22:8.6,23:8.7,24:8.9,25:9,26:9.2,27:9.3,28:9.5,29:9.6,30:9.8,31:9.9,32:10.1,33:10.2,34:10.3,35:10.5,36:10.6,37:10.8,38:10.9,39:11,40:11.2,41:11.3,42:11.4,43:11.5,44:11.7,45:11.8,46:11.9,47:12,48:12.2,49:12.3,50:12.4,51:12.5,52:12.6,53:12.7,54:12.8,55:13,56:13.1,57:13.2,58:13.3,59:13.4,60:13.5,61:13.6,62:13.7,63:13.8,64:13.9,65:14,66:14.1,67:14.2,68:14.2,69:14.3,70:14.4,71:14.5,72:14.6,73:14.7,74:14.8,75:14.8,76:14.9,77:15,78:15.1,79:15.1,80:15.2,81:15.3,82:15.3,83:15.4,84:15.5,85:15.5,86:15.6,87:15.7,88:15.7,89:15.8,90:15.8,91:15.9,92:15.9,93:16,94:16.1,95:16.1,96:16.1};
// Exchange transfusion thresholds (AAP 2022, hour-by-hour from PediTools)
var exchangeThresholds38 = {12:19.7,13:19.9,14:20,15:20.1,16:20.3,17:20.4,18:20.6,19:20.7,20:20.8,21:21,22:21.1,23:21.2,24:21.4,25:21.5,26:21.6,27:21.7,28:21.9,29:22,30:22.1,31:22.2,32:22.3,33:22.4,34:22.6,35:22.7,36:22.8,37:22.9,38:23,39:23.1,40:23.2,41:23.3,42:23.4,43:23.5,44:23.6,45:23.7,46:23.8,47:23.9,48:24,49:24.1,50:24.2,51:24.3,52:24.4,53:24.5,54:24.6,55:24.7,56:24.7,57:24.8,58:24.9,59:25,60:25.1,61:25.2,62:25.2,63:25.3,64:25.4,65:25.5,66:25.5,67:25.6,68:25.7,69:25.7,70:25.8,71:25.9,72:25.9,73:26,74:26,75:26.1,76:26.2,77:26.2,78:26.3,79:26.3,80:26.4,81:26.4,82:26.5,83:26.5,84:26.6,85:26.6,86:26.7,87:26.7,88:26.7,89:26.8,90:26.8,91:26.9,92:26.9,93:26.9,94:27,95:27,96:27};
var exchangeThresholds38risk = {12:16.3,13:16.4,14:16.5,15:16.6,16:16.7,17:16.9,18:17,19:17.1,20:17.2,21:17.3,22:17.4,23:17.6,24:17.7,25:17.8,26:17.9,27:18,28:18.1,29:18.2,30:18.3,31:18.4,32:18.5,33:18.7,34:18.8,35:18.9,36:19,37:19.1,38:19.2,39:19.3,40:19.4,41:19.5,42:19.6,43:19.7,44:19.8,45:19.9,46:19.9,47:20,48:20.1,49:20.2,50:20.3,51:20.4,52:20.5,53:20.6,54:20.7,55:20.8,56:20.8,57:20.9,58:21,59:21.1,60:21.2,61:21.3,62:21.3,63:21.4,64:21.5,65:21.6,66:21.7,67:21.7,68:21.8,69:21.9,70:22,71:22,72:22.1,73:22.2,74:22.2,75:22.3,76:22.4,77:22.5,78:22.5,79:22.6,80:22.7,81:22.7,82:22.8,83:22.8,84:22.9,85:23,86:23,87:23.1,88:23.1,89:23.2,90:23.3,91:23.3,92:23.4,93:23.4,94:23.5,95:23.5,96:23.5};
var exchangeThresholds36 = {12:17.5,13:17.7,14:17.8,15:17.9,16:18.1,17:18.2,18:18.3,19:18.5,20:18.6,21:18.7,22:18.9,23:19,24:19.1,25:19.2,26:19.4,27:19.5,28:19.6,29:19.7,30:19.9,31:20,32:20.1,33:20.2,34:20.4,35:20.5,36:20.6,37:20.7,38:20.8,39:20.9,40:21,41:21.2,42:21.3,43:21.4,44:21.5,45:21.6,46:21.7,47:21.8,48:21.9,49:22,50:22.1,51:22.2,52:22.3,53:22.4,54:22.5,55:22.6,56:22.7,57:22.8,58:22.9,59:23,60:23.1,61:23.2,62:23.2,63:23.3,64:23.4,65:23.5,66:23.6,67:23.7,68:23.8,69:23.8,70:23.9,71:24,72:24.1,73:24.1,74:24.2,75:24.3,76:24.4,77:24.4,78:24.5,79:24.6,80:24.6,81:24.7,82:24.8,83:24.8,84:24.9,85:25,86:25,87:25.1,88:25.2,89:25.2,90:25.3,91:25.3,92:25.4,93:25.4,94:25.5,95:25.5,96:25.5};
var exchangeThresholds36risk = {12:15.2,13:15.3,14:15.4,15:15.6,16:15.7,17:15.8,18:15.9,19:16.1,20:16.2,21:16.3,22:16.4,23:16.5,24:16.6,25:16.8,26:16.9,27:17,28:17.1,29:17.2,30:17.3,31:17.4,32:17.5,33:17.6,34:17.7,35:17.8,36:17.9,37:18,38:18.1,39:18.2,40:18.3,41:18.4,42:18.5,43:18.6,44:18.7,45:18.8,46:18.9,47:19,48:19.1,49:19.2,50:19.2,51:19.3,52:19.4,53:19.5,54:19.6,55:19.7,56:19.7,57:19.8,58:19.9,59:20,60:20.1,61:20.1,62:20.2,63:20.3,64:20.3,65:20.4,66:20.5,67:20.6,68:20.6,69:20.7,70:20.8,71:20.8,72:20.9,73:20.9,74:21,75:21.1,76:21.1,77:21.2,78:21.2,79:21.3,80:21.4,81:21.4,82:21.5,83:21.5,84:21.6,85:21.6,86:21.7,87:21.7,88:21.8,89:21.8,90:21.9,91:21.9,92:22,93:22,94:22,95:22.1,96:22.1};
var exchangeThresholds35 = {12:16.4,13:16.5,14:16.6,15:16.8,16:16.9,17:17,18:17.2,19:17.3,20:17.4,21:17.5,22:17.7,23:17.8,24:17.9,25:18,26:18.2,27:18.3,28:18.4,29:18.5,30:18.7,31:18.8,32:18.9,33:19,34:19.1,35:19.2,36:19.4,37:19.5,38:19.6,39:19.7,40:19.8,41:19.9,42:20,43:20.1,44:20.2,45:20.3,46:20.5,47:20.6,48:20.7,49:20.8,50:20.9,51:21,52:21.1,53:21.2,54:21.3,55:21.4,56:21.5,57:21.6,58:21.7,59:21.7,60:21.8,61:21.9,62:22,63:22.1,64:22.2,65:22.3,66:22.4,67:22.5,68:22.6,69:22.6,70:22.7,71:22.8,72:22.9,73:23,74:23.1,75:23.1,76:23.2,77:23.3,78:23.4,79:23.4,80:23.5,81:23.6,82:23.7,83:23.7,84:23.8,85:23.9,86:23.9,87:24,88:24.1,89:24.1,90:24.2,91:24.3,92:24.3,93:24.4,94:24.4,95:24.5,96:24.5};
var exchangeThresholds35risk = {12:14.6,13:14.8,14:14.9,15:15,16:15.1,17:15.3,18:15.4,19:15.5,20:15.6,21:15.8,22:15.9,23:16,24:16.1,25:16.2,26:16.3,27:16.4,28:16.5,29:16.6,30:16.8,31:16.9,32:17,33:17.1,34:17.2,35:17.3,36:17.4,37:17.5,38:17.6,39:17.7,40:17.7,41:17.8,42:17.9,43:18,44:18.1,45:18.2,46:18.3,47:18.4,48:18.5,49:18.5,50:18.6,51:18.7,52:18.8,53:18.9,54:18.9,55:19,56:19.1,57:19.2,58:19.2,59:19.3,60:19.4,61:19.4,62:19.5,63:19.6,64:19.6,65:19.7,66:19.8,67:19.8,68:19.9,69:19.9,70:20,71:20.1,72:20.1,73:20.2,74:20.2,75:20.3,76:20.3,77:20.4,78:20.4,79:20.5,80:20.5,81:20.6,82:20.6,83:20.6,84:20.7,85:20.7,86:20.8,87:20.8,88:20.8,89:20.9,90:20.9,91:20.9,92:21,93:21,94:21,95:21.1,96:21.1};
function interpolateThreshold(table, hours) {
var keys = Object.keys(table).map(Number).sort(function(a,b){return a-b;});
if (hours <= keys[0]) return table[keys[0]];
if (hours >= keys[keys.length-1]) return table[keys[keys.length-1]];
for (var i = 0; i < keys.length-1; i++) {
if (hours >= keys[i] && hours <= keys[i+1]) {
var t = (hours - keys[i]) / (keys[i+1] - keys[i]);
return table[keys[i]] + t * (table[keys[i+1]] - table[keys[i]]);
}
}
return table[keys[0]];
}
// Bili sub-pill nav
document.querySelectorAll('[data-bili]').forEach(function(pill) {
pill.addEventListener('click', function() {
document.querySelectorAll('[data-bili]').forEach(function(p) { p.classList.remove('active'); });
pill.classList.add('active');
document.getElementById('bili-aap-panel').style.display = pill.dataset.bili === 'aap' ? '' : 'none';
document.getElementById('bili-bhutani-panel').style.display = pill.dataset.bili === 'bhutani' ? '' : 'none';
document.getElementById('bili-result').classList.add('hidden');
var biliChartC = document.getElementById('bili-chart-container');
if (biliChartC) biliChartC.classList.add('hidden');
if (_chartInstances['bili-chart-canvas']) { _chartInstances['bili-chart-canvas'].destroy(); _chartInstances['bili-chart-canvas'] = null; }
});
});
document.getElementById('btn-calc-bili-aap').addEventListener('click', function() {
var ga = document.getElementById('bili-ga').value;
var hours = parseFloat(document.getElementById('bili-age-hours').value);
var tsb = parseFloat(document.getElementById('bili-tsb').value);
var risk = document.getElementById('bili-risk').value;
if (!ga || isNaN(hours) || isNaN(tsb)) { showToast('Fill in all fields', 'error'); return; }
var gaNum = parseInt(ga);
var table;
if (gaNum >= 38) table = risk === 'medium' ? photoThresholds38risk : photoThresholds38;
else if (gaNum === 36 || gaNum === 37) table = risk === 'medium' ? photoThresholds36risk : photoThresholds36;
else table = risk === 'medium' ? photoThresholds35risk : photoThresholds35;
var threshold = interpolateThreshold(table, hours);
var aboveThreshold = tsb >= threshold;
// Check exchange transfusion threshold too
var exchangeTable;
if (gaNum >= 38) exchangeTable = risk === 'medium' ? exchangeThresholds38risk : exchangeThresholds38;
else if (gaNum >= 36) exchangeTable = risk === 'medium' ? exchangeThresholds36risk : exchangeThresholds36;
else exchangeTable = risk === 'medium' ? exchangeThresholds35risk : exchangeThresholds35;
var exchangeThreshold = exchangeTable ? interpolateThreshold(exchangeTable, hours) : null;
var aboveExchange = exchangeThreshold && tsb >= exchangeThreshold;
var cl;
if (aboveExchange) cl = { text: 'ABOVE EXCHANGE TRANSFUSION THRESHOLD', color: '#7f1d1d', bg: '#fecaca' };
else if (aboveThreshold) cl = { text: 'Above Phototherapy Threshold', color: '#ef4444', bg: '#fee2e2' };
else cl = { text: 'Below Phototherapy Threshold', color: '#10b981', bg: '#d1fae5' };
var resultDiv = document.getElementById('bili-result');
resultDiv.classList.remove('hidden');
resultDiv.innerHTML =
'<div class="calc-result-header" style="background:' + cl.bg + ';border-color:' + cl.color + ';">' +
'<div style="font-size:18px;font-weight:700;color:' + cl.color + ';">' + cl.text + '</div>' +
'<div style="font-size:13px;color:var(--g600);margin-top:4px;">TSB ' + tsb + ' mg/dL at ' + hours + ' hours of life</div>' +
'</div>' +
'<div class="calc-result-grid">' +
'<div class="calc-result-item"><div class="calc-result-label">Patient TSB</div><div class="calc-result-value">' + tsb + '</div><div class="calc-result-sub">mg/dL</div></div>' +
'<div class="calc-result-item"><div class="calc-result-label">Photo Threshold</div><div class="calc-result-value">' + threshold.toFixed(1) + '</div><div class="calc-result-sub">mg/dL at ' + hours + 'h</div></div>' +
'<div class="calc-result-item"><div class="calc-result-label">Margin</div><div class="calc-result-value" style="color:' + cl.color + ';">' + (tsb >= threshold ? '+' : '') + (tsb - threshold).toFixed(1) + '</div><div class="calc-result-sub">mg/dL ' + (aboveThreshold ? 'above' : 'below') + ' photo</div></div>' +
(exchangeThreshold ? '<div class="calc-result-item"><div class="calc-result-label">Exchange Threshold</div><div class="calc-result-value" style="color:#7f1d1d;">' + exchangeThreshold.toFixed(1) + '</div><div class="calc-result-sub">mg/dL' + (aboveExchange ? ' — EXCEEDED' : '') + '</div></div>' : '') +
'</div>' +
'<p style="font-size:11px;color:var(--g400);margin:12px 0 0;">GA ' + ga + ' weeks, ' + (risk === 'medium' ? 'with' : 'without') + ' neurotoxicity risk factors. AAP 2022 CPG (exact values from published nomograms). Always use clinical judgment.</p>';
// Chart: phototherapy + exchange threshold lines vs patient
var chartDatasets = [
{ label: 'Phototherapy Threshold', data: generateThresholdCurve(table), borderColor: '#ef4444', borderWidth: 2, borderDash: [], fill: { target: 'origin', above: 'rgba(239,68,68,0.08)' } }
];
if (exchangeTable) {
chartDatasets.push({ label: 'Exchange Transfusion', data: generateThresholdCurve(exchangeTable), borderColor: '#7f1d1d', borderWidth: 2, borderDash: [6,3], fill: false });
}
renderBiliChart(hours, tsb, chartDatasets);
});
document.getElementById('btn-clear-bili-aap').addEventListener('click', function() {
['bili-ga', 'bili-age-hours', 'bili-tsb', 'bili-risk'].forEach(function(id) {
var el = document.getElementById(id); if (el) el.value = '';
});
document.getElementById('bili-result').classList.add('hidden');
var bc = document.getElementById('bili-chart-container'); if (bc) bc.classList.add('hidden');
});
// Bhutani 1999 hour-specific risk nomogram — 40th / 75th / 95th
// percentile TSB boundaries. Values are a pre-digitized transcription
// of the original Figure 2 (Bhutani VK et al., Pediatrics 1999;103(1):6-14),
// lifted verbatim from the JS data arrays used by the codingace.net
// Bhutani calculator:
// https://codingace.net/health/neonate_bilirubin_bhutani.html
// Cross-checked against the AAP 2004 CPG reproduction of the same chart:
// https://staffnet.southernhealth.ca/wp-content/uploads/Bhutani-Nomogram.pdf
// (Reproduced with AAP permission from Pediatrics 2004;114:297-316)
// 6-hour granularity through the first 72 h, 12-hour after.
//
// Zone semantics (per AAP 2004 reproduction legend):
// High-risk: TSB >= 95th percentile
// High-intermediate: 75th <= TSB < 95th
// Low-intermediate: 40th <= TSB < 75th
// Low-risk: TSB < 40th
//
// Clinical note: this nomogram is for RISK STRATIFICATION only.
// For phototherapy/exchange decisions use the AAP 2022 tab
// (which supersedes the 2004 treatment thresholds).
var bhutaniZones = {
p95: { 6:6.0, 12:7.2, 18:8.5, 24:9.6, 30:11.2, 36:12.8, 42:13.8, 48:14.8,
54:15.6, 60:16.2, 66:16.8, 72:17.4, 84:18.0, 96:18.4, 108:18.8, 120:19.0 },
p75: { 6:4.5, 12:5.5, 18:6.6, 24:7.8, 30:9.2, 36:10.6, 42:11.6, 48:12.6,
54:13.4, 60:14.0, 66:14.6, 72:15.0, 84:15.4, 96:15.6, 108:15.8, 120:16.0 },
p40: { 6:3.0, 12:4.0, 18:5.0, 24:6.2, 30:7.2, 36:8.4, 42:9.2, 48:10.0,
54:10.6, 60:11.2, 66:11.8, 72:12.2, 84:12.6, 96:12.8, 108:13.0, 120:13.2 }
};
document.getElementById('btn-calc-bhutani').addEventListener('click', function() {
var hours = parseFloat(document.getElementById('bhutani-age').value);
var tsb = parseFloat(document.getElementById('bhutani-tsb').value);
if (isNaN(hours) || isNaN(tsb)) { showToast('Fill in all fields', 'error'); return; }
var p95 = interpolateThreshold(bhutaniZones.p95, hours);
var p75 = interpolateThreshold(bhutaniZones.p75, hours);
var p40 = interpolateThreshold(bhutaniZones.p40, hours);
var zone, cl;
if (tsb >= p95) { zone = 'High-Risk Zone'; cl = { color: '#ef4444', bg: '#fee2e2' }; }
else if (tsb >= p75) { zone = 'High-Intermediate Zone'; cl = { color: '#f97316', bg: '#ffedd5' }; }
else if (tsb >= p40) { zone = 'Low-Intermediate Zone'; cl = { color: '#f59e0b', bg: '#fef3c7' }; }
else { zone = 'Low-Risk Zone'; cl = { color: '#10b981', bg: '#d1fae5' }; }
var resultDiv = document.getElementById('bili-result');
resultDiv.classList.remove('hidden');
resultDiv.innerHTML =
'<div class="calc-result-header" style="background:' + cl.bg + ';border-color:' + cl.color + ';">' +
'<div style="font-size:18px;font-weight:700;color:' + cl.color + ';">' + zone + '</div>' +
'<div style="font-size:13px;color:var(--g600);margin-top:4px;">TSB ' + tsb + ' mg/dL at ' + hours + ' hours of life</div>' +
'</div>' +
'<div class="calc-result-grid">' +
'<div class="calc-result-item"><div class="calc-result-label">95th %ile</div><div class="calc-result-value" style="font-size:16px;color:#ef4444;">' + p95.toFixed(1) + '</div><div class="calc-result-sub">High-risk</div></div>' +
'<div class="calc-result-item"><div class="calc-result-label">75th %ile</div><div class="calc-result-value" style="font-size:16px;color:#f97316;">' + p75.toFixed(1) + '</div><div class="calc-result-sub">High-intermediate</div></div>' +
'<div class="calc-result-item"><div class="calc-result-label">40th %ile</div><div class="calc-result-value" style="font-size:16px;color:#f59e0b;">' + p40.toFixed(1) + '</div><div class="calc-result-sub">Low-intermediate</div></div>' +
'</div>' +
'<p style="font-size:11px;color:var(--g400);margin:12px 0 0;">Bhutani hour-specific risk nomogram for infants &ge; 35 weeks GA. Digitized values from Bhutani et al., Pediatrics 1999 (cross-checked against the AAP 2004 CPG reproduction). For phototherapy decisions use the AAP 2022 tab.</p>';
// Chart: Bhutani zone curves with patient
renderBiliChart(hours, tsb, [
{ label: '95th (High-Risk)', data: generateThresholdCurve(bhutaniZones.p95), borderColor: '#ef4444', borderWidth: 2, fill: false, borderDash: [] },
{ label: '75th (High-Intermed)', data: generateThresholdCurve(bhutaniZones.p75), borderColor: '#f97316', borderWidth: 1.5, fill: { target: '-1', above: 'rgba(239,68,68,0.08)' }, borderDash: [3,3] },
{ label: '40th (Low-Intermed)', data: generateThresholdCurve(bhutaniZones.p40), borderColor: '#f59e0b', borderWidth: 1.5, fill: { target: '-1', above: 'rgba(249,115,22,0.08)' }, borderDash: [3,3] }
]);
});
document.getElementById('btn-clear-bhutani').addEventListener('click', function() {
['bhutani-age', 'bhutani-tsb'].forEach(function(id) {
var el = document.getElementById(id); if (el) el.value = '';
});
document.getElementById('bili-result').classList.add('hidden');
var bc = document.getElementById('bili-chart-container'); if (bc) bc.classList.add('hidden');
});
// ═══════════════════════════════════════════════════════════
// VITAL SIGNS — Interactive age selector
// Harriet Lane Handbook 23rd Edition reference values
// ═══════════════════════════════════════════════════════════
var VITALS_DATA = {
premie: {
label: 'Premie',
hr: { awake: '120-170', sleeping: '100-150' },
rr: '40-70',
sbp: '55-75', dbp: '35-45',
temp: '36.5-37.5',
weight: '0.5-2.5 kg',
spo2: '88-95% (target)',
notes: [
'HR and RR are highly variable and depend on gestational age',
'BP increases with gestational age and postnatal age',
'Target SpO2 88-95% to reduce retinopathy of prematurity risk',
'Temperature instability is common — use servo-controlled warmers',
'Bradycardia (<100 bpm) and apnea are common in premature infants'
]
},
'0-3mo': {
label: '0-3 Months',
hr: { awake: '100-150', sleeping: '85-135' },
rr: '35-55',
sbp: '65-85', dbp: '45-55',
temp: '36.5-37.5',
weight: '2.5-6 kg',
spo2: '>95%',
notes: [
'HR normally increases with crying (up to 180-190 bpm) — this is physiologic',
'Periodic breathing (pauses <10 sec) is normal in neonates',
'Acrocyanosis (blue hands/feet) is normal; central cyanosis is not',
'BP is best measured in the right arm (pre-ductal) in neonates',
'Normal weight loss of 5-7% in first 3-5 days; regain by 10-14 days'
]
},
'3-6mo': {
label: '3-6 Months',
hr: { awake: '90-120', sleeping: '75-110' },
rr: '30-45',
sbp: '70-90', dbp: '50-65',
temp: '36.5-37.5',
weight: '5-8 kg',
spo2: '>95%',
notes: [
'Expected weight gain: 20-30 g/day (150-200 g/week)',
'HR gradually decreases as vagal tone matures',
'RR >60 at rest may indicate lower respiratory tract disease',
'BP should be measured with appropriate cuff size (width 40% of arm circumference)'
]
},
'6-12mo': {
label: '6-12 Months',
hr: { awake: '80-120', sleeping: '70-110' },
rr: '25-40',
sbp: '80-100', dbp: '55-65',
temp: '36.0-37.5',
weight: '8-10 kg',
spo2: '>95%',
notes: [
'Expected weight: triple birth weight by 12 months (~10 kg average)',
'Weight gain slows to ~10-15 g/day',
'Sinus arrhythmia (HR varies with breathing) is normal',
'Febrile tachycardia: HR increases ~10 bpm per 1 degree C above 37'
]
},
'1-3yr': {
label: '1-3 Years',
hr: { awake: '70-110', sleeping: '60-100' },
rr: '20-30',
sbp: '90-105', dbp: '55-70',
temp: '36.0-37.5',
weight: '10-15 kg',
spo2: '>95%',
notes: [
'Expected weight gain: ~200-250 g/month (2-2.5 kg/year)',
'Tachycardia: HR >110 at rest warrants evaluation',
'Tachypnea: RR >30 at rest may indicate respiratory distress',
'BP screening begins at age 3 per AAP 2017 guidelines',
'Estimated weight: 2 x (age in years) + 8'
]
},
'3-6yr': {
label: '3-6 Years',
hr: { awake: '65-110', sleeping: '55-100' },
rr: '20-25',
sbp: '95-110', dbp: '60-75',
temp: '36.0-37.5',
weight: '14-20 kg',
spo2: '>95%',
notes: [
'Annual BP screening recommended from age 3',
'Normal BP <90th percentile for age, sex, and height',
'Elevated BP: 90th to <95th percentile (or 120/80 if lower)',
'Estimated weight: 2 x (age in years) + 8',
'ETT size (uncuffed): (age/4) + 4'
]
},
'6-12yr': {
label: '6-12 Years',
hr: { awake: '60-95', sleeping: '50-85' },
rr: '14-22',
sbp: '100-120', dbp: '60-75',
temp: '36.0-37.5',
weight: '20-40 kg',
spo2: '>95%',
notes: [
'Resting HR >95 or <60 warrants evaluation',
'BP should be measured at every clinical encounter',
'Stage 1 HTN: >=95th percentile on 3 separate occasions',
'Estimated weight: 3 x (age in years) + 7',
'ETT size (cuffed): (age/4) + 3.5'
]
},
'>12yr': {
label: '>12 Years',
hr: { awake: '55-85', sleeping: '45-75' },
rr: '12-18',
sbp: '110-135', dbp: '65-85',
temp: '36.0-37.5',
weight: '40-80 kg',
spo2: '>95%',
notes: [
'Vital signs approach adult values',
'From age 13: use adult BP thresholds (AAP 2017)',
'Normal: <120/<80 mmHg; Elevated: 120-129/<80 mmHg',
'Stage 1 HTN: 130-139/80-89 mmHg; Stage 2 HTN: >=140/>=90 mmHg',
'Orthostatic vitals: measure lying, sitting, standing if dizzy',
'Athletic bradycardia (HR 45-60) may be normal in trained adolescents'
]
}
};
// Use event delegation on the vitals panel so the listener works even
// when the panel is hidden at init time (hidden elements are still in the DOM,
// but a setTimeout-based approach can race with dynamic content loading).
var vitalsPanel = document.getElementById('calc-vitals');
if (vitalsPanel) {
vitalsPanel.addEventListener('change', function(e) {
if (e.target.id !== 'vitals-age-select') return;
var key = e.target.value;
var resultDiv = document.getElementById('vitals-result');
if (!key || !VITALS_DATA[key]) { resultDiv.classList.add('hidden'); return; }
var v = VITALS_DATA[key];
resultDiv.classList.remove('hidden');
resultDiv.innerHTML =
'<div class="calc-result-header" style="background:#eff6ff;border-color:#2563eb;">' +
'<div style="font-size:18px;font-weight:700;color:#1d4ed8;">' + v.label + '</div>' +
'</div>' +
'<div class="calc-result-grid" style="margin-top:12px;">' +
'<div class="calc-result-item"><div class="calc-result-label">Heart Rate (awake)</div><div class="calc-result-value" style="font-size:18px;color:#ef4444;">' + v.hr.awake + '</div><div class="calc-result-sub">bpm</div></div>' +
'<div class="calc-result-item"><div class="calc-result-label">Heart Rate (sleep)</div><div class="calc-result-value" style="font-size:18px;color:#8b5cf6;">' + v.hr.sleeping + '</div><div class="calc-result-sub">bpm</div></div>' +
'<div class="calc-result-item"><div class="calc-result-label">Respiratory Rate</div><div class="calc-result-value" style="font-size:18px;color:#0ea5e9;">' + v.rr + '</div><div class="calc-result-sub">breaths/min</div></div>' +
'<div class="calc-result-item"><div class="calc-result-label">Systolic BP</div><div class="calc-result-value" style="font-size:18px;color:#f97316;">' + v.sbp + '</div><div class="calc-result-sub">mmHg</div></div>' +
'<div class="calc-result-item"><div class="calc-result-label">Diastolic BP</div><div class="calc-result-value" style="font-size:18px;color:#f59e0b;">' + v.dbp + '</div><div class="calc-result-sub">mmHg</div></div>' +
'<div class="calc-result-item"><div class="calc-result-label">Temperature</div><div class="calc-result-value" style="font-size:18px;color:#10b981;">' + v.temp + '</div><div class="calc-result-sub">&deg;C</div></div>' +
'<div class="calc-result-item"><div class="calc-result-label">SpO2</div><div class="calc-result-value" style="font-size:18px;color:#06b6d4;">' + v.spo2 + '</div><div class="calc-result-sub"></div></div>' +
'<div class="calc-result-item"><div class="calc-result-label">Weight Range</div><div class="calc-result-value" style="font-size:18px;color:#6366f1;">' + v.weight + '</div><div class="calc-result-sub"></div></div>' +
'</div>' +
'<div style="margin-top:14px;padding:12px;background:var(--g50);border-radius:8px;">' +
'<div style="font-size:12px;font-weight:600;color:var(--g600);margin-bottom:6px;">Clinical Notes</div>' +
'<ul style="margin:0;padding-left:16px;font-size:12px;color:var(--g700);line-height:1.7;">' +
v.notes.map(function(n) { return '<li>' + n + '</li>'; }).join('') +
'</ul>' +
'</div>';
});
}
// ═══════════════════════════════════════════════════════════
// RESUSCITATION MEDICATIONS — Harriet Lane Handbook / AHA PALS 2020
// ═══════════════════════════════════════════════════════════
var RESUS_MEDS = [
{
name: 'Adenosine', indication: 'SVT', category: 'cardiac',
route: 'IV/IO rapid bolus',
calc: function(w) {
var d1 = +(w * 0.1).toFixed(2);
var d2 = +(w * 0.2).toFixed(2);
var d3 = +(w * 0.3).toFixed(2);
return {
dose: d1 + ' mg (0.1 mg/kg)',
extra: 'May repeat: ' + Math.min(d2, 12) + ' mg (0.2 mg/kg), then ' + Math.min(d3, 12) + ' mg (0.3 mg/kg)',
max: 'Max first dose 6 mg, max subsequent 12 mg'
};
}
},
{
name: 'Amiodarone', indication: 'VT / VF', category: 'cardiac',
route: 'IV/IO',
calc: function(w) {
var d = +(w * 5).toFixed(1);
return {
dose: Math.min(d, 300) + ' mg (5 mg/kg)',
extra: 'No pulse: push undiluted. Pulse: over 20-60 min. Subsequent max 150 mg.',
max: 'Max first 300 mg, max total 15 mg/kg/24hr or 2200 mg'
};
}
},
{
name: 'Atropine', indication: 'Bradycardia', category: 'cardiac',
route: 'IV/IO/IM',
calc: function(w) {
var d = +(w * 0.02).toFixed(3);
var ett = (w * 0.04).toFixed(3) + '-' + (w * 0.06).toFixed(3);
return {
dose: Math.min(d, 0.5) + ' mg (0.02 mg/kg)',
extra: 'ETT dose: ' + ett + ' mg (0.04-0.06 mg/kg)',
max: 'Max single 0.5 mg, max total 1 mg'
};
}
},
{
name: 'Calcium Chloride 10%', indication: 'Hypocalcemia / Hyperkalemia', category: 'metabolic',
route: 'IV/IO',
calc: function(w) {
var d = +(w * 20).toFixed(0);
return {
dose: Math.min(d, 1000) + ' mg (20 mg/kg)',
extra: 'Give slowly. Central line preferred.',
max: 'Max 1 g (1000 mg)'
};
}
},
{
name: 'Calcium Gluconate 10%', indication: 'Hypocalcemia / Hyperkalemia', category: 'metabolic',
route: 'IV/IO',
calc: function(w) {
var d = +(w * 60).toFixed(0);
return {
dose: Math.min(d, 3000) + ' mg (60 mg/kg)',
extra: 'Give slowly over 10-20 min with cardiac monitoring.',
max: 'Max 3 g (3000 mg)'
};
}
},
{
name: 'Dextrose', indication: 'Hypoglycemia', category: 'metabolic',
route: 'IV',
calc: function(w) {
var grams = +(w * 0.5).toFixed(1) + '-' + +(w * 1).toFixed(1);
var detail = '';
if (w < 5) {
var ml = (w * 5).toFixed(1) + '-' + (w * 10).toFixed(1);
detail = 'D10W: ' + ml + ' mL (5-10 mL/kg)';
} else if (w < 45) {
var ml = (w * 2).toFixed(1) + '-' + (w * 4).toFixed(1);
detail = 'D25W: ' + ml + ' mL (2-4 mL/kg)';
} else {
var ml = (w * 1).toFixed(1) + '-' + (w * 2).toFixed(1);
detail = 'D50W: ' + ml + ' mL (1-2 mL/kg)';
}
return {
dose: grams + ' g (0.5-1 g/kg)',
extra: detail,
max: 'Max 25 g'
};
}
},
{
name: 'Epinephrine', indication: 'Pulseless arrest / Anaphylaxis', category: 'cardiac',
route: 'IV/IO/IM/ETT',
calc: function(w) {
var iv = +(w * 0.01).toFixed(3);
var ivVol = +(w * 0.1).toFixed(2);
var ett = +(w * 0.1).toFixed(2);
var im = +(w * 0.01).toFixed(3);
return {
dose: Math.min(iv, 1) + ' mg IV/IO (0.01 mg/kg of 0.1 mg/mL = ' + Math.min(ivVol, 10) + ' mL) q3-5 min',
extra: 'ETT: ' + Math.min(ett, 2.5) + ' mg (0.1 mg/kg of 1 mg/mL). Anaphylaxis IM: ' + Math.min(im, 0.5) + ' mg (0.01 mg/kg)',
max: 'Max IV 1 mg, max ETT 2.5 mg, max IM 0.5 mg'
};
}
},
{
name: 'Hydrocortisone', indication: 'Adrenal crisis', category: 'metabolic',
route: 'IV/IM/IO',
calc: function(w) {
var d = +(w * 2).toFixed(1);
return {
dose: Math.min(d, 100) + ' mg (2 mg/kg)',
extra: 'Stress dosing for adrenal insufficiency.',
max: 'Max 100 mg'
};
}
},
{
name: 'Insulin (Regular)', indication: 'Hyperkalemia', category: 'metabolic',
route: 'IV',
calc: function(w) {
var d = +(w * 0.1).toFixed(2);
var dex = +(w * 0.5).toFixed(1);
return {
dose: Math.min(d, 5) + ' units (0.1 units/kg)',
extra: 'Give with ' + dex + ' g/kg dextrose (0.5 g/kg). Monitor glucose closely.',
max: 'Max 5 units'
};
}
},
{
name: 'Lidocaine', indication: 'Antiarrhythmic', category: 'cardiac',
route: 'IV/IO',
calc: function(w) {
var d = +(w * 1).toFixed(1);
var ett = (w * 2).toFixed(1) + '-' + (w * 3).toFixed(1);
return {
dose: Math.min(d, 100) + ' mg (1 mg/kg)',
extra: 'ETT: ' + ett + ' mg (2-3 mg/kg). May repeat q5 min.',
max: 'Max 100 mg/dose, max total 3 mg/kg'
};
}
},
{
name: 'Magnesium Sulfate', indication: 'Torsades de Pointes', category: 'cardiac',
route: 'IV/IO',
calc: function(w) {
var d = +(w * 50).toFixed(0);
return {
dose: Math.min(d, 2000) + ' mg (50 mg/kg)',
extra: 'Give over 10-20 min (faster if pulseless).',
max: 'Max 2 g (2000 mg)'
};
}
},
{
name: 'Naloxone', indication: 'Opioid overdose', category: 'reversal',
route: 'IV/IO/IM/IN/ETT',
calc: function(w) {
var partial = +(w * 0.001).toFixed(4) + '-' + +(w * 0.005).toFixed(4);
var full = +(w * 0.1).toFixed(3);
return {
dose: 'Partial: ' + partial + ' mg (0.001-0.005 mg/kg)',
extra: 'Full reversal: ' + Math.min(full, 2) + ' mg (0.1 mg/kg)',
max: 'Max partial first dose 0.1 mg, max full 2 mg'
};
}
},
{
name: 'Sodium Bicarbonate', indication: 'Metabolic acidosis', category: 'metabolic',
route: 'IV/IO',
calc: function(w) {
var d = +(w * 1).toFixed(1);
return {
dose: Math.min(d, 50) + ' mEq (1 mEq/kg)',
extra: w < 10 ? 'Dilute to 0.5 mEq/mL (use 4.2% solution) for neonates/small infants.' : 'Use 8.4% solution (1 mEq/mL).',
max: 'Max 50 mEq'
};
}
}
];
var categoryColors = { cardiac: '#ef4444', metabolic: '#3b82f6', reversal: '#10b981' };
var categoryLabels = { cardiac: 'Cardiac', metabolic: 'Metabolic', reversal: 'Reversal' };
// Use event delegation for resus panel
var resusPanel = document.getElementById('calc-resus');
if (resusPanel) {
resusPanel.addEventListener('click', function(e) {
var btn = e.target.closest('#btn-calc-resus, #btn-clear-resus');
if (!btn) return;
if (btn.id === 'btn-clear-resus') {
var wi = document.getElementById('resus-weight'); if (wi) wi.value = '';
var rd = document.getElementById('resus-result'); if (rd) { rd.classList.add('hidden'); rd.innerHTML = ''; }
return;
}
// Calculate
var weightEl = document.getElementById('resus-weight');
var resultDiv = document.getElementById('resus-result');
var w = parseFloat(weightEl.value);
if (!w || w <= 0) { alert('Please enter a valid weight.'); return; }
var html = '<div style="margin-bottom:12px;font-size:14px;font-weight:700;color:var(--g800);">Doses for ' + w + ' kg patient</div>';
html += '<div style="display:flex;gap:6px;flex-wrap:wrap;margin-bottom:14px;font-size:11px;">';
Object.keys(categoryColors).forEach(function(cat) {
html += '<span style="display:inline-flex;align-items:center;gap:4px;"><span style="width:10px;height:10px;border-radius:50%;background:' + categoryColors[cat] + ';display:inline-block;"></span>' + categoryLabels[cat] + '</span>';
});
html += '</div>';
html += '<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:12px;">';
RESUS_MEDS.forEach(function(med) {
var r = med.calc(w);
var color = categoryColors[med.category] || '#6b7280';
html += '<div style="border:1.5px solid ' + color + '33;border-radius:10px;overflow:hidden;background:#fff;">' +
'<div style="padding:10px 14px;background:' + color + '0d;border-bottom:1px solid ' + color + '22;">' +
'<div style="font-size:14px;font-weight:700;color:' + color + ';">' + med.name + '</div>' +
'<div style="font-size:11px;color:var(--g500);margin-top:2px;">' + med.indication + '</div>' +
'</div>' +
'<div style="padding:12px 14px;font-size:13px;">' +
'<div style="margin-bottom:6px;"><strong>Dose:</strong> ' + r.dose + '</div>' +
'<div style="margin-bottom:6px;font-size:12px;color:var(--g600);">' + r.extra + '</div>' +
'<div style="font-size:11px;color:var(--g500);"><strong>Max:</strong> ' + r.max + '</div>' +
'<div style="font-size:11px;color:var(--g400);margin-top:4px;"><strong>Route:</strong> ' + med.route + '</div>' +
'</div>' +
'</div>';
});
html += '</div>';
html += '<div style="margin-top:14px;padding:10px;background:#fef3c7;border-radius:8px;font-size:11px;color:#92400e;">' +
'<strong>Disclaimer:</strong> Always verify doses against institutional protocols and current guidelines. This tool is for educational reference only.' +
'</div>';
resultDiv.innerHTML = html;
resultDiv.classList.remove('hidden');
});
}
// ═══════════════════════════════════════════════════════════
// GLASGOW COMA SCALE
// ═══════════════════════════════════════════════════════════
// GCS sub-pill navigation
var gcsPanel = document.getElementById('calc-gcs');
if (gcsPanel) {
gcsPanel.addEventListener('click', function(e) {
var pill = e.target.closest('[data-gcs]');
if (!pill) return;
gcsPanel.querySelectorAll('[data-gcs]').forEach(function(p) { p.classList.remove('active'); });
pill.classList.add('active');
var isInfant = pill.dataset.gcs === 'infant';
var childP = document.getElementById('gcs-child-panel');
var infantP = document.getElementById('gcs-infant-panel');
if (childP) childP.style.display = isInfant ? 'none' : '';
if (infantP) infantP.style.display = isInfant ? '' : 'none';
updateGCS();
});
gcsPanel.addEventListener('change', function(e) {
if (e.target.tagName === 'SELECT') updateGCS();
});
}
function updateGCS() {
var isInfant = document.querySelector('[data-gcs="infant"].active') !== null;
var prefix = isInfant ? 'gcs-infant' : 'gcs-child';
var eye = parseInt(document.getElementById(prefix + '-eye').value) || 0;
var verbal = parseInt(document.getElementById(prefix + '-verbal').value) || 0;
var motor = parseInt(document.getElementById(prefix + '-motor').value) || 0;
var total = eye + verbal + motor;
var severity, color, bg;
if (total <= 8) { severity = 'Severe (Coma)'; color = '#ef4444'; bg = '#fee2e2'; }
else if (total <= 12) { severity = 'Moderate'; color = '#f59e0b'; bg = '#fef3c7'; }
else { severity = 'Mild'; color = '#10b981'; bg = '#d1fae5'; }
var resultDiv = document.getElementById('gcs-result');
if (resultDiv) {
resultDiv.innerHTML =
'<div class="calc-result-header" style="background:' + bg + ';border-color:' + color + ';">' +
'<div style="font-size:24px;font-weight:700;color:' + color + ';">GCS: ' + total + '/15</div>' +
'<div style="font-size:14px;color:var(--g600);margin-top:4px;">' + severity + '</div>' +
'</div>' +
'<div class="calc-result-grid" style="margin-top:12px;">' +
'<div class="calc-result-item"><div class="calc-result-label">Eye (E)</div><div class="calc-result-value">' + eye + '</div></div>' +
'<div class="calc-result-item"><div class="calc-result-label">Verbal (V)</div><div class="calc-result-value">' + verbal + '</div></div>' +
'<div class="calc-result-item"><div class="calc-result-label">Motor (M)</div><div class="calc-result-value">' + motor + '</div></div>' +
'</div>' +
'<div style="margin-top:12px;font-size:12px;color:var(--g500);">' +
'<strong>Interpretation:</strong> 13-15 Mild, 9-12 Moderate, 3-8 Severe/Coma. ' +
'Intubation typically considered at GCS &le; 8. ' +
(isInfant ? 'Using infant-modified verbal and motor scales.' : '') +
'</div>';
}
}
// Initial GCS render
setTimeout(updateGCS, 200);
// ═══════════════════════════════════════════════════════════
// EQUIPMENT SIZING — Harriet Lane Handbook
// ═══════════════════════════════════════════════════════════
var EQUIP_DATA = {
premie: {
label: 'Premie (1-3 kg)',
bvm: 'Infant', nasal: '12 Fr', oral: 'Infant', blade: 'Miller 0',
ett: '2.5-3.0', lma: '1', glidescope: '1',
iv: '22-24 ga', cvl: '3 Fr', ngt: '5 Fr', chest: '10-12 Fr', foley: '6 Fr'
},
newborn: {
label: 'Newborn (2-4 kg)',
bvm: 'Infant', nasal: '14-16 Fr', oral: 'Small 50 mm', blade: 'Miller 0',
ett: '3.0-3.5', lma: '1', glidescope: '1',
iv: '22-24 ga', cvl: '3-4 Fr', ngt: '5-8 Fr', chest: '10-12 Fr', foley: '6 Fr'
},
'6mo': {
label: '6 months (6-8 kg)',
bvm: 'Infant', nasal: '14-16 Fr', oral: 'Small 60 mm', blade: 'Miller 1',
ett: '3.5', lma: '1.5', glidescope: '2',
iv: '20-24 ga', cvl: '4 Fr', ngt: '8 Fr', chest: '12-18 Fr', foley: '8 Fr'
},
'1yr': {
label: '1 year (10 kg)',
bvm: 'Small child', nasal: '14-18 Fr', oral: 'Small 60 mm', blade: 'Miller 1 / MAC 2',
ett: '4.0', lma: '2', glidescope: '2',
iv: '20-24 ga', cvl: '4-5 Fr', ngt: '10 Fr', chest: '16-20 Fr', foley: '8 Fr'
},
'2-3yr': {
label: '2-3 years (12-16 kg)',
bvm: 'Small child', nasal: '14-18 Fr', oral: 'Small 70 mm', blade: 'Miller 1 / MAC 2',
ett: '4.0-4.5', lma: '2', glidescope: '2',
iv: '18-22 ga', cvl: '4-5 Fr', ngt: '10-12 Fr', chest: '16-24 Fr', foley: '8 Fr'
},
'4-6yr': {
label: '4-6 years (20-25 kg)',
bvm: 'Child', nasal: '16-20 Fr', oral: 'Small 70-80 mm', blade: 'Miller 2 / MAC 2',
ett: '4.5-5.0', lma: '2.5', glidescope: '3',
iv: '18-22 ga', cvl: '5 Fr', ngt: '12-14 Fr', chest: '20-28 Fr', foley: '8 Fr'
},
'7-10yr': {
label: '7-10 years (25-35 kg)',
bvm: 'Child / Small adult', nasal: '18-22 Fr', oral: 'Medium 80-90 mm', blade: 'Miller 2 / MAC 2',
ett: '5.5-6.0', lma: '2.5-3', glidescope: '3',
iv: '18-22 ga', cvl: '5 Fr', ngt: '12-14 Fr', chest: '20-32 Fr', foley: '8 Fr'
},
'11-15yr': {
label: '11-15 years (40-50 kg)',
bvm: 'Adult', nasal: '22-36 Fr', oral: 'Medium 90 mm', blade: 'Miller 2 / MAC 3',
ett: '6.0-6.5', lma: '3', glidescope: '3 or 4',
iv: '18-20 ga', cvl: '7 Fr', ngt: '14-18 Fr', chest: '28-38 Fr', foley: '10 Fr'
},
'16yr': {
label: '16+ years (>50 kg)',
bvm: 'Adult', nasal: '22-36 Fr', oral: 'Medium 90 mm', blade: 'Miller 2 / MAC 3',
ett: '7.0-8.0', lma: '4', glidescope: '3 or 4',
iv: '18-20 ga', cvl: '7 Fr', ngt: '14-18 Fr', chest: '28-42 Fr', foley: '12 Fr'
}
};
var equipPanel = document.getElementById('calc-equipment');
if (equipPanel) {
equipPanel.addEventListener('change', function(e) {
if (e.target.id !== 'equip-age-select') return;
var key = e.target.value;
var resultDiv = document.getElementById('equip-result');
if (!key || !EQUIP_DATA[key]) { resultDiv.classList.add('hidden'); return; }
var eq = EQUIP_DATA[key];
resultDiv.classList.remove('hidden');
resultDiv.innerHTML =
'<div class="calc-result-header" style="background:#eff6ff;border-color:#2563eb;">' +
'<div style="font-size:18px;font-weight:700;color:#1d4ed8;">' + eq.label + '</div>' +
'</div>' +
'<div style="margin-top:12px;overflow-x:auto;">' +
'<table class="admin-table" style="font-size:13px;width:100%;">' +
'<tbody>' +
'<tr><td style="font-weight:600;width:40%;">Bag-Valve Mask</td><td>' + eq.bvm + '</td></tr>' +
'<tr><td style="font-weight:600;">Oral Airway</td><td>' + eq.oral + '</td></tr>' +
'<tr><td style="font-weight:600;">Nasal Airway</td><td>' + eq.nasal + '</td></tr>' +
'<tr><td style="font-weight:600;">Laryngoscope Blade</td><td>' + eq.blade + '</td></tr>' +
'<tr><td style="font-weight:600;">ETT Size</td><td>' + eq.ett + '</td></tr>' +
'<tr><td style="font-weight:600;">LMA Size</td><td>' + eq.lma + '</td></tr>' +
'<tr><td style="font-weight:600;">Glidescope</td><td>' + eq.glidescope + '</td></tr>' +
'<tr><td style="font-weight:600;">IV Catheter</td><td>' + eq.iv + '</td></tr>' +
'<tr><td style="font-weight:600;">Central Line</td><td>' + eq.cvl + '</td></tr>' +
'<tr><td style="font-weight:600;">NGT / OGT</td><td>' + eq.ngt + '</td></tr>' +
'<tr><td style="font-weight:600;">Chest Tube</td><td>' + eq.chest + '</td></tr>' +
'<tr><td style="font-weight:600;">Foley Catheter</td><td>' + eq.foley + '</td></tr>' +
'</tbody>' +
'</table>' +
'</div>' +
'<div style="margin-top:10px;font-size:11px;color:var(--g400);">' +
'<strong>ETT Formulas:</strong> Uncuffed = (age/4)+4, Cuffed = (age/4)+3, Depth = ETT size x 3. ' +
'Source: Harriet Lane Handbook.' +
'</div>';
});
}
}
})();
// ============================================================
// NEONATAL ASSESSMENT
// ============================================================
(function() {
document.addEventListener('click', function(e) {
if (e.target.id === 'btn-neo-assess' || e.target.closest('#btn-neo-assess')) neoAssess();
});
// Fenton 2013 LMS data (weight in grams, GA in weeks)
var fentonLMS = {
male: {
22:{L:0.21,M:496,S:0.17},23:{L:0.21,M:575,S:0.17},24:{L:0.21,M:660,S:0.17},25:{L:0.21,M:762,S:0.16},
26:{L:0.21,M:870,S:0.16},27:{L:0.20,M:993,S:0.15},28:{L:0.20,M:1124,S:0.15},29:{L:0.19,M:1272,S:0.14},
30:{L:0.18,M:1430,S:0.14},31:{L:0.17,M:1607,S:0.14},32:{L:0.15,M:1795,S:0.14},33:{L:0.13,M:2008,S:0.13},
34:{L:0.12,M:2230,S:0.13},35:{L:0.10,M:2467,S:0.13},36:{L:0.08,M:2710,S:0.13},37:{L:0.06,M:2948,S:0.12},
38:{L:0.04,M:3195,S:0.12},39:{L:0.02,M:3380,S:0.12},40:{L:0.01,M:3530,S:0.12},41:{L:0.00,M:3660,S:0.12},
42:{L:-0.02,M:3820,S:0.12}
},
female: {
22:{L:0.23,M:474,S:0.17},23:{L:0.22,M:538,S:0.17},24:{L:0.22,M:610,S:0.17},25:{L:0.22,M:705,S:0.16},
26:{L:0.22,M:810,S:0.16},27:{L:0.21,M:920,S:0.15},28:{L:0.21,M:1040,S:0.15},29:{L:0.20,M:1178,S:0.14},
30:{L:0.19,M:1330,S:0.14},31:{L:0.18,M:1500,S:0.14},32:{L:0.16,M:1680,S:0.14},33:{L:0.14,M:1880,S:0.13},
34:{L:0.12,M:2090,S:0.13},35:{L:0.10,M:2310,S:0.13},36:{L:0.08,M:2540,S:0.13},37:{L:0.06,M:2766,S:0.12},
38:{L:0.04,M:3000,S:0.12},39:{L:0.02,M:3180,S:0.12},40:{L:0.01,M:3340,S:0.12},41:{L:0.00,M:3480,S:0.12},
42:{L:-0.02,M:3630,S:0.12}
}
};
function interpolateLMS(table, val) {
var keys = Object.keys(table).map(Number).sort(function(a,b){return a-b;});
if (val <= keys[0]) return table[keys[0]];
if (val >= keys[keys.length-1]) return table[keys[keys.length-1]];
for (var i = 0; i < keys.length - 1; i++) {
if (val >= keys[i] && val <= keys[i+1]) {
var t = (val - keys[i]) / (keys[i+1] - keys[i]);
var a = table[keys[i]], b = table[keys[i+1]];
return { L: a.L + t*(b.L-a.L), M: a.M + t*(b.M-a.M), S: a.S + t*(b.S-a.S) };
}
}
return table[keys[0]];
}
function calcZ(value, L, M, S) {
if (Math.abs(L) < 0.001) return Math.log(value / M) / S;
return (Math.pow(value / M, L) - 1) / (L * S);
}
function zToPercentile(z) {
// Approximation of the standard normal CDF
var a1=0.254829592, a2=-0.284496736, a3=1.421413741, a4=-1.453152027, a5=1.061405429, p=0.3275911;
var sign = z < 0 ? -1 : 1;
var x = Math.abs(z) / Math.sqrt(2);
var t = 1 / (1 + p * x);
var y = 1 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t * Math.exp(-x*x);
return Math.round(((1 + sign * y) / 2) * 1000) / 10;
}
function classifyGA(weeks, days) {
var total = weeks + (days || 0) / 7;
if (total < 28) return { label: 'Extremely Preterm', color: '#dc2626', icon: 'fa-triangle-exclamation' };
if (total < 32) return { label: 'Very Preterm', color: '#ea580c', icon: 'fa-triangle-exclamation' };
if (total < 34) return { label: 'Moderate Preterm', color: '#d97706', icon: 'fa-circle-exclamation' };
if (total < 37) return { label: 'Late Preterm', color: '#ca8a04', icon: 'fa-circle-info' };
if (total < 39) return { label: 'Early Term', color: '#2563eb', icon: 'fa-circle-info' };
if (total < 41) return { label: 'Full Term', color: '#16a34a', icon: 'fa-circle-check' };
if (total < 42) return { label: 'Late Term', color: '#d97706', icon: 'fa-circle-info' };
return { label: 'Post Term', color: '#dc2626', icon: 'fa-triangle-exclamation' };
}
function classifyWeight(percentile) {
if (percentile < 3) return { label: 'Severely SGA', color: '#dc2626', detail: '<3rd percentile' };
if (percentile < 10) return { label: 'SGA', color: '#ea580c', detail: '<10th percentile' };
if (percentile > 97) return { label: 'Severely LGA', color: '#dc2626', detail: '>97th percentile' };
if (percentile > 90) return { label: 'LGA', color: '#ea580c', detail: '>90th percentile' };
return { label: 'AGA', color: '#16a34a', detail: '10th-90th percentile' };
}
function classifyBirthWeight(grams) {
if (grams < 1000) return { label: 'Extremely Low Birth Weight (ELBW)', color: '#dc2626' };
if (grams < 1500) return { label: 'Very Low Birth Weight (VLBW)', color: '#ea580c' };
if (grams < 2500) return { label: 'Low Birth Weight (LBW)', color: '#d97706' };
if (grams <= 4000) return { label: 'Normal Birth Weight', color: '#16a34a' };
return { label: 'Macrosomia (>4000g)', color: '#ea580c' };
}
function neoAssess() {
var weeks = parseInt(document.getElementById('neo-ga-weeks').value);
var days = parseInt(document.getElementById('neo-ga-days').value) || 0;
var weight = parseFloat(document.getElementById('neo-weight').value);
var sex = document.getElementById('neo-sex').value;
var resultDiv = document.getElementById('neo-result');
if (!weeks || !weight) {
resultDiv.innerHTML = '<p style="color:var(--red);font-size:13px;">Enter GA and birth weight.</p>';
return;
}
var gaDecimal = weeks + days / 7;
var gaClass = classifyGA(weeks, days);
var bwClass = classifyBirthWeight(weight);
// Calculate percentile using Fenton LMS
var lms = interpolateLMS(fentonLMS[sex], gaDecimal);
var z = calcZ(weight, lms.L, lms.M, lms.S);
var percentile = zToPercentile(z);
var wtClass = classifyWeight(percentile);
var expectedWeight = Math.round(lms.M);
var html = '';
// GA Classification
html += '<div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:12px;">';
html += '<div style="flex:1;min-width:200px;padding:14px;border-radius:10px;background:' + gaClass.color + '10;border:1.5px solid ' + gaClass.color + '30;">';
html += '<div style="font-size:12px;color:var(--g500);margin-bottom:4px;">Gestational Age Classification</div>';
html += '<div style="font-size:18px;font-weight:700;color:' + gaClass.color + ';"><i class="fas ' + gaClass.icon + '"></i> ' + gaClass.label + '</div>';
html += '<div style="font-size:13px;color:var(--g600);margin-top:4px;">' + weeks + ' weeks ' + days + ' days (' + gaDecimal.toFixed(1) + ' weeks)</div>';
html += '</div>';
// Weight Classification (AGA/SGA/LGA)
html += '<div style="flex:1;min-width:200px;padding:14px;border-radius:10px;background:' + wtClass.color + '10;border:1.5px solid ' + wtClass.color + '30;">';
html += '<div style="font-size:12px;color:var(--g500);margin-bottom:4px;">Weight for Gestational Age</div>';
html += '<div style="font-size:18px;font-weight:700;color:' + wtClass.color + ';">' + wtClass.label + '</div>';
html += '<div style="font-size:13px;color:var(--g600);margin-top:4px;">' + percentile.toFixed(1) + 'th percentile (' + wtClass.detail + ')</div>';
html += '</div>';
html += '</div>';
// Birth Weight Category
html += '<div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:12px;">';
html += '<div style="flex:1;min-width:200px;padding:14px;border-radius:10px;background:' + bwClass.color + '10;border:1.5px solid ' + bwClass.color + '30;">';
html += '<div style="font-size:12px;color:var(--g500);margin-bottom:4px;">Birth Weight Category</div>';
html += '<div style="font-size:18px;font-weight:700;color:' + bwClass.color + ';">' + bwClass.label + '</div>';
html += '<div style="font-size:13px;color:var(--g600);margin-top:4px;">' + weight + 'g (' + (weight/1000).toFixed(2) + ' kg)</div>';
html += '</div>';
// Stats
html += '<div style="flex:1;min-width:200px;padding:14px;border-radius:10px;background:var(--g50);border:1.5px solid var(--g200);">';
html += '<div style="font-size:12px;color:var(--g500);margin-bottom:4px;">Fenton Growth Data (' + (sex === 'male' ? 'Male' : 'Female') + ')</div>';
html += '<div style="font-size:13px;color:var(--g700);line-height:1.8;">';
html += '<strong>Expected weight (50th %ile):</strong> ' + expectedWeight + 'g<br>';
html += '<strong>Z-score:</strong> ' + z.toFixed(2) + '<br>';
html += '<strong>Percentile:</strong> ' + percentile.toFixed(1) + '%';
html += '</div></div>';
html += '</div>';
// Reference
html += '<p style="font-size:11px;color:var(--g400);margin:8px 0 0;">Fenton TR, Kim JH. A systematic review and meta-analysis to revise the Fenton growth chart for preterm infants. BMC Pediatrics 2013;13:59. GA classification per ACOG/AAP definitions.</p>';
resultDiv.innerHTML = html;
}
})();
// ============================================================
// RESPIRATORY MANAGEMENT (Asthma, Croup, Bronchiolitis)
// ============================================================
(function() {
// Sub-pill navigation
document.addEventListener('click', function(e) {
var pill = e.target.closest('[data-resp]');
if (pill) {
document.querySelectorAll('[data-resp]').forEach(function(p) { p.classList.remove('active'); });
pill.classList.add('active');
['asthma','croup','bronchiolitis'].forEach(function(s) {
var el = document.getElementById('resp-' + s);
if (el) el.style.display = pill.dataset.resp === s ? '' : 'none';
});
}
if (e.target.closest('[data-asthma-severity]')) asthmaManagement(e.target.closest('[data-asthma-severity]').dataset.asthmaSeverity);
if (e.target.id === 'btn-pram-calc' || e.target.closest('#btn-pram-calc')) calcPRAM();
if (e.target.id === 'btn-croup-calc' || e.target.closest('#btn-croup-calc')) calcCroup();
if (e.target.id === 'btn-bronch-calc' || e.target.closest('#btn-bronch-calc')) calcBronchiolitis();
});
function dose(wt, mgPerKg, maxMg) { var d = Math.round(wt * mgPerKg * 10) / 10; return maxMg ? Math.min(d, maxMg) : d; }
// Delegates to the shared _EM.dStr so the per-kg math is visible to the prescriber.
function doseStr(wt, mgPerKg, maxMg, unit) {
return window._EM.dStr(wt, mgPerKg, maxMg, unit);
}
function drugRow(name, doseText, route, notes) {
return '<tr><td style="font-weight:600;">' + name + '</td><td>' + doseText + '</td><td>' + route + '</td><td style="font-size:12px;color:var(--g500);">' + (notes || '') + '</td></tr>';
}
function drugTable(rows) {
return '<div style="overflow-x:auto;-webkit-overflow-scrolling:touch;margin:8px 0;"><table style="width:100%;min-width:500px;border-collapse:collapse;font-size:13px;"><thead><tr style="background:var(--g100);"><th style="text-align:left;padding:6px 8px;">Drug</th><th style="padding:6px 8px;">Dose</th><th style="padding:6px 8px;">Route</th><th style="padding:6px 8px;">Notes</th></tr></thead><tbody>' + rows + '</tbody></table></div>';
}
function severityBadge(label, color) { return '<span style="display:inline-block;padding:4px 12px;border-radius:6px;background:' + color + '20;color:' + color + ';font-weight:700;font-size:14px;">' + label + '</span>'; }
function asthmaManagement(severity) {
var wt = parseFloat(document.getElementById('resp-weight').value);
var resultDiv = document.getElementById('asthma-result');
if (!wt) { resultDiv.innerHTML = '<p style="color:var(--red);font-size:13px;">Enter weight (kg).</p>'; return; }
var html = '';
if (severity === 'mild') {
html += severityBadge('Mild Exacerbation', '#10b981');
html += '<p style="font-size:13px;margin:8px 0;">Speaks in sentences, no accessory muscle use, SpO2 ≥94%</p>';
html += drugTable(
drugRow('Albuterol (MDI)', '4-8 puffs via spacer', 'Inhaled', 'q20min x 3 doses, then q1-4h') +
drugRow('Albuterol (neb)', doseStr(wt, 0.15, 5, ' mg') + ' (min 2.5 mg)', 'Nebulized', 'q20min x 3 doses') +
drugRow('Dexamethasone', doseStr(wt, 0.6, 16), 'PO/IV', 'Single dose, or 2 days') +
drugRow('Prednisolone', doseStr(wt, 1, 60) + '/day', 'PO', 'Alternative: 3-5 day course')
);
html += '<div style="margin-top:8px;padding:8px 12px;background:#d1fae5;border-radius:6px;font-size:12px;color:#065f46;"><strong>Reassess after 1 hour.</strong> If improving → discharge with albuterol MDI + spacer + oral steroid course. If not improving → escalate to moderate.</div>';
} else if (severity === 'moderate') {
html += severityBadge('Moderate Exacerbation', '#f59e0b');
html += '<p style="font-size:13px;margin:8px 0;">Speaks in phrases, some accessory muscle use, SpO2 90-93%</p>';
html += drugTable(
drugRow('Albuterol (neb)', doseStr(wt, 0.15, 5, ' mg') + ' (min 2.5 mg)', 'Nebulized', 'q20min x 3 doses, then continuous if needed') +
drugRow('Ipratropium', wt < 20 ? '250 mcg' : '500 mcg', 'Nebulized', 'q20min x 3 doses with albuterol') +
drugRow('Dexamethasone', doseStr(wt, 0.6, 16), 'PO/IV/IM', 'Single dose') +
drugRow('O2 supplemental', 'Target SpO2 ≥94%', 'Nasal cannula/mask', 'Titrate to effect')
);
html += '<div style="margin-top:8px;padding:8px 12px;background:#fef3c7;border-radius:6px;font-size:12px;color:#92400e;"><strong>Reassess after 1-2 hours.</strong> If improving → step down to mild protocol. If worsening or no improvement → escalate to severe.</div>';
} else {
html += severityBadge('Severe / Life-Threatening', '#ef4444');
html += '<p style="font-size:13px;margin:8px 0;">Speaks in words only, significant accessory muscle use, SpO2 &lt;90%. Consider ICU.</p>';
html += drugTable(
drugRow('Albuterol continuous', doseStr(wt, 0.5, 20, ' mg') + '/hr', 'Continuous neb', 'Or 0.15-0.3 mg/kg q20min') +
drugRow('Ipratropium', wt < 20 ? '250 mcg' : '500 mcg', 'Nebulized', 'q20min x 3 doses with albuterol') +
drugRow('Dexamethasone', doseStr(wt, 0.6, 16), 'IV', 'Or methylprednisolone 2 mg/kg IV (max 60 mg)') +
drugRow('Magnesium sulfate', doseStr(wt, 50, 2000) + ' IV over 20 min', 'IV', 'Single dose, monitor BP') +
drugRow('Epinephrine (IM)', doseStr(wt, 0.01, 0.5) + ' (1:1000)', 'IM', 'If impending arrest / no IV access') +
drugRow('Terbutaline', doseStr(wt, 0.01, 0.4) + ' SC/IV', 'SC or IV bolus', 'Then 0.1-10 mcg/kg/min infusion') +
drugRow('O2 supplemental', 'Target SpO2 ≥94%', 'High flow / NIPPV', 'Consider BiPAP/CPAP')
);
html += '<div style="margin-top:8px;padding:8px 12px;background:#fee2e2;border-radius:6px;font-size:12px;color:#991b1b;"><strong>Continuous monitoring.</strong> Consider ICU admission. If no response to magnesium → terbutaline infusion. If impending respiratory failure → intubation (ketamine preferred induction agent).</div>';
// Clinical decision points specific to severe asthma
html += '<div style="margin-top:10px;display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:8px;">';
// ABG
html += '<div style="padding:10px 12px;background:white;border:1px solid var(--g200);border-radius:8px;font-size:12px;line-height:1.5;">' +
'<div style="font-weight:700;color:var(--blue-dark);margin-bottom:4px;"><i class="fas fa-flask"></i> When to obtain a blood gas</div>' +
'&bull; Severe exacerbation <strong>not responding</strong> after 1-2 h aggressive therapy<br>' +
'&bull; Impending respiratory failure — altered mentation, fatigue, silent chest<br>' +
'&bull; SpO2 &lt;92% despite supplemental O2<br>' +
'&bull; Suspected CO2 retention (rising PCO2 in a previously tachypneic patient)<br>' +
'<strong style="color:#991b1b;">Interpretation:</strong> asthmatics hyperventilate → expect <em>low</em> PCO2. A <strong>"normal" or rising PCO2 = impending failure</strong>. Don\'t delay treatment for the gas.' +
'</div>';
// Intubation
html += '<div style="padding:10px 12px;background:white;border:1px solid var(--g200);border-radius:8px;font-size:12px;line-height:1.5;">' +
'<div style="font-weight:700;color:#dc2626;margin-bottom:4px;"><i class="fas fa-stethoscope"></i> When to intubate (mostly clinical)</div>' +
'&bull; <strong>Absolute:</strong> apnea, cardiac arrest, coma, inability to protect airway<br>' +
'&bull; Progressive fatigue despite maximal therapy (NIV, mag, terbutaline, heliox)<br>' +
'&bull; Refractory hypoxemia / hypercapnia with acidosis<br>' +
'&bull; Silent chest + deteriorating consciousness<br>' +
'<strong>RSI choice:</strong> <span style="color:#065f46;font-weight:600;">ketamine 1-2 mg/kg</span> (bronchodilator, preserves BP) + <span style="color:#065f46;font-weight:600;">rocuronium</span>. Avoid succs if hyperkalemic. Permissive hypercapnia after tube; allow expiration (low rate, I:E 1:3-4).' +
'</div>';
// Heliox
html += '<div style="padding:10px 12px;background:white;border:1px solid var(--g200);border-radius:8px;font-size:12px;line-height:1.5;">' +
'<div style="font-weight:700;color:#7c3aed;margin-bottom:4px;"><i class="fas fa-wind"></i> Heliox (He/O2)</div>' +
'&bull; Lower gas density → less turbulence → reduced work of breathing through narrowed airways.<br>' +
'&bull; <strong>Consider in:</strong> severe asthma not responding to max therapy (bridge), upper airway obstruction (croup, post-extubation stridor, FB partial).<br>' +
'&bull; Typical mix: <strong>70:30 He:O2</strong> (or 80:20). Delivered via tight non-rebreather or in-line with neb.<br>' +
'&bull; <strong>Limitation:</strong> requires FiO2 ≤ 30-40%. If patient needs higher FiO2, heliox can\'t help.<br>' +
'&bull; Evidence in asthma is mixed — use as adjunct, not substitute.' +
'</div>';
html += '</div>';
}
html += '<p style="font-size:11px;color:var(--g400);margin:12px 0 0;">NAEPP/GINA guidelines. Always use clinical judgment. Verify doses against institutional protocols.</p>';
resultDiv.innerHTML = html;
}
function calcPRAM() {
var total = ['pram-spo2','pram-retractions','pram-scalene','pram-air','pram-wheeze'].reduce(function(s, id) {
return s + parseInt(document.getElementById(id).value);
}, 0);
var severity = total <= 3 ? 'Mild' : total <= 7 ? 'Moderate' : 'Severe';
var color = total <= 3 ? '#10b981' : total <= 7 ? '#f59e0b' : '#ef4444';
document.getElementById('pram-result').innerHTML = '<div style="padding:10px 14px;border-radius:8px;background:' + color + '10;border:1.5px solid ' + color + '30;"><span style="font-size:18px;font-weight:700;color:' + color + ';">PRAM Score: ' + total + '/12 — ' + severity + '</span><p style="font-size:12px;color:var(--g600);margin:4px 0 0;">Mild (0-3): outpatient management. Moderate (4-7): consider oral steroids + frequent bronchodilators. Severe (8-12): aggressive treatment, consider ICU.</p></div>';
}
function calcCroup() {
var wt = parseFloat(document.getElementById('resp-weight').value) || 10;
var total = ['croup-conscious','croup-cyanosis','croup-stridor','croup-air','croup-retractions'].reduce(function(s, id) {
return s + parseInt(document.getElementById(id).value);
}, 0);
var severity, color, treatment;
if (total <= 2) { severity = 'Mild'; color = '#10b981'; treatment = drugTable(drugRow('Dexamethasone', doseStr(wt, 0.6, 16), 'PO (single dose)', 'Preferred corticosteroid') + drugRow('Supportive care', 'Cool mist, comfort measures', '', 'Discharge if tolerating PO')); }
else if (total <= 5) { severity = 'Moderate'; color = '#f59e0b'; treatment = drugTable(drugRow('Dexamethasone', doseStr(wt, 0.6, 16), 'PO/IM', 'Single dose') + drugRow('Racemic epinephrine', '0.5 mL of 2.25% solution', 'Nebulized', 'Observe 2-4 hrs after for rebound') + drugRow('Nebulized epinephrine', '0.5 mL/kg of 1:1000 (max 5 mL)', 'Nebulized', 'Alternative to racemic')); }
else if (total <= 11) { severity = 'Severe'; color = '#ef4444'; treatment = drugTable(drugRow('Dexamethasone', doseStr(wt, 0.6, 16), 'IV/IM', 'Immediate') + drugRow('Racemic epinephrine', '0.5 mL of 2.25% solution', 'Nebulized', 'May repeat q15-20min, observe 2-4 hrs') + drugRow('Nebulized epinephrine', '0.5 mL/kg of 1:1000 (max 5 mL)', 'Nebulized', 'Alternative') + drugRow('Heliox', '70:30 or 80:20', 'Face mask', 'Consider if not responding') + drugRow('O2 supplemental', 'Target SpO2 ≥94%', 'Blow-by preferred', 'Minimize agitation')); }
else { severity = 'Impending Respiratory Failure'; color = '#dc2626'; treatment = '<div style="padding:10px;background:#fee2e2;border-radius:6px;font-size:13px;color:#991b1b;font-weight:600;">Immediate airway management. Prepare for intubation (use ETT 0.5-1 size smaller than predicted). Call anesthesia/ENT. Continue nebulized epinephrine and dexamethasone IV.</div>'; }
document.getElementById('croup-result').innerHTML = '<div style="padding:10px 14px;border-radius:8px;background:' + color + '10;border:1.5px solid ' + color + '30;margin-bottom:12px;"><span style="font-size:18px;font-weight:700;color:' + color + ';">Westley Score: ' + total + '/17 — ' + severity + '</span></div>' + treatment + '<p style="font-size:11px;color:var(--g400);margin:8px 0 0;">Westley WJ et al. Nebulized racemic epinephrine by IPPB for the treatment of croup. Am J Dis Child 1978. Mild ≤2, Moderate 3-5, Severe 6-11, Impending failure ≥12.</p>';
}
function calcBronchiolitis() {
var wt = parseFloat(document.getElementById('resp-weight').value) || 5;
var age = document.getElementById('bronch-age').value;
var spo2 = document.getElementById('bronch-spo2').value;
var hydration = document.getElementById('bronch-hydration').value;
var distress = document.getElementById('bronch-distress').value;
var html = '<h4 style="font-size:15px;font-weight:700;color:var(--g800);margin:0 0 8px;">Bronchiolitis Management</h4>';
var admit = distress === 'severe' || spo2 === 'low' || hydration === 'poor' || age === '<12w';
if (admit) {
html += severityBadge('Admit / Observe', '#ef4444');
html += '<div style="margin:10px 0;">';
if (age === '<12w') html += '<p style="font-size:13px;color:var(--red);font-weight:600;">⚠ Age &lt;12 weeks — high risk for apnea. Monitor closely.</p>';
html += '</div>';
} else {
html += severityBadge('Likely Safe for Discharge', '#10b981');
}
html += '<div style="margin:12px 0;"><strong style="font-size:13px;">Supportive Care (evidence-based):</strong></div>';
html += drugTable(
drugRow('Nasal suctioning', 'Bulb suction or NasalClear', 'Nasal', 'Before feeds and as needed') +
drugRow('O2 supplemental', 'Target SpO2 ≥90%', 'NC / high flow', spo2 === 'low' ? 'Required' : 'If needed') +
drugRow('Hypertonic saline 3%', '4 mL nebulized', 'Nebulized', 'Consider in inpatients (AAP weak recommendation)') +
(hydration === 'poor' ? drugRow('IV fluids', 'NS/LR bolus ' + doseStr(wt, 20, null, ' mL'), 'IV', 'Then maintenance D5 0.45NS') + drugRow('NG feeds', 'If unable to feed orally', 'NG tube', 'Preferred over IV if gut functional') : '')
);
html += '<div style="margin:12px 0;padding:10px 12px;background:var(--amber-light);border-radius:6px;font-size:12px;color:#92400e;"><strong>NOT recommended (AAP 2014/2023):</strong> Albuterol/salbutamol (no benefit in bronchiolitis), epinephrine (no evidence of benefit), systemic corticosteroids (no benefit), antibiotics (unless secondary bacterial infection), chest physiotherapy.</div>';
html += '<p style="font-size:11px;color:var(--g400);margin:8px 0 0;">AAP Clinical Practice Guideline: Management of Bronchiolitis in Infants and Children (2014, reaffirmed 2023). RSV is the most common cause (50-80%).</p>';
document.getElementById('bronch-result').innerHTML = html;
}
})();
// ============================================================
// SEIZURE MANAGEMENT
// ============================================================
(function() {
document.addEventListener('click', function(e) {
if (e.target.id === 'btn-seizure-calc' || e.target.closest('#btn-seizure-calc')) calcSeizure();
});
function d(wt, mgPerKg, max) { var v = Math.round(wt * mgPerKg * 100) / 100; return max ? Math.min(v, max) : v; }
function row(phase, drug, dose, route, notes) {
return '<tr><td style="font-weight:600;color:var(--blue);">' + phase + '</td><td style="font-weight:600;">' + drug + '</td><td>' + dose + '</td><td>' + route + '</td><td style="font-size:12px;color:var(--g500);">' + notes + '</td></tr>';
}
// Visual pathway row — time badge + step card linked by vertical line
function stepRow(time, color, title, bodyHtml, isLast) {
return '<div style="display:flex;gap:12px;align-items:stretch;">' +
'<div style="flex:0 0 auto;width:70px;display:flex;flex-direction:column;align-items:center;">' +
'<div style="background:' + color + ';color:white;padding:6px 0;border-radius:20px;font-size:12px;font-weight:700;width:60px;text-align:center;box-shadow:0 1px 3px rgba(0,0,0,0.15);">' + time + '</div>' +
(isLast ? '' : '<div style="flex:1;width:3px;background:' + color + '40;margin:2px 0;"></div>') +
'</div>' +
'<div style="flex:1;padding:10px 14px;border-left:4px solid ' + color + ';background:' + color + '10;border-radius:0 8px 8px 0;margin-bottom:' + (isLast ? '4px' : '12px') + ';">' +
'<div style="font-weight:700;color:' + color + ';font-size:13px;margin-bottom:6px;text-transform:uppercase;letter-spacing:0.3px;">' + title + '</div>' +
'<div style="font-size:13px;color:var(--g700);line-height:1.55;">' + bodyHtml + '</div>' +
'</div>' +
'</div>';
}
// Fallback inline data — mirrors the non-refractory seizure entries in
// drugs.json. Refractory infusion drips are kept inline below because
// their dose strings (bolus → gtt range) don't map cleanly to the
// single-row JSON schema.
var SEIZURE_FALLBACK = [
{ name: 'Lorazepam', phase: '1st benzo', dose_mg_per_kg: 0.1, max_mg: 4, unit: 'mg', route: 'IV / IO', label_suffix: ' <span style="color:#065f46;font-weight:600;">(IV preferred)</span>', notes: 'Slow push over 1-2 min.' },
{ name: 'Midazolam', phase: '1st benzo', dose_mg_per_kg: 0.2, max_mg: 10, unit: 'mg', route: 'IM / IN / buccal', notes: 'Use 5 mg/mL concentrate for IN; split between nares.' },
{ name: 'Diazepam', phase: '1st benzo', dose_mg_per_kg: 0.5, max_mg: 20, unit: 'mg', route: 'PR', notes: 'Only if no IV/IM/IN access.' },
{ name: 'Levetiracetam', phase: '2nd-line', dose_mg_per_kg: 60, max_mg: 4500, unit: 'mg', route: 'IV over 5-15 min', label_suffix: ' <span style="color:#065f46;font-weight:600;">(preferred)</span>', notes: 'Best tolerability. No ECG monitoring needed.' },
{ name: 'Fosphenytoin', phase: '2nd-line', dose_mg_per_kg: 20, max_mg: 1500, unit: 'mg PE', route: 'IV over 10 min', notes: 'Max rate 3 mg PE/kg/min. Monitor ECG, BP. Avoid if cardiac dysrhythmia.' },
{ name: 'Valproic acid', phase: '2nd-line', dose_mg_per_kg: 40, max_mg: 3000, unit: 'mg', route: 'IV over 10 min', notes: '<strong>Avoid &lt;2 yr, hepatic / mitochondrial disease, pregnancy.</strong>' },
{ name: 'Phenobarbital', phase: '2nd-line', dose_mg_per_kg: 20, max_mg: 1000, unit: 'mg', route: 'IV over 20 min', notes: 'Last-choice 2nd line. High risk of resp depression + hypotension.' }
];
function seizureDrugs() {
var s = window._DRUGS && window._DRUGS.sections && window._DRUGS.sections.seizure;
if (s && s.drugs && s.drugs.length) {
return s.drugs.map(function(d) {
var fb = SEIZURE_FALLBACK.filter(function(x) { return x.name === d.name; })[0] || {};
return Object.assign({}, fb, d);
});
}
return SEIZURE_FALLBACK;
}
// Build the joined S.drugRow output for one phase ("1st benzo" / "2nd-line").
function seizureRowsByPhase(wt, phase) {
var S = window._EM;
return seizureDrugs().filter(function(dg) { return dg.phase === phase; }).map(function(dg) {
var label = dg.name + (dg.label_suffix || '');
var unitArg = dg.unit && dg.unit !== 'mg' ? ' ' + dg.unit : undefined;
var dose = unitArg
? S.dStr(wt, dg.dose_mg_per_kg, dg.max_mg, unitArg)
: S.dStr(wt, dg.dose_mg_per_kg, dg.max_mg);
return S.drugRow(label, dose, dg.route, dg.notes);
}).join('');
}
function calcSeizure() {
var wt = parseFloat(document.getElementById('seizure-weight').value);
var resultDiv = document.getElementById('seizure-result');
if (!wt) { resultDiv.innerHTML = '<p style="color:var(--red);font-size:13px;">Enter weight (kg).</p>'; return; }
var S = window._EM;
var d10Low = Math.round(wt * 2 * 10) / 10;
var d10High = Math.round(wt * 5 * 10) / 10;
var html = '<div style="padding:10px 14px;border-radius:8px;background:#fee2e2;border:1.5px solid #ef4444;margin-bottom:14px;"><strong style="color:#dc2626;font-size:14px;"><i class="fas fa-bolt"></i> Status Epilepticus Pathway — ' + wt + ' kg</strong><div style="font-size:12px;color:var(--g600);margin-top:3px;">Time = 0 at seizure onset. Do not pause between steps for benzo to take effect — act on the clock.</div></div>';
// 0 min — STABILIZE
html += stepRow('0 min', '#3b82f6', 'Stabilize',
'<strong>ABCs</strong> — position, 100% O2 via NC / NRB, suction. <strong>IV or IO</strong> × 2. Continuous SpO2, ECG, BP. ' +
'<strong>POC glucose</strong> — if &lt;60 mg/dL: <strong>D10W ' + d10Low + '-' + d10High + ' mL IV</strong> (2-5 mL/kg). ' +
'<strong>Labs</strong>: CBC, CMP, Mg, Ca, Phos, VBG, lactate, AED levels, toxicology if unclear etiology. ' +
'<strong>Consider pyridoxine</strong> 100 mg IV in infants &lt;18 mo or INH ingestion. Temperature: treat hyperthermia aggressively.'
);
// 5 min — 1ST BENZO
html += stepRow('5 min', '#8b5cf6', '1st benzodiazepine (give once, pick by access)',
S.drugTable(seizureRowsByPhase(wt, '1st benzo'))
);
// 10 min — 2ND BENZO
html += stepRow('10 min', '#a855f7', '2nd benzodiazepine — if still seizing',
'Repeat same agent + dose <strong>once</strong>. Prepare 2nd-line now (don\'t wait to see if benzo works). If apnea/airway compromise: BVM, consider advanced airway.'
);
// 20 min — 2ND-LINE
html += stepRow('20 min', '#f59e0b', '2nd-line anti-epileptic — pick one (ESETT: equivalent efficacy)',
S.drugTable(seizureRowsByPhase(wt, '2nd-line'))
);
// 30 min — 2nd of 2nd-line (optional)
html += stepRow('30 min', '#ef4444', 'Still seizing? Consider 2nd agent from 2nd-line OR proceed to refractory',
'If the first 2nd-line drug failed, give a different 2nd-line agent <strong>OR</strong> move directly to refractory therapy. Activate ICU, prepare for intubation. Confirm etiology not reversible (electrolytes, glucose, fever, toxin).'
);
// 40 min — REFRACTORY
html += stepRow('40 min', '#dc2626', 'Refractory status — intubate + continuous infusion + continuous EEG',
S.drugTable(
S.drugRow('Midazolam <span style="color:#065f46;font-weight:600;">(1st-line infusion)</span>', 'Bolus ' + d(wt, 0.2, 10) + ' mg → gtt ' + d(wt, 0.05, 2) + '-' + d(wt, 0.5, 18) + ' mg/hr <span style="color:var(--g500);font-size:11px;">(bolus 0.2 mg/kg, gtt 0.05-0.5 mg/kg/hr)</span>', 'IV', 'Titrate to seizure control / burst suppression.') +
S.drugRow('Pentobarbital', 'Bolus ' + d(wt, 5, 200) + ' mg → gtt ' + d(wt, 1, null) + '-' + d(wt, 5, null) + ' mg/hr <span style="color:var(--g500);font-size:11px;">(bolus 5 mg/kg, gtt 1-5 mg/kg/hr)</span>', 'IV', 'Causes hypotension — often need pressors.') +
S.drugRow('Propofol', 'Bolus ' + d(wt, 2, 100) + ' mg → gtt ' + d(wt, 2, null) + '-' + d(wt, 5, null) + ' mg/hr <span style="color:var(--g500);font-size:11px;">(bolus 2 mg/kg, gtt 2-5 mg/kg/hr)</span>', 'IV', '<strong>PRIS risk in children</strong> — limit to &lt;4 mg/kg/hr and duration &lt;48 h.') +
S.drugRow('Ketamine', 'Bolus ' + d(wt, 2, 100) + ' mg → gtt ' + d(wt, 1, null) + '-' + d(wt, 5, null) + ' mg/hr <span style="color:var(--g500);font-size:11px;">(bolus 2 mg/kg, gtt 1-5 mg/kg/hr)</span>', 'IV', 'NMDA antagonist — rescue. Good BP profile; useful if refractory to GABAergics.')
) +
'<div style="margin-top:8px;font-size:12px;color:var(--g600);"><strong>Continuous EEG within 1 h</strong> — target electrographic seizure suppression × 24-48 h, then wean. Reassess etiology: CNS imaging, LP, expanded workup.</div>'
, true);
// Key points
html += '<div style="margin-top:16px;padding:10px 12px;background:#fef3c7;border-radius:6px;font-size:12px;color:#92400e;line-height:1.55;"><strong>Key points</strong><br>' +
'• Do <strong>NOT</strong> wait for benzo response before starting the 2nd-line — parallel preparation.<br>' +
'• Maximum <strong>2 benzo doses</strong> total (1 pre-hospital + 1 in ED, or 2 in ED).<br>' +
'• Respiratory depression is common — have BVM, airway equipment, naloxone, flumazenil accessible (but avoid flumazenil here).<br>' +
'• ESETT trial: levetiracetam = fosphenytoin = valproate for efficacy. Pick by tolerability / contraindications.<br>' +
'• Always reassess: ongoing seizure? Non-convulsive status? Pseudo-seizure? → continuous EEG if any doubt.</div>';
html += '<p style="font-size:11px;color:var(--g400);margin:8px 0 0;font-style:italic;">Based on AES Guidelines 2016 and ESETT (Kapur et al., NEJM 2019). Verify all doses against institutional protocols.</p>';
resultDiv.innerHTML = html;
}
})();
// ============================================================
// ANAPHYLAXIS MANAGEMENT
// ============================================================
(function() {
document.addEventListener('click', function(e) {
if (e.target.id === 'btn-anaph-calc' || e.target.closest('#btn-anaph-calc')) calcAnaphylaxis();
});
function d(wt, mgPerKg, max) { var v = Math.round(wt * mgPerKg * 100) / 100; return max ? Math.min(v, max) : v; }
// Lookup a drug entry (by name) from window._DRUGS.sections.anaphylaxis,
// falling back to a hardcoded record so rendering stays identical if the
// JSON fetch hasn't resolved (or failed). Returns an object exposing the
// per-kg + max fields needed by S.dStr.
var ANAPH_FALLBACK = {
'Epinephrine IM': { dose_mg_per_kg: 0.01, max_mg: 0.5, unit: 'mg' },
'Normal saline bolus': { dose_mg_per_kg: 20, max_mg: null, unit: 'mL' },
'Diphenhydramine': { dose_mg_per_kg: 1.25, max_mg: 50, unit: 'mg' },
'Ranitidine': { dose_mg_per_kg: 1, max_mg: 50, unit: 'mg' },
'Dexamethasone': { dose_mg_per_kg: 0.6, max_mg: 16, unit: 'mg' },
'Methylprednisolone': { dose_mg_per_kg: 2, max_mg: 125, unit: 'mg' },
'Glucagon': { dose_mg_per_kg: 0.02, max_mg: 1, unit: 'mg' }
};
function anaphDrug(name) {
var s = window._DRUGS && window._DRUGS.sections && window._DRUGS.sections.anaphylaxis;
if (s && s.drugs) {
var hit = s.drugs.filter(function(x) { return x.name === name; })[0];
if (hit) return hit;
}
return ANAPH_FALLBACK[name] || {};
}
function calcAnaphylaxis() {
var wt = parseFloat(document.getElementById('anaph-weight').value);
var age = document.getElementById('anaph-age').value;
var resultDiv = document.getElementById('anaph-result');
if (!wt) { resultDiv.innerHTML = '<p style="color:var(--red);font-size:13px;">Enter weight (kg).</p>'; return; }
var S = window._EM;
var epi = anaphDrug('Epinephrine IM');
var fluids = anaphDrug('Normal saline bolus');
var dph = anaphDrug('Diphenhydramine');
var rnt = anaphDrug('Ranitidine');
var dex = anaphDrug('Dexamethasone');
var mpn = anaphDrug('Methylprednisolone');
var glc = anaphDrug('Glucagon');
var epiDose = d(wt, epi.dose_mg_per_kg, epi.max_mg);
var epiVol = Math.round(epiDose * 10) / 10; // 1:1000 = 1 mg/mL
var autoInjector = wt < 10 ? 'Draw up manually' : wt <= 25 ? 'EpiPen Jr / Auvi-Q 0.15 mg' : 'EpiPen / Auvi-Q 0.3 mg';
var html = '<div style="padding:14px;border-radius:10px;background:#fee2e2;border:2px solid #ef4444;margin-bottom:16px;">';
html += '<div style="font-size:18px;font-weight:700;color:#dc2626;margin-bottom:6px;"><i class="fas fa-triangle-exclamation"></i> STEP 1: Epinephrine IM — GIVE IMMEDIATELY</div>';
html += '<div style="font-size:15px;font-weight:600;color:var(--g800);margin-bottom:4px;">Epinephrine 1:1000 (1 mg/mL): <span style="color:#dc2626;">' + epiDose + ' mg (' + epiVol + ' mL)</span> IM to lateral thigh</div>';
html += '<div style="font-size:13px;color:var(--g600);">' + epi.dose_mg_per_kg + ' mg/kg (max ' + epi.max_mg + ' mg) | Auto-injector: ' + autoInjector + '</div>';
html += '<div style="font-size:12px;color:#991b1b;margin-top:6px;">May repeat every 5-15 minutes if symptoms persist. No contraindications in anaphylaxis.</div>';
html += '</div>';
html += '<div style="overflow-x:auto;-webkit-overflow-scrolling:touch;margin-bottom:12px;"><table style="width:100%;min-width:560px;border-collapse:collapse;font-size:13px;"><thead><tr style="background:var(--g100);"><th style="text-align:left;padding:6px 8px;">Step</th><th style="padding:6px 8px;">Drug</th><th style="padding:6px 8px;">Dose</th><th style="padding:6px 8px;">Route</th><th style="padding:6px 8px;">Notes</th></tr></thead><tbody>';
html += '<tr><td style="font-weight:600;color:var(--blue);">STEP 2</td><td style="font-weight:600;">Position</td><td>Supine + legs elevated</td><td>—</td><td style="font-size:12px;color:var(--g500);">If dyspneic: sitting position. If vomiting: recovery position</td></tr>';
html += '<tr><td style="font-weight:600;color:var(--blue);">STEP 3</td><td style="font-weight:600;">O2</td><td>High flow 10-15 L/min</td><td>Face mask</td><td style="font-size:12px;color:var(--g500);">100% O2. Prepare for airway management</td></tr>';
html += '<tr><td style="font-weight:600;color:var(--blue);">STEP 4</td><td style="font-weight:600;">IV fluids</td><td>NS ' + S.dStr(wt, fluids.dose_mg_per_kg, fluids.max_mg, ' mL') + ' bolus</td><td>IV/IO</td><td style="font-size:12px;color:var(--g500);">Repeat up to 60 mL/kg for hypotension</td></tr>';
html += '<tr><td style="font-weight:600;color:var(--blue);">STEP 5</td><td style="font-weight:600;">Diphenhydramine</td><td>' + S.dStr(wt, dph.dose_mg_per_kg, dph.max_mg) + '</td><td>IV/IM/PO</td><td style="font-size:12px;color:var(--g500);">H1 blocker. NOT first-line — adjunct only</td></tr>';
html += '<tr><td></td><td style="font-weight:600;">Ranitidine</td><td>' + S.dStr(wt, rnt.dose_mg_per_kg, rnt.max_mg) + '</td><td>IV over 5 min</td><td style="font-size:12px;color:var(--g500);">H2 blocker. Optional adjunct</td></tr>';
html += '<tr><td style="font-weight:600;color:var(--blue);">STEP 6</td><td style="font-weight:600;">Dexamethasone</td><td>' + S.dStr(wt, dex.dose_mg_per_kg, dex.max_mg) + '</td><td>IV/IM/PO</td><td style="font-size:12px;color:var(--g500);">Prevents biphasic reaction (4-6 hrs later)</td></tr>';
html += '<tr><td></td><td style="font-weight:600;">Methylprednisolone</td><td>' + S.dStr(wt, mpn.dose_mg_per_kg, mpn.max_mg) + '</td><td>IV</td><td style="font-size:12px;color:var(--g500);">Alternative steroid</td></tr>';
html += '<tr style="background:#fef3c7;"><td style="font-weight:600;color:#dc2626;">IF REFRACTORY</td><td style="font-weight:600;">Epinephrine gtt</td><td>0.1-1 mcg/kg/min</td><td>IV infusion</td><td style="font-size:12px;color:var(--g500);">For persistent hypotension despite fluids + IM epi</td></tr>';
html += '<tr style="background:#fef3c7;"><td></td><td style="font-weight:600;">Glucagon</td><td>' + S.dStr(wt, glc.dose_mg_per_kg, glc.max_mg) + '</td><td>IV/IM</td><td style="font-size:12px;color:var(--g500);">For patients on beta-blockers not responding to epi</td></tr>';
html += '</tbody></table></div>';
html += '<div style="padding:10px 12px;background:var(--amber-light);border-radius:6px;font-size:12px;color:#92400e;"><strong>Observe minimum 4-6 hours</strong> after last dose of epinephrine (biphasic reactions occur in 5-20% of cases). Discharge with EpiPen prescription and anaphylaxis action plan. Refer to allergist.</div>';
html += '<p style="font-size:11px;color:var(--g400);margin:8px 0 0;">ASCIA Anaphylaxis Guidelines 2021. WAO Anaphylaxis Guidance 2020. AAP/ACAAI Practice Parameters.</p>';
resultDiv.innerHTML = html;
}
})();
// ============================================================
// PROCEDURAL SEDATION
// ============================================================
(function() {
document.addEventListener('click', function(e) {
if (e.target.id === 'btn-sed-calc' || e.target.closest('#btn-sed-calc')) calcSedation();
});
function d(wt, mgPerKg, max) { var v = Math.round(wt * mgPerKg * 100) / 100; return max ? Math.min(v, max) : v; }
// Fallback inline data — mirrors drugs.json sedation section. The first
// table's rows group by drug (Ketamine has both IV + IM lines), hence the
// display vs name split. `reverses` marks the final 2 rows as reversal
// agents shown in a separate table.
var SED_FALLBACK = [
{ name: 'Ketamine IV', display: 'Ketamine', dose_mg_per_kg_low: 1.5, dose_mg_per_kg_high: 2, max_mg_low: 100, max_mg_high: 150, unit: 'mg', route: 'IV', onset: '1 min', duration: '15-30 min', notes: 'Dissociative. Preserves airway reflexes.' },
{ name: 'Ketamine IM', display: '', dose_mg_per_kg_low: 4, dose_mg_per_kg_high: 5, max_mg_low: 300, max_mg_high: 400, unit: 'mg', route: 'IM', onset: '3-5 min', duration: '30-60 min', notes: 'Give atropine 0.01 mg/kg to reduce secretions.' },
{ name: 'Midazolam IV', display: 'Midazolam', dose_mg_per_kg_low: 0.05, dose_mg_per_kg_high: 0.1, max_mg_low: 2, max_mg_high: 5, unit: 'mg', route: 'IV', onset: '2-3 min', duration: '30-60 min', notes: 'Anxiolysis. Titrate q3-5 min.' },
{ name: 'Midazolam IN/PO', display: '', dose_mg_per_kg: 0.5, max_mg: 20, unit: 'mg', route: 'IN/PO', onset: '10-15 min', duration: '30-60 min', notes: 'IN (max 10 mg / naris) or PO (max 20 mg).' },
{ name: 'Propofol', display: 'Propofol', dose_mg_per_kg: 1, max_mg: 40, unit: 'mg', route: 'IV', onset: '30 sec', duration: '5-10 min', notes: 'Short procedures. Causes apnea — manage airway.' },
{ name: 'Fentanyl IV', display: 'Fentanyl', dose_mg_per_kg: 1, max_mg: 100, unit: 'mcg', route: 'IV', onset: '2-3 min', duration: '30-60 min', notes: 'Analgesic. Often combined with midazolam.' },
{ name: 'Fentanyl IN', display: '', dose_mg_per_kg: 2, max_mg: 100, unit: 'mcg', route: 'IN', onset: '5-10 min', duration: '30-60 min', notes: 'Intranasal.' },
{ name: 'Nitrous oxide', display: 'Nitrous oxide', dose_display: '50:50 or 70:30 mix', unit: 'mix', route: 'Inhaled',onset: '2-5 min', duration: '5 min off', notes: 'Self-administered via demand valve. Anxiolysis + mild analgesia.' },
{ name: 'Dexmedetomidine IN', display: 'Dexmedetomidine', dose_mg_per_kg_low: 2, dose_mg_per_kg_high: 3, max_mg_low: 100, max_mg_high: null, unit: 'mcg', route: 'IN', onset: '15-30 min', duration: '60-90 min', notes: 'Intranasal. No respiratory depression. Good for imaging.' },
{ name: 'Naloxone', display: 'Naloxone', dose_mg_per_kg: 0.1, max_mg: 2, unit: 'mg', route: 'IV/IM/IN', reverses: 'Opioids (fentanyl, morphine)', notes: 'Max 2 mg. Repeat q2-3 min. Duration shorter than opioids — monitor for re-sedation.' },
{ name: 'Flumazenil', display: 'Flumazenil', dose_mg_per_kg: 0.01, max_mg: 0.2, unit: 'mg', route: 'IV', reverses: 'Benzodiazepines (midazolam)', notes: 'Max 0.2 mg single dose. Repeat q1 min to max 1 mg total. Risk of seizures — use cautiously.' }
];
function sedDrugs() {
var s = window._DRUGS && window._DRUGS.sections && window._DRUGS.sections.sedation;
if (s && s.drugs && s.drugs.length) {
return s.drugs.map(function(d) {
var fb = SED_FALLBACK.filter(function(x) { return x.name === d.name; })[0] || {};
return Object.assign({}, fb, d);
});
}
return SED_FALLBACK;
}
// perKg footer that matches the original inline format exactly.
function sedPerKg(lo, hi, unit) {
unit = unit || 'mg';
return ' <span style="color:var(--g500);font-size:11px;">(' + lo + (hi != null ? '-' + hi : '') + ' ' + unit + '/kg)</span>';
}
// Build the Dose cell text for a sedation drug (supports low/high range
// and single-dose entries; honors custom dose_display for fixed doses).
function sedDoseCell(wt, dg) {
if (dg.dose_display) return dg.dose_display;
var unitLabel = dg.unit === 'mcg' ? ' mcg' : (dg.unit === 'mix' ? '' : ' mg');
var perKgUnit = dg.unit === 'mcg' ? 'mcg' : 'mg';
if (dg.dose_mg_per_kg_low != null) {
var lo = d(wt, dg.dose_mg_per_kg_low, dg.max_mg_low);
if (dg.dose_mg_per_kg_high != null) {
var hi = d(wt, dg.dose_mg_per_kg_high, dg.max_mg_high);
return lo + '-' + hi + unitLabel + sedPerKg(dg.dose_mg_per_kg_low, dg.dose_mg_per_kg_high, perKgUnit);
}
return lo + unitLabel + sedPerKg(dg.dose_mg_per_kg_low, null, perKgUnit);
}
if (dg.dose_mg_per_kg != null) {
var v = d(wt, dg.dose_mg_per_kg, dg.max_mg);
return v + unitLabel + sedPerKg(dg.dose_mg_per_kg, null, perKgUnit);
}
return '';
}
function sedRow(wt, dg, showReverses) {
var displayName = dg.display == null ? dg.name : dg.display;
var nameCell = displayName
? '<td style="font-weight:600;">' + displayName + '</td>'
: '<td></td>';
var dose = sedDoseCell(wt, dg);
if (showReverses) {
return '<tr>' + nameCell + '<td>' + dose + '</td><td>' + dg.route + '</td><td>' + (dg.reverses || '') + '</td><td style="font-size:12px;color:var(--g500);">' + dg.notes + '</td></tr>';
}
return '<tr>' + nameCell + '<td>' + dose + '</td><td>' + dg.route + '</td><td>' + (dg.onset || '') + '</td><td>' + (dg.duration || '') + '</td><td style="font-size:12px;color:var(--g500);">' + dg.notes + '</td></tr>';
}
function calcSedation() {
var wt = parseFloat(document.getElementById('sed-weight').value);
var resultDiv = document.getElementById('sed-result');
if (!wt) { resultDiv.innerHTML = '<p style="color:var(--red);font-size:13px;">Enter weight (kg).</p>'; return; }
var all = sedDrugs();
var agents = all.filter(function(dg) { return !dg.reverses; });
var reversals = all.filter(function(dg) { return !!dg.reverses; });
var html = '<div style="padding:10px 14px;border-radius:8px;background:var(--purple-light);border:1.5px solid var(--purple);margin-bottom:12px;"><span style="font-size:14px;font-weight:700;color:var(--purple);">Procedural Sedation — ' + wt + ' kg patient</span></div>';
// Sedation agents
html += '<h4 style="font-size:14px;font-weight:700;color:var(--g800);margin:0 0 8px;">Sedation Agents</h4>';
html += '<div style="overflow-x:auto;-webkit-overflow-scrolling:touch;margin-bottom:16px;"><table style="width:100%;min-width:640px;border-collapse:collapse;font-size:13px;"><thead><tr style="background:var(--g100);"><th style="text-align:left;padding:6px 8px;">Drug</th><th style="padding:6px 8px;">Dose</th><th style="padding:6px 8px;">Route</th><th style="padding:6px 8px;">Onset</th><th style="padding:6px 8px;">Duration</th><th style="padding:6px 8px;">Notes</th></tr></thead><tbody>';
html += agents.map(function(dg) { return sedRow(wt, dg, false); }).join('');
html += '</tbody></table></div>';
// Reversal agents
html += '<h4 style="font-size:14px;font-weight:700;color:var(--red);margin:0 0 8px;"><i class="fas fa-rotate-left"></i> Reversal Agents</h4>';
html += '<div style="overflow-x:auto;-webkit-overflow-scrolling:touch;"><table style="width:100%;min-width:560px;border-collapse:collapse;font-size:13px;"><thead><tr style="background:#fee2e2;"><th style="text-align:left;padding:6px 8px;">Drug</th><th style="padding:6px 8px;">Dose</th><th style="padding:6px 8px;">Route</th><th style="padding:6px 8px;">Reverses</th><th style="padding:6px 8px;">Notes</th></tr></thead><tbody>';
html += reversals.map(function(dg) { return sedRow(wt, dg, true); }).join('');
html += '</tbody></table></div>';
html += '<div style="margin-top:12px;padding:10px 12px;background:var(--amber-light);border-radius:6px;font-size:12px;color:#92400e;"><strong>Pre-sedation checklist:</strong> NPO status (2h clear liquids, 6h solids), consent, monitoring equipment (pulse ox, capnography, BP), resuscitation equipment at bedside, suction ready, IV access. Minimum monitoring: continuous SpO2, HR, capnography. Provider capable of managing airway must be present.</div>';
html += '<p style="font-size:11px;color:var(--g400);margin:8px 0 0;">AAP Guidelines for Monitoring and Management of Pediatric Patients Before, During, and After Sedation. ASA Practice Guidelines for Sedation and Analgesia by Non-Anesthesiologists.</p>';
resultDiv.innerHTML = html;
}
})();
// ============================================================
// IMAGE LIGHTBOX — any element with data-img-src opens fullscreen
// ============================================================
(function() {
document.addEventListener('click', function(e) {
var opener = e.target.closest && e.target.closest('[data-img-src]');
if (opener) {
e.preventDefault();
var lb = document.getElementById('img-lightbox');
if (!lb) return;
var src = opener.dataset.imgSrc;
var title = opener.dataset.imgTitle || '';
document.getElementById('img-lightbox-img').src = src;
document.getElementById('img-lightbox-img').alt = title;
document.getElementById('img-lightbox-title').textContent = title;
document.getElementById('img-lightbox-open').href = src;
lb.style.display = 'flex';
return;
}
// Close on close button, on backdrop click (not on image), and on Escape (below)
var closeBtn = e.target.closest && e.target.closest('#img-lightbox-close');
var lb2 = document.getElementById('img-lightbox');
if (!lb2 || lb2.style.display !== 'flex') return;
if (closeBtn || e.target === lb2) {
lb2.style.display = 'none';
document.getElementById('img-lightbox-img').src = '';
}
});
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
var lb = document.getElementById('img-lightbox');
if (lb && lb.style.display === 'flex') {
lb.style.display = 'none';
document.getElementById('img-lightbox-img').src = '';
}
}
});
})();