<?php include "../autoload.php"; ?> <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script> <style> @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap'); .gradient-bg { background: linear-gradient(135deg, #1e40af 0%, #60a5fa 100%); } .result-card { background: linear-gradient(145deg, #ffffff, #f0f7ff); box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15); transition: transform 0.3s ease, opacity 0.3s ease; } .result-card.hidden { transform: translateY(20px); opacity: 0; } .result-card:not(.hidden) { transform: translateY(0); opacity: 1; } .input-container { background: linear-gradient(145deg, #ffffff, #f9fafb); transition: all 0.3s ease; } .input-container:hover { transform: translateY(-2px); box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1); } .range-input::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 20px; height: 20px; background: #1e40af; border-radius: 50%; cursor: pointer; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2); } .range-input::-moz-range-thumb { width: 20px; height: 20px; background: #1e40af; border-radius: 50%; cursor: pointer; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2); } .btn-primary { transition: all 0.3s ease; } .btn-primary:hover { transform: translateY(-2px); box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2); } .visual-container { background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><rect fill="%23f3f4f6" width="100" height="100"/><circle cx="50" cy="50" r="30" fill="%23dbeafe" opacity="0.5"/></svg>') repeat; border-radius: 12px; box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.05); } select { appearance: none; background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"><path fill="%234b5563" d="M7 10l5 5 5-5H7z"/></svg>'); background-repeat: no-repeat; background-position: right 0.75rem center; background-size: 12px; } </style> <div class="x"> <div class="x"> <!-- Input Form --> <div class="mb-12"> <h2 class="text-3xl font-semibold text-gray-800 mb-6">Enter Your Device & Bag/Case Details</h2> <p class="text-gray-500 mb-8 text-lg">Compare two devices and check if they fit in a bag or case.</p> <form id="deviceComparisonForm" class="space-y-8"> <div class="grid grid-cols-1 md:grid-cols-3 gap-6"> <div class="space-y-3"> <label for="device1" class="block text-sm font-medium text-gray-700">Device 1</label> <div class="relative flex items-center"> <i data-lucide="smartphone" class="absolute left-4 top-1/2 transform -translate-y-1/2 text-gray-400"></i> <select id="device1" class="pl-12 pr-10 py-3 block w-full rounded-lg border-gray-300 shadow-sm focus:border-blue-600 focus:ring focus:ring-blue-600 focus:ring-opacity-50 text-lg" required> <option value="iPhone 15 Pro" selected>iPhone 15 Pro</option> <option value="Samsung Galaxy S24">Samsung Galaxy S24</option> <option value="MacBook Air 13">MacBook Air 13</option> <option value="Dell XPS 15">Dell XPS 15</option> <option value="Google Pixel 8">Google Pixel 8</option> </select> </div> </div> <div class="space-y-3"> <label for="device2" class="block text-sm font-medium text-gray-700">Device 2</label> <div class="relative flex items-center"> <i data-lucide="laptop" class="absolute left-4 top-1/2 transform -translate-y-1/2 text-gray-400"></i> <select id="device2" class="pl-12 pr-10 py-3 block w-full rounded-lg border-gray-300 shadow-sm focus:border-blue-600 focus:ring focus:ring-blue-600 focus:ring-opacity-50 text-lg" required> <option value="MacBook Air 13" selected>MacBook Air 13</option> <option value="iPhone 15 Pro">iPhone 15 Pro</option> <option value="Samsung Galaxy S24">Samsung Galaxy S24</option> <option value="Dell XPS 15">Dell XPS 15</option> <option value="Google Pixel 8">Google Pixel 8</option> </select> </div> </div> <div class="space-y-3"> <label for="bagWidth" class="block text-sm font-medium text-gray-700">Bag/Case Width (in)</label> <div class="relative flex items-center"> <i data-lucide="briefcase" class="absolute left-4 top-1/2 transform -translate-y-1/2 text-gray-400"></i> <input type="number" id="bagWidth" class="pl-12 pr-4 py-3 block w-full rounded-lg border-gray-300 shadow-sm focus:border-blue-600 focus:ring focus:ring-blue-600 focus:ring-opacity-50 text-lg" placeholder="16.0" step="0.1" min="5" max="24" value="16.0" required> </div> <input type="range" id="bagWidthRange" class="range-input w-full h-2 bg-gray-200 rounded-lg cursor-pointer" min="5" max="24" step="0.1" value="16"> <p id="bagWidthValue" class="text-sm text-gray-500">16.0 in</p> </div> </div> <div class="grid grid-cols-1 md:grid-cols-2 gap-6"> <div class="space-y-3"> <label for="bagDepth" class="block text-sm font-medium text-gray-700">Bag/Case Depth (in)</label> <div class="relative flex items-center"> <i data-lucide="expand" class="absolute left-4 top-1/2 transform -translate-y-1/2 text-gray-400"></i> <input type="number" id="bagDepth" class="pl-12 pr-4 py-3 block w-full rounded-lg border-gray-300 shadow-sm focus:border-blue-600 focus:ring focus:ring-blue-600 focus:ring-opacity-50 text-lg" placeholder="12.0" step="0.1" min="4" max="18" value="12.0" required> </div> <input type="range" id="bagDepthRange" class="range-input w-full h-2 bg-gray-200 rounded-lg cursor-pointer" min="4" max="18" step="0.1" value="12"> <p id="bagDepthValue" class="text-sm text-gray-500">12.0 in</p> </div> <div class="space-y-3"> <label for="bagHeight" class="block text-sm font-medium text-gray-700">Bag/Case Height (in)</label> <div class="relative flex items-center"> <i data-lucide="ruler" class="absolute left-4 top-1/2 transform -translate-y-1/2 text-gray-400"></i> <input type="number" id="bagHeight" class="pl-12 pr-4 py-3 block w-full rounded-lg border-gray-300 shadow-sm focus:border-blue-600 focus:ring focus:ring-blue-600 focus:ring-opacity-50 text-lg" placeholder="4.0" step="0.1" min="1" max="10" value="4.0" required> </div> <input type="range" id="bagHeightRange" class="range-input w-full h-2 bg-gray-200 rounded-lg cursor-pointer" min="1" max="10" step="0.1" value="4"> <p id="bagHeightValue" class="text-sm text-gray-500">4.0 in</p> </div> </div> <button type="submit" class="btn-primary w-full bg-blue-600 text-white py-4 px-8 rounded-xl hover:bg-blue-700 flex items-center justify-center text-lg"> <i data-lucide="search" class="mr-3 h-5 w-5"></i> Compare Devices & Check Fit </button> </form> </div> <!-- Result Section --> <div id="resultSection" class="result-card rounded-2xl p-10 hidden"> <h2 class="text-3xl font-semibold text-gray-800 mb-6 flex items-center"> <i data-lucide="check-circle-2" class="mr-3 text-green-500 h-7 w-7"></i> Your Device Comparison & Fit Assessment </h2> <div id="resultOutput" class="text-gray-700 space-y-6 text-base"> <!-- Results will be dynamically inserted here --> </div> <div class="mt-10 flex flex-col md:flex-row justify-between items-center gap-6"> <div class="flex items-center text-blue-600"> <i data-lucide="info" class="mr-2 h-5 w-5"></i> <p class="text-sm font-medium">Based on standard device and bag dimensions.</p> </div> <button id="downloadPdf" class="btn-primary bg-green-600 text-white py-3 px-8 rounded-xl hover:bg-green-700 flex items-center text-base"> <i data-lucide="download" class="mr-2 h-5 w-5"></i> Download PDF Report </button> </div> <!-- Visual Representation --> <div class="mt-10 visual-container p-8"> <h3 class="text-xl font-medium text-gray-800 mb-4 flex items-center"> <i data-lucide="smartphone" class="mr-3 text-blue-500 h-6 w-6"></i> Interactive Device Comparison </h3> <div class="relative w-full h-96 bg-gray-200 rounded-xl overflow-hidden shadow-lg"> <canvas id="deviceCanvas" class="w-full h-full"></canvas> </div> <p class="text-sm text-gray-600 mt-4">Side-by-side visualization of devices and bag/case, scaled to width.</p> </div> <!-- Expert Insights --> <div class="mt-10 bg-blue-50 p-8 rounded-xl shadow-sm"> <h3 class="text-xl font-medium text-gray-800 mb-4 flex items-center"> <i data-lucide="lightbulb" class="mr-3 text-yellow-500 h-6 w-6"></i> Expert Insights for Device Portability </h3> <ul class="list-none space-y-4 text-gray-700 text-sm"> <li class="flex items-start"> <i data-lucide="check" class="mr-2 text-green-500 h-5 w-5"></i> <span><strong>Clearance:</strong> Allow 0.5 in clearance for easy insertion/removal.</span> </li> <li class="flex items-start"> <i data-lucide="check" class="mr-2 text-green-500 h-5 w-5"></i> <span><strong>Orientation:</strong> Stack devices vertically or side-by-side to optimize space.</span> </li> <li class="flex items-start"> <i data-lucide="check" class="mr-2 text-green-500 h-5 w-5"></i> <span><strong>Padding:</strong> Use padded cases to protect devices from scratches.</span> </li> <li class="flex items-start"> <i data-lucide="check" class="mr-2 text-green-500 h-5 w-5"></i> <span><strong>Compartments:</strong> Choose bags with dedicated device slots for organization.</span> </li> <li class="flex items-start"> <i data-lucide="check" class="mr-2 text-green-500 h-5 w-5"></i> <span><strong>Weight:</strong> Consider combined device weight for comfortable carrying.</span> </li> </ul> </div> </div> </div> </div> <script> // Initialize Lucid Icons lucide.createIcons(); // Device dimensions (in inches, approximate averages from manufacturer data) const deviceDimensions = { 'iPhone 15 Pro': { width: 2.8, depth: 5.8, height: 0.3 }, 'Samsung Galaxy S24': { width: 2.8, depth: 5.9, height: 0.3 }, 'Google Pixel 8': { width: 2.8, depth: 5.9, height: 0.4 }, 'MacBook Air 13': { width: 12.0, depth: 8.5, height: 0.6 }, 'Dell XPS 15': { width: 13.6, depth: 9.1, height: 0.7 } }; // Sync range and number inputs function syncInputs(numberId, rangeId, valueId) { const numberInput = document.getElementById(numberId); const rangeInput = document.getElementById(rangeId); const valueDisplay = document.getElementById(valueId); numberInput.addEventListener('input', () => { rangeInput.value = numberInput.value; valueDisplay.textContent = `${parseFloat(numberInput.value).toFixed(1)} in`; }); rangeInput.addEventListener('input', () => { numberInput.value = rangeInput.value; valueDisplay.textContent = `${parseFloat(rangeInput.value).toFixed(1)} in`; }); } syncInputs('bagWidth', 'bagWidthRange', 'bagWidthValue'); syncInputs('bagDepth', 'bagDepthRange', 'bagDepthValue'); syncInputs('bagHeight', 'bagHeightRange', 'bagHeightValue'); // Form Submission document.getElementById('deviceComparisonForm').addEventListener('submit', function (e) { e.preventDefault(); calculateDeviceFit(); }); function calculateDeviceFit() { const device1 = document.getElementById('device1').value; const device2 = document.getElementById('device2').value; const bagWidth = parseFloat(document.getElementById('bagWidth').value); const bagDepth = parseFloat(document.getElementById('bagDepth').value); const bagHeight = parseFloat(document.getElementById('bagHeight').value); if (!device1 || !device2 || !bagWidth || !bagDepth || !bagHeight || bagWidth < 5 || bagDepth < 4 || bagHeight < 1) { alert('Please enter valid values (Bag Width ≥ 5 in, Depth ≥ 4 in, Height ≥ 1 in).'); return; } if (device1 === device2) { alert('Please select two different devices for comparison.'); return; } const d1 = deviceDimensions[device1]; const d2 = deviceDimensions[device2]; // Check fit: Devices stacked side-by-side or vertically const totalWidthSideBySide = Math.max(d1.width, d2.width) + Math.min(d1.width, d2.width) + 0.5; // 0.5 in clearance const totalDepthSideBySide = Math.max(d1.depth, d2.depth) + 0.5; const totalHeightSideBySide = Math.max(d1.height, d2.height) + 0.5; const totalWidthVertical = Math.max(d1.width, d2.width) + 0.5; const totalDepthVertical = Math.max(d1.depth, d2.depth) + 0.5; const totalHeightVertical = d1.height + d2.height + 0.5; const sideBySideFit = bagWidth >= totalWidthSideBySide && bagDepth >= totalDepthSideBySide && bagHeight >= totalHeightSideBySide; const verticalFit = bagWidth >= totalWidthVertical && bagDepth >= totalDepthVertical && bagHeight >= totalHeightVertical; const overallFit = sideBySideFit || verticalFit ? 'Yes' : 'No'; const bestOrientation = sideBySideFit ? 'Side-by-Side' : verticalFit ? 'Vertical' : 'None'; // Calculate clearances const sideBySideWidthClearance = bagWidth - totalWidthSideBySide; const sideBySideDepthClearance = bagDepth - totalDepthSideBySide; const sideBySideHeightClearance = bagHeight - totalHeightSideBySide; const verticalWidthClearance = bagWidth - totalWidthVertical; const verticalDepthClearance = bagDepth - totalDepthVertical; const verticalHeightClearance = bagHeight - totalHeightVertical; // Generate output const output = ` <div class="grid grid-cols-1 md:grid-cols-2 gap-6 bg-white p-6 rounded-xl shadow-sm"> <div> <p class="font-medium text-gray-700">Device 1</p> <p class="text-lg">${device1}</p> <p class="text-sm text-gray-600">${d1.width.toFixed(1)} x ${d1.depth.toFixed(1)} x ${d1.height.toFixed(1)} in</p> </div> <div> <p class="font-medium text-gray-700">Device 2</p> <p class="text-lg">${device2}</p> <p class="text-sm text-gray-600">${d2.width.toFixed(1)} x ${d2.depth.toFixed(1)} x ${d2.height.toFixed(1)} in</p> </div> <div> <p class="font-medium text-gray-700">Bag/Case Dimensions</p> <p class="text-lg">${bagWidth.toFixed(1)} x ${bagDepth.toFixed(1)} x ${bagHeight.toFixed(1)} in</p> </div> <div> <p class="font-medium text-gray-700">Fit Assessment</p> <p class="text-lg ${overallFit === 'Yes' ? 'text-green-600' : 'text-red-600'} font-semibold"> ${overallFit === 'Yes' ? 'Perfect Fit' : 'May Not Fit Comfortably'} </p> <p class="text-sm text-gray-600">${ overallFit === 'Yes' ? `Best orientation: ${bestOrientation}. Clearances in ${bestOrientation.toLowerCase()} orientation: ${bestOrientation === 'Side-by-Side' ? `${sideBySideWidthClearance.toFixed(1)} in (width), ${sideBySideDepthClearance.toFixed(1)} in (depth), ${sideBySideHeightClearance.toFixed(1)} in (height)` : `${verticalWidthClearance.toFixed(1)} in (width), ${verticalDepthClearance.toFixed(1)} in (depth), ${verticalHeightClearance.toFixed(1)} in (height)`}.` : `Issues: ${ !sideBySideFit && !verticalFit ? 'Devices do not fit in either side-by-side or vertical orientation.' : !sideBySideFit ? `Side-by-side orientation fails (need ≥${totalWidthSideBySide.toFixed(1)} in width, ${totalDepthSideBySide.toFixed(1)} in depth, ${totalHeightSideBySide.toFixed(1)} in height).` : `Vertical orientation fails (need ≥${totalWidthVertical.toFixed(1)} in width, ${totalDepthVertical.toFixed(1)} in depth, ${totalHeightVertical.toFixed(1)} in height).` }` }</p> </div> </div> <div class="bg-blue-50 p-4 rounded-lg"> <p class="text-sm"><span class="font-medium">Tip:</span> Measure your bag's internal dimensions and consider padding for protection.</p> </div> `; document.getElementById('resultOutput').innerHTML = output; document.getElementById('resultSection').classList.remove('hidden'); // Draw visualization drawVisualization(d1.width, d1.depth, d1.height, d2.width, d2.depth, d2.height, bagWidth, bagDepth, bestOrientation); // Setup PDF download setupPdfDownload(device1, d1.width, d1.depth, d1.height, device2, d2.width, d2.depth, d2.height, bagWidth, bagDepth, bagHeight, overallFit, bestOrientation, sideBySideWidthClearance, sideBySideDepthClearance, sideBySideHeightClearance, verticalWidthClearance, verticalDepthClearance, verticalHeightClearance); } function drawVisualization(d1Width, d1Depth, d1Height, d2Width, d2Depth, d2Height, bagWidth, bagDepth, bestOrientation) { const canvas = document.getElementById('deviceCanvas'); const ctx = canvas.getContext('2d'); canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; // Clear canvas ctx.clearRect(0, 0, canvas.width, canvas.height); // Scale factors const scale = canvas.width / (bagWidth * 1.5); // Scale to fit canvas const d1W = d1Width * scale; const d1H = d1Depth * scale; const d2W = d2Width * scale; const d2H = d2Depth * scale; const bagW = bagWidth * scale; const bagH = bagDepth * scale; // Draw background const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height); gradient.addColorStop(0, '#e5e7eb'); gradient.addColorStop(1, '#d1d5db'); ctx.fillStyle = gradient; ctx.fillRect(0, 0, canvas.width, canvas.height); // Draw bag/case outline (dashed) ctx.strokeStyle = '#1e40af'; ctx.lineWidth = 2; ctx.setLineDash([5, 5]); ctx.strokeRect(canvas.width * 0.55, canvas.height * 0.2, bagW, bagH); ctx.fillStyle = '#bfdbfe'; ctx.globalAlpha = 0.3; ctx.fillRect(canvas.width * 0.55, canvas.height * 0.2, bagW, bagH); ctx.globalAlpha = 1.0; ctx.setLineDash([]); // Draw devices ctx.shadowColor = 'rgba(0, 0, 0, 0.4)'; ctx.shadowBlur = 15; ctx.shadowOffsetX = 8; ctx.shadowOffsetY = 8; const deviceX1 = canvas.width * 0.15; const deviceY = canvas.height * 0.3; let deviceX2; if (bestOrientation === 'Side-by-Side' || bestOrientation === 'None') { deviceX2 = deviceX1 + d1W + 10; } else { deviceX2 = deviceX1; } // Device 1 ctx.fillStyle = '#4b5563'; ctx.fillRect(deviceX1, deviceY, d1W, d1H); const d1Gradient = ctx.createLinearGradient(deviceX1, deviceY, deviceX1 + d1W, deviceY + d1H); d1Gradient.addColorStop(0, 'rgba(255, 255, 255, 0.15)'); d1Gradient.addColorStop(1, 'rgba(255, 255, 255, 0.05)'); ctx.fillStyle = d1Gradient; ctx.fillRect(deviceX1 + 5, deviceY + 5, d1W - 10, d1H - 10); // Device 2 ctx.fillStyle = '#2d3748'; ctx.fillRect(deviceX2, deviceY + (bestOrientation === 'Vertical' ? d1H + 10 : 0), d2W, d2H); const d2Gradient = ctx.createLinearGradient(deviceX2, deviceY + (bestOrientation === 'Vertical' ? d1H + 10 : 0), deviceX2 + d2W, deviceY + (bestOrientation === 'Vertical' ? d1H + 10 + d2H : d2H)); d2Gradient.addColorStop(0, 'rgba(255, 255, 255, 0.15)'); d2Gradient.addColorStop(1, 'rgba(255, 255, 255, 0.05)'); ctx.fillStyle = d2Gradient; ctx.fillRect(deviceX2 + 5, deviceY + (bestOrientation === 'Vertical' ? d1H + 10 + 5 : 5), d2W - 10, d2H - 10); // Draw text ctx.shadowColor = 'transparent'; ctx.fillStyle = '#ffffff'; ctx.font = 'bold 18px Poppins'; ctx.textAlign = 'center'; ctx.fillText(`Device 1 (${d1Width.toFixed(1)} x ${d1Depth.toFixed(1)} in)`, deviceX1 + d1W / 2, deviceY + d1H / 2); ctx.fillText(`Device 2 (${d2Width.toFixed(1)} x ${d2Depth.toFixed(1)} in)`, deviceX2 + d2W / 2, deviceY + (bestOrientation === 'Vertical' ? d1H + 10 + d2H / 2 : d2H / 2)); ctx.fillStyle = '#1e40af'; ctx.fillText(`Bag/Case (${bagWidth.toFixed(1)} x ${bagDepth.toFixed(1)} in)`, canvas.width * 0.55 + bagW / 2, canvas.height * 0.2 + bagH / 2); ctx.font = '14px Poppins'; ctx.fillStyle = '#4b5563'; ctx.fillText(`Devices vs. Bag/Case (${bestOrientation} Orientation)`, canvas.width / 2, canvas.height - 30); } function setupPdfDownload(device1, d1Width, d1Depth, d1Height, device2, d2Width, d2Depth, d2Height, bagWidth, bagDepth, bagHeight, overallFit, bestOrientation, sideBySideWidthClearance, sideBySideDepthClearance, sideBySideHeightClearance, verticalWidthClearance, verticalDepthClearance, verticalHeightClearance) { document.getElementById('downloadPdf').onclick = function () { const { jsPDF } = window.jspdf; const doc = new jsPDF(); // Header doc.setFont('helvetica', 'bold'); doc.setFontSize(20); doc.setTextColor(31, 64, 175); doc.text('HomeFit Tools - Device Comparison & Fit Assessment', 20, 20); doc.setFont('helvetica', 'normal'); doc.setFontSize(10); doc.setTextColor(100, 100, 100); doc.text(`Generated on: ${new Date().toLocaleString()}`, 20, 28); // Results doc.setFontSize(14); doc.setTextColor(0, 0, 0); doc.text('Your Device Comparison & Fit Assessment', 20, 40); doc.setFontSize(11); doc.text(`Device 1: ${device1} (${d1Width.toFixed(1)} x ${d1Depth.toFixed(1)} x ${d1Height.toFixed(1)} in)`, 20, 50); doc.text(`Device 2: ${device2} (${d2Width.toFixed(1)} x ${d2Depth.toFixed(1)} x ${d2Height.toFixed(1)} in)`, 20, 58); doc.text(`Bag/Case Dimensions: ${bagWidth.toFixed(1)} x ${bagDepth.toFixed(1)} x ${bagHeight.toFixed(1)} in`, 20, 66); doc.text(`Fit Assessment: ${overallFit === 'Yes' ? 'Perfect Fit' : 'May Not Fit Comfortably'}`, 20, 74); doc.text(`Best Orientation: ${bestOrientation}`, 20, 82); doc.text(`Clearances (${bestOrientation.toLowerCase()}): ${bestOrientation === 'Side-by-Side' ? `${sideBySideWidthClearance.toFixed(1)} in (width), ${sideBySideDepthClearance.toFixed(1)} in (depth), ${sideBySideHeightClearance.toFixed(1)} in (height)` : `${verticalWidthClearance.toFixed(1)} in (width), ${verticalDepthClearance.toFixed(1)} in (depth), ${verticalHeightClearance.toFixed(1)} in (height)`}`, 20, 90); doc.text(`Recommendation: ${ overallFit === 'Yes' ? `Both devices fit well in the ${bestOrientation.toLowerCase()} orientation.` : 'Consider a larger bag/case or different orientation.' }`, 20, 98); // Expert Insights doc.setFont('helvetica', 'bold'); doc.setFontSize(12); doc.text('Expert Insights', 20, 110); doc.setFont('helvetica', 'normal'); doc.setFontSize(10); doc.text('• Clearance: Allow 0.5 in for easy insertion/removal.', 20, 118); doc.text('• Orientation: Stack vertically or side-by-side to optimize space.', 20, 126); doc.text('• Padding: Use padded cases to protect devices.', 20, 134); doc.text('• Compartments: Choose bags with dedicated slots.', 20, 142); doc.text('• Weight: Consider combined device weight for carrying.', 20, 150); doc.save('HomeFit_Device_Comparison_Assessment.pdf'); }; } </script>