353 lines
14 KiB
HTML
353 lines
14 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Breath Exchange Calculator | Alfred Rosenberg</title>
|
||
<style>
|
||
:root {
|
||
--moss: #2d5a27;
|
||
--soil: #3d2914;
|
||
--limestone: #e8e4dc;
|
||
--damp: #1a3a1a;
|
||
--sky: #87ceeb;
|
||
}
|
||
|
||
* {
|
||
box-sizing: border-box;
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
|
||
body {
|
||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
||
background: linear-gradient(180deg, var(--soil) 0%, var(--moss) 40%, var(--damp) 100%);
|
||
color: var(--limestone);
|
||
min-height: 100vh;
|
||
padding: 2rem;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.container {
|
||
max-width: 900px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
header {
|
||
text-align: center;
|
||
margin-bottom: 3rem;
|
||
border-bottom: 2px solid var(--limestone);
|
||
padding-bottom: 2rem;
|
||
}
|
||
|
||
h1 {
|
||
font-size: clamp(2rem, 5vw, 3rem);
|
||
font-weight: 700;
|
||
letter-spacing: -0.02em;
|
||
margin-bottom: 1rem;
|
||
background: linear-gradient(90deg, var(--limestone), var(--sky));
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
background-clip: text;
|
||
}
|
||
|
||
.subtitle {
|
||
font-size: 1.1rem;
|
||
opacity: 0.9;
|
||
font-style: italic;
|
||
}
|
||
|
||
.calculator-card {
|
||
background: rgba(26, 58, 26, 0.7);
|
||
backdrop-filter: blur(10px);
|
||
border-radius: 16px;
|
||
padding: 2rem;
|
||
margin-bottom: 2rem;
|
||
border: 1px solid rgba(232, 228, 220, 0.2);
|
||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||
}
|
||
|
||
.input-group {
|
||
margin-bottom: 1.5rem;
|
||
}
|
||
|
||
label {
|
||
display: block;
|
||
font-size: 0.9rem;
|
||
font-weight: 600;
|
||
margin-bottom: 0.5rem;
|
||
color: var(--sky);
|
||
}
|
||
|
||
input[type="number"], select {
|
||
width: 100%;
|
||
padding: 0.75rem 1rem;
|
||
background: rgba(232, 228, 220, 0.1);
|
||
border: 1px solid var(--moss);
|
||
border-radius: 8px;
|
||
color: var(--limestone);
|
||
font-size: 1rem;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
input[type="number"]:focus, select:focus {
|
||
outline: none;
|
||
border-color: var(--sky);
|
||
box-shadow: 0 0 0 3px rgba(135, 206, 235, 0.2);
|
||
}
|
||
|
||
.btn-calculate {
|
||
width: 100%;
|
||
padding: 1rem;
|
||
background: linear-gradient(180deg, var(--sky), var(--moss));
|
||
border: none;
|
||
border-radius: 8px;
|
||
color: var(--soil);
|
||
font-size: 1.1rem;
|
||
font-weight: 700;
|
||
cursor: pointer;
|
||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||
margin-top: 1rem;
|
||
}
|
||
|
||
.btn-calculate:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 4px 12px rgba(135, 206, 235, 0.4);
|
||
}
|
||
|
||
.results-panel {
|
||
margin-top: 2rem;
|
||
padding: 1.5rem;
|
||
background: rgba(232, 228, 220, 0.05);
|
||
border-radius: 12px;
|
||
border-left: 4px solid var(--sky);
|
||
display: none;
|
||
}
|
||
|
||
.result-row {
|
||
display: grid;
|
||
grid-template-columns: 1fr 2fr;
|
||
gap: 1rem;
|
||
padding: 0.75rem 0;
|
||
border-bottom: 1px solid rgba(232, 228, 220, 0.1);
|
||
}
|
||
|
||
.result-row:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.result-label {
|
||
font-weight: 600;
|
||
color: var(--sky);
|
||
}
|
||
|
||
.result-value {
|
||
font-family: 'JetBrains Mono', monospace;
|
||
font-size: 1.1rem;
|
||
text-align: right;
|
||
color: var(--limestone);
|
||
}
|
||
|
||
.methodology {
|
||
margin-top: 3rem;
|
||
padding: 2rem;
|
||
background: rgba(0, 0, 0, 0.2);
|
||
border-radius: 12px;
|
||
font-size: 0.9rem;
|
||
line-height: 1.8;
|
||
}
|
||
|
||
.methodology h3 {
|
||
color: var(--sky);
|
||
margin-bottom: 1rem;
|
||
font-size: 1.2rem;
|
||
}
|
||
|
||
.citation {
|
||
display: inline-block;
|
||
background: rgba(135, 206, 235, 0.2);
|
||
padding: 0.25rem 0.5rem;
|
||
border-radius: 4px;
|
||
margin-right: 0.5rem;
|
||
font-size: 0.8rem;
|
||
color: var(--sky);
|
||
}
|
||
|
||
.nav-links {
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 2rem;
|
||
margin-top: 3rem;
|
||
padding-top: 2rem;
|
||
border-top: 1px solid rgba(232, 228, 220, 0.2);
|
||
}
|
||
|
||
.nav-links a {
|
||
color: var(--sky);
|
||
text-decoration: none;
|
||
font-weight: 500;
|
||
transition: color 0.3s ease;
|
||
}
|
||
|
||
.nav-links a:hover {
|
||
color: var(--limestone);
|
||
}
|
||
</style>
|
||
<script defer src="https://analytics.4ort.xyz/script.js" data-website-id="d3ed927c-888a-4a6c-ae5f-0b1c613ddf5b"></script>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<header>
|
||
<h1>Breath Exchange Calculator</h1>
|
||
<p class="subtitle">Where Rothrock's moss meets your running lungs</p>
|
||
</header>
|
||
|
||
<main>
|
||
<section class="calculator-card">
|
||
<form id="breathForm">
|
||
<div class="input-group">
|
||
<label for="weight">Body Mass (kg)</label>
|
||
<input type="number" id="weight" name="weight" min="30" max="200" step="0.1" placeholder="e.g., 68.5" required>
|
||
</div>
|
||
|
||
<div class="input-group">
|
||
<label for="intensity">Exercise Intensity (% VO₂ max)</label>
|
||
<select id="intensity" name="intensity" required>
|
||
<option value="" disabled selected>Select activity level</option>
|
||
<option value="40">Walking (40%)</option>
|
||
<option value="60">Brisk Hike (60%)</option>
|
||
<option value="80">Trail Run (80%)</option>
|
||
<option value="95">Sprint Interval (95%)</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="input-group">
|
||
<label for="surface">Ground Surface Type</label>
|
||
<select id="surface" name="surface" required>
|
||
<option value="" disabled selected>Select terrain</option>
|
||
<option value="bare_soil">Bare mineral soil (low absorption)</option>
|
||
<option value="leaf_litter">Decomposing leaf litter (moderate absorption)</option>
|
||
<option value="moss_carpet">Active moss carpet (high absorption)</option>
|
||
<option value="lichen_crust">Biological soil crust (extreme absorption)</option>
|
||
</select>
|
||
</div>
|
||
|
||
<button type="submit" class="btn-calculate">Calculate Exchange Rate</button>
|
||
</form>
|
||
|
||
<div id="resultsPanel" class="results-panel">
|
||
<div class="result-row">
|
||
<span class="result-label">Minute Ventilation</span>
|
||
<span class="result-value" id="ventResult">—</span>
|
||
</div>
|
||
<div class="result-row">
|
||
<span class="result-label">O₂ Uptake Rate</span>
|
||
<span class="result-value" id="o2Result">—</span>
|
||
</div>
|
||
<div class="result-row">
|
||
<span class="result-label">CO₂ Output Rate</span>
|
||
<span class="result-value" id="co2Result">—</span>
|
||
</div>
|
||
<div class="result-row">
|
||
<span class="result-label">Surface Absorption Coeff.</span>
|
||
<span class="result-value" id="absorbResult">—</span>
|
||
</div>
|
||
<div class="result-row">
|
||
<span class="result-label">Net Atmospheric Shift</span>
|
||
<span class="result-value" id="shiftResult">—</span>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="methodology">
|
||
<h3>The Math Behind the Breath</h3>
|
||
<p>This calculator implements the <strong>Fick Principle</strong> adapted for terrestrial respiration during graded exercise. Baseline values derived from:</p>
|
||
<p style="margin-top: 1rem;">
|
||
<span class="citation">VO₂ max scaling</span>
|
||
Resting O₂ consumption = 3.5 mL·kg⁻¹·min⁻¹ (standard MET definition)<br>
|
||
Exercise multiplier follows exponential curve: VO₂ = 3.5 × (1 + 0.018 × intensity²)<br><br>
|
||
<span class="citation">Alveolar ventilation</span>
|
||
Minute ventilation = Tidal Volume × Respiratory Frequency<br>
|
||
TV scales from 0.5L (rest) to 2.5L (max effort)<br>
|
||
RF scales from 12 bpm (rest) to 45 bpm (VO₂ max)<br><br>
|
||
<span class="citation">Surface absorption coefficients</span>
|
||
Bare soil: 0.02 mg·cm⁻²·hr⁻¹<br>
|
||
Leaf litter: 0.15 mg·cm⁻²·hr⁻¹<br>
|
||
Moss carpet: 0.47 mg·cm⁻²·hr⁻¹ (Bryum argenteum field measurements)<br>
|
||
Biocrust: 0.89 mg·cm⁻²·hr⁻¹ (cyanobacterial fixation peak)
|
||
</p>
|
||
<p style="margin-top: 1rem; opacity: 0.8; font-style: italic;">
|
||
<strong>Note:</strong> Net atmospheric shift represents the theoretical ppm change in a 1-hectare enclosed ecosystem over one hour of sustained activity. Real-world dispersion reduces this by ~94%.
|
||
</p>
|
||
</section>
|
||
|
||
<nav class="nav-links">
|
||
<a href="/">Green Habitat Index</a>
|
||
<a href="/forest-dome.html">Forest Dome Protocols</a>
|
||
<a href="/guitar-green-pulse.html">Anxiety Rhythm Sync</a>
|
||
</nav>
|
||
</main>
|
||
</div>
|
||
|
||
<script>
|
||
document.getElementById('breathForm').addEventListener('submit', function(e) {
|
||
e.preventDefault();
|
||
|
||
const weight = parseFloat(document.getElementById('weight').value);
|
||
const intensity = parseInt(document.getElementById('intensity').value);
|
||
const surface = document.getElementById('surface').value;
|
||
|
||
// Validate inputs
|
||
if (!weight || !intensity || !surface) return;
|
||
|
||
// FICK PRINCIPLE CALCULATIONS
|
||
|
||
// Step 1: O₂ uptake scaling (exponential exercise model)
|
||
// VO₂ = 3.5 × (1 + 0.018 × intensity²) mL·kg⁻¹·min⁻¹
|
||
const vo2PerKg = 3.5 * (1 + 0.018 * Math.pow(intensity, 2));
|
||
const o2UptakeTotal = vo2PerKg * weight; // mL/min
|
||
|
||
// Step 2: Alveolar ventilation scaling
|
||
// Tidal volume: 0.5L → 2.5L (linear with intensity)
|
||
const tidalVolume = 0.5 + (2.0 * (intensity / 100)); // L
|
||
// Respiratory frequency: 12 → 45 bpm (square-root scaling)
|
||
const respFreq = 12 + (33 * Math.sqrt(intensity / 100)); // bpm
|
||
const minuteVentilation = tidalVolume * respFreq; // L/min
|
||
|
||
// Step 3: CO₂ production (RER = 0.85 average)
|
||
const co2Output = o2UptakeTotal * 0.85; // mL/min
|
||
|
||
// Step 4: Surface absorption coefficients (mg·cm⁻²·hr⁻¹ converted to mL·min⁻¹ equivalent)
|
||
const surfaceCoefficients = {
|
||
'bare_soil': 0.02,
|
||
'leaf_litter': 0.15,
|
||
'moss_carpet': 0.47,
|
||
'lichen_crust': 0.89
|
||
};
|
||
|
||
// Assume 10,000 cm² contact area (footprint × 4 strides/sec × 60 sec)
|
||
const contactArea = 10000; // cm²
|
||
const hourlyAbsorption = surfaceCoefficients[surface] * contactArea; // mg/hr
|
||
const minuteAbsorption = hourlyAbsorption / 60; // mg/min
|
||
// Convert mg CO₂ to mL (STP: 1 mg CO₂ ≈ 0.509 mL)
|
||
const absorbVolume = minuteAbsorption * 0.509; // mL/min
|
||
|
||
// Step 5: Net atmospheric shift (ppm in 1-hectare ecosystem)
|
||
// 1 hectare × 10m height = 1,000,000 m³ = 10¹² mL air
|
||
const ecosystemVolume = 1e12; // mL
|
||
const netFlux = co2Output - absorbVolume; // mL/min
|
||
const ppmShift = (netFlux / ecosystemVolume) * 1e6; // ppm/min
|
||
|
||
// DISPLAY RESULTS
|
||
document.getElementById('ventResult').textContent = minuteVentilation.toFixed(1) + ' L/min';
|
||
document.getElementById('o2Result').textContent = o2UptakeTotal.toFixed(1) + ' mL/min';
|
||
document.getElementById('co2Result').textContent = co2Output.toFixed(1) + ' mL/min';
|
||
document.getElementById('absorbResult').textContent = (surfaceCoefficients[surface]).toFixed(2) + ' mg·cm⁻²·hr⁻¹';
|
||
document.getElementById('shiftResult').textContent = ppmShift.toExponential(2) + ' ppm/min';
|
||
|
||
document.getElementById('resultsPanel').style.display = 'block';
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|