This utility is designed to be open to the public so that they can put in their information and it will draw plans so that they can cut them out and build it having a preview is also good. I currently can’t see the preview. - Follow Up Deployment
c6313bc verified | <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Custom Step Stool Designer</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| .preview-container { | |
| perspective: 1000px; | |
| background: linear-gradient(135deg, #f0f4ff 0%, #e6ecfa 100%); | |
| border: 1px solid #d1d5db; | |
| box-shadow: inset 0 0 20px rgba(0,0,0,0.05); | |
| } | |
| .stool-preview { | |
| transform-style: preserve-3d; | |
| transition: transform 0.5s ease; | |
| width: 100%; | |
| height: 100%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .stool-step { | |
| position: absolute; | |
| background: #d1a05a; | |
| border: 2px solid #8b5a2b; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| font-weight: bold; | |
| box-shadow: | |
| inset 0 0 10px rgba(0,0,0,0.2), | |
| 0 5px 15px rgba(0,0,0,0.1); | |
| transition: all 0.3s ease; | |
| } | |
| .stool-leg { | |
| position: absolute; | |
| background: #8b5a2b; | |
| box-shadow: inset 0 0 5px rgba(0,0,0,0.3); | |
| } | |
| .color-option { | |
| width: 30px; | |
| height: 30px; | |
| border-radius: 50%; | |
| cursor: pointer; | |
| transition: transform 0.2s; | |
| } | |
| .color-option:hover { | |
| transform: scale(1.1); | |
| } | |
| .preview-container::before { | |
| content: ""; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background-image: | |
| linear-gradient(rgba(0,0,0,0.05) 1px, transparent 1px), | |
| linear-gradient(90deg, rgba(0,0,0,0.05) 1px, transparent 1px); | |
| background-size: 20px 20px; | |
| opacity: 0.5; | |
| pointer-events: none; | |
| } | |
| input[type="range"]::-webkit-slider-thumb { | |
| -webkit-appearance: none; | |
| width: 20px; | |
| height: 20px; | |
| background: #4f46e5; | |
| border-radius: 50%; | |
| cursor: pointer; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-100 min-h-screen"> | |
| <div class="container mx-auto px-4 py-8"> | |
| <header class="text-center mb-12"> | |
| <h1 class="text-4xl font-bold text-indigo-800 mb-2">Step Stool Designer</h1> | |
| <p class="text-gray-600 max-w-2xl mx-auto">Create your perfect custom step stool with our interactive designer tool</p> | |
| </header> | |
| <div class="flex flex-col lg:flex-row gap-8"> | |
| <!-- Design Controls --> | |
| <div class="lg:w-1/3 bg-white rounded-xl shadow-lg p-6"> | |
| <h2 class="text-2xl font-semibold text-gray-800 mb-6 flex items-center"> | |
| <i class="fas fa-ruler-combined mr-2 text-indigo-600"></i> Design Specifications | |
| </h2> | |
| <div class="space-y-6"> | |
| <!-- Step Count --> | |
| <div> | |
| <label class="block text-gray-700 font-medium mb-2">Number of Steps</label> | |
| <div class="flex items-center space-x-4"> | |
| <button id="step-decrease" class="bg-gray-200 hover:bg-gray-300 rounded-full w-8 h-8 flex items-center justify-center"> | |
| <i class="fas fa-minus"></i> | |
| </button> | |
| <input type="number" id="step-count" min="1" max="5" value="2" class="w-16 text-center border border-gray-300 rounded py-2"> | |
| <button id="step-increase" class="bg-gray-200 hover:bg-gray-300 rounded-full w-8 h-8 flex items-center justify-center"> | |
| <i class="fas fa-plus"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Dimensions --> | |
| <div> | |
| <label class="block text-gray-700 font-medium mb-2">Dimensions (cm)</label> | |
| <div class="space-y-4"> | |
| <div> | |
| <div class="flex justify-between mb-1"> | |
| <span>Height: <span id="height-value">30</span>cm</span> | |
| <span class="text-gray-500">Max: 50cm</span> | |
| </div> | |
| <input type="range" id="height" min="20" max="50" value="30" class="w-full"> | |
| </div> | |
| <div> | |
| <div class="flex justify-between mb-1"> | |
| <span>Width: <span id="width-value">40</span>cm</span> | |
| <span class="text-gray-500">Max: 60cm</span> | |
| </div> | |
| <input type="range" id="width" min="30" max="60" value="40" class="w-full"> | |
| </div> | |
| <div> | |
| <div class="flex justify-between mb-1"> | |
| <span>Depth: <span id="depth-value">30</span>cm</span> | |
| <span class="text-gray-500">Max: 50cm</span> | |
| </div> | |
| <input type="range" id="depth" min="20" max="50" value="30" class="w-full"> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Step Configuration --> | |
| <div> | |
| <label class="block text-gray-700 font-medium mb-2">Step Style</label> | |
| <div class="grid grid-cols-2 gap-3"> | |
| <button id="style-open" class="py-2 px-4 border border-indigo-300 rounded-lg bg-indigo-50 text-indigo-700 font-medium flex items-center justify-center"> | |
| <i class="fas fa-box-open mr-2"></i> Open | |
| </button> | |
| <button id="style-box" class="py-2 px-4 border border-gray-300 rounded-lg bg-white text-gray-700 font-medium flex items-center justify-center"> | |
| <i class="fas fa-box mr-2"></i> Boxed | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Color Selection --> | |
| <div> | |
| <label class="block text-gray-700 font-medium mb-2">Color</label> | |
| <div class="flex flex-wrap gap-3"> | |
| <div class="color-option bg-amber-700 border-2 border-amber-900" data-color="#b45309"></div> | |
| <div class="color-option bg-amber-600 border-2 border-amber-800" data-color="#d97706"></div> | |
| <div class="color-option bg-amber-500 border-2 border-amber-700" data-color="#f59e0b"></div> | |
| <div class="color-option bg-gray-700 border-2 border-gray-900" data-color="#4b5563"></div> | |
| <div class="color-option bg-gray-500 border-2 border-gray-700" data-color="#6b7280"></div> | |
| <div class="color-option bg-white border-2 border-gray-300" data-color="#ffffff"></div> | |
| </div> | |
| </div> | |
| <!-- Safety Features --> | |
| <div> | |
| <label class="block text-gray-700 font-medium mb-2">Safety Features</label> | |
| <div class="space-y-2"> | |
| <label class="flex items-center space-x-3"> | |
| <input type="checkbox" id="non-slip" class="rounded text-indigo-600"> | |
| <span>Non-slip surface</span> | |
| </label> | |
| <label class="flex items-center space-x-3"> | |
| <input type="checkbox" id="handrail" class="rounded text-indigo-600"> | |
| <span>Handrail</span> | |
| </label> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="mt-8 pt-6 border-t border-gray-200"> | |
| <button id="generate-btn" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-3 px-4 rounded-lg flex items-center justify-center"> | |
| <i class="fas fa-magic mr-2"></i> Generate 3D Preview | |
| </button> | |
| </div> | |
| </div> | |
| <!-- 3D Preview --> | |
| <div class="lg:w-2/3"> | |
| <div class="bg-white rounded-xl shadow-lg p-6 h-full"> | |
| <div class="flex justify-between items-center mb-6"> | |
| <h2 class="text-2xl font-semibold text-gray-800 flex items-center"> | |
| <i class="fas fa-cube mr-2 text-indigo-600"></i> 3D Preview | |
| </h2> | |
| <div class="flex space-x-2"> | |
| <button id="rotate-left" class="bg-gray-200 hover:bg-gray-300 rounded-full w-8 h-8 flex items-center justify-center"> | |
| <i class="fas fa-undo"></i> | |
| </button> | |
| <button id="rotate-right" class="bg-gray-200 hover:bg-gray-300 rounded-full w-8 h-8 flex items-center justify-center"> | |
| <i class="fas fa-redo"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="preview-container w-full h-96 bg-gray-50 rounded-lg flex items-center justify-center relative"> | |
| <div id="stool-preview" class="stool-preview relative"> | |
| <!-- Generated stool will appear here --> | |
| </div> | |
| <div id="pieces-view" class="absolute bottom-4 right-4 bg-white p-2 rounded-lg shadow-md hidden"> | |
| <h3 class="text-sm font-medium mb-1">Stool Pieces</h3> | |
| <div id="pieces-list" class="text-xs space-y-1"></div> | |
| </div> | |
| </div> | |
| <div class="mt-6 pt-6 border-t border-gray-200"> | |
| <div class="flex flex-col sm:flex-row justify-between items-center gap-4"> | |
| <div> | |
| <h3 class="font-medium text-gray-700">Your Custom Stool</h3> | |
| <p class="text-sm text-gray-500">Estimated material: <span id="material-estimate">2.5</span> sq ft</p> | |
| </div> | |
| <div class="flex space-x-3"> | |
| <button class="bg-white border border-indigo-600 text-indigo-600 hover:bg-indigo-50 font-medium py-2 px-4 rounded-lg flex items-center"> | |
| <i class="fas fa-download mr-2"></i> Save Design | |
| </button> | |
| <button class="bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-2 px-4 rounded-lg flex items-center"> | |
| <i class="fas fa-shopping-cart mr-2"></i> Order Now ($<span id="price">49</span>) | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Design Tips --> | |
| <div class="mt-12 bg-white rounded-xl shadow-lg p-6"> | |
| <h2 class="text-2xl font-semibold text-gray-800 mb-4 flex items-center"> | |
| <i class="fas fa-lightbulb mr-2 text-yellow-500"></i> Design Tips | |
| </h2> | |
| <div class="grid md:grid-cols-3 gap-6"> | |
| <div class="bg-indigo-50 p-4 rounded-lg"> | |
| <h3 class="font-medium text-indigo-800 mb-2 flex items-center"> | |
| <i class="fas fa-ruler-vertical mr-2"></i> Height Considerations | |
| </h3> | |
| <p class="text-gray-700">For safety, each step should be no more than 20cm high. Our tool automatically calculates optimal step heights based on your total height.</p> | |
| </div> | |
| <div class="bg-amber-50 p-4 rounded-lg"> | |
| <h3 class="font-medium text-amber-800 mb-2 flex items-center"> | |
| <i class="fas fa-weight mr-2"></i> Weight Capacity | |
| </h3> | |
| <p class="text-gray-700">Standard designs support up to 150kg. For heavier use, consider adding reinforcement or choosing boxed step style.</p> | |
| </div> | |
| <div class="bg-green-50 p-4 rounded-lg"> | |
| <h3 class="font-medium text-green-800 mb-2 flex items-center"> | |
| <i class="fas fa-child mr-2"></i> Child Safety | |
| </h3> | |
| <p class="text-gray-700">For children, add handrails and non-slip surfaces. Keep step depth at least 25cm for secure footing.</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // DOM Elements | |
| const stepCountInput = document.getElementById('step-count'); | |
| const stepDecreaseBtn = document.getElementById('step-decrease'); | |
| const stepIncreaseBtn = document.getElementById('step-increase'); | |
| const heightSlider = document.getElementById('height'); | |
| const widthSlider = document.getElementById('width'); | |
| const depthSlider = document.getElementById('depth'); | |
| const heightValue = document.getElementById('height-value'); | |
| const widthValue = document.getElementById('width-value'); | |
| const depthValue = document.getElementById('depth-value'); | |
| const styleOpenBtn = document.getElementById('style-open'); | |
| const styleBoxBtn = document.getElementById('style-box'); | |
| const nonSlipCheckbox = document.getElementById('non-slip'); | |
| const handrailCheckbox = document.getElementById('handrail'); | |
| const generateBtn = document.getElementById('generate-btn'); | |
| const stoolPreview = document.getElementById('stool-preview'); | |
| const rotateLeftBtn = document.getElementById('rotate-left'); | |
| const rotateRightBtn = document.getElementById('rotate-right'); | |
| const materialEstimate = document.getElementById('material-estimate'); | |
| const priceElement = document.getElementById('price'); | |
| const colorOptions = document.querySelectorAll('.color-option'); | |
| // State variables | |
| let stepCount = 2; | |
| let height = 30; | |
| let width = 40; | |
| let depth = 30; | |
| let stepStyle = 'open'; | |
| let stoolColor = '#d1a05a'; | |
| let rotationAngle = 0; | |
| // Event Listeners | |
| stepDecreaseBtn.addEventListener('click', () => { | |
| if (stepCount > 1) { | |
| stepCount--; | |
| stepCountInput.value = stepCount; | |
| updatePrice(); | |
| } | |
| }); | |
| stepIncreaseBtn.addEventListener('click', () => { | |
| if (stepCount < 5) { | |
| stepCount++; | |
| stepCountInput.value = stepCount; | |
| updatePrice(); | |
| } | |
| }); | |
| stepCountInput.addEventListener('change', (e) => { | |
| let value = parseInt(e.target.value); | |
| if (isNaN(value) || value < 1) value = 1; | |
| if (value > 5) value = 5; | |
| stepCount = value; | |
| e.target.value = value; | |
| updatePrice(); | |
| }); | |
| heightSlider.addEventListener('input', (e) => { | |
| height = parseInt(e.target.value); | |
| heightValue.textContent = height; | |
| }); | |
| widthSlider.addEventListener('input', (e) => { | |
| width = parseInt(e.target.value); | |
| widthValue.textContent = width; | |
| }); | |
| depthSlider.addEventListener('input', (e) => { | |
| depth = parseInt(e.target.value); | |
| depthValue.textContent = depth; | |
| }); | |
| styleOpenBtn.addEventListener('click', () => { | |
| stepStyle = 'open'; | |
| styleOpenBtn.classList.add('border-indigo-300', 'bg-indigo-50', 'text-indigo-700'); | |
| styleOpenBtn.classList.remove('border-gray-300', 'bg-white', 'text-gray-700'); | |
| styleBoxBtn.classList.add('border-gray-300', 'bg-white', 'text-gray-700'); | |
| styleBoxBtn.classList.remove('border-indigo-300', 'bg-indigo-50', 'text-indigo-700'); | |
| }); | |
| styleBoxBtn.addEventListener('click', () => { | |
| stepStyle = 'box'; | |
| styleBoxBtn.classList.add('border-indigo-300', 'bg-indigo-50', 'text-indigo-700'); | |
| styleBoxBtn.classList.remove('border-gray-300', 'bg-white', 'text-gray-700'); | |
| styleOpenBtn.classList.add('border-gray-300', 'bg-white', 'text-gray-700'); | |
| styleOpenBtn.classList.remove('border-indigo-300', 'bg-indigo-50', 'text-indigo-700'); | |
| }); | |
| colorOptions.forEach(option => { | |
| option.addEventListener('click', (e) => { | |
| stoolColor = e.target.dataset.color; | |
| // Update active color indicator | |
| colorOptions.forEach(opt => opt.style.transform = 'scale(1)'); | |
| e.target.style.transform = 'scale(1.2)'; | |
| }); | |
| }); | |
| generateBtn.addEventListener('click', generateStoolPreview); | |
| rotateLeftBtn.addEventListener('click', () => { | |
| rotationAngle -= 45; | |
| stoolPreview.style.transform = `rotateY(${rotationAngle}deg)`; | |
| }); | |
| rotateRightBtn.addEventListener('click', () => { | |
| rotationAngle += 45; | |
| stoolPreview.style.transform = `rotateY(${rotationAngle}deg)`; | |
| }); | |
| // Initialize | |
| styleOpenBtn.click(); | |
| colorOptions[0].style.transform = 'scale(1.2)'; | |
| generateStoolPreview(); | |
| // Functions | |
| function generateStoolPreview() { | |
| // Clear previous stool | |
| stoolPreview.innerHTML = ''; | |
| const piecesList = document.getElementById('pieces-list'); | |
| piecesList.innerHTML = ''; | |
| document.getElementById('pieces-view').classList.remove('hidden'); | |
| // Calculate dimensions | |
| const stepHeight = height / stepCount; | |
| const legWidth = 5; // cm in preview scale | |
| const scaleFactor = 3; // Scale down for display | |
| // Create steps | |
| for (let i = 0; i < stepCount; i++) { | |
| const step = document.createElement('div'); | |
| step.className = 'stool-step'; | |
| // Calculate dimensions for this step | |
| const stepWidth = width - (i * 5); | |
| const stepDepth = depth - (i * 5); | |
| const stepTop = i * stepHeight; | |
| // Set step styles | |
| step.style.width = `${stepWidth / scaleFactor}px`; | |
| step.style.height = `${stepHeight / scaleFactor}px`; | |
| step.style.top = `${(height - stepTop - stepHeight) / scaleFactor}px`; | |
| step.style.left = `${(i * 5 / 2) / scaleFactor}px`; | |
| step.style.backgroundColor = stoolColor; | |
| step.style.zIndex = stepCount - i; | |
| // Add non-slip texture if selected | |
| if (nonSlipCheckbox.checked) { | |
| step.style.backgroundImage = 'radial-gradient(circle, rgba(0,0,0,0.1) 1px, transparent 1px)'; | |
| step.style.backgroundSize = '10px 10px'; | |
| } | |
| // Add step number | |
| step.textContent = i + 1; | |
| stoolPreview.appendChild(step); | |
| // Add to pieces list | |
| const pieceItem = document.createElement('div'); | |
| pieceItem.textContent = `Step ${i+1}: ${stepWidth.toFixed(1)}cm × ${stepDepth.toFixed(1)}cm`; | |
| pieceItem.style.color = stoolColor; | |
| piecesList.appendChild(pieceItem); | |
| // Create legs for open style | |
| if (stepStyle === 'open' && i === 0) { | |
| // Front legs | |
| const frontLeftLeg = createLeg(0, stepHeight * stepCount, stepHeight, legWidth, scaleFactor); | |
| const frontRightLeg = createLeg(stepWidth - legWidth, stepHeight * stepCount, stepHeight, legWidth, scaleFactor); | |
| // Back legs (only visible in 3D) | |
| const backLeftLeg = createLeg(0, stepHeight * stepCount, stepHeight, legWidth, scaleFactor); | |
| const backRightLeg = createLeg(stepWidth - legWidth, stepHeight * stepCount, stepHeight, legWidth, scaleFactor); | |
| // Position back legs in 3D space | |
| backLeftLeg.style.transform = `translateZ(${stepDepth / scaleFactor}px)`; | |
| backRightLeg.style.transform = `translateZ(${stepDepth / scaleFactor}px)`; | |
| stoolPreview.appendChild(frontLeftLeg); | |
| const legItem = document.createElement('div'); | |
| legItem.textContent = `Leg: 5cm × ${stepHeight.toFixed(1)}cm`; | |
| legItem.style.color = '#8b5a2b'; | |
| piecesList.appendChild(legItem); | |
| stoolPreview.appendChild(frontRightLeg); | |
| stoolPreview.appendChild(backLeftLeg); | |
| stoolPreview.appendChild(backRightLeg); | |
| } | |
| // For box style, add side panels | |
| if (stepStyle === 'box' && i < stepCount - 1) { | |
| const sidePanelDepth = stepDepth - ((i + 1) * 5); | |
| // Left side panel | |
| const leftPanel = document.createElement('div'); | |
| leftPanel.className = 'stool-leg'; | |
| leftPanel.style.width = `${legWidth / scaleFactor}px`; | |
| leftPanel.style.height = `${stepHeight / scaleFactor}px`; | |
| leftPanel.style.top = `${(height - stepTop - stepHeight) / scaleFactor}px`; | |
| leftPanel.style.left = `${(i * 5 / 2) / scaleFactor}px`; | |
| leftPanel.style.transform = `translateZ(${(stepDepth - legWidth) / scaleFactor}px) rotateY(90deg)`; | |
| leftPanel.style.transformOrigin = 'left center'; | |
| leftPanel.style.backgroundColor = '#8b5a2b'; | |
| leftPanel.style.zIndex = stepCount - i - 0.5; | |
| // Right side panel | |
| const rightPanel = document.createElement('div'); | |
| rightPanel.className = 'stool-leg'; | |
| rightPanel.style.width = `${legWidth / scaleFactor}px`; | |
| rightPanel.style.height = `${stepHeight / scaleFactor}px`; | |
| rightPanel.style.top = `${(height - stepTop - stepHeight) / scaleFactor}px`; | |
| rightPanel.style.left = `${((i * 5 / 2) + stepWidth - legWidth) / scaleFactor}px`; | |
| rightPanel.style.transform = `translateZ(${(stepDepth - legWidth) / scaleFactor}px) rotateY(90deg)`; | |
| rightPanel.style.transformOrigin = 'left center'; | |
| rightPanel.style.backgroundColor = '#8b5a2b'; | |
| rightPanel.style.zIndex = stepCount - i - 0.5; | |
| stoolPreview.appendChild(leftPanel); | |
| const panelItem = document.createElement('div'); | |
| panelItem.textContent = `Side Panel: 5cm × ${stepHeight.toFixed(1)}cm`; | |
| panelItem.style.color = '#8b5a2b'; | |
| piecesList.appendChild(panelItem); | |
| stoolPreview.appendChild(rightPanel); | |
| } | |
| } | |
| // Add handrail if selected | |
| if (handrailCheckbox.checked) { | |
| const handrailHeight = stepHeight * 1.5; | |
| const handrail = document.createElement('div'); | |
| handrail.className = 'stool-leg'; | |
| handrail.style.width = `${legWidth / scaleFactor}px`; | |
| handrail.style.height = `${handrailHeight / scaleFactor}px`; | |
| handrail.style.top = `${(height - stepHeight * stepCount - handrailHeight) / scaleFactor}px`; | |
| handrail.style.left = `${(width / 2 - legWidth / 2) / scaleFactor}px`; | |
| handrail.style.backgroundColor = '#8b5a2b'; | |
| handrail.style.zIndex = stepCount + 1; | |
| // Horizontal rail | |
| const topRail = document.createElement('div'); | |
| topRail.className = 'stool-leg'; | |
| topRail.style.width = `${(width * 0.8) / scaleFactor}px`; | |
| topRail.style.height = `${legWidth / scaleFactor}px`; | |
| topRail.style.top = `${(height - stepHeight * stepCount - handrailHeight) / scaleFactor}px`; | |
| topRail.style.left = `${(width * 0.1) / scaleFactor}px`; | |
| topRail.style.backgroundColor = '#8b5a2b'; | |
| topRail.style.zIndex = stepCount + 2; | |
| stoolPreview.appendChild(handrail); | |
| const railItem = document.createElement('div'); | |
| railItem.textContent = `Handrail: 5cm × ${handrailHeight.toFixed(1)}cm`; | |
| railItem.style.color = '#8b5a2b'; | |
| piecesList.appendChild(railItem); | |
| stoolPreview.appendChild(topRail); | |
| } | |
| // Update material estimate and price | |
| updateMaterialEstimate(); | |
| updatePrice(); | |
| } | |
| function createLeg(x, totalHeight, stepHeight, width, scaleFactor) { | |
| const leg = document.createElement('div'); | |
| leg.className = 'stool-leg'; | |
| leg.style.width = `${width / scaleFactor}px`; | |
| leg.style.height = `${totalHeight / scaleFactor}px`; | |
| leg.style.top = '0'; | |
| leg.style.left = `${x / scaleFactor}px`; | |
| return leg; | |
| } | |
| function updateMaterialEstimate() { | |
| // Simplified material calculation | |
| const baseMaterial = width * depth / 600; // Base material in sq ft | |
| const stepMaterial = (width * depth * 0.7 * stepCount) / 600; // Steps material | |
| const legMaterial = (height * 4 * 5) / 600; // Legs material | |
| let total = baseMaterial + stepMaterial + legMaterial; | |
| if (stepStyle === 'box') total *= 1.3; | |
| if (handrailCheckbox.checked) total += 0.5; | |
| materialEstimate.textContent = total.toFixed(1); | |
| } | |
| function updatePrice() { | |
| // Base price | |
| let price = 30; | |
| // Add for steps | |
| price += (stepCount - 1) * 10; | |
| // Add for size | |
| price += (width - 30) * 0.2; | |
| price += (depth - 20) * 0.2; | |
| // Add for features | |
| if (stepStyle === 'box') price += 15; | |
| if (nonSlipCheckbox.checked) price += 8; | |
| if (handrailCheckbox.checked) price += 12; | |
| priceElement.textContent = Math.round(price); | |
| } | |
| }); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=MarkTheArtist/step-stool-configuration" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |