${item.icon} ${item.name}
`).join('');
}function toggleSW(id) {
document.getElementById(id).classList.toggle('checked');
}function renderAccessories() {
const grid = document.getElementById('accChecklist');
grid.innerHTML = ACC_ITEMS.map(item => `
${item.icon}
${item.name}
Yes
No
`).join('');
}function setAcc(id, val, btn) {
const item = document.getElementById(id);
item.querySelectorAll('.toggle-btn').forEach(b => {
b.classList.remove('yes','no');
});
btn.classList.add(val);
item.classList.toggle('checked', val === 'yes');
}/* ═══════════════════════════════════════════════
STEPPER NAVIGATION
═══════════════════════════════════════════════ */
let currentStep = 0;
const TOTAL_STEPS = 6;function updateStepper(step) {
document.querySelectorAll('.step').forEach((el, i) => {
el.classList.remove('active','done');
if (i {
el.classList.toggle('done', i el.classList.remove('active'));
const target = document.getElementById(`step-${step}`);
if (target) {
target.classList.add('active');
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
updateStepper(step);
}/* ═══════════════════════════════════════════════
VALIDATION
═══════════════════════════════════════════════ */
function validateStep(step) {
const stepEl = document.getElementById(`step-${step}`);
const required = stepEl.querySelectorAll('[required]');
let valid = true;required.forEach(field => {
const group = field.closest('.field-group');
const val = field.value.trim();
if (!val) {
group && group.classList.add('error');
valid = false;
} else {
group && group.classList.remove('error');
}
});// Email validation
const emailField = stepEl.querySelector('input[type="email"]');
if (emailField && emailField.value) {
const emailGroup = emailField.closest('.field-group');
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailField.value)) {
emailGroup && emailGroup.classList.add('error');
valid = false;
}
}if (!valid) {
const firstError = stepEl.querySelector('.field-group.error [required]');
firstError && firstError.focus();
}return valid;
}// Clear error on input
document.addEventListener('input', e => {
const group = e.target.closest('.field-group');
if (group) group.classList.remove('error');
});document.addEventListener('change', e => {
const group = e.target.closest('.field-group');
if (group) group.classList.remove('error');
});/* ═══════════════════════════════════════════════
SIGNATURE CANVASES
═══════════════════════════════════════════════ */
const sigPads = {};function initSignaturePad(canvasId) {
const canvas = document.getElementById(canvasId);
const ctx = canvas.getContext('2d');// Set actual size to display size for retina
const rect = canvas.getBoundingClientRect();
canvas.width = canvas.offsetWidth * window.devicePixelRatio || canvas.offsetWidth;
canvas.height = 130 * window.devicePixelRatio || 130;
ctx.scale(window.devicePixelRatio || 1, window.devicePixelRatio || 1);ctx.strokeStyle = '#c9a84c';
ctx.lineWidth = 2;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';let drawing = false;
let lastX = 0, lastY = 0;function getPos(e) {
const r = canvas.getBoundingClientRect();
const t = e.touches ? e.touches[0] : e;
return { x: t.clientX - r.left, y: t.clientY - r.top };
}function start(e) {
e.preventDefault();
drawing = true;
const p = getPos(e);
lastX = p.x; lastY = p.y;
ctx.beginPath();
ctx.moveTo(lastX, lastY);
}function draw(e) {
if (!drawing) return;
e.preventDefault();
const p = getPos(e);
ctx.lineTo(p.x, p.y);
ctx.stroke();
lastX = p.x; lastY = p.y;
}function stop() { drawing = false; }canvas.addEventListener('mousedown', start);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stop);
canvas.addEventListener('mouseleave', stop);
canvas.addEventListener('touchstart', start, { passive: false });
canvas.addEventListener('touchmove', draw, { passive: false });
canvas.addEventListener('touchend', stop);// Hint text
ctx.fillStyle = 'rgba(160,133,53,0.35)';
ctx.font = '13px Nunito Sans, sans-serif';
ctx.textAlign = 'center';
ctx.fillText('Sign here…', canvas.width / (window.devicePixelRatio || 1) / 2, 70);sigPads[canvasId] = { ctx, canvas };
}function clearSig(canvasId) {
const { ctx, canvas } = sigPads[canvasId];
const w = canvas.width / (window.devicePixelRatio || 1);
const h = canvas.height / (window.devicePixelRatio || 1);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'rgba(160,133,53,0.35)';
ctx.font = '13px Nunito Sans, sans-serif';
ctx.textAlign = 'center';
ctx.fillText('Sign here…', w/2, 70);
}/* ═══════════════════════════════════════════════
FORM SUBMISSION
═══════════════════════════════════════════════ */
function submitForm() {
if (!validateStep(5)) return;const ref = document.getElementById('formRef').value || generateRef();
document.getElementById('successRef').textContent = `📋 Reference: ${ref}`;document.getElementById('dhForm').style.display = 'none';
document.getElementById('stepper').style.display = 'none';
document.querySelector('.hero').style.display = 'none';
document.getElementById('successScreen').style.display = 'block';
window.scrollTo({ top: 0, behavior: 'smooth' });
}function generateRef() {
const d = new Date();
return `NJ-DHF-${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}${String(d.getDate()).padStart(2,'0')}-${Math.floor(Math.random()*900+100)}`;
}function resetForm() {
document.getElementById('dhForm').reset();
document.getElementById('dhForm').style.display = 'block';
document.getElementById('stepper').style.display = 'flex';
document.querySelector('.hero').style.display = 'block';
document.getElementById('successScreen').style.display = 'none';
currentStep = 0;
showStep(0);
// Re-render dynamic elements
renderSoftware();
renderAccessories();
clearSig('sigIT');
clearSig('sigNJ');
}/* ═══════════════════════════════════════════════
INIT
═══════════════════════════════════════════════ */
document.addEventListener('DOMContentLoaded', () => {
renderSoftware();
renderAccessories();
initSignaturePad('sigIT');
initSignaturePad('sigNJ');// Auto-set today's date
const today = new Date().toISOString().split('T')[0];
const issueDate = document.getElementById('issueDate');
const dateSigned = document.getElementById('dateSigned');
if (issueDate && !issueDate.value) issueDate.value = today;
if (dateSigned && !dateSigned.value) dateSigned.value = today;
});