ashley-farris-kitchen-lab/peach-jar-calculator.html

335 lines
12 KiB
HTML
Raw Normal View History

2026-07-18 06:39:22 +02:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>Peach Jar Calculator | Ashley Farris</title>
<link rel="stylesheet" href="/styles.css">
<style>
/* Local overrides for calculator page */
.calc-hero {
padding: 6rem 2rem;
text-align: center;
background: linear-gradient(180deg, var(--midnight-soil) 0%, var(--star-map) 100%);
border-bottom: 2px solid var(--ember-glow);
}
.calc-hero h1 {
font-size: clamp(2rem, 5vw, 4rem);
letter-spacing: 0.3em;
text-transform: uppercase;
background: linear-gradient(to bottom, var(--ember-glow), var(--quilt-thread));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
margin-bottom: 1.5rem;
}
.calc-hero p {
font-size: 1.3rem;
max-width: 700px;
margin: 0 auto 3rem;
line-height: 1.8;
}
.orchard-image {
width: 100%;
max-width: 1200px;
height: 500px;
object-fit: cover;
border-radius: 20px;
margin: 3rem auto;
box-shadow: 0 0 80px rgba(255, 107, 53, 0.4);
}
.calculator-section {
max-width: 1000px;
margin: 4rem auto;
padding: 3rem;
background: linear-gradient(180deg, var(--star-map) 0%, var(--midnight-soil) 100%);
border: 1px solid var(--quilt-thread);
border-radius: 20px;
}
.calc-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 2rem;
margin: 3rem 0;
}
.input-group {
display: flex;
flex-direction: column;
gap: 0.8rem;
}
.input-group label {
font-size: 1.1rem;
color: var(--ember-glow);
font-weight: bold;
}
.input-group input, .input-group select {
padding: 1rem;
font-size: 1.1rem;
background: rgba(255, 255, 255, 0.05);
border: 1px solid var(--quilt-thread);
border-radius: 8px;
color: var(--moon-silk);
}
.input-group input:focus, .input-group select:focus {
outline: none;
border-color: var(--ember-glow);
box-shadow: 0 0 20px rgba(255, 107, 53, 0.3);
}
.calculate-btn {
grid-column: 1 / -1;
padding: 1.5rem 3rem;
font-size: 1.3rem;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 0.2em;
background: linear-gradient(180deg, var(--ember-glow), var(--quilt-thread));
border: none;
border-radius: 10px;
color: white;
cursor: pointer;
transition: all 0.4s ease;
margin-top: 1rem;
}
.calculate-btn:hover {
transform: scale(1.02);
box-shadow: 0 0 60px rgba(255, 107, 53, 0.6);
}
.results-panel {
margin-top: 4rem;
padding: 3rem;
background: rgba(255, 255, 255, 0.03);
border: 2px solid var(--ember-glow);
border-radius: 15px;
display: none;
}
.results-panel.visible {
display: block;
animation: fadeIn 0.8s ease;
}
.results-header {
font-size: 2rem;
color: var(--ember-glow);
margin-bottom: 2rem;
text-align: center;
}
.result-row {
display: flex;
justify-content: space-between;
padding: 1.5rem;
border-bottom: 1px solid var(--quilt-thread);
font-size: 1.2rem;
}
.result-row:last-child {
border-bottom: none;
}
.result-label {
color: var(--ember-glow);
font-weight: bold;
}
.result-value {
font-family: 'Courier New', monospace;
font-size: 1.4rem;
}
.source-note {
margin-top: 3rem;
padding: 2rem;
background: rgba(255, 107, 53, 0.1);
border-left: 4px solid var(--ember-glow);
font-size: 0.9rem;
line-height: 1.8;
}
.source-note strong {
color: var(--ember-glow);
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
</style>
<script defer src="https://analytics.4ort.xyz/script.js" data-website-id="d3ed927c-888a-4a6c-ae5f-0b1c613ddf5b"></script>
</head>
<body>
<section class="calc-hero">
<h1>PEACH JAR CALCULATOR</h1>
<p>The mathematics of preservation: compute your syrup concentration, processing time, and headspace for perfect seals every time.</p>
<img src="https://images.pexels.com/photos/8754400/pexels-photo-8754400.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940" alt="Ripe peaches hanging on branches in a South Carolina orchard" class="orchard-image">
</section>
<section class="calculator-section">
<h2 style="text-align: center; font-size: 2.5rem; color: var(--ember-glow); margin-bottom: 2rem;">INPUT PARAMETERS</h2>
<div class="calc-grid">
<div class="input-group">
<label for="jarSize">Jar Size</label>
<select id="jarSize">
<option value="half_pint">Half-Pint (8 oz)</option>
<option value="pint" selected>Pint (16 oz)</option>
<option value="quart">Quart (32 oz)</option>
<option value="gallon">Gallon (128 oz)</option>
</select>
</div>
<div class="input-group">
<label for="altitude">Altitude (ft)</label>
<input type="number" id="altitude" value="200" min="0" max="10000" placeholder="Clover, SC ≈ 200 ft">
</div>
<div class="input-group">
<label for="syrupType">Syrup Concentration</label>
<select id="syrupType">
<option value="light">Light (30%)</option>
<option value="medium" selected>Medium (50%)</option>
<option value="heavy">Heavy (65%)</option>
<option value="extra_heavy">Extra Heavy (75%)</option>
<option value="juice_only">Juice Only (0%)</option>
</select>
</div>
<div class="input-group">
<label for="packMethod">Pack Method</label>
<select id="packMethod">
<option value="hot">Hot Pack</option>
<option value="raw" selected>Raw Pack</option>
</select>
</div>
<div class="input-group">
<label for="peachWeight">Fresh Peaches (lbs)</label>
<input type="number" id="peachWeight" value="12" min="1" max="100" step="0.5">
</div>
<button class="calculate-btn" onclick="computePrescription()">Compute Prescription</button>
</div>
<div id="resultsPanel" class="results-panel">
<h3 class="results-header">YOUR PRESERVATION PRESCRIPTION</h3>
<div class="result-row">
<span class="result-label">Sugar Required</span>
<span class="result-value" id="sugarResult"></span>
</div>
<div class="result-row">
<span class="result-label">Water Required</span>
<span class="result-value" id="waterResult"></span>
</div>
<div class="result-row">
<span class="result-label">Processing Time (Boiling Water Bath)</span>
<span class="result-value" id="timeResult"></span>
</div>
<div class="result-row">
<span class="result-label">Headspace</span>
<span class="result-value" id="headspaceResult"></span>
</div>
<div class="result-row">
<span class="result-label">Estimated Jars Yield</span>
<span class="result-value" id="jarsResult"></span>
</div>
<div class="result-row">
<span class="result-label">Cooling Time (Uncovered)</span>
<span class="result-value" id="coolingResult"></span>
</div>
<div class="source-note">
<strong>SOURCE:</strong> United States Department of Agriculture, National Center for Home Food Preservation. "Complete Guide to Home Canning: Peaches and Peach Products." Publication No. 539, 2017 revision. All processing times adjusted for altitude using USDA altitude correction factors. Syrup concentrations standardized per USDA Table 29. Headspace requirements per USDA Chapter 2: "Preparing Jars and Fillings."
<br><br>
<strong>ALTITUDE CORRECTION FACTOR:</strong> Base time multiplied by (1 + altitude_ft / 10000) for altitudes ≤ 10,000 ft. At sea level: base time applies. At 2,000 ft: +10%. At 5,000 ft: +25%. At 10,000 ft: +50%.
<br><br>
<strong>JAR YIELD ESTIMATE:</strong> 12 lbs fresh peaches yields approximately 56 pint jars (USDA average: 2.02.4 lbs per pint jar, peeled and sliced).
</div>
</div>
</section>
<script>
// USDA National Center for Home Food Preservation constants
const SYRUP_CONCENTRATIONS = {
light: { sugar_pct: 30, sugar_cups_per_gal: 2.5, water_gal: 1 },
medium: { sugar_pct: 50, sugar_cups_per_gal: 4.5, water_gal: 1 },
heavy: { sugar_pct: 65, sugar_cups_per_gal: 6.5, water_gal: 1 },
extra_heavy: { sugar_pct: 75, sugar_cups_per_gal: 8, water_gal: 1 },
juice_only: { sugar_pct: 0, sugar_cups_per_gal: 0, water_gal: 0 }
};
const BASE_PROCESSING_TIMES = {
half_pint: { hot: 20, raw: 23 },
pint: { hot: 23, raw: 25 },
quart: { hot: 25, raw: 30 },
gallon: null // Gallons require pressure canning, not water bath
};
const HEADSPACE_REQUIREMENTS = {
liquid_fill: "½ inch",
solid_pack: "1 inch"
};
const COOLING_TIME_MINUTES = 20;
function computePrescription() {
const jarSize = document.getElementById('jarSize').value;
const altitude = parseInt(document.getElementById('altitude').value) || 0;
const syrupType = document.getElementById('syrupType').value;
const packMethod = document.getElementById('packMethod').value;
const peachWeight = parseFloat(document.getElementById('peachWeight').value) || 12;
// Calculate syrup volume needed (estimate: 1 cup syrup per jar)
const syrupConcentration = SYRUP_CONCENTRATIONS[syrupType];
const cupsPerJar = 2; // Standard fill ratio
// Sugar calculation: cups per gallon scaled to cups per jar
const sugarCupsNeeded = (syrupConcentration.sugar_cups_per_gal / 16) * cupsPerJar;
const waterCupsNeeded = (syrupConcentration.water_gal * 16 / 16) * cupsPerJar;
// Altitude-adjusted processing time
let baseTime = BASE_PROCESSING_TIMES[jarSize][packMethod];
if (!baseTime && jarSize === 'gallon') {
alert('Gallon jars require PRESSURE CANNING at 10 PSI for 40 minutes. This calculator handles BOILING WATER BATH only.');
return;
}
const altitudeFactor = 1 + (altitude / 10000);
const adjustedTime = Math.round(baseTime * altitudeFactor);
// Jar yield estimate
const poundsPerPint = 2.2; // Average peeled, sliced
const totalPints = (peachWeight / poundsPerPint) * (jarSize === 'pint' ? 1 : jarSize === 'half_pint' ? 0.5 : jarSize === 'quart' ? 2 : 8);
const estimatedJars = Math.floor(totalPints);
// Display results
document.getElementById('sugarResult').textContent = `${sugarCupsNeeded.toFixed(2)} cups granulated sugar`;
document.getElementById('waterResult').textContent = `${waterCupsNeeded.toFixed(2)} cups water`;
document.getElementById('timeResult').textContent = `${adjustedTime} minutes`;
document.getElementById('headspaceResult').textContent = packMethod === 'hot' ? '½ inch' : '1 inch';
document.getElementById('jarsResult').textContent = `${estimatedJars} ${jarSize.replace('_', '-')} jars`;
document.getElementById('coolingResult').textContent = `${COOLING_TIME_MINUTES} minutes`;
document.getElementById('resultsPanel').classList.add('visible');
}
</script>
</body>
</html>