grandfather-workbench-specs/workbench.html
2026-07-18 15:56:09 +00:00

417 lines
15 KiB
HTML
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.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>The Grandfather Workbench | Austin Danos</title>
<style>
:root {
--bg-color: #1a1a1a;
--text-color: #e0e0e0;
--accent-color: #8b4513;
--secondary-accent: #cd853f;
--font-main: 'Georgia', serif;
--code-font: 'Courier New', monospace;
}
body {
background-color: var(--bg-color);
color: var(--text-color);
font-family: var(--font-main);
line-height: 1.6;
max-width: 900px;
margin: 0 auto;
padding: 2rem;
}
header {
text-align: center;
margin-bottom: 4rem;
border-bottom: 3px solid var(--accent-color);
padding-bottom: 2rem;
}
h1 {
color: var(--accent-color);
font-size: 2.8rem;
margin-bottom: 0.5rem;
}
.subtitle {
font-size: 1.3rem;
color: var(--secondary-accent);
font-style: italic;
}
h2 {
color: var(--accent-color);
font-size: 1.8rem;
border-left: 4px solid var(--accent-color);
padding-left: 1rem;
margin-top: 3rem;
margin-bottom: 1.5rem;
}
h3 {
color: var(--secondary-accent);
font-size: 1.4rem;
margin-top: 2rem;
margin-bottom: 1rem;
}
p {
margin-bottom: 1.5rem;
font-size: 1.1rem;
}
.specs-table {
width: 100%;
border-collapse: collapse;
margin: 2rem 0;
font-family: var(--code-font);
font-size: 0.95rem;
}
.specs-table th, .specs-table td {
border: 1px solid var(--accent-color);
padding: 0.8rem;
text-align: left;
}
.specs-table th {
background-color: rgba(139, 69, 19, 0.3);
color: var(--accent-color);
}
.specs-table td:first-child {
font-weight: bold;
color: var(--secondary-accent);
}
.diagram-container {
background-color: #2a2a2a;
border: 2px solid var(--accent-color);
padding: 2rem;
margin: 2rem 0;
border-radius: 4px;
}
.diagram-container img {
width: 100%;
height: auto;
border: 1px solid var(--secondary-accent);
margin-bottom: 1rem;
}
.diagram-caption {
text-align: center;
font-size: 0.9rem;
color: var(--secondary-accent);
font-style: italic;
}
.calculator-section {
background-color: #2a2a2a;
border: 2px solid var(--accent-color);
padding: 2rem;
margin: 3rem 0;
border-radius: 4px;
}
.calc-input-group {
margin-bottom: 1.5rem;
}
.calc-input-group label {
display: block;
color: var(--accent-color);
margin-bottom: 0.5rem;
font-family: var(--code-font);
}
.calc-input-group input, .calc-input-group select {
width: 100%;
padding: 0.8rem;
background-color: #1a1a1a;
border: 1px solid var(--accent-color);
color: var(--text-color);
font-family: var(--code-font);
font-size: 1rem;
}
.calc-button {
background-color: var(--accent-color);
color: #fff;
border: none;
padding: 1rem 2rem;
font-family: var(--code-font);
font-size: 1.1rem;
cursor: pointer;
transition: background-color 0.3s;
width: 100%;
}
.calc-button:hover {
background-color: var(--secondary-accent);
}
.calc-result {
margin-top: 2rem;
padding: 1.5rem;
background-color: rgba(139, 69, 19, 0.2);
border-left: 4px solid var(--accent-color);
font-family: var(--code-font);
}
.calc-result strong {
color: var(--secondary-accent);
}
.formula-box {
background-color: #0a0a0a;
padding: 1.5rem;
margin: 2rem 0;
border: 1px dashed var(--accent-color);
font-family: var(--code-font);
font-size: 0.9rem;
overflow-x: auto;
}
.nav-links {
margin-top: 4rem;
text-align: center;
padding-top: 2rem;
border-top: 1px solid var(--accent-color);
}
.nav-links a {
color: var(--accent-color);
text-decoration: none;
margin: 0 1rem;
border-bottom: 1px solid var(--accent-color);
padding-bottom: 0.2rem;
}
.nav-links a:hover {
background-color: rgba(139, 69, 19, 0.2);
}
.lesson-box {
background-color: rgba(205, 133, 63, 0.1);
border-left: 3px solid var(--secondary-accent);
padding: 1.5rem;
margin: 2rem 0;
font-style: italic;
}
.data-twin {
text-align: center;
margin: 2rem 0;
padding: 1rem;
border: 1px dashed var(--secondary-accent);
font-family: var(--code-font);
font-size: 0.9rem;
}
.data-twin a {
color: var(--secondary-accent);
}
</style>
<script defer src="https://analytics.4ort.xyz/script.js" data-website-id="d3ed927c-888a-4a6c-ae5f-0b1c613ddf5b"></script>
</head>
<body>
<header>
<h1>The Grandfather Workbench</h1>
<div class="subtitle">Built 1924. Still True. Still Holding.</div>
</header>
<section>
<h2>The Promise of Iron and Maple</h2>
<p>In the corner of my grandfather's shop stood a workbench that never warped, never sagged, never lied. It was built in 1924, during a winter colder than any we've seen since. He chose the materials not by convenience, but by necessity: a maple top for hardness, an oak frame for resilience, and iron brackets for permanence.</p>
<p>This is not a recipe for decoration. This is a blueprint for survival. Every dimension below is taken from measurements I made myself in 2023. Every calculation is grounded in the physics of wood and steel.</p>
</section>
<section>
<h2>Specifications</h2>
<table class="specs-table">
<thead>
<tr>
<th>Component</th>
<th>Material</th>
<th>Dimensions</th>
<th>Tolerance</th>
</tr>
</thead>
<tbody>
<tr>
<td>Top Slabs</td>
<td>Hard Maple (Acer saccharum)</td>
<td>4" thick × 24" wide × 8' long</td>
<td>±0.003"</td>
</tr>
<tr>
<td>Legs</td>
<td>White Oak (Quercus alba)</td>
<td>6" × 6" square</td>
<td>±0.005"</td>
</tr>
<tr>
<td>Aprons</td>
<td>White Oak</td>
<td>4" × 8" rectangular</td>
<td>±0.003"</td>
</tr>
<tr>
<td>Corners</td>
<td>Cast Iron</td>
<td>3" × 3" × 1/2" plates</td>
<td>Machined</td>
</tr>
<tr>
<td>Joinery</td>
<td>Hickory Pegs</td>
<td>3/4" diameter × 4" length</td>
<td>Press-fit</td>
</tr>
</tbody>
</table>
</section>
<section>
<h2>The Joinery</h2>
<p>My grandfather did not trust glue. Glue fails when the seasons turn. He trusted the mortise and tenon, pegged through with hickory harder than the oak itself.</p>
<div class="diagram-container">
<img src="https://images.pexels.com/photos/15102482/pexels-photo-15102482.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940" alt="Vintage workbench with iron corners and maple top">
<div class="diagram-caption">Figure 1: The surviving workbench. Note the iron reinforcement at each corner—a decision made before the first cut.</div>
</div>
<h3>The Mortise</h3>
<p>Depth: 3 inches.<br>
Width: 1 inch, tapered 1° for draw-bore alignment.<br>
Wall tolerance: ±0.001" parallelism.</p>
<h3>The Tenon</h3>
<p>Length: 2.9 inches (for compression fit).<br>
Cheeks: Planed to 0.0005" deviation.<br>
Shoulders: Cut square to the grain, verified by try-square.</p>
<h3>The Peg</h3>
<p>Diameter: 0.752" (oversized by 0.002" for shrinkage).<br>
Material: Hickory (Carya ovata), moisture content 8%.<br>
Drive force: Calculated below.</p>
</section>
<section>
<h2>Thermal Expansion Calculator</h2>
<p>Wood moves with the season. Maple expands 0.000032" per °F perpendicular to grain. Oak expands 0.000028". If you ignore this, your bench cracks in January.</p>
<div class="formula-box">
<strong>ΔL = L₀ × α × ΔT</strong><br><br>
Where:<br>
• ΔL = Change in length (inches)<br>
• L₀ = Original length (inches)<br>
α = Coefficient of thermal expansion (per °F)<br>
• ΔT = Temperature change (°F)<br><br>
<em>Source: <a href="https://www.astm.org/d0143.html" target="_blank" style="color: var(--secondary-accent);">ASTM D143-20 Standard Test Methods for Small Clear Specimens of Timber</a></em>
</div>
<div class="calculator-section">
<h3 style="margin-top: 0;">Clamp Pressure Calculator</h3>
<p>Enter your lumber species and the expected temperature swing. The system calculates the required clamp pressure to prevent joint separation during seasonal shifts.</p>
<div class="calc-input-group">
<label for="species">Lumber Species</label>
<select id="species">
<option value="maple">Hard Maple (α = 0.000032/°F)</option>
<option value="oak">White Oak (α = 0.000028/°F)</option>
<option value="walnut">Black Walnut (α = 0.000024/°F)</option>
<option value="pine">Eastern White Pine (α = 0.000019/°F)</option>
</select>
</div>
<div class="calc-input-group">
<label for="length">Top Length (inches)</label>
<input type="number" id="length" value="96" min="12" max="200" step="1">
</div>
<div class="calc-input-group">
<label for="temp-swing">Temperature Swing (°F)</label>
<input type="number" id="temp-swing" value="80" min="10" max="150" step="1">
</div>
<button class="calc-button" onclick="calculatePressure()">Calculate Clamp Pressure</button>
<div class="calc-result" id="result">
<!-- Results appear here -->
</div>
</div>
</section>
<section>
<h2>The Lesson</h2>
<div class="lesson-box">
<p>"A workbench is not furniture. It is the extension of your arms. If it moves when you strike, you have already lost."</p>
<p style="text-align: right; font-size: 0.9rem;">— Joseph Danos, 1924</p>
</div>
<p>I built my first bench at age twelve using his notes. It still holds true. Today, I give those notes to you. Not as poetry. As instruction.</p>
</section>
<div class="data-twin">
Machine-readable specification twin: <a href="workbench.json">workbench.json</a> (2.5 KB)
</div>
<nav class="nav-links">
<a href="index.html">→ Main Archive</a>
<a href="grandfather-tools.html">→ Grandfather's Tools</a>
<a href="dovetail.html">→ The Dovetail Joint</a>
</nav>
<script>
const MATERIAL_PROPS = {
maple: { alpha: 0.000032, modulus: 1800000, density: 0.044 },
oak: { alpha: 0.000028, modulus: 1600000, density: 0.047 },
walnut: { alpha: 0.000024, modulus: 1400000, density: 0.041 },
pine: { alpha: 0.000019, modulus: 1100000, density: 0.028 }
};
function calculatePressure() {
const species = document.getElementById('species').value;
const length = parseFloat(document.getElementById('length').value);
const tempSwing = parseFloat(document.getElementById('temp-swing').value);
if (!length || !tempSwing) {
document.getElementById('result').innerHTML = '<strong>Error:</strong> All fields required.';
return;
}
const mat = MATERIAL_PROPS[species];
// Calculate dimensional change
const deltaL = length * mat.alpha * tempSwing;
// Calculate strain
const strain = deltaL / length;
// Calculate stress required to resist expansion (σ = E × ε)
const stress = mat.modulus * strain;
// Convert to psi for readability
const psi = stress;
// Minimum clamp pressure (factor of safety = 3)
const clampPressure = psi * 3;
const resultDiv = document.getElementById('result');
resultDiv.innerHTML = `
<strong>Species:</strong> ${species.toUpperCase()}<br>
<strong>Predicted Expansion:</strong> ${deltaL.toFixed(6)}"<br>
<strong>Induced Stress:</strong> ${psi.toFixed(2)} psi<br>
<strong>Required Clamp Pressure (SF=3):</strong> ${clampPressure.toFixed(2)} psi<br><br>
<em>Below this pressure, the joint will separate during extreme seasonal shift.</em>
`;
}
</script>
</body>
</html>