carmelina-rubio-site/surfactant-calculator.html
2026-07-18 13:45:33 +00:00

445 lines
13 KiB
HTML
Raw Permalink 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.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Critical Micelle Concentration Calculator | Carmelina Rubio</title>
<style>
:root {
--bg: #0a0e14;
--surface: #121821;
--border: #2a3544;
--text: #e8ecf1;
--accent: #4ade80;
--secondary: #60a5fa;
--error: #f87171;
--success: #22c55e;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.6;
padding: 2rem;
max-width: 1200px;
margin: 0 auto;
}
header {
border-bottom: 2px solid var(--accent);
padding-bottom: 1.5rem;
margin-bottom: 2rem;
}
h1 {
font-size: 2.5rem;
font-weight: 700;
letter-spacing: -0.02em;
margin-bottom: 0.5rem;
}
.subtitle {
color: var(--secondary);
font-size: 1.1rem;
font-weight: 500;
}
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
margin-top: 2rem;
}
@media (max-width: 900px) {
.grid { grid-template-columns: 1fr; }
}
.panel {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
padding: 1.5rem;
}
.panel h2 {
font-size: 1.4rem;
margin-bottom: 1rem;
color: var(--accent);
}
.input-group {
margin-bottom: 1.2rem;
}
label {
display: block;
font-size: 0.9rem;
font-weight: 600;
margin-bottom: 0.4rem;
color: #94a3b8;
}
input[type="number"], select {
width: 100%;
padding: 0.75rem 1rem;
background: #0a0e14;
border: 1px solid var(--border);
border-radius: 6px;
color: var(--text);
font-size: 1rem;
transition: border-color 0.2s;
}
input:focus, select:focus {
outline: none;
border-color: var(--accent);
}
.unit {
font-size: 0.8rem;
color: #64748b;
margin-left: 0.5rem;
}
button.calculate {
width: 100%;
padding: 1rem;
background: var(--accent);
color: #0a0e14;
border: none;
border-radius: 8px;
font-size: 1.1rem;
font-weight: 700;
cursor: pointer;
transition: transform 0.1s, filter 0.2s;
margin-top: 1rem;
}
button.calculate:hover {
filter: brightness(1.1);
transform: translateY(-2px);
}
button.calculate:active {
transform: translateY(0);
}
.result-panel {
position: relative;
}
.result-panel::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image: url('https://pixabay.com/get/g9ca99b935e14c9c5764e696b016bb92295d9e26bad48db74d14d31b2210d490a4368fc067d53d5fdcb0ae271f8a9e40a_1280.png');
background-size: cover;
background-position: center;
opacity: 0.03;
border-radius: 12px;
z-index: 0;
}
.result-content {
position: relative;
z-index: 1;
}
.metric {
background: rgba(74, 222, 128, 0.1);
border: 1px solid var(--accent);
border-radius: 8px;
padding: 1rem;
margin-bottom: 1rem;
}
.metric-label {
font-size: 0.85rem;
color: #94a3b8;
margin-bottom: 0.3rem;
}
.metric-value {
font-size: 2rem;
font-weight: 700;
color: var(--accent);
}
.metric-unit {
font-size: 1rem;
color: #64748b;
}
.warning {
background: rgba(248, 113, 113, 0.1);
border: 1px solid var(--error);
border-radius: 8px;
padding: 1rem;
margin-top: 1rem;
}
.warning-title {
color: var(--error);
font-weight: 600;
margin-bottom: 0.5rem;
}
.citation {
font-size: 0.8rem;
color: #64748b;
margin-top: 2rem;
padding-top: 1rem;
border-top: 1px solid var(--border);
}
.citation a {
color: var(--secondary);
text-decoration: none;
}
.citation a:hover {
text-decoration: underline;
}
.nav-links {
display: flex;
gap: 2rem;
margin-top: 1rem;
justify-content: center;
}
.nav-links a {
color: var(--secondary);
text-decoration: none;
font-weight: 500;
padding: 0.5rem 1rem;
border: 1px solid transparent;
border-radius: 6px;
transition: border-color 0.2s;
}
.nav-links a:hover {
border-color: var(--secondary);
}
.agent-twin {
background: rgba(96, 165, 250, 0.1);
border: 1px solid var(--secondary);
border-radius: 8px;
padding: 1rem;
margin-top: 1.5rem;
}
.agent-twin-title {
font-size: 0.9rem;
font-weight: 600;
color: var(--secondary);
margin-bottom: 0.5rem;
}
.agent-twin a {
color: var(--accent);
text-decoration: none;
font-family: monospace;
font-size: 0.85rem;
}
.agent-twin a:hover {
text-decoration: underline;
}
</style>
<script defer src="https://analytics.4ort.xyz/script.js" data-website-id="d3ed927c-888a-4a6c-ae5f-0b1c613ddf5b"></script>
</head>
<body>
<header>
<h1>Critical Micelle Concentration Calculator</h1>
<div class="subtitle">Optimal surfactant dosing for eco-efficient cleaning — grounded in physical chemistry</div>
<nav class="nav-links">
<a href="/">Home</a>
<a href="/first-clean.html">The First Clean</a>
<a href="/perfect-fold.html">The Perfect Fold</a>
<a href="/surfcatant-calculator.html" style="border-color: var(--accent); color: var(--accent);">CMC Calculator</a>
</nav>
</header>
<main class="grid">
<section class="panel">
<h2>🧪 Input Parameters</h2>
<div class="input-group">
<label for="surfactant-type">Surfactant Type</label>
<select id="surfactant-type">
<option value="sds">Sodium Lauryl Sulfate (SDS)</option>
<option value="las">Linear Alkylbenzene Sulfonate (LAS)</option>
<option value="betaine">Cocamidopropyl Betaine</option>
<option value="glucoside">Alkyl Polyglucoside (APG)</option>
<option value="custom">Custom Surfactant</option>
</select>
</div>
<div class="input-group">
<label for="cmc-base">Base CMC Value</label>
<input type="number" id="cmc-base" step="0.001" placeholder="Enter CMC in mM">
<span class="unit">(millimolar)</span>
</div>
<div class="input-group">
<label for="temperature">Ambient Temperature</label>
<input type="number" id="temperature" value="20" min="-40" max="100">
<span class="unit">(°C)</span>
</div>
<div class="input-group">
<label for="ionic-strength">Ionic Strength (Water Hardness)</label>
<input type="number" id="ionic-strength" value="0.01" step="0.001" min="0" max="1">
<span class="unit">(mol/L)</span>
</div>
<div class="input-group">
<label for="volume">Solution Volume</label>
<input type="number" id="volume" value="10" min="0.1" step="0.1">
<span class="unit">(liters)</span>
</div>
<button class="calculate" onclick="calculateCMC()">Calculate Optimal Concentration</button>
</section>
<section class="panel result-panel">
<div class="result-content">
<h2>📊 Results</h2>
<div class="metric">
<div class="metric-label">Critical Micelle Concentration (adjusted)</div>
<span class="metric-value" id="cmc-result"></span>
<span class="metric-unit">mM</span>
</div>
<div class="metric">
<div class="metric-label">Mass of Surfactant Required</div>
<span class="metric-value" id="mass-result"></span>
<span class="metric-unit">grams</span>
</div>
<div class="metric">
<div class="metric-label">Efficiency Factor</div>
<span class="metric-value" id="efficiency-result"></span>
<span class="metric-unit">% above CMC</span>
</div>
<div class="warning" id="warning-box" style="display:none;">
<div class="warning-title">⚠️ Below Threshold Warning</div>
<div id="warning-text"></div>
</div>
<div class="agent-twin">
<div class="agent-twin-title">🤖 Agent-Legible Twin</div>
<div>All constants, molecular weights, and formulas exposed for programmatic consumption:</div>
<br>
<a href="/surfactant-calculator.json" download>surfactant-calculator.json</a>
</div>
<div class="citation">
<strong>Grounded in:</strong>
<a href="https://wikidata.org/entity/Q607000" target="_blank">Wikidata Q607000</a> (Critical Micelle Concentration),
<a href="https://wikidata.org/entity/Q422241" target="_blank">Q422241</a> (Sodium Lauryl Sulfate),
<a href="https://wikidata.org/entity/Q1139139" target="_blank">Q1139139</a> (DebyeHückel Equation)
</div>
</div>
</section>
</main>
<script>
// Surfactant database with base CMC values (mM) and molecular weights (g/mol)
const SURFACTANTS = {
sds: { name: 'Sodium Lauryl Sulfate', cmc: 8.2, mw: 288.38 },
las: { name: 'Linear Alkylbenzene Sulfonate', cmc: 0.26, mw: 348.48 },
betaine: { name: 'Cocamidopropyl Betaine', cmc: 0.17, mw: 359.52 },
glucoside: { name: 'Alkyl Polyglucoside (APG)', cmc: 0.08, mw: 524.58 }
};
// Temperature correction factor (°C⁻¹)
const TEMP_COEFFICIENT = -0.02; // CMC decreases ~2% per °C increase
// Ionic strength screening effect (Debye-Hückel approximation)
const IONIC_SCREENING = 0.15; // Reduction factor per mol/L
function calculateCMC() {
// Gather inputs
const surfactantType = document.getElementById('surfactant-type').value;
const customCMC = parseFloat(document.getElementById('cmc-base').value);
const temperature = parseFloat(document.getElementById('temperature').value);
const ionicStrength = parseFloat(document.getElementById('ionic-strength').value);
const volume = parseFloat(document.getElementById('volume').value);
// Validate inputs
if (!volume || volume <= 0) {
alert('Please enter a valid solution volume.');
return;
}
// Get base surfactant data
let surfactantData;
if (surfactantType === 'custom') {
if (!customCMC || customCMC <= 0) {
alert('For custom surfactant, please enter a base CMC value.');
return;
}
surfactantData = { name: 'Custom Surfactant', cmc: customCMC, mw: 300 }; // Default MW
} else {
surfactantData = SURFACTANTS[surfactantType];
}
// Apply temperature correction: CMC(T) = CMC₀ × exp(k × ΔT)
const deltaT = temperature - 25; // Reference: 25°C
const tempAdjustedCMC = surfactantData.cmc * Math.exp(TEMP_COEFFICIENT * deltaT);
// Apply ionic strength screening (reduces CMC for ionic surfactants)
const ionicAdjustedCMC = tempAdjustedCMC * (1 - IONIC_SCREENING * ionicStrength);
// Calculate mass required (at CMC threshold)
// mass = CMC × MW × volume / 1000 (convert mM to M, then to moles, then to grams)
const massAtCMC = (ionicAdjustedCMC * surfactantData.mw * volume) / 1000;
// Efficiency factor: recommend operating at 1.5× CMC for robust micelle formation
const efficiencyFactor = 1.5;
const recommendedMass = massAtCMC * efficiencyFactor;
// Display results
document.getElementById('cmc-result').textContent = ionicAdjustedCMC.toFixed(3);
document.getElementById('mass-result').textContent = recommendedMass.toFixed(2);
document.getElementById('efficiency-result').textContent = ((efficiencyFactor - 1) * 100).toFixed(0);
// Check warning condition
const warningBox = document.getElementById('warning-box');
const warningText = document.getElementById('warning-text');
if (recommendedMass < massAtCMC * 0.9) {
warningBox.style.display = 'block';
warningText.textContent = `Current configuration falls below safe threshold. Increase surfactant mass by ${(1 - recommendedMass/massAtCMC)*100.toFixed(1)}% to ensure stable micelle formation.`;
} else {
warningBox.style.display = 'none';
}
}
// Auto-populate CMC when surfactant type changes
document.getElementById('surfactant-type').addEventListener('change', function() {
const type = this.value;
if (type !== 'custom') {
document.getElementById('cmc-base').value = SURFACTANTS[type].cmc.toFixed(3);
document.getElementById('cmc-base').readOnly = true;
} else {
document.getElementById('cmc-base').value = '';
document.getElementById('cmc-base').readOnly = false;
}
});
</script>
</body>
</html>