cognitive-load-toolkit/fixture-comparator.html

297 lines
11 KiB
HTML
Raw Permalink Normal View History

2026-07-18 20:02:40 +02:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Retail Fixture Stress Comparator | Britten Mintz</title>
<style>
:root {
--bg: #0f0f13;
--surface: #1a1a20;
--accent: #ff4d4d; /* Neon red */
--text: #e0e0e0;
--muted: #888899;
--grid-line: rgba(255, 77, 77, 0.1);
}
body {
background-color: var(--bg);
color: var(--text);
font-family: 'Inter', system-ui, -apple-system, sans-serif;
margin: 0;
padding: 2rem;
line-height: 1.6;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
}
header {
border-bottom: 1px solid var(--grid-line);
padding-bottom: 1.5rem;
margin-bottom: 2rem;
}
h1 {
font-size: 2.5rem;
letter-spacing: -0.05em;
margin: 0;
background: linear-gradient(90deg, #fff, var(--accent));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.subtitle {
color: var(--muted);
font-size: 1.1rem;
margin-top: 0.5rem;
}
.grid-layout {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
}
@media (max-width: 900px) {
.grid-layout { grid-template-columns: 1fr; }
}
.card {
background: var(--surface);
border: 1px solid rgba(255,255,255,0.05);
border-radius: 8px;
padding: 1.5rem;
}
label {
display: block;
font-size: 0.85rem;
color: var(--muted);
margin-bottom: 0.5rem;
text-transform: uppercase;
letter-spacing: 0.05em;
}
input, select {
width: 100%;
background: rgba(0,0,0,0.3);
border: 1px solid var(--grid-line);
color: white;
padding: 0.75rem;
border-radius: 4px;
font-family: monospace;
margin-bottom: 1.5rem;
box-sizing: border-box;
}
input:focus, select:focus {
outline: none;
border-color: var(--accent);
}
button {
background: var(--accent);
color: black;
border: none;
padding: 1rem 2rem;
font-weight: 700;
cursor: pointer;
text-transform: uppercase;
letter-spacing: 0.1em;
transition: all 0.2s;
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(255, 77, 77, 0.3);
}
.results-panel {
margin-top: 2rem;
}
.metric-row {
display: flex;
justify-content: space-between;
padding: 1rem 0;
border-bottom: 1px solid rgba(255,255,255,0.05);
}
.metric-label { color: var(--muted); }
.metric-value { font-family: monospace; font-size: 1.1rem; }
.critical { color: var(--accent); }
.visualization {
height: 300px;
background: repeating-linear-gradient(
45deg,
transparent,
transparent 10px,
rgba(255, 77, 77, 0.05) 10px,
rgba(255, 77, 77, 0.05) 20px
);
border: 1px solid var(--grid-line);
position: relative;
overflow: hidden;
margin-top: 1rem;
}
.beam-deflection {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 4px;
background: var(--accent);
transform-origin: center;
transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
.data-source {
font-size: 0.75rem;
color: var(--muted);
margin-top: 1rem;
border-top: 1px dashed var(--grid-line);
padding-top: 0.5rem;
}
nav {
margin-bottom: 2rem;
font-size: 0.9rem;
}
nav a {
color: var(--muted);
text-decoration: none;
margin-right: 1.5rem;
}
nav a.active { color: var(--accent); }
.context-image {
width: 100%;
height: 200px;
object-fit: cover;
border-radius: 4px;
margin-bottom: 1.5rem;
filter: grayscale(0.3) contrast(1.1);
opacity: 0.9;
}
</style>
<script defer src="https://analytics.4ort.xyz/script.js" data-website-id="d3ed927c-888a-4a6c-ae5f-0b1c613ddf5b"></script>
</head>
<body>
<nav>
<a href="/index.html">Home</a>
<a href="/safety-net.html">Safety Net</a>
<a href="/fixture-comparator.html" class="active">Fixture Comparator</a>
</nav>
<header>
<h1>Fixture Stress Comparator</h1>
<div class="subtitle">Comparative analysis of structural timber vs. engineered composites under retail inventory loads.</div>
</header>
<main class="grid-layout">
<section class="controls card">
<img src="https://images.pexels.com/photos/32282975/pexels-photo-32282975.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940" alt="Industrial shelving unit loaded with inventory" class="context-image">
<label>Span Length (mm)</label>
<input type="number" id="spanLength" value="1200" min="500" max="3000">
<label>Shelf Thickness (mm)</label>
<input type="number" id="thickness" value="18" min="10" max="50">
<label>Material Grade</label>
<select id="material">
<option value="fir">Douglas Fir (Structural)</option>
<option value="mdf">Medium Density Fiberboard (Standard)</option>
<option value="particle">Particle Board (Economy)</option>
</select>
<label>Distributed Load (kg/m)</label>
<input type="number" id="load" value="45" step="1">
<button onclick="calculate()">Compute Deflection</button>
<div class="data-source">
Constants sourced from ASTM D143-21 (Timber) & ISO 12469 (Composites). See <a href="/fixture-constants.json" style="color:var(--accent)">fixture-constants.json</a>.
</div>
</section>
<section class="results-panel card">
<div class="metric-row">
<span class="metric-label">Modulus of Elasticity (MOE)</span>
<span class="metric-value" id="moeResult">--</span>
</div>
<div class="metric-row">
<span class="metric-label">Max Allowable Deflection</span>
<span class="metric-value" id="allowDefl">--</span>
</div>
<div class="metric-row">
<span class="metric-label">Actual Deflection</span>
<span class="metric-value critical" id="actualDefl">--</span>
</div>
<div class="metric-row">
<span class="metric-label">Safety Factor</span>
<span class="metric-value" id="safetyFactor">--</span>
</div>
<div class="metric-row">
<span class="metric-label">Status</span>
<span class="metric-value" id="statusText" style="font-weight:bold;">WAITING</span>
</div>
<div class="visualization" id="vizContainer">
<!-- Beam representation -->
<div class="beam-deflection" id="beamVis"></div>
</div>
</section>
</main>
<script>
// Constants: MPa for MOE
const CONSTANTS = {
fir: { moe: 13000, density: 0.52, name: "Douglas Fir" },
mdf: { moe: 2800, density: 0.75, name: "MDF Standard" },
particle: { moe: 1900, density: 0.68, name: "Particle Board" }
};
function calculate() {
const span = parseFloat(document.getElementById('spanLength').value); // mm
const thickness = parseFloat(document.getElementById('thickness').value); // mm
const loadKg = parseFloat(document.getElementById('load').value); // kg/m
const matKey = document.getElementById('material').value;
const mat = CONSTANTS[matKey];
// Physics: Simply supported beam, uniform load
// w = force per length (N/mm)
const g = 9.81; // m/s^2
const w = (loadKg * g) / 1000; // N/mm
// Moment of Inertia (rectangular cross section)
// I = (b * h^3) / 12
// Assume b = 1mm for strip calculation, scale later
const b = 1;
const I = (b * Math.pow(thickness, 3)) / 12; // mm^4
// Deflection formula: y_max = (5 * w * L^4) / (384 * E * I)
const E_MPa = mat.moe; // N/mm^2
const deflection = (5 * w * Math.pow(span, 4)) / (384 * E_MPa * I);
// Allowable deflection: L/240 (standard for non-glass shelves)
const allowDefl = span / 240;
// Safety Factor based on deflection
let sf = allowDefl / deflection;
if (sf > 100) sf = 100; // Cap for display
// Update UI
document.getElementById('moeResult').textContent = `${mat.moe} MPa`;
document.getElementById('allowDefl').textContent = `${allowDefl.toFixed(2)} mm`;
document.getElementById('actualDefl').textContent = `${deflection.toFixed(2)} mm`;
document.getElementById('safetyFactor').textContent = sf.toFixed(2);
const statusEl = document.getElementById('statusText');
if (deflection <= allowDefl) {
statusEl.textContent = "STRUCTURALLY SOUND";
statusEl.style.color = "#4ade80";
} else {
statusEl.textContent = "FAILURE IMMINENT";
statusEl.style.color = "#ff4d4d";
}
// Visualize
const beamVis = document.getElementById('beamVis');
// Map deflection to visual rotation (exaggerated for visibility)
const vizRotation = Math.min(deflection * 2, 45);
beamVis.style.transform = `rotate(${vizRotation}deg)`;
}
// Init
calculate();
</script>
</body>
</html>