Insurance — File a Claim
A four-step file-a-claim wizard with a progress tracker that walks through policy and incident type, incident details with date and location, a drag-and-drop evidence dropzone and a review screen, validating each step before issuing a generated claim number on a confirmation screen.
MCP
Code
:root {
--blue: #2563eb;
--blue-d: #1d4ed8;
--blue-50: #eef4ff;
--green: #15a06b;
--green-50: #e7f7f0;
--ink: #0f1a2b;
--muted: #5a6b82;
--bg: #f3f7fc;
--white: #ffffff;
--line: #e2eaf4;
--line-strong: #cdd9ea;
--danger: #d8453a;
--radius: 16px;
--radius-sm: 11px;
--shadow: 0 18px 48px -22px rgba(15, 26, 43, 0.32);
--font: 'Inter', system-ui, -apple-system, sans-serif;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: var(--font);
background:
radial-gradient(900px 520px at 90% -10%, #e3edfd 0%, transparent 60%),
var(--bg);
color: var(--ink);
line-height: 1.55;
-webkit-font-smoothing: antialiased;
min-height: 100vh;
padding: 28px 18px 56px;
}
.wrap { max-width: 720px; margin: 0 auto; }
/* Masthead */
.masthead {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
margin-bottom: 18px;
}
.brand { display: flex; align-items: center; gap: 11px; }
.brand-mark {
width: 40px; height: 40px;
display: grid; place-items: center;
border-radius: 11px;
background: var(--blue); color: #fff;
box-shadow: 0 8px 18px -8px rgba(37, 99, 235, 0.7);
}
.brand-name { font-weight: 800; font-size: 15px; letter-spacing: -0.01em; }
.brand-sub { font-size: 12px; color: var(--muted); font-weight: 500; }
.help-line { font-size: 12.5px; color: var(--muted); font-weight: 500; display: flex; align-items: center; gap: 7px; }
.help-line a { color: var(--blue-d); font-weight: 700; text-decoration: none; }
.help-line a:hover { text-decoration: underline; }
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--green); box-shadow: 0 0 0 4px var(--green-50); }
/* Card */
.card {
background: var(--white);
border: 1px solid var(--line);
border-radius: var(--radius);
box-shadow: var(--shadow);
padding: 28px 30px 30px;
}
.title { font-size: 26px; font-weight: 800; letter-spacing: -0.02em; }
.subtitle { color: var(--muted); font-size: 14.5px; margin-top: 4px; }
/* Steps */
.steps {
list-style: none;
display: flex;
margin: 24px 0 26px;
counter-reset: none;
}
.step {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
position: relative;
font-size: 12.5px;
color: var(--muted);
font-weight: 600;
text-align: center;
}
.step::before {
content: "";
position: absolute;
top: 15px;
left: -50%;
width: 100%;
height: 2px;
background: var(--line-strong);
z-index: 0;
}
.step:first-child::before { display: none; }
.step-dot {
width: 32px; height: 32px;
border-radius: 50%;
background: var(--white);
border: 2px solid var(--line-strong);
display: grid; place-items: center;
position: relative; z-index: 1;
transition: background .25s, border-color .25s, color .25s;
}
.step-num { font-size: 13px; font-weight: 700; color: var(--muted); }
.step.is-active .step-dot { border-color: var(--blue); background: var(--blue-50); }
.step.is-active .step-num { color: var(--blue-d); }
.step.is-active .step-label { color: var(--ink); }
.step.is-done .step-dot { background: var(--green); border-color: var(--green); }
.step.is-done .step-num { color: #fff; }
.step.is-done::before,
.step.is-active::before { background: var(--green); }
.step.is-done .step-num { font-size: 0; }
.step.is-done .step-dot::after {
content: "✓"; color: #fff; font-size: 15px; font-weight: 800;
}
/* Panels */
.panel { border: 0; display: none; }
.panel.is-current { display: block; animation: fade .3s ease; }
@keyframes fade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.panel-title { font-size: 16px; font-weight: 700; letter-spacing: -0.01em; margin-bottom: 14px; }
.panel-title.sub { margin-top: 24px; }
/* Pick cards */
.radio-grid { display: grid; grid-template-columns: 1fr; gap: 10px; }
.radio-grid.two { grid-template-columns: repeat(3, 1fr); }
.pick { cursor: pointer; }
.pick input { position: absolute; opacity: 0; pointer-events: none; }
.pick-body {
display: flex; align-items: center; gap: 12px;
border: 1.5px solid var(--line-strong);
border-radius: var(--radius-sm);
padding: 13px 15px;
background: var(--white);
transition: border-color .18s, background .18s, box-shadow .18s;
}
.pick.small .pick-body { flex-direction: column; gap: 6px; text-align: center; padding: 14px 10px; }
.pick-icon { font-size: 22px; line-height: 1; }
.pick.small .pick-icon { font-size: 24px; }
.pick-main { font-weight: 700; font-size: 14.5px; }
.pick-meta { display: block; font-size: 12px; color: var(--muted); font-weight: 500; }
.pick:hover .pick-body { border-color: var(--blue); }
.pick input:focus-visible + .pick-body { outline: 3px solid var(--blue-50); outline-offset: 2px; border-color: var(--blue); }
.pick input:checked + .pick-body {
border-color: var(--blue);
background: var(--blue-50);
box-shadow: 0 0 0 1px var(--blue) inset;
}
/* Fields */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.field { margin-bottom: 16px; }
.field label, .check { font-size: 13px; font-weight: 600; color: var(--ink); display: block; margin-bottom: 6px; }
input[type="text"], input[type="date"], input[type="time"], textarea, .inline-input {
width: 100%;
font: inherit;
font-size: 14.5px;
color: var(--ink);
background: var(--white);
border: 1.5px solid var(--line-strong);
border-radius: var(--radius-sm);
padding: 11px 13px;
transition: border-color .18s, box-shadow .18s;
}
textarea { resize: vertical; }
input:focus-visible, textarea:focus-visible {
outline: none;
border-color: var(--blue);
box-shadow: 0 0 0 3px var(--blue-50);
}
input.invalid, textarea.invalid { border-color: var(--danger); box-shadow: 0 0 0 3px rgba(216, 69, 58, 0.12); }
.counter { font-size: 12px; color: var(--muted); margin-top: 6px; }
.field-error { color: var(--danger); font-size: 12.5px; font-weight: 600; margin-top: 6px; }
.field-row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.check { display: flex; align-items: center; gap: 8px; font-weight: 600; cursor: pointer; margin: 0; }
.check input { width: 17px; height: 17px; accent-color: var(--blue); cursor: pointer; }
.inline-input { max-width: 160px; }
/* Dropzone */
.hint { font-size: 13px; color: var(--muted); margin-bottom: 14px; }
.dropzone {
border: 2px dashed var(--line-strong);
border-radius: var(--radius);
background: var(--blue-50);
padding: 32px 20px;
text-align: center;
cursor: pointer;
transition: border-color .18s, background .18s;
}
.dropzone:hover, .dropzone:focus-visible { border-color: var(--blue); outline: none; }
.dropzone.is-drag { border-color: var(--blue); background: #e2ecff; transform: scale(1.005); }
.dz-icon { color: var(--blue); display: inline-flex; }
.dz-main { font-weight: 700; font-size: 15px; margin-top: 8px; }
.dz-sub { font-size: 13px; color: var(--muted); margin-top: 2px; }
.dz-link { color: var(--blue-d); font-weight: 700; text-decoration: underline; }
.file-list { list-style: none; margin: 16px 0 6px; display: grid; gap: 9px; }
.file-item {
display: flex; align-items: center; gap: 12px;
border: 1px solid var(--line); border-radius: var(--radius-sm);
padding: 10px 12px; background: var(--white);
animation: fade .25s ease;
}
.file-thumb {
width: 38px; height: 38px; border-radius: 9px; flex: 0 0 auto;
display: grid; place-items: center; font-size: 17px;
background: var(--blue-50); color: var(--blue-d); font-weight: 700;
overflow: hidden;
}
.file-thumb img { width: 100%; height: 100%; object-fit: cover; }
.file-meta { flex: 1; min-width: 0; }
.file-name { font-size: 13.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.file-size { font-size: 12px; color: var(--muted); }
.file-remove {
border: 0; background: none; cursor: pointer; color: var(--muted);
font-size: 20px; line-height: 1; padding: 4px 6px; border-radius: 7px;
transition: color .15s, background .15s;
}
.file-remove:hover { color: var(--danger); background: #fbeceb; }
.files-count { font-size: 12.5px; color: var(--muted); font-weight: 500; }
/* Review */
.review { display: grid; gap: 0; border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; margin-bottom: 18px; }
.review-row { display: flex; justify-content: space-between; gap: 16px; padding: 12px 15px; border-bottom: 1px solid var(--line); }
.review-row:last-child { border-bottom: 0; }
.review-row:nth-child(even) { background: #f9fbfe; }
.review-k { font-size: 13px; color: var(--muted); font-weight: 600; flex: 0 0 auto; }
.review-v { font-size: 13.5px; font-weight: 600; text-align: right; }
.review-edit { font-size: 12px; color: var(--blue-d); font-weight: 700; background: none; border: 0; cursor: pointer; padding: 0; margin-left: 10px; }
.review-edit:hover { text-decoration: underline; }
.attest { margin-top: 4px; }
/* Nav */
.nav { display: flex; align-items: center; gap: 12px; margin-top: 26px; padding-top: 22px; border-top: 1px solid var(--line); }
.nav-spacer { flex: 1; }
.btn {
font: inherit; font-weight: 700; font-size: 14.5px;
border-radius: var(--radius-sm); padding: 12px 22px;
cursor: pointer; border: 1.5px solid transparent;
transition: background .18s, transform .08s, box-shadow .18s;
}
.btn:active { transform: translateY(1px); }
.btn.primary { background: var(--blue); color: #fff; box-shadow: 0 10px 22px -10px rgba(37, 99, 235, 0.8); }
.btn.primary:hover { background: var(--blue-d); }
.btn.ghost { background: var(--white); color: var(--ink); border-color: var(--line-strong); }
.btn.ghost:hover { border-color: var(--muted); }
.btn[disabled] { opacity: .6; cursor: progress; }
/* Confirmation */
.confirm { text-align: center; padding: 10px 0 4px; animation: fade .35s ease; }
.confirm-badge {
width: 72px; height: 72px; margin: 6px auto 16px;
border-radius: 50%; background: var(--green); color: #fff;
display: grid; place-items: center;
box-shadow: 0 14px 30px -12px rgba(21, 160, 107, 0.7);
}
.confirm-title { font-size: 23px; font-weight: 800; letter-spacing: -0.02em; }
.confirm-text { color: var(--muted); font-size: 14.5px; margin-top: 6px; }
.claim-no {
margin: 22px auto; max-width: 340px;
background: var(--blue-50); border: 1px solid #d6e3fb;
border-radius: var(--radius-sm); padding: 16px;
}
.claim-no-label { display: block; font-size: 12px; color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: .06em; }
.claim-no strong { font-size: 27px; font-weight: 800; color: var(--blue-d); letter-spacing: .02em; }
.next-steps { list-style: none; max-width: 380px; margin: 0 auto 22px; text-align: left; display: grid; gap: 11px; }
.next-steps li { display: flex; align-items: center; gap: 12px; font-size: 14px; color: var(--ink); }
.ns-num {
flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%;
background: var(--white); border: 1.5px solid var(--line-strong);
display: grid; place-items: center; font-size: 13px; font-weight: 800; color: var(--blue-d);
}
.legal { text-align: center; font-size: 12px; color: var(--muted); margin-top: 18px; }
/* Responsive */
@media (max-width: 520px) {
body { padding: 18px 12px 40px; }
.card { padding: 20px 16px 22px; }
.title { font-size: 22px; }
.masthead { flex-direction: column; align-items: flex-start; gap: 8px; }
.step-label { font-size: 0; }
.step.is-active .step-label, .step:hover .step-label { font-size: 11px; }
.radio-grid.two { grid-template-columns: 1fr 1fr; }
.grid-2 { grid-template-columns: 1fr; }
.nav { flex-wrap: wrap; }
.btn { flex: 1; text-align: center; }
.nav-spacer { display: none; }
.claim-no strong { font-size: 22px; }
}(function () {
'use strict';
var form = document.getElementById('claim-form');
if (!form) return;
var steps = Array.prototype.slice.call(document.querySelectorAll('.step'));
var panels = Array.prototype.slice.call(document.querySelectorAll('.panel'));
var backBtn = document.getElementById('back');
var nextBtn = document.getElementById('next');
var submitBtn = document.getElementById('submit');
var confirmEl = document.getElementById('confirm');
var restartBtn = document.getElementById('restart');
var TOTAL = panels.length;
var current = 1;
var files = [];
/* ---------- step navigation ---------- */
function render() {
panels.forEach(function (p) {
p.classList.toggle('is-current', Number(p.dataset.panel) === current);
});
steps.forEach(function (s) {
var n = Number(s.dataset.step);
s.classList.toggle('is-active', n === current);
s.classList.toggle('is-done', n < current);
});
backBtn.hidden = current === 1;
nextBtn.hidden = current === TOTAL;
submitBtn.hidden = current !== TOTAL;
if (current === TOTAL) buildReview();
form.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
function goTo(step) {
current = Math.min(Math.max(step, 1), TOTAL);
render();
}
/* ---------- validation ---------- */
function showError(name, show) {
var el = document.querySelector('[data-error="' + name + '"]');
if (el) el.hidden = !show;
}
function validateStep(step) {
var ok = true;
if (step === 1) {
var policy = form.querySelector('input[name="policy"]:checked');
var incident = form.querySelector('input[name="incident"]:checked');
showError('policy', !policy); if (!policy) ok = false;
showError('incident', !incident); if (!incident) ok = false;
} else if (step === 2) {
var date = form.date, loc = form.location, desc = form.description;
[['date', date.value.trim() !== ''],
['location', loc.value.trim() !== ''],
['description', desc.value.trim().length >= 20]
].forEach(function (pair) {
var valid = pair[1];
var input = form[pair[0]];
input.classList.toggle('invalid', !valid);
showError(pair[0], !valid);
if (!valid) ok = false;
});
} else if (step === 4) {
var attest = document.getElementById('attest');
showError('attest', !attest.checked);
if (!attest.checked) ok = false;
}
return ok;
}
nextBtn.addEventListener('click', function () {
if (validateStep(current)) goTo(current + 1);
});
backBtn.addEventListener('click', function () { goTo(current - 1); });
/* live clear of errors */
['date', 'location', 'description'].forEach(function (n) {
var el = form[n];
if (el) el.addEventListener('input', function () {
el.classList.remove('invalid');
showError(n, false);
});
});
form.querySelectorAll('input[name="policy"],input[name="incident"]').forEach(function (r) {
r.addEventListener('change', function () { showError(r.name, false); });
});
/* ---------- description counter ---------- */
var desc = form.description;
var counter = document.querySelector('[data-counter="description"]');
if (desc && counter) {
desc.addEventListener('input', function () {
counter.textContent = desc.value.trim().length;
});
}
/* ---------- police report toggle ---------- */
var police = document.getElementById('police');
var reportNo = document.getElementById('report-no');
if (police && reportNo) {
police.addEventListener('change', function () {
reportNo.hidden = !police.checked;
if (police.checked) reportNo.focus();
});
}
/* ---------- dropzone ---------- */
var dropzone = document.getElementById('dropzone');
var fileInput = document.getElementById('file-input');
var fileList = document.getElementById('file-list');
var filesCount = document.getElementById('files-count');
function formatSize(bytes) {
if (bytes < 1024) return bytes + ' B';
if (bytes < 1048576) return (bytes / 1024).toFixed(0) + ' KB';
return (bytes / 1048576).toFixed(1) + ' MB';
}
function renderFiles() {
fileList.innerHTML = '';
files.forEach(function (f, i) {
var li = document.createElement('li');
li.className = 'file-item';
var thumb = document.createElement('span');
thumb.className = 'file-thumb';
if (f.type && f.type.indexOf('image/') === 0) {
var img = document.createElement('img');
img.alt = '';
img.src = URL.createObjectURL(f);
thumb.appendChild(img);
} else {
thumb.textContent = 'PDF';
}
var meta = document.createElement('div');
meta.className = 'file-meta';
var nm = document.createElement('div');
nm.className = 'file-name';
nm.textContent = f.name;
var sz = document.createElement('div');
sz.className = 'file-size';
sz.textContent = formatSize(f.size);
meta.appendChild(nm); meta.appendChild(sz);
var rm = document.createElement('button');
rm.type = 'button';
rm.className = 'file-remove';
rm.setAttribute('aria-label', 'Remove ' + f.name);
rm.innerHTML = '×';
rm.addEventListener('click', function () {
files.splice(i, 1);
renderFiles();
});
li.appendChild(thumb); li.appendChild(meta); li.appendChild(rm);
fileList.appendChild(li);
});
filesCount.textContent = files.length === 0
? 'No files added yet.'
: files.length + (files.length === 1 ? ' file added.' : ' files added.');
}
function addFiles(list) {
Array.prototype.forEach.call(list, function (f) {
if (f.size > 10 * 1048576) return;
files.push(f);
});
renderFiles();
}
if (dropzone) {
dropzone.addEventListener('click', function () { fileInput.click(); });
dropzone.addEventListener('keydown', function (e) {
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); fileInput.click(); }
});
fileInput.addEventListener('change', function () { addFiles(fileInput.files); fileInput.value = ''; });
['dragenter', 'dragover'].forEach(function (ev) {
dropzone.addEventListener(ev, function (e) { e.preventDefault(); dropzone.classList.add('is-drag'); });
});
['dragleave', 'drop'].forEach(function (ev) {
dropzone.addEventListener(ev, function (e) { e.preventDefault(); dropzone.classList.remove('is-drag'); });
});
dropzone.addEventListener('drop', function (e) {
if (e.dataTransfer && e.dataTransfer.files) addFiles(e.dataTransfer.files);
});
}
/* ---------- review ---------- */
function buildReview() {
var review = document.getElementById('review');
review.innerHTML = '';
var policy = (form.querySelector('input[name="policy"]:checked') || {}).value || '—';
var incident = (form.querySelector('input[name="incident"]:checked') || {}).value || '—';
var dateVal = form.date.value || '—';
var timeVal = form.time.value || '';
var rows = [
['Policy', policy, 1],
['Incident type', incident, 1],
['Date / time', dateVal + (timeVal ? ' · ' + timeVal : ''), 2],
['Location', form.location.value || '—', 2],
['Description', form.description.value || '—', 2],
['Evidence', files.length + (files.length === 1 ? ' file' : ' files'), 3]
];
if (police && police.checked) {
rows.splice(5, 0, ['Police report', '#' + (reportNo.value || 'on file'), 2]);
}
rows.forEach(function (r) {
var row = document.createElement('div');
row.className = 'review-row';
var k = document.createElement('dt');
k.className = 'review-k';
k.textContent = r[0];
var wrap = document.createElement('dd');
wrap.style.display = 'flex';
wrap.style.alignItems = 'center';
var v = document.createElement('span');
v.className = 'review-v';
v.textContent = r[1];
var edit = document.createElement('button');
edit.type = 'button';
edit.className = 'review-edit';
edit.textContent = 'Edit';
edit.addEventListener('click', function () { goTo(r[2]); });
wrap.appendChild(v); wrap.appendChild(edit);
row.appendChild(k); row.appendChild(wrap);
review.appendChild(row);
});
}
/* ---------- submit ---------- */
function genClaimNo() {
var yr = new Date().getFullYear();
var n = Math.floor(100000 + Math.random() * 900000);
return 'NW-CLM-' + yr + '-' + n;
}
form.addEventListener('submit', function (e) {
e.preventDefault();
if (!validateStep(4)) return;
submitBtn.disabled = true;
submitBtn.textContent = 'Submitting…';
setTimeout(function () {
form.hidden = true;
document.getElementById('steps').hidden = true;
document.getElementById('claim-number').textContent = genClaimNo();
confirmEl.hidden = false;
confirmEl.scrollIntoView({ behavior: 'smooth', block: 'center' });
}, 1100);
});
restartBtn.addEventListener('click', function () {
form.reset();
files = [];
renderFiles();
if (counter) counter.textContent = '0';
if (reportNo) reportNo.hidden = true;
form.querySelectorAll('.invalid').forEach(function (el) { el.classList.remove('invalid'); });
document.querySelectorAll('.field-error').forEach(function (el) { el.hidden = true; });
submitBtn.disabled = false;
submitBtn.textContent = 'Submit claim';
form.hidden = false;
document.getElementById('steps').hidden = false;
confirmEl.hidden = true;
goTo(1);
});
/* init */
render();
})();<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>File a Claim — Northwind Mutual</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<main class="wrap">
<header class="masthead">
<div class="brand">
<span class="brand-mark" aria-hidden="true">
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
</span>
<div>
<p class="brand-name">Northwind Mutual</p>
<p class="brand-sub">Claims Center</p>
</div>
</div>
<div class="help-line">
<span class="dot" aria-hidden="true"></span>
24/7 support · <a href="#">1-800-555-0147</a>
</div>
</header>
<section class="card" aria-labelledby="claim-title">
<h1 id="claim-title" class="title">File a claim</h1>
<p class="subtitle">It takes about 5 minutes. We’ll save your answers as you go.</p>
<!-- Progress tracker -->
<ol class="steps" id="steps" aria-label="Claim progress">
<li class="step is-active" data-step="1">
<span class="step-dot"><span class="step-num">1</span></span>
<span class="step-label">Policy & incident</span>
</li>
<li class="step" data-step="2">
<span class="step-dot"><span class="step-num">2</span></span>
<span class="step-label">Details</span>
</li>
<li class="step" data-step="3">
<span class="step-dot"><span class="step-num">3</span></span>
<span class="step-label">Evidence</span>
</li>
<li class="step" data-step="4">
<span class="step-dot"><span class="step-num">4</span></span>
<span class="step-label">Review</span>
</li>
</ol>
<form id="claim-form" novalidate>
<!-- STEP 1 -->
<fieldset class="panel is-current" data-panel="1">
<legend class="panel-title">Which policy is this about?</legend>
<div class="radio-grid" role="radiogroup" aria-label="Policy">
<label class="pick">
<input type="radio" name="policy" value="Auto · NW-AUT-48213" required />
<span class="pick-body">
<span class="pick-icon" aria-hidden="true">🚗</span>
<span class="pick-main">Auto</span>
<span class="pick-meta">NW-AUT-48213 · 2021 Honda Civic</span>
</span>
</label>
<label class="pick">
<input type="radio" name="policy" value="Homeowners · NW-HOM-77104" />
<span class="pick-body">
<span class="pick-icon" aria-hidden="true">🏠</span>
<span class="pick-main">Homeowners</span>
<span class="pick-meta">NW-HOM-77104 · 14 Larkspur Ln</span>
</span>
</label>
<label class="pick">
<input type="radio" name="policy" value="Renters · NW-REN-30558" />
<span class="pick-body">
<span class="pick-icon" aria-hidden="true">🛋️</span>
<span class="pick-main">Renters</span>
<span class="pick-meta">NW-REN-30558 · Apt 5B</span>
</span>
</label>
</div>
<p class="field-error" data-error="policy" hidden>Please choose a policy.</p>
<p class="panel-title sub">What kind of incident?</p>
<div class="radio-grid two" role="radiogroup" aria-label="Incident type">
<label class="pick small"><input type="radio" name="incident" value="Collision" required /><span class="pick-body"><span class="pick-icon" aria-hidden="true">💥</span><span class="pick-main">Collision</span></span></label>
<label class="pick small"><input type="radio" name="incident" value="Theft" /><span class="pick-body"><span class="pick-icon" aria-hidden="true">🔓</span><span class="pick-main">Theft</span></span></label>
<label class="pick small"><input type="radio" name="incident" value="Water damage" /><span class="pick-body"><span class="pick-icon" aria-hidden="true">💧</span><span class="pick-main">Water damage</span></span></label>
<label class="pick small"><input type="radio" name="incident" value="Fire" /><span class="pick-body"><span class="pick-icon" aria-hidden="true">🔥</span><span class="pick-main">Fire</span></span></label>
<label class="pick small"><input type="radio" name="incident" value="Weather / hail" /><span class="pick-body"><span class="pick-icon" aria-hidden="true">⛈️</span><span class="pick-main">Weather / hail</span></span></label>
<label class="pick small"><input type="radio" name="incident" value="Other" /><span class="pick-body"><span class="pick-icon" aria-hidden="true">📋</span><span class="pick-main">Other</span></span></label>
</div>
<p class="field-error" data-error="incident" hidden>Please choose an incident type.</p>
</fieldset>
<!-- STEP 2 -->
<fieldset class="panel" data-panel="2">
<legend class="panel-title">Tell us what happened</legend>
<div class="grid-2">
<div class="field">
<label for="date">Date of incident</label>
<input type="date" id="date" name="date" max="2026-06-22" required />
<p class="field-error" data-error="date" hidden>Please enter the date.</p>
</div>
<div class="field">
<label for="time">Approx. time</label>
<input type="time" id="time" name="time" />
</div>
</div>
<div class="field">
<label for="location">Where did it happen?</label>
<input type="text" id="location" name="location" placeholder="e.g. Maple St & 4th Ave, Riverton" autocomplete="off" required />
<p class="field-error" data-error="location" hidden>Please enter a location.</p>
</div>
<div class="field">
<label for="description">Describe the incident</label>
<textarea id="description" name="description" rows="4" minlength="20" placeholder="What happened, who was involved, and any damage you noticed…" required></textarea>
<div class="counter"><span data-counter="description">0</span> / 20 characters minimum</div>
<p class="field-error" data-error="description" hidden>Please add at least 20 characters.</p>
</div>
<div class="field-row">
<label class="check"><input type="checkbox" id="police" name="police" /> A police report was filed</label>
<input type="text" id="report-no" name="report-no" class="inline-input" placeholder="Report #" hidden />
</div>
</fieldset>
<!-- STEP 3 -->
<fieldset class="panel" data-panel="3">
<legend class="panel-title">Upload supporting evidence</legend>
<p class="hint">Photos of the damage, receipts, or any documents. JPG, PNG or PDF up to 10 MB each.</p>
<div class="dropzone" id="dropzone" tabindex="0" role="button" aria-label="Upload evidence: drag files here or press Enter to browse">
<span class="dz-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" width="34" height="34" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
</span>
<p class="dz-main">Drag & drop files here</p>
<p class="dz-sub">or <span class="dz-link">browse from your device</span></p>
<input type="file" id="file-input" multiple accept="image/*,.pdf" hidden />
</div>
<ul class="file-list" id="file-list" aria-live="polite"></ul>
<p class="files-count" id="files-count">No files added yet.</p>
</fieldset>
<!-- STEP 4 -->
<fieldset class="panel" data-panel="4">
<legend class="panel-title">Review & submit</legend>
<dl class="review" id="review"></dl>
<label class="check attest"><input type="checkbox" id="attest" name="attest" required /> I confirm the information above is accurate to the best of my knowledge.</label>
<p class="field-error" data-error="attest" hidden>Please confirm before submitting.</p>
</fieldset>
<!-- Nav -->
<div class="nav">
<button type="button" class="btn ghost" id="back" hidden>Back</button>
<span class="nav-spacer"></span>
<button type="button" class="btn primary" id="next">Continue</button>
<button type="submit" class="btn primary submit" id="submit" hidden>Submit claim</button>
</div>
</form>
<!-- CONFIRMATION -->
<div class="confirm" id="confirm" hidden>
<div class="confirm-badge" aria-hidden="true">
<svg viewBox="0 0 24 24" width="36" height="36" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
</div>
<h2 class="confirm-title">Your claim is filed</h2>
<p class="confirm-text">We’ve received everything and a claims specialist will be in touch.</p>
<div class="claim-no">
<span class="claim-no-label">Claim number</span>
<strong id="claim-number">—</strong>
</div>
<ul class="next-steps">
<li><span class="ns-num">1</span> Review begins within <strong>24–48 hours</strong>.</li>
<li><span class="ns-num">2</span> An adjuster may call to confirm details.</li>
<li><span class="ns-num">3</span> Track status anytime in your dashboard.</li>
</ul>
<button type="button" class="btn ghost" id="restart">File another claim</button>
</div>
</section>
<p class="legal">Illustrative UI only — not a real insurance claim or binding submission.</p>
</main>
<script src="script.js"></script>
</body>
</html>File a Claim
A reassuring, multi-step claim filing flow built for clarity under stress. A horizontal progress tracker marks the four stages — Policy & incident, Details, Evidence and Review — and each step validates before the wizard advances, so policyholders never lose their place or submit an incomplete form.
Step one picks a policy and the type of incident with friendly icon cards. Step two captures what happened, when and where, with a calm date and location form and a short description. Step three is a drag-and-drop evidence dropzone that accepts photos and documents, lists each file with its size and a remove control, and shows a running count. The review step summarises every answer with quick edit links back to any stage.
Submitting runs a brief processing state, then lands on a confirmation screen with a generated claim number, an estimated review window and what happens next. Everything is deterministic, dependency-free vanilla JS — easy to wire to a real claims API.
Illustrative UI only — not a real insurance claim or binding submission.