@jjlmoya/utils-forensic-science 1.7.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/package.json +2 -2
  2. package/src/category/index.ts +21 -16
  3. package/src/entries.ts +8 -1
  4. package/src/tests/locale_completeness.test.ts +2 -2
  5. package/src/tests/tool_validation.test.ts +2 -2
  6. package/src/tool/time-of-death-algor-mortis-calculator/bibliography.astro +14 -0
  7. package/src/tool/time-of-death-algor-mortis-calculator/bibliography.ts +7 -0
  8. package/src/tool/time-of-death-algor-mortis-calculator/component.astro +133 -0
  9. package/src/tool/time-of-death-algor-mortis-calculator/controller.ts +254 -0
  10. package/src/tool/time-of-death-algor-mortis-calculator/dom-views.ts +144 -0
  11. package/src/tool/time-of-death-algor-mortis-calculator/entry.ts +29 -0
  12. package/src/tool/time-of-death-algor-mortis-calculator/evaluator.ts +34 -0
  13. package/src/tool/time-of-death-algor-mortis-calculator/i18n/de.ts +139 -0
  14. package/src/tool/time-of-death-algor-mortis-calculator/i18n/en.ts +136 -0
  15. package/src/tool/time-of-death-algor-mortis-calculator/i18n/es.ts +136 -0
  16. package/src/tool/time-of-death-algor-mortis-calculator/i18n/fr.ts +136 -0
  17. package/src/tool/time-of-death-algor-mortis-calculator/i18n/id.ts +139 -0
  18. package/src/tool/time-of-death-algor-mortis-calculator/i18n/it.ts +136 -0
  19. package/src/tool/time-of-death-algor-mortis-calculator/i18n/ja.ts +136 -0
  20. package/src/tool/time-of-death-algor-mortis-calculator/i18n/ko.ts +136 -0
  21. package/src/tool/time-of-death-algor-mortis-calculator/i18n/nl.ts +139 -0
  22. package/src/tool/time-of-death-algor-mortis-calculator/i18n/pl.ts +139 -0
  23. package/src/tool/time-of-death-algor-mortis-calculator/i18n/pt.ts +136 -0
  24. package/src/tool/time-of-death-algor-mortis-calculator/i18n/ru.ts +139 -0
  25. package/src/tool/time-of-death-algor-mortis-calculator/i18n/sv.ts +139 -0
  26. package/src/tool/time-of-death-algor-mortis-calculator/i18n/tr.ts +139 -0
  27. package/src/tool/time-of-death-algor-mortis-calculator/i18n/zh.ts +136 -0
  28. package/src/tool/time-of-death-algor-mortis-calculator/index.ts +11 -0
  29. package/src/tool/time-of-death-algor-mortis-calculator/logic.test.ts +77 -0
  30. package/src/tool/time-of-death-algor-mortis-calculator/logic.ts +177 -0
  31. package/src/tool/time-of-death-algor-mortis-calculator/seo.astro +15 -0
  32. package/src/tool/time-of-death-algor-mortis-calculator/storage.ts +21 -0
  33. package/src/tool/time-of-death-algor-mortis-calculator/time-of-death-algor-mortis-calculator.css +596 -0
  34. package/src/tool/time-of-death-algor-mortis-calculator/ui.ts +60 -0
  35. package/src/tools.ts +3 -1
@@ -0,0 +1,144 @@
1
+ import type { TimeOfDeathAlgorMortisUI } from './ui';
2
+ import type { AlgorMortisResult, AlgorMortisInputs, CurvePoint } from './logic';
3
+ import { evaluateCoolingStatus } from './evaluator';
4
+
5
+ export interface SvgRenderConfig {
6
+ result: AlgorMortisResult;
7
+ inputs: AlgorMortisInputs;
8
+ ui: TimeOfDeathAlgorMortisUI;
9
+ }
10
+
11
+ interface PlotBounds {
12
+ w: number;
13
+ h: number;
14
+ padLeft: number;
15
+ padBottom: number;
16
+ minTemp: number;
17
+ maxTemp: number;
18
+ maxTime: number;
19
+ }
20
+
21
+ export function formatDuration(decimalHours: number, ui: TimeOfDeathAlgorMortisUI): string {
22
+ const h = Math.floor(decimalHours);
23
+ const m = Math.round((decimalHours - h) * 60);
24
+ if (m === 60) return `${h + 1} ${ui.hoursUnit}`;
25
+ if (h === 0) return `${m} ${ui.minutesUnit}`;
26
+ return `${h} ${ui.hoursUnit} ${m} ${ui.minutesUnit}`;
27
+ }
28
+
29
+ export function renderTelemetry(container: HTMLElement, result: AlgorMortisResult, inputs: AlgorMortisInputs, ui: TimeOfDeathAlgorMortisUI): void {
30
+ const isImp = inputs.unitSystem === 'imperial';
31
+ const tempUnit = isImp ? ui.fahrenheitUnit : ui.celsiusUnit;
32
+ const rateUnit = isImp ? ui.fahrenheitPerHour : ui.celsiusPerHour;
33
+ const status = evaluateCoolingStatus({ result, ui, rectalTemp: result.rectalTempDisplay, ambientTemp: result.ambientTempDisplay, refTemp: result.refTempDisplay });
34
+
35
+ container.innerHTML = `
36
+ <div class="sc-hero-card">
37
+ <div class="sc-hero-header">
38
+ <span class="sc-hero-title">${ui.estimatedPmiLabel}</span>
39
+ <span class="sc-badge ${status.badgeClass}">${status.phaseLabel}</span>
40
+ </div>
41
+ <div class="sc-hero-val">${formatDuration(result.pmiHours, ui)}</div>
42
+ <div class="sc-hero-sub">${ui.deathWindowLabel}: <strong>${result.timeOfDeathMin} - ${result.timeOfDeathMax}</strong> (${result.timeOfDeathEstimated} est.)</div>
43
+ <div class="sc-gauge-wrap">
44
+ <div class="sc-gauge-track">
45
+ <div class="sc-gauge-bar ${status.badgeClass}" style="width: ${status.gaugePercent}%"></div>
46
+ </div>
47
+ <div class="sc-gauge-labels">
48
+ <span>${result.refTempDisplay}${tempUnit} ${ui.referenceBodyTempLabel || ''}</span>
49
+ <span>${result.ambientTempDisplay}${tempUnit} ${ui.baselineAmbientLabel || ''}</span>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ <div class="sc-stats-grid">
54
+ <div class="sc-stat-card"><span class="sc-stat-label">${ui.confidenceMarginLabel}</span><span class="sc-stat-val">± ${formatDuration(result.confidenceMarginHours, ui)}</span><span class="sc-stat-sub">${ui.confidenceMarginSub || '95%'}</span></div>
55
+ <div class="sc-stat-card"><span class="sc-stat-label">${ui.coolingRateLabel}</span><span class="sc-stat-val">${result.coolingRateDisplay} ${rateUnit}</span><span class="sc-stat-sub">${ui.coolingRateSub || 'ΔT/h'}</span></div>
56
+ <div class="sc-stat-card"><span class="sc-stat-label">${ui.glaisterEstimateLabel}</span><span class="sc-stat-val">${formatDuration(result.glaisterPmiHours, ui)}</span><span class="sc-stat-sub">${ui.glaisterEstimateSub || 'Glaister'}</span></div>
57
+ </div>
58
+ `;
59
+ }
60
+
61
+ function buildPathString(points: CurvePoint[], b: PlotBounds): string {
62
+ const span = Math.max(1, b.maxTemp - b.minTemp);
63
+ const plotW = b.w - b.padLeft - 30;
64
+ const plotH = b.h - b.padBottom - 25;
65
+ return points.reduce((acc, pt, i) => {
66
+ const x = b.padLeft + (pt.time / b.maxTime) * plotW;
67
+ const y = 25 + plotH - ((pt.temp - b.minTemp) / span) * plotH;
68
+ return i === 0 ? `M ${x.toFixed(1)} ${y.toFixed(1)}` : `${acc} L ${x.toFixed(1)} ${y.toFixed(1)}`;
69
+ }, '');
70
+ }
71
+
72
+ function buildBandPolygon(points: CurvePoint[], b: PlotBounds): string {
73
+ const span = Math.max(1, b.maxTemp - b.minTemp);
74
+ const plotW = b.w - b.padLeft - 30;
75
+ const plotH = b.h - b.padBottom - 25;
76
+ const upper = points.map((pt) => `${(b.padLeft + (pt.time / b.maxTime) * plotW).toFixed(1)},${(25 + plotH - ((pt.upperTemp - b.minTemp) / span) * plotH).toFixed(1)}`);
77
+ const lower = points.slice().reverse().map((pt) => `${(b.padLeft + (pt.time / b.maxTime) * plotW).toFixed(1)},${(25 + plotH - ((pt.lowerTemp - b.minTemp) / span) * plotH).toFixed(1)}`);
78
+ return `${upper.join(' ')} ${lower.join(' ')}`;
79
+ }
80
+
81
+ function renderAxesAndGrid(b: PlotBounds, tempUnit: string): string {
82
+ const plotW = b.w - b.padLeft - 30;
83
+ const plotH = b.h - b.padBottom - 25;
84
+ const span = Math.max(1, b.maxTemp - b.minTemp);
85
+
86
+ const yVals = [b.maxTemp, b.minTemp + span * 0.66, b.minTemp + span * 0.33, b.minTemp];
87
+ const yTicks = yVals.map((val) => {
88
+ const y = 25 + plotH - ((val - b.minTemp) / span) * plotH;
89
+ return `<line x1="${b.padLeft}" y1="${y}" x2="${b.w - 30}" y2="${y}" class="sc-chart-grid" /><text x="${b.padLeft - 10}" y="${y + 4}" text-anchor="end" class="sc-chart-axis-label">${Math.round(val)}${tempUnit}</text>`;
90
+ });
91
+
92
+ const xSteps = [0, b.maxTime * 0.25, b.maxTime * 0.5, b.maxTime * 0.75, b.maxTime].map((t) => {
93
+ const x = b.padLeft + (t / b.maxTime) * plotW;
94
+ return `<line x1="${x}" y1="25" x2="${x}" y2="${25 + plotH}" class="sc-chart-grid" /><text x="${x}" y="${b.h - 15}" text-anchor="middle" class="sc-chart-axis-label">${Math.round(t)}h</text>`;
95
+ });
96
+
97
+ return `${yTicks.join('')}${xSteps.join('')}<line x1="${b.padLeft}" y1="25" x2="${b.padLeft}" y2="${25 + plotH}" class="sc-chart-axis" /><line x1="${b.padLeft}" y1="${25 + plotH}" x2="${b.w - 30}" y2="${25 + plotH}" class="sc-chart-axis" />`;
98
+ }
99
+
100
+ function buildSvgContent(cfg: SvgRenderConfig, b: PlotBounds, tUnit: string): string {
101
+ const { result, ui } = cfg;
102
+ const plotW = b.w - b.padLeft - 30;
103
+ const plotH = b.h - b.padBottom - 25;
104
+ const span = Math.max(1, b.maxTemp - b.minTemp);
105
+ const pathD = buildPathString(result.curvePoints, b);
106
+ const bandPoly = buildBandPolygon(result.curvePoints, b);
107
+ const ptX = b.padLeft + (result.pmiHours / b.maxTime) * plotW;
108
+ const ptY = 25 + plotH - ((result.rectalTempDisplay - b.minTemp) / span) * plotH;
109
+ const ambY = 25 + plotH - ((result.ambientTempDisplay - b.minTemp) / span) * plotH;
110
+ const plateauW = (2.5 / boundsOrDefault(b.maxTime)) * plotW;
111
+
112
+ return `
113
+ <defs><linearGradient id="sc-curve-grad" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="var(--n-accent-cyan)" /><stop offset="100%" stop-color="var(--n-primary)" /></linearGradient></defs>
114
+ ${renderAxesAndGrid(b, tUnit)}
115
+ <rect x="${b.padLeft}" y="25" width="${plateauW}" height="${plotH}" class="sc-chart-plateau" />
116
+ <polygon points="${bandPoly}" class="sc-chart-band" />
117
+ <line x1="${b.padLeft}" y1="${ambY}" x2="${b.w - 30}" y2="${ambY}" class="sc-chart-amb" />
118
+ <path d="${pathD}" class="sc-chart-line" />
119
+ <circle cx="${ptX}" cy="${ptY}" r="9" class="sc-chart-pulse" />
120
+ <circle cx="${ptX}" cy="${ptY}" r="5" class="sc-chart-core" />
121
+ <text x="${b.padLeft + plateauW / 2}" y="45" text-anchor="middle" class="sc-chart-tag">${ui.chartPlateauMarker}</text>
122
+ <text x="${b.w - 35}" y="${ambY - 8}" text-anchor="end" class="sc-chart-tag">${result.ambientTempDisplay}${tUnit} ${ui.ambientTempLabel}</text>
123
+ <text x="${Math.min(b.w - 110, ptX + 14)}" y="${Math.max(45, ptY - 12)}" class="sc-chart-pt-label">${result.rectalTempDisplay}${tUnit} (${result.pmiHours.toFixed(1)}h)</text>
124
+ `;
125
+ }
126
+
127
+ function boundsOrDefault(maxTime: number): number {
128
+ return Math.max(1, maxTime);
129
+ }
130
+
131
+ export function renderSvgNomogram(svg: SVGSVGElement, cfg: SvgRenderConfig): void {
132
+ const isImp = cfg.inputs.unitSystem === 'imperial';
133
+ const bounds: PlotBounds = {
134
+ w: 700,
135
+ h: 340,
136
+ padLeft: 70,
137
+ padBottom: 45,
138
+ minTemp: Math.min(cfg.result.ambientTempDisplay, cfg.result.rectalTempDisplay) - (isImp ? 4 : 2),
139
+ maxTemp: cfg.result.refTempDisplay + (isImp ? 3 : 1.5),
140
+ maxTime: Math.max(24, Math.ceil(cfg.result.pmiHours + 6))
141
+ };
142
+ svg.setAttribute('viewBox', `0 0 ${bounds.w} ${bounds.h}`);
143
+ svg.innerHTML = buildSvgContent(cfg, bounds, isImp ? cfg.ui.fahrenheitUnit : cfg.ui.celsiusUnit);
144
+ }
@@ -0,0 +1,29 @@
1
+ import type { ScienceToolEntry, ToolLocaleContent } from '../../types';
2
+ import type { TimeOfDeathAlgorMortisUI } from './ui';
3
+
4
+ export type TimeOfDeathAlgorMortisLocaleContent = ToolLocaleContent<TimeOfDeathAlgorMortisUI>;
5
+
6
+ export const timeOfDeathAlgorMortisCalculator: ScienceToolEntry<TimeOfDeathAlgorMortisUI> = {
7
+ id: 'time-of-death-algor-mortis-calculator',
8
+ icons: {
9
+ bg: 'mdi:thermometer',
10
+ fg: 'mdi:timer-outline'
11
+ },
12
+ i18n: {
13
+ de: () => import('./i18n/de').then((m) => m.content),
14
+ en: () => import('./i18n/en').then((m) => m.content),
15
+ es: () => import('./i18n/es').then((m) => m.content),
16
+ fr: () => import('./i18n/fr').then((m) => m.content),
17
+ id: () => import('./i18n/id').then((m) => m.content),
18
+ it: () => import('./i18n/it').then((m) => m.content),
19
+ ja: () => import('./i18n/ja').then((m) => m.content),
20
+ ko: () => import('./i18n/ko').then((m) => m.content),
21
+ nl: () => import('./i18n/nl').then((m) => m.content),
22
+ pl: () => import('./i18n/pl').then((m) => m.content),
23
+ pt: () => import('./i18n/pt').then((m) => m.content),
24
+ ru: () => import('./i18n/ru').then((m) => m.content),
25
+ sv: () => import('./i18n/sv').then((m) => m.content),
26
+ tr: () => import('./i18n/tr').then((m) => m.content),
27
+ zh: () => import('./i18n/zh').then((m) => m.content)
28
+ }
29
+ };
@@ -0,0 +1,34 @@
1
+ import type { TimeOfDeathAlgorMortisUI } from './ui';
2
+ import type { AlgorMortisResult } from './logic';
3
+
4
+ export interface EvaluatedStatus {
5
+ phaseLabel: string;
6
+ badgeClass: string;
7
+ gaugePercent: number;
8
+ }
9
+
10
+ export interface StatusEvaluationParams {
11
+ result: AlgorMortisResult;
12
+ ui: TimeOfDeathAlgorMortisUI;
13
+ rectalTemp: number;
14
+ ambientTemp: number;
15
+ refTemp: number;
16
+ }
17
+
18
+ export function evaluateCoolingStatus(params: StatusEvaluationParams): EvaluatedStatus {
19
+ const { result, ui, rectalTemp, ambientTemp, refTemp } = params;
20
+ const totalSpan = Math.max(1, refTemp - ambientTemp);
21
+ const dropped = Math.max(0, refTemp - rectalTemp);
22
+ const gaugePercent = Math.min(100, Math.max(0, Math.round((dropped / totalSpan) * 100)));
23
+
24
+ if (result.coolingPhase === 'hyperthermia') {
25
+ return { phaseLabel: ui.phaseHyperthermia, badgeClass: 'badge-danger', gaugePercent: 0 };
26
+ }
27
+ if (result.coolingPhase === 'equilibrium') {
28
+ return { phaseLabel: ui.phaseEquilibrium, badgeClass: 'badge-warning', gaugePercent: 100 };
29
+ }
30
+ if (result.coolingPhase === 'plateau') {
31
+ return { phaseLabel: ui.phasePlateau, badgeClass: 'badge-info', gaugePercent };
32
+ }
33
+ return { phaseLabel: ui.phaseDescent, badgeClass: 'badge-success', gaugePercent };
34
+ }
@@ -0,0 +1,139 @@
1
+ import { bibliography } from '../bibliography';
2
+ import type { TimeOfDeathAlgorMortisLocaleContent } from '../entry';
3
+
4
+ const slug = 'todeszeitpunkt-berechnen-algor-mortis';
5
+ const title = 'Todeszeitpunkt Rechner mit Henssge Nomogramm';
6
+ const description = 'Berechnen Sie das postmortale Intervall und den Todeszeitpunkt anhand der Rektaltemperatur und des Henssge Abkühlungsmodells.';
7
+
8
+ const howTo = [
9
+ { name: 'Rektal und Umgebungstemperatur erfassen', text: 'Geben Sie die gemessene tiefe Körperkerntemperatur und die Umgebungstemperatur am Fundort ein.' },
10
+ { name: 'Körpergewicht und Korrekturfaktor wählen', text: 'Tragen Sie das Körpergewicht in Kilogramm ein und bestimmen Sie den Faktor für Kleidung oder Wasser.' },
11
+ { name: 'Messzeitpunkt festlegen', text: 'Geben Sie die genaue Uhrzeit der thermischen Messung ein oder wählen Sie die aktuelle Uhrzeit.' },
12
+ { name: 'Postmortales Intervall analysieren', text: 'Überprüfen Sie das berechnete Intervall, das 95 Prozent Konfidenzfenster und die Temperaturkurve.' }
13
+ ];
14
+
15
+ const faq = [
16
+ { question: 'Was bedeutet Algor Mortis in der Rechtsmedizin?', answer: 'Algor Mortis bezeichnet die fortschreitende postmortale Leichenabkühlung bis zum Erreichen des thermischen Umgebungsgleichgewichts.' },
17
+ { question: 'Warum ist das Henssge Nomogramm genauer als lineare Faustregeln?', answer: 'Weil es das anfängliche Temperaturplateau sowie die doppel exponentielle Abkühlung unter Berücksichtigung von Körpermasse und Bekleidung abbildet.' },
18
+ { question: 'Wie präzise ist die rektale Todeszeitbestimmung?', answer: 'Unter kontrollierten Standardbedingungen beträgt die statistische 95 Prozent Vertrauensgrenze in den ersten 10 Stunden etwa plus minus 2.8 Stunden.' },
19
+ { question: 'Was versteht man unter dem postmortalen Temperaturplateau?', answer: 'Das Plateau beschreibt die ersten 1 bis 3 Stunden nach dem Tod, in denen die Kerntemperatur durch den bestehenden Temperaturgradienten kaum absinkt.' }
20
+ ];
21
+
22
+ export const content: TimeOfDeathAlgorMortisLocaleContent = {
23
+ slug,
24
+ title,
25
+ description,
26
+ ui: {
27
+ title,
28
+ subtitle: 'Postmortales Intervall und Henssge Nomogramm Rechner',
29
+ disclaimer: 'Nur für Ausbildungs und Simulationszwecke. Gerichtsverwertbare Gutachten erfordern eine vollständige Obduktion und gesicherte Temperaturprotokolle.',
30
+ unitSystemLabel: 'Einheitensystem',
31
+ unitMetricLabel: 'Metrisch',
32
+ unitImperialLabel: 'Imperial',
33
+ presetsHeader: 'Forensische Standardszenarien',
34
+ presetCustom: 'Benutzerdefinierte Werte',
35
+ presetNakedCalm: 'Entkleidet in ruhigem Raum (20°C)',
36
+ presetDressedIndoor: 'Bekleidet in Innenräumen (19.5°C)',
37
+ presetWinterOutdoor: 'Winterliche Außenluft (4°C)',
38
+ presetSubmergedWater: 'In stehendem Wasser (12°C)',
39
+ presetHeavyDuvet: 'Unter dicker Daunendecke (18°C)',
40
+ inputsHeader: 'Messwerte und Umgebungsparameter',
41
+ rectalTempLabel: 'Rektale Kerntemperatur',
42
+ ambientTempLabel: 'Umgebungstemperatur',
43
+ bodyWeightLabel: 'Körpergewicht',
44
+ factorLabel: 'Umgebungskorrekturfaktor',
45
+ measurementTimeLabel: 'Messuhrzeit',
46
+ factorNaked: 'Entkleidet in ruhender Luft',
47
+ factorLightClothes: 'Leichte Kleidung (1-2 Schichten)',
48
+ factorStandardClothes: 'Standardkleidung (3-4 Schichten)',
49
+ factorHeavyWinter: 'Dicke Winterbekleidung',
50
+ factorLightBlanket: 'Bett mit leichter Decke',
51
+ factorHeavyDuvet: 'Bett mit dicker Daunendecke',
52
+ factorStillWater: 'In stehendem Wasser',
53
+ factorFlowingWater: 'In fließendem kaltem Wasser',
54
+ factorWetClothing: 'Nasse Kleidung bei Windzug',
55
+ factorMovingAir: 'Bewegte Luft mit Ventilator',
56
+ resultsHeader: 'Analyse des postmortalen Intervalls',
57
+ estimatedPmiLabel: 'Geschätzte Zeit seit Todeseintritt',
58
+ deathWindowLabel: 'Wahrscheinlicher Todeszeitraum',
59
+ confidenceMarginLabel: 'Konfidenzintervall (95%)',
60
+ coolingPhaseLabel: 'Thermodynamische Phase',
61
+ coolingRateLabel: 'Momentane Abkühlungsrate',
62
+ glaisterEstimateLabel: 'Vergleich mit Glaister Regel',
63
+ chartHeader: 'Henssge Doppel Exponentielle Abkühlungskurve',
64
+ chartXAxis: 'Stunden postmortal',
65
+ chartYAxis: 'Körpertemperatur',
66
+ chartNowMarker: 'Messwert',
67
+ chartPlateauMarker: 'Temperaturplateau',
68
+ phasePlateau: 'Plateauphase',
69
+ phaseDescent: 'Exponentieller Abfall',
70
+ phaseEquilibrium: 'Thermisches Gleichgewicht',
71
+ phaseHyperthermia: 'Warnung vor Hyperthermie',
72
+ hoursUnit: 'Stunden',
73
+ minutesUnit: 'Min',
74
+ celsiusUnit: '°C',
75
+ fahrenheitUnit: '°F',
76
+ kgUnit: 'kg',
77
+ lbUnit: 'lb',
78
+ celsiusPerHour: '°C/h',
79
+ fahrenheitPerHour: '°F/h',
80
+ resetBtn: 'Zurücksetzen',
81
+ nowBtn: 'Jetzt',
82
+ coreThermometerLabel: 'Körperkerntemperatur',
83
+ baselineAmbientLabel: 'Umgebungsgrenze',
84
+ referenceBodyTempLabel: 'Normaltemperatur'
85
+ },
86
+ seo: [
87
+ { type: 'title', text: 'Physikalische Grundlagen der Leichenabkühlung und Todeszeitschätzung', level: 2 },
88
+ { type: 'paragraph', html: 'Die verlässliche Bestimmung der Todeszeit und des postmortalen Intervalls gehört zu den zentralen Aufgaben der rechtsmedizinischen Kriminalistik bei der Leichenschau am Fundort. <strong>Algor Mortis</strong> beschreibt den physikalischen Wärmeverlust eines menschlichen Körpers nach dem irreversiblen Herz Kreislauf Stillstand bis zum vollständigen Angleich an die herrschende Umgebungstemperatur. Durch tiefe rektale Temperaturmessung und thermodynamische mathematische Modelle lässt sich der Todeszeitpunkt wissenschaftlich eingrenzen und objektiv rekonstruieren.' },
89
+ { type: 'paragraph', html: 'Die Wärmeübertragung erfolgt über Strahlung, Wärmeleitung, Konvektion und Verdunstung. Da der Körperkern die Wärme zunächst an die Körperschale abgibt, entsteht ein komplexer Temperaturgradient, der nicht durch einfache lineare Gleichungen erfasst werden kann.' },
90
+ { type: 'diagnostic', variant: 'info', title: 'Thermodynamischer Abkühlungsverlauf', html: 'Die Leichenabkühlung erfolgt nicht linear ab der ersten Minute nach dem Todeseintritt. Sie weist eine charakteristische anfängliche Verzögerung namens <em>Temperaturplateau</em> auf, gefolgt von einem steilen doppel exponentiellen Temperaturabfall bis zum thermischen Ausgleich.' },
91
+ { type: 'stats', columns: 3, items: [
92
+ { value: '37.2°C', label: 'Rektale Normtemperatur' },
93
+ { value: '±2.8 h', label: 'Konfidenzbereich erste 10h' },
94
+ { value: '2 Exponenten', label: 'Henssge Berechnungsmodell' }
95
+ ] },
96
+ { type: 'title', text: 'Die Doppel Exponentielle Formel nach Claus Henssge', level: 3 },
97
+ { type: 'paragraph', html: 'Einfache Faustformeln wie die historische Glaister Regel unterstellen einen konstanten Verlust von etwa 0.83 Grad Celsius pro Stunde. Dieses stark vereinfachte Vorgehen vernachlässigt jedoch den maßgeblichen Einfluss der Körpermasse, isolierender Bekleidungsschichten und das postmortale Plateau der tiefen Eingeweideorgane.' },
98
+ { type: 'code', ariaLabel: 'Henssge Formel', code: 'Q = (T_rektal - T_umgebung) / (37.2 - T_umgebung)\nQ = 1.25 * exp(-k * t) - 0.25 * exp(-5 * k * t)\nk = 1.2815 / (Koerpergewicht^0.625 * Korrekturfaktor) - 0.0284' },
99
+ { type: 'paragraph', html: 'Professor Claus Henssge entwickelte eine doppel exponentielle Gleichung, welche die Wärmeübertragung von Körperkern und Körperschale präzise berücksichtigt. Die mathematische Auflösung nach der Zeit liefert das probabilistische postmortale Zeitfenster mit hoher forensischer Belastbarkeit.' },
100
+ { type: 'paragraph', html: 'Der dimensionslose Quotient Q beschreibt den Anteil der verbleibenden Körperwärme im Verhältnis zum thermischen Ausgangszustand. Diese Formulierung stellt sicher, dass die Berechnung unabhängig von absoluten Temperaturskalen exakte Zeitschätzungen liefert.' },
101
+ { type: 'title', text: 'Relevante Umwelt und Isolationskorrekturfaktoren', level: 3 },
102
+ { type: 'paragraph', html: 'Die Wärmeabgabe hängt entscheidend von der Körperoberfläche, Luftströmungen am Auffindeort und isolierenden Textilschichten ab.' },
103
+ { type: 'table', headers: ['Auffindesituation', 'Korrekturfaktor', 'Wirkungsmechanismus'], rows: [
104
+ ['Entkleidet in stehender Raumluft', '1.0', 'Standardmäßige Wärmeabstrahlung und Eigenkonvektion'],
105
+ ['Leichte Bekleidung (1-2 Lagen)', '1.1', 'Geringe Verminderung der konvektiven Wärmeabgabe'],
106
+ ['Normale Straßenkleidung (3-4 Lagen)', '1.2', 'Mäßige thermische Barriere an Rumpf und Extremitäten'],
107
+ ['Dicke Winterbekleidung', '1.4', 'Starke thermische Isolation durch Lufteinschluss'],
108
+ ['Unter dicker Daunendecke im Bett', '1.8', 'Sehr hohe Wärmespeicherung und verzögerte Abkühlung'],
109
+ ['In stehendem Wasser', '0.5', 'Wärmeleitfähigkeit von Wasser ist 24 mal höher als Luft'],
110
+ ['In fließendem kaltem Wasser', '0.35', 'Erzwungene Konvektion beschleunigt den Entzug drastisch']
111
+ ] },
112
+ { type: 'title', text: 'Phasen der postmortalen Thermodynamik', level: 3 },
113
+ { type: 'comparative', columns: 2, items: [
114
+ { title: 'Postmortales Temperaturplateau', description: 'In den ersten 1 bis 3 Stunden fällt die rektale Temperatur kaum ab, während sich der Temperaturgradient zur Haut aufbaut.', points: ['Kern Schale Gradient bildet sich aus', 'Lineare Formeln unterschätzen die Zeitspanne', 'Mathematisch erfasst durch -0.25 exp(-5kt)'] },
115
+ { title: 'Steiler Exponentieller Abfall', description: 'Nach Ausbildung des Gradienten erfolgt eine kontinuierliche Wärmeabgabe mit maximaler thermometrischer Aussagekraft.', highlight: true, points: ['Höchste analytische Trennschärfe', 'Engstes statistisches Vertrauensintervall', 'Optimaler Zeitraum für die Temperaturmethode'] }
116
+ ] },
117
+ { type: 'title', text: 'Methodische Hinweise zur Temperaturmessung am Fundort', level: 3 },
118
+ { type: 'paragraph', html: 'Für die gerichtsmedizinische Praxis ist die Einhaltung strenger Messstandards unerlässlich. Abweichungen bei der Messtiefe oder ungenaue Erfassungen der Umgebungstemperatur können zu erheblichen Verzerrungen des berechneten Zeitfensters führen.' },
119
+ { type: 'list', items: [
120
+ '<strong>Tiefe rektale Kerntemperatur messen:</strong> Den kalibrierten Messfühler mindestens 8 bis 10 cm tief in das Rektum einführen.',
121
+ '<strong>Umgebungstemperatur unmittelbar am Leichnam erfassen:</strong> Thermometer maximal 10 cm neben dem Körper platzieren.',
122
+ '<strong>Thermische Konstanz des Fundorts dokumentieren:</strong> Heizkörper, offene Fenster oder Sonneneinstrahlung protokollieren.',
123
+ '<strong>Feuchtigkeit der Kleidung prüfen:</strong> Nasse Stoffe steigern die Verdunstungskälte erheblich.'
124
+ ] },
125
+ { type: 'summary', title: 'Methodische Zusammenfassung', items: [
126
+ 'Das Henssge Nomogramm ist der international anerkannte Goldstandard der rechtsmedizinischen Todeszeitberechnung.',
127
+ 'Es sollte stets ein Zeitintervall mit Vertrauensgrenzen statt eines isolierten Zeitpunkts angegeben werden.',
128
+ 'Die Temperaturmessung ist mit Totenstarre, Totenflecken und supravitalen Reaktionen zu kombinieren.'
129
+ ] }
130
+ ],
131
+ faq,
132
+ bibliography,
133
+ howTo,
134
+ schemas: [
135
+ { '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: title, description, applicationCategory: 'ForensicApplication', operatingSystem: 'Any' },
136
+ { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) },
137
+ { '@context': 'https://schema.org', '@type': 'HowTo', name: title, step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) }
138
+ ]
139
+ };
@@ -0,0 +1,136 @@
1
+ import { bibliography } from '../bibliography';
2
+ import type { TimeOfDeathAlgorMortisLocaleContent } from '../entry';
3
+
4
+ const slug = 'time-of-death-algor-mortis-calculator';
5
+ const title = 'Time of Death Algor Mortis Calculator';
6
+ const description = 'Estimate postmortem interval and time of death using the Henssge nomogram method and body cooling thermodynamics.';
7
+
8
+ const howTo = [
9
+ { name: 'Enter Body and Ambient Temperatures', text: 'Input the measured core rectal temperature and the ambient environmental temperature at the scene.' },
10
+ { name: 'Set Body Mass and Corrective Factors', text: 'Specify the body weight in kilograms and choose the environmental correction factor according to clothing, bed covers, or water immersion.' },
11
+ { name: 'Specify Measurement Time', text: 'Enter the exact time the temperature was taken or click Current Time to calculate backwards.' },
12
+ { name: 'Analyze PMI and Cooling Curve', text: 'Review the estimated postmortem interval, the 95 percent confidence death window, and the thermal cooling curve.' }
13
+ ];
14
+
15
+ const faq = [
16
+ { question: 'What is Algor Mortis in forensic medicine?', answer: 'Algor Mortis is the postmortem decrease in body temperature until thermal equilibrium with the surrounding environment is reached.' },
17
+ { question: 'Why is the Henssge nomogram preferred over linear rules?', answer: 'The Henssge model accounts for the initial temperature plateau and exponential cooling curves using body weight and corrective environmental factors.' },
18
+ { question: 'How accurate is temperature based time of death estimation?', answer: 'Under controlled standard conditions, the 95 percent confidence interval is approximately plus or minus 2.8 hours in the first 10 hours, widening in later stages.' },
19
+ { question: 'What is the postmortem temperature plateau?', answer: 'The temperature plateau is the initial period of 1 to 3 hours after death during which the core temperature decreases very slowly due to core to surface thermal gradients.' }
20
+ ];
21
+
22
+ export const content: TimeOfDeathAlgorMortisLocaleContent = {
23
+ slug,
24
+ title,
25
+ description,
26
+ ui: {
27
+ title,
28
+ subtitle: 'Postmortem Interval Estimator and Thermal Decay Nomogram',
29
+ disclaimer: 'Educational and academic simulation only. Actual death time determinations require comprehensive forensic examination, livor and rigor mortis correlation, and documented scene temperature records.',
30
+ unitSystemLabel: 'Unit System',
31
+ unitMetricLabel: 'Metric',
32
+ unitImperialLabel: 'Imperial',
33
+ presetsHeader: 'Forensic Scenario Presets',
34
+ presetCustom: 'Custom Parameters',
35
+ presetNakedCalm: 'Naked in Still Room (20°C)',
36
+ presetDressedIndoor: 'Dressed Indoors (19.5°C)',
37
+ presetWinterOutdoor: 'Winter Outdoor (4°C)',
38
+ presetSubmergedWater: 'Submerged in Still Water (12°C)',
39
+ presetHeavyDuvet: 'Under Heavy Down Duvet Bed (18°C)',
40
+ inputsHeader: 'Scene Parameters and Thermal Measurements',
41
+ rectalTempLabel: 'Rectal Core Temp',
42
+ ambientTempLabel: 'Ambient Temp',
43
+ bodyWeightLabel: 'Body Weight',
44
+ factorLabel: 'Environmental Factor',
45
+ measurementTimeLabel: 'Measurement Time',
46
+ factorNaked: 'Naked in still air',
47
+ factorLightClothes: 'Light clothing (1-2 layers)',
48
+ factorStandardClothes: 'Standard clothing (3-4 layers)',
49
+ factorHeavyWinter: 'Heavy insulated winter clothes',
50
+ factorLightBlanket: 'Bed with light blanket',
51
+ factorHeavyDuvet: 'Bed with thick down duvet',
52
+ factorStillWater: 'Submerged in still water',
53
+ factorFlowingWater: 'Submerged in flowing cold water',
54
+ factorWetClothing: 'Wet clothing in wind',
55
+ factorMovingAir: 'Moving air with draft or fan',
56
+ resultsHeader: 'Postmortem Interval Analysis',
57
+ estimatedPmiLabel: 'Estimated Time Since Death',
58
+ deathWindowLabel: 'Probable Death Window',
59
+ confidenceMarginLabel: 'Confidence Margin (95%)',
60
+ coolingPhaseLabel: 'Thermodynamic Phase',
61
+ coolingRateLabel: 'Instant Heat Loss Rate',
62
+ glaisterEstimateLabel: 'Glaister Linear Comparison',
63
+ chartHeader: 'Henssge Exponential Cooling Trajectory',
64
+ chartXAxis: 'Hours Postmortem',
65
+ chartYAxis: 'Core Temperature',
66
+ chartNowMarker: 'Measured Reading',
67
+ chartPlateauMarker: 'Initial Plateau',
68
+ phasePlateau: 'Plateau Stage',
69
+ phaseDescent: 'Exponential Cooling',
70
+ phaseEquilibrium: 'Thermal Equilibrium',
71
+ phaseHyperthermia: 'Hyperthermia Warning',
72
+ hoursUnit: 'hours',
73
+ minutesUnit: 'min',
74
+ celsiusUnit: '°C',
75
+ fahrenheitUnit: '°F',
76
+ kgUnit: 'kg',
77
+ lbUnit: 'lb',
78
+ celsiusPerHour: '°C/h',
79
+ fahrenheitPerHour: '°F/h',
80
+ resetBtn: 'Reset',
81
+ nowBtn: 'Current Time',
82
+ coreThermometerLabel: 'Core Temperature',
83
+ baselineAmbientLabel: 'Ambient Baseline',
84
+ referenceBodyTempLabel: 'Reference Body Temp'
85
+ },
86
+ seo: [
87
+ { type: 'title', text: 'How Postmortem Body Cooling Estimates Time of Death', level: 2 },
88
+ { type: 'paragraph', html: 'Estimating the time since death (Postmortem Interval or PMI) is one of the most critical challenges in legal medicine and death investigation. <strong>Algor Mortis</strong> refers to the progressive cooling of a human body after circulatory arrest until it reaches ambient thermal equilibrium. Because heat dissipation follows thermodynamic principles, measuring the deep core temperature allows forensic pathologists to reconstruct the time window when death occurred.' },
89
+ { type: 'diagnostic', variant: 'info', title: 'Thermodynamic Foundation', html: 'Body cooling does not proceed linearly from the moment of death. It exhibits an initial delay known as the <em>temperature plateau</em>, followed by steep exponential decay, and eventually flattens as core temperature approaches ambient temperature.' },
90
+ { type: 'stats', columns: 3, items: [
91
+ { value: '37.2°C', label: 'Reference Normothermic Core' },
92
+ { value: '±2.8 h', label: 'Initial 95% Confidence Margin' },
93
+ { value: '2 Exponential', label: 'Henssge Mathematical Model' }
94
+ ] },
95
+ { type: 'title', text: 'The Claus Henssge Double Exponential Equation', level: 3 },
96
+ { type: 'paragraph', html: 'Historically, investigators applied linear rules of thumb such as the Glaister equation, which assumes a steady drop of approximately 0.83 degrees Celsius per hour. While simple, linear approximations fail to account for the protective insulation of body mass and clothing or the plateau phenomenon in the first few hours.' },
97
+ { type: 'code', ariaLabel: 'Henssge Formula', code: 'Q = (T_rectal - T_ambient) / (37.2 - T_ambient)\nQ = 1.25 * exp(-k * t) - 0.25 * exp(-5 * k * t)\nk = 1.2815 / (BodyWeight^0.625 * CorrectionFactor) - 0.0284' },
98
+ { type: 'paragraph', html: 'Professor Claus Henssge developed a two exponential equation that accounts for both the surface cooling gradient and deep core retention. The normalized thermal quotient Q describes the fraction of heat remaining relative to the ambient baseline. Solving this transcendental equation for time yields an accurate mathematical estimate of hours elapsed.' },
99
+ { type: 'title', text: 'Key Environmental and Physiological Correction Factors', level: 3 },
100
+ { type: 'paragraph', html: 'Heat transfer rate depends heavily on body mass, air convection, and surface insulation. In the Henssge nomogram system, body weight is adjusted through a multiplication factor known as the corrective factor.' },
101
+ { type: 'table', headers: ['Scene Condition', 'Factor Value', 'Physical Mechanism'], rows: [
102
+ ['Naked in still room air', '1.0', 'Standard baseline radiation and natural convection'],
103
+ ['Light clothing (1-2 layers)', '1.1', 'Mild reduction in skin convective heat loss'],
104
+ ['Standard indoor clothing', '1.2', 'Moderate thermal barrier on torso and extremities'],
105
+ ['Heavy winter garments', '1.4', 'Significant insulation trapping warm air layer'],
106
+ ['Under thick down duvet in bed', '1.8', 'High insulation and delayed thermal dissipation'],
107
+ ['Submerged in still water', '0.5', 'Water thermal conductivity is 24 times greater than air'],
108
+ ['Submerged in flowing cold water', '0.35', 'Forced convective liquid heat transfer accelerated']
109
+ ] },
110
+ { type: 'title', text: 'Thermodynamic Phases of Postmortem Cooling', level: 3 },
111
+ { type: 'comparative', columns: 2, items: [
112
+ { title: 'The Postmortem Temperature Plateau', description: 'During the first 1 to 3 hours after death, core rectal temperature drops very slowly while the skin and outer tissues cool first.', points: ['Core to surface gradient establishing', 'Linear formulas underestimate PMI here', 'Correctly modeled by the -0.25 exp(-5kt) term'] },
113
+ { title: 'The Rapid Exponential Descent', description: 'Once the gradient is established, heat transfers continuously from core to environment at a rate determined by body mass and delta T.', highlight: true, points: ['Highest mathematical sensitivity', 'Narrowest statistical confidence interval', 'Optimal window for thermometric precision'] }
114
+ ] },
115
+ { type: 'title', text: 'Best Practices for Forensic Temperature Recording', level: 3 },
116
+ { type: 'list', items: [
117
+ '<strong>Measure deep core rectal temperature:</strong> insert a calibrated digital thermistor probe at least 8 to 10 cm into the rectum.',
118
+ '<strong>Record ambient temperature at the corpse level:</strong> measure room or ground air temperature within 10 cm of the body.',
119
+ '<strong>Document environmental stability:</strong> verify if heating, air conditioning, open windows, or sunlight altered the scene ambient temperature.',
120
+ '<strong>Assess clothing wetness:</strong> wet textiles drastically increase evaporative cooling and require lower corrective factor values.'
121
+ ] },
122
+ { type: 'summary', title: 'Methodological Summary', items: [
123
+ 'The Henssge nomogram is the internationally accepted standard for thermometric death time estimation.',
124
+ 'Always report a time window with standard deviation margins rather than an isolated point in time.',
125
+ 'Combine thermometric findings with rigor mortis, livor mortis, and supravital excitability testing for robust case reconstruction.'
126
+ ] }
127
+ ],
128
+ faq,
129
+ bibliography,
130
+ howTo,
131
+ schemas: [
132
+ { '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: title, description, applicationCategory: 'ForensicApplication', operatingSystem: 'Any' },
133
+ { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) },
134
+ { '@context': 'https://schema.org', '@type': 'HowTo', name: title, step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) }
135
+ ]
136
+ };
@@ -0,0 +1,136 @@
1
+ import { bibliography } from '../bibliography';
2
+ import type { TimeOfDeathAlgorMortisLocaleContent } from '../entry';
3
+
4
+ const slug = 'calculadora-hora-muerte-algor-mortis';
5
+ const title = 'Calculadora de Hora de Muerte por Algor Mortis';
6
+ const description = 'Estima el intervalo post mortem y la hora probable de fallecimiento mediante el nomograma termométrico de Henssge y el enfriamiento cadavérico.';
7
+
8
+ const howTo = [
9
+ { name: 'Introduce las temperaturas rectal y ambiente', text: 'Ingresa la temperatura rectal profunda del cadáver y la temperatura ambiente del lugar de los hechos.' },
10
+ { name: 'Configura la masa corporal y el factor ambiental', text: 'Indica el peso del individuo y selecciona el factor de corrección según la vestimenta, mantas o inmersión en agua.' },
11
+ { name: 'Indica la hora de la toma térmica', text: 'Introduce la hora exacta de la medición o haz clic en Hora actual para calcular retrospectivamente.' },
12
+ { name: 'Analiza el IPM y la curva de enfriamiento', text: 'Consulta el intervalo post mortem estimado, la ventana horaria con 95 por ciento de confianza y la gráfica térmica.' }
13
+ ];
14
+
15
+ const faq = [
16
+ { question: '¿Qué es el Algor Mortis en medicina legal y forense?', answer: 'El Algor Mortis es el proceso biofísico de pérdida de temperatura corporal que experimenta un cadáver tras el cese circulatorio hasta equilibrarse con el ambiente.' },
17
+ { question: '¿Por qué se prefiere el nomograma de Henssge frente a reglas lineales?', answer: 'Porque modela con precisión la meseta térmica inicial de las primeras horas y el decaimiento bi exponencial ajustado al peso y la vestimenta.' },
18
+ { question: '¿Qué precisión tiene la estimación termométrica del fallecimiento?', answer: 'En condiciones estándar controladas, el intervalo de confianza al 95 por ciento es de aproximadamente más o menos 2.8 horas durante las primeras diez horas.' },
19
+ { question: '¿En qué consiste la meseta térmica post mortem inicial?', answer: 'Es el periodo inicial de una a tres horas tras el deceso en el que la temperatura rectal apenas desciende mientras se establece el gradiente térmico hacia la piel.' }
20
+ ];
21
+
22
+ export const content: TimeOfDeathAlgorMortisLocaleContent = {
23
+ slug,
24
+ title,
25
+ description,
26
+ ui: {
27
+ title,
28
+ subtitle: 'Estimador del Intervalo Post Mortem y Nomograma de Enfriamiento',
29
+ disclaimer: 'Simulación académica y formativa. Las conclusiones periciales reales exigen autopsia judicial, análisis de livideces y rigidez cadavérica y registro ambiental verificado.',
30
+ unitSystemLabel: 'Sistema de unidades',
31
+ unitMetricLabel: 'Métrico',
32
+ unitImperialLabel: 'Imperial',
33
+ presetsHeader: 'Escenarios forenses predefinidos',
34
+ presetCustom: 'Parámetros personalizados',
35
+ presetNakedCalm: 'Desnudo en habitación calma (20°C)',
36
+ presetDressedIndoor: 'Vestido en interior (19.5°C)',
37
+ presetWinterOutdoor: 'Exterior en invierno (4°C)',
38
+ presetSubmergedWater: 'Sumergido en agua calma (12°C)',
39
+ presetHeavyDuvet: 'Bajo edredón grueso en cama (18°C)',
40
+ inputsHeader: 'Mediciones térmicas y parámetros del escenario',
41
+ rectalTempLabel: 'Temp. rectal profunda',
42
+ ambientTempLabel: 'Temp. ambiente',
43
+ bodyWeightLabel: 'Peso corporal',
44
+ factorLabel: 'Factor de corrección ambiental',
45
+ measurementTimeLabel: 'Hora de la medición',
46
+ factorNaked: 'Desnudo en aire quieto',
47
+ factorLightClothes: 'Ropa ligera (1-2 capas)',
48
+ factorStandardClothes: 'Ropa estándar (3-4 capas)',
49
+ factorHeavyWinter: 'Ropa térmica de invierno',
50
+ factorLightBlanket: 'Cama con sábana o manta ligera',
51
+ factorHeavyDuvet: 'Cama con edredón nórdico grueso',
52
+ factorStillWater: 'Sumergido en agua estancada',
53
+ factorFlowingWater: 'Sumergido en agua corriente fría',
54
+ factorWetClothing: 'Ropa mojada con viento',
55
+ factorMovingAir: 'Aire en movimiento con ventilador',
56
+ resultsHeader: 'Análisis del intervalo post mortem',
57
+ estimatedPmiLabel: 'Tiempo estimado desde la muerte',
58
+ deathWindowLabel: 'Ventana horaria de defunción',
59
+ confidenceMarginLabel: 'Margen de confianza (95%)',
60
+ coolingPhaseLabel: 'Fase termodinámica',
61
+ coolingRateLabel: 'Tasa instantánea de pérdida térmica',
62
+ glaisterEstimateLabel: 'Comparativa con regla de Glaister',
63
+ chartHeader: 'Trayectoria de enfriamiento bi exponencial de Henssge',
64
+ chartXAxis: 'Horas post mortem',
65
+ chartYAxis: 'Temperatura central',
66
+ chartNowMarker: 'Medición registrada',
67
+ chartPlateauMarker: 'Meseta inicial',
68
+ phasePlateau: 'Fase de meseta',
69
+ phaseDescent: 'Descenso exponencial',
70
+ phaseEquilibrium: 'Equilibrio térmico',
71
+ phaseHyperthermia: 'Alerta por hipertermia previa',
72
+ hoursUnit: 'horas',
73
+ minutesUnit: 'min',
74
+ celsiusUnit: '°C',
75
+ fahrenheitUnit: '°F',
76
+ kgUnit: 'kg',
77
+ lbUnit: 'lb',
78
+ celsiusPerHour: '°C/h',
79
+ fahrenheitPerHour: '°F/h',
80
+ resetBtn: 'Restablecer',
81
+ nowBtn: 'Hora actual',
82
+ coreThermometerLabel: 'Temperatura central',
83
+ baselineAmbientLabel: 'Límite ambiental',
84
+ referenceBodyTempLabel: 'Referencia corporal'
85
+ },
86
+ seo: [
87
+ { type: 'title', text: 'Fundamentos del Enfriamiento Cadavérico y Estimación de la Hora de Muerte', level: 2 },
88
+ { type: 'paragraph', html: 'La determinación del intervalo post mortem o IPM representa uno de los objetivos esenciales de la tanatología forense. El <strong>Algor Mortis</strong> describe el enfriamiento progresivo del cuerpo humano tras el paro cardiopulmonar irreversible hasta alcanzar la temperatura del entorno. Mediante la termometría profunda y leyes físicas de disipación de calor, los médicos legistas pueden reconstruir con base científica la franja horaria en la que aconteció la muerte.' },
89
+ { type: 'diagnostic', variant: 'info', title: 'Comportamiento Termodinámico Cadavérico', html: 'El descenso térmico no es una línea recta constante desde el primer minuto. Presenta una demora inicial denominada <em>meseta térmica</em>, seguida de una etapa de caída exponencial pronunciada y una asíntota suave cuando el cuerpo se aproxima al equilibrio ambiental.' },
90
+ { type: 'stats', columns: 3, items: [
91
+ { value: '37.2°C', label: 'Referencia rectal normotérmica' },
92
+ { value: '±2.8 h', label: 'Margen estadístico al 95%' },
93
+ { value: 'Bi Exponencial', label: 'Modelo matemático de Henssge' }
94
+ ] },
95
+ { type: 'title', text: 'La Ecuación Bi Exponencial de Claus Henssge', level: 3 },
96
+ { type: 'paragraph', html: 'Históricamente se recurría a aproximaciones lineales como la regla de Glaister, que calculaba una pérdida fija cercana a 0.83 grados Celsius por hora. No obstante, las fórmulas lineales carecen de precisión al ignorar la masa corporal, el aislamiento textil o el fenómeno de la meseta térmica inicial.' },
97
+ { type: 'code', ariaLabel: 'Ecuación de Henssge', code: 'Q = (T_rectal - T_ambiente) / (37.2 - T_ambiente)\nQ = 1.25 * exp(-k * t) - 0.25 * exp(-5 * k * t)\nk = 1.2815 / (PesoCorporal^0.625 * FactorCorreccion) - 0.0284' },
98
+ { type: 'paragraph', html: 'El profesor Claus Henssge formuló un modelo matemático de dos exponenciales que contempla tanto el gradiente de disipación superficial como la retención de energía del núcleo visceral. La resolución de esta ecuación permite obtener el tiempo transcurrido con un alto grado de fiabilidad estadística.' },
99
+ { type: 'title', text: 'Factores de Corrección Ambientales y de Vestimenta', level: 3 },
100
+ { type: 'paragraph', html: 'La transferencia de calor varía drásticamente según la superficie de contacto, la convección del aire y las capas de abrigo que protegen el torso del individuo.' },
101
+ { type: 'table', headers: ['Condición del Escenario', 'Factor Cf', 'Efecto Físico'], rows: [
102
+ ['Desnudo en aire quieto', '1.0', 'Disipación estándar por radiación y convección natural'],
103
+ ['Ropa ligera interior (1-2 capas)', '1.1', 'Atenuación leve de la pérdida superficial cutánea'],
104
+ ['Ropa estándar de calle (3-4 capas)', '1.2', 'Barrera térmica moderada sobre torso y extremidades'],
105
+ ['Prendas gruesas de abrigo de invierno', '1.4', 'Aislamiento elevado que atrapa aire caliente'],
106
+ ['Bajo edredón nórdico grueso en cama', '1.8', 'Alta retención calórica y retraso del enfriamiento'],
107
+ ['Sumergido en agua estancada', '0.5', 'Conductividad térmica del agua 24 veces superior al aire'],
108
+ ['Sumergido en agua corriente fría', '0.35', 'Convección forzada acelerada por flujo líquido']
109
+ ] },
110
+ { type: 'title', text: 'Fases Termodinámicas del Proceso Tanatológico', level: 3 },
111
+ { type: 'comparative', columns: 2, items: [
112
+ { title: 'Meseta Térmica Post Mortem', description: 'Durante las primeras 1 a 3 horas, la temperatura central rectal desciende muy lentamente mientras los tejidos periféricos ceden calor.', points: ['Establecimiento del gradiente centro a periferia', 'Las fórmulas lineales infraestiman el tiempo aquí', 'Modelada por el término correctivo -0.25 exp(-5kt)'] },
113
+ { title: 'Descenso Exponencial Rápido', description: 'Una vez establecido el gradiente térmico, el calor se transfiere de forma constante a un ritmo dependiente del peso corporal.', highlight: true, points: ['Máxima sensibilidad analítica', 'Margen de incertidumbre estadística más estrecho', 'Ventana óptima para la termometría forense'] }
114
+ ] },
115
+ { type: 'title', text: 'Buenas Prácticas Periciales en la Medición de Temperatura', level: 3 },
116
+ { type: 'list', items: [
117
+ '<strong>Medir temperatura rectal profunda:</strong> introducir la sonda termométrica calibrada al menos 8 a 10 cm en la ampolla rectal.',
118
+ '<strong>Registrar la temperatura ambiente junto al cuerpo:</strong> colocar el termómetro a no más de 10 cm del cadáver.',
119
+ '<strong>Comprobar la estabilidad del entorno:</strong> registrar si hubo calefacción encendida, ventanas abiertas o exposición solar directa.',
120
+ '<strong>Evaluar humedad en textiles:</strong> la ropa húmeda incrementa drásticamente la evaporación y exige factores menores.'
121
+ ] },
122
+ { type: 'summary', title: 'Resumen Metodológico', items: [
123
+ 'El nomograma de Henssge es el estándar internacionalmente validado para la estimación termométrica de la data de la muerte.',
124
+ 'Siempre debe informarse un intervalo horario con márgenes de desviación típica y no una hora aislada fija.',
125
+ 'Conviene correlacionar la termometría con el examen de rigidez cadavérica, livideces y excitabilidad eléctrica muscular.'
126
+ ] }
127
+ ],
128
+ faq,
129
+ bibliography,
130
+ howTo,
131
+ schemas: [
132
+ { '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: title, description, applicationCategory: 'ForensicApplication', operatingSystem: 'Any' },
133
+ { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) },
134
+ { '@context': 'https://schema.org', '@type': 'HowTo', name: title, step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) }
135
+ ]
136
+ };