Complete Study Closeout
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Complete Study Closeout</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background: #f5f6f7;
color: #1a1a1a;
line-height: 1.6;
padding: 24px 16px 48px;
}
.wrap {
max-width: 720px;
margin: 0 auto;
}
/* ── Header ── */
.page-header {
background: #ffffff;
border-radius: 10px;
padding: 28px 32px 24px;
margin-bottom: 20px;
border-top: 4px solid #087a6a;
}
.header-eyebrow {
font-size: 11px;
font-weight: 600;
letter-spacing: 0.12em;
text-transform: uppercase;
color: #087a6a;
margin-bottom: 8px;
}
.page-header h1 {
font-size: 24px;
font-weight: 700;
color: #111;
margin-bottom: 6px;
}
.header-sub {
font-size: 13px;
color: #555;
margin-bottom: 16px;
}
.header-note {
background: #f0faf8;
border-left: 3px solid #087a6a;
border-radius: 0 6px 6px 0;
padding: 10px 14px;
font-size: 13px;
color: #333;
line-height: 1.6;
}
.header-note strong { color: #111; font-weight: 600; }
/* ── Progress bar ── */
.progress-wrap {
background: #fff;
border-radius: 10px;
padding: 16px 24px;
margin-bottom: 20px;
display: flex;
align-items: center;
gap: 16px;
}
.progress-label {
font-size: 13px;
font-weight: 600;
color: #333;
white-space: nowrap;
flex-shrink: 0;
}
.progress-track {
flex: 1;
height: 8px;
background: #d0d0d0;
border-radius: 4px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: #087a6a;
border-radius: 4px;
transition: width 0.35s ease;
width: 0%;
}
.progress-count {
font-size: 13px;
font-weight: 700;
color: #087a6a;
white-space: nowrap;
flex-shrink: 0;
min-width: 48px;
text-align: right;
}
/* ── Section card ── */
.section-card {
background: #fff;
border-radius: 10px;
margin-bottom: 14px;
overflow: hidden;
border: 1px solid #e4e4e4;
transition: border-color 0.2s;
}
.section-card.all-done {
border-color: #087a6a;
}
/* Section header is a <button> for full keyboard + screen-reader support */
.section-header {
display: flex;
align-items: center;
gap: 12px;
padding: 14px 20px;
cursor: pointer;
width: 100%;
background: transparent;
border: none;
border-bottom: 1px solid #f0f0f0;
text-align: left;
transition: background 0.15s;
font-family: inherit;
}
.section-header:hover { background: #f9f9f9; }
.section-header:focus-visible {
outline: 3px solid #087a6a;
outline-offset: -3px;
border-radius: 9px 9px 0 0;
}
.section-card.all-done .section-header { background: #f0faf8; border-bottom-color: #cceee8; }
.section-num {
width: 28px; height: 28px;
border-radius: 50%;
background: #087a6a;
color: #fff;
font-size: 12px;
font-weight: 700;
display: flex; align-items: center; justify-content: center;
flex-shrink: 0;
transition: background 0.2s;
/* Hidden from AT — the button label provides context */
aria-hidden: true;
}
.section-card.all-done .section-num { background: #065a4f; }
.section-title-wrap { flex: 1; }
.section-title {
font-size: 14px;
font-weight: 700;
color: #111;
line-height: 1.3;
}
.section-subtitle {
font-size: 12px;
color: #666;
margin-top: 1px;
}
.section-badge {
font-size: 11px;
font-weight: 600;
padding: 3px 10px;
border-radius: 20px;
background: #e8e8e8;
color: #444;
flex-shrink: 0;
transition: all 0.2s;
}
.section-card.all-done .section-badge { background: #d0ede8; color: #065a4f; }
.section-chevron {
font-size: 12px;
color: #666;
flex-shrink: 0;
transition: transform 0.2s;
/* Decorative — aria-expanded on the button conveys state */
}
.section-card.collapsed .section-chevron { transform: rotate(-90deg); }
/* ── Section body ── */
.section-body {
padding: 4px 0 8px;
}
.section-card.collapsed .section-body { display: none; }
/* ── Checklist items ── */
/* Each item is a <div role="checkbox"> with tabindex for keyboard nav */
.check-item {
display: flex;
align-items: flex-start;
gap: 12px;
padding: 10px 20px;
cursor: pointer;
transition: background 0.12s;
border-radius: 6px;
margin: 0 8px;
}
.check-item:hover { background: #f5fdf9; }
.check-item:focus-visible {
outline: 3px solid #087a6a;
outline-offset: 1px;
}
.check-item.checked { opacity: 0.75; }
.check-box {
width: 18px; height: 18px;
border: 2px solid #767676;
border-radius: 4px;
flex-shrink: 0;
margin-top: 2px;
display: flex; align-items: center; justify-content: center;
transition: all 0.15s;
background: #fff;
}
.check-item.checked .check-box {
background: #087a6a;
border-color: #087a6a;
}
.check-tick {
display: none;
color: #fff;
font-size: 11px;
font-weight: 700;
line-height: 1;
}
.check-item.checked .check-tick { display: block; }
.check-text {
font-size: 13px;
color: #222;
line-height: 1.6;
flex: 1;
}
.check-item.checked .check-text {
text-decoration: line-through;
color: #767676;
}
.check-text strong { font-weight: 600; color: #111; }
.check-item.checked .check-text strong { color: #767676; }
/* Sub-items (indented) */
.sub-items {
margin: 0 8px 2px 52px;
}
.sub-item {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 6px 12px 6px 0;
cursor: pointer;
border-radius: 6px;
transition: background 0.12s;
}
.sub-item:hover { background: #f5fdf9; }
.sub-item:focus-visible {
outline: 3px solid #087a6a;
outline-offset: 1px;
}
.sub-item.checked { opacity: 0.75; }
.sub-box {
width: 16px; height: 16px;
border: 2px solid #767676;
border-radius: 3px;
flex-shrink: 0;
margin-top: 3px;
display: flex; align-items: center; justify-content: center;
transition: all 0.15s;
background: #fff;
}
.sub-item.checked .sub-box { background: #087a6a; border-color: #087a6a; }
.sub-tick { display: none; color: #fff; font-size: 9px; font-weight: 700; }
.sub-item.checked .sub-tick { display: block; }
.sub-text {
font-size: 13px;
color: #222;
line-height: 1.5;
flex: 1;
}
.sub-item.checked .sub-text { text-decoration: line-through; color: #767676; }
/* ── Completion banner ── */
.completion-banner {
display: none;
background: #065a4f;
border-radius: 10px;
padding: 20px 24px;
margin-bottom: 20px;
text-align: center;
color: #fff;
}
.completion-banner.show { display: block; }
.completion-banner h2 { font-size: 18px; font-weight: 700; margin-bottom: 6px; }
.completion-banner p { font-size: 13px; color: rgba(255,255,255,0.9); margin-bottom: 14px; }
.reset-btn {
display: inline-block;
padding: 8px 20px;
border: 2px solid rgba(255,255,255,0.8);
border-radius: 6px;
color: #fff;
font-size: 13px;
font-weight: 600;
cursor: pointer;
background: transparent;
transition: background 0.15s;
font-family: inherit;
}
.reset-btn:hover { background: rgba(255,255,255,0.2); }
.reset-btn:focus-visible {
outline: 3px solid #fff;
outline-offset: 2px;
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
.progress-fill,
.section-chevron,
.check-box,
.sub-box { transition: none; }
}
</style>
</head>
<body>
<div class="wrap">
<!-- Header -->
<div class="page-header">
<p class="header-eyebrow" aria-hidden="true">Certified Workflow · Verily Viewpoint Site CTMS</p>
<h1>Complete Study Closeout</h1>
<p class="header-sub">TrialPath · Finance · Enterprise · Insights</p>
<div class="header-note" role="note">
<strong>Note:</strong> Sites may have varying internal processes for study closeout. Use this workflow to develop SOPs, support training, and define CTMS-related closeout activities. Check off each step in order to track your progress.
</div>
</div>
<!-- Progress -->
<div class="progress-wrap">
<p class="progress-label" id="progress-label">Overall progress</p>
<div class="progress-track" role="progressbar" aria-labelledby="progress-label" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" id="progress-bar">
<div class="progress-fill" id="progress-fill"></div>
</div>
<p class="progress-count" id="progress-count" aria-live="polite" aria-atomic="true">0 / 0</p>
</div>
<!-- Completion banner -->
<div class="completion-banner" id="completion-banner" role="status" aria-live="polite">
<h2>✓ Study closeout complete</h2>
<p>All steps have been checked off. Make sure study documentation is archived and stakeholders have been notified.</p>
<button class="reset-btn" onclick="resetAll()">Reset checklist</button>
</div>
<!-- ── Section 1: TrialPath — Participants & visits ── -->
<div class="section-card" id="sec-1">
<button class="section-header" onclick="toggleSection('sec-1')" aria-expanded="true" aria-controls="body-sec-1" id="hdr-sec-1">
<span class="section-num" aria-hidden="true">1</span>
<span class="section-title-wrap">
<span class="section-title">TrialPath — Participants & visits</span>
<span class="section-subtitle">Confirm participant data is finalized before proceeding to Finance</span>
</span>
<span class="section-badge" id="badge-sec-1" aria-hidden="true">0 / 6</span>
<span class="section-chevron" aria-hidden="true">▼</span>
</button>
<div class="section-body" id="body-sec-1" role="group" aria-labelledby="hdr-sec-1">
<div class="check-item" id="c-1-1" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-1-1')" onkeydown="handleKey(event,'c-1-1')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text"><strong>Confirm each participant is on the correct protocol version.</strong> If needed, migrate participants to the correct version. For more, see the <strong>Migrate Study Participants</strong> guide.</span>
</div>
<div class="check-item" id="c-1-2" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-1-2')" onkeydown="handleKey(event,'c-1-2')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text"><strong>Confirm all participants are linked to the correct consent version.</strong> If needed, update or add final consent versions. For more, see the <strong>Consent and Reconsent Study Participants</strong> guide.</span>
</div>
<div class="check-item" id="c-1-3" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-1-3')" onkeydown="handleKey(event,'c-1-3')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text"><strong>Complete all outstanding participant visits and activities</strong> to avoid leaving outstanding charges. For more, see the <strong>Complete Visits</strong> guide and the <strong>Complete Study Activities</strong> guide.</span>
</div>
<div class="check-item" id="c-1-4" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-1-4')" onkeydown="handleKey(event,'c-1-4')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text"><strong>Confirm all participant statuses have been updated</strong> to one of the following:</span>
</div>
<div class="sub-items" role="group" aria-label="Participant status options">
<div class="sub-item" id="c-1-5" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-1-5')" onkeydown="handleKey(event,'c-1-5')">
<span class="sub-box" aria-hidden="true"><span class="sub-tick">✓</span></span>
<span class="sub-text"><strong>Completed</strong> — Participant fully completed study.</span>
</div>
<div class="sub-item" id="c-1-6" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-1-6')" onkeydown="handleKey(event,'c-1-6')">
<span class="sub-box" aria-hidden="true"><span class="sub-tick">✓</span></span>
<span class="sub-text"><strong>Off Study</strong> — Participant dropped out, withdrew, etc. prior to study closeout.</span>
</div>
</div>
</div>
</div>
<!-- ── Section 2: Finance ── -->
<div class="section-card" id="sec-2">
<button class="section-header" onclick="toggleSection('sec-2')" aria-expanded="true" aria-controls="body-sec-2" id="hdr-sec-2">
<span class="section-num" aria-hidden="true">2</span>
<span class="section-title-wrap">
<span class="section-title">Finance — Revenue, expenses, & payments</span>
<span class="section-subtitle">Requires Section 1 to be finalized first</span>
</span>
<span class="section-badge" id="badge-sec-2" aria-hidden="true">0 / 5</span>
<span class="section-chevron" aria-hidden="true">▼</span>
</button>
<div class="section-body" id="body-sec-2" role="group" aria-labelledby="hdr-sec-2">
<div class="check-item" id="c-2-1" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-2-1')" onkeydown="handleKey(event,'c-2-1')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text"><strong>Confirm all TrialPath participant data has been finalized</strong> (Section 1 above) to avoid leaving outstanding charges.</span>
</div>
<div class="check-item" id="c-2-2" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-2-2')" onkeydown="handleKey(event,'c-2-2')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text"><strong>Confirm all study-related activities are accounted for</strong> and all relevant dates have been entered. For more, see the <strong>Add Invoiceable Study Activities</strong> guide.</span>
</div>
<div class="check-item" id="c-2-3" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-2-3')" onkeydown="handleKey(event,'c-2-3')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text"><strong>Reconcile any pending accountables in Accounts Receivable (AR) and Accounts Payable (AP).</strong> For more, see the <strong>Manage Accounts Receivable</strong> guide and the <strong>Manage Accounts Payable</strong> guide.</span>
</div>
<div class="check-item" id="c-2-4" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-2-4')" onkeydown="handleKey(event,'c-2-4')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text"><strong>Reconcile and log all payments,</strong> applying them to invoices and/or accountables. Verify all payments have been correctly allocated — there should be no outstanding AR and AP items remaining. For more, see the <strong>Record Payments</strong> guide.</span>
</div>
<div class="check-item" id="c-2-5" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-2-5')" onkeydown="handleKey(event,'c-2-5')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text"><strong>Confirm budget end dates have been updated accordingly.</strong> If additional study-level charges or administrative fees are anticipated, budget end dates may be left blank for now — return later to enter a budget end date once all charges and/or fees are settled.</span>
</div>
</div>
</div>
<!-- ── Section 3: TrialPath — Site study closeout ── -->
<div class="section-card" id="sec-3">
<button class="section-header" onclick="toggleSection('sec-3')" aria-expanded="true" aria-controls="body-sec-3" id="hdr-sec-3">
<span class="section-num" aria-hidden="true">3</span>
<span class="section-title-wrap">
<span class="section-title">TrialPath — Site study closeout</span>
<span class="section-subtitle">Update study details and team end dates at the site level</span>
</span>
<span class="section-badge" id="badge-sec-3" aria-hidden="true">0 / 4</span>
<span class="section-chevron" aria-hidden="true">▼</span>
</button>
<div class="section-body" id="body-sec-3" role="group" aria-labelledby="hdr-sec-3">
<div class="check-item" id="c-3-0" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-3-0')" onkeydown="handleKey(event,'c-3-0')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text">On the <strong>Study Details tab,</strong> complete the following. For more, see the <strong>Edit Site Study Details</strong> guide.</span>
</div>
<div class="sub-items" role="group" aria-label="Study Details tab steps">
<div class="sub-item" id="c-3-1" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-3-1')" onkeydown="handleKey(event,'c-3-1')">
<span class="sub-box" aria-hidden="true"><span class="sub-tick">✓</span></span>
<span class="sub-text"><strong>Update the site study status to Completed or Finished,</strong> as applicable. Site study status updates only apply to the site level.</span>
</div>
<div class="sub-item" id="c-3-2" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-3-2')" onkeydown="handleKey(event,'c-3-2')">
<span class="sub-box" aria-hidden="true"><span class="sub-tick">✓</span></span>
<span class="sub-text"><strong>Enter the Site Study End Date.</strong></span>
</div>
<div class="sub-item" id="c-3-3" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-3-3')" onkeydown="handleKey(event,'c-3-3')">
<span class="sub-box" aria-hidden="true"><span class="sub-tick">✓</span></span>
<span class="sub-text"><strong>Enter the Site Enrollment End Date.</strong></span>
</div>
</div>
<div class="check-item" id="c-3-4" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-3-4')" onkeydown="handleKey(event,'c-3-4')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text">On the <strong>Site Team tab, add an End Date</strong> for each person assigned to the study.</span>
</div>
</div>
</div>
<!-- ── Section 4: Enterprise ── -->
<div class="section-card" id="sec-4">
<button class="section-header" onclick="toggleSection('sec-4')" aria-expanded="true" aria-controls="body-sec-4" id="hdr-sec-4">
<span class="section-num" aria-hidden="true">4</span>
<span class="section-title-wrap">
<span class="section-title">Enterprise — Network study closeout</span>
<span class="section-subtitle">Only required if the study is closing across the entire network</span>
</span>
<span class="section-badge" id="badge-sec-4" aria-hidden="true">0 / 2</span>
<span class="section-chevron" aria-hidden="true">▼</span>
</button>
<div class="section-body" id="body-sec-4" role="group" aria-labelledby="hdr-sec-4">
<div class="check-item" id="c-4-1" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-4-1')" onkeydown="handleKey(event,'c-4-1')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text"><strong>Update the Network Study Status and Network Study Status Date</strong> in the Study Information tab. Updating the Enterprise status ensures the closure is visible in network-level reporting and portfolio data in Insights. For more, see the <strong>Add and Manage Network Studies</strong> guide.</span>
</div>
<div class="check-item" id="c-4-2" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-4-2')" onkeydown="handleKey(event,'c-4-2')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text"><strong>Update the Network Enrollment End Date.</strong></span>
</div>
</div>
</div>
<!-- ── Section 5: Insights ── -->
<div class="section-card" id="sec-5">
<button class="section-header" onclick="toggleSection('sec-5')" aria-expanded="true" aria-controls="body-sec-5" id="hdr-sec-5">
<span class="section-num" aria-hidden="true">5</span>
<span class="section-title-wrap">
<span class="section-title">Insights — Reporting & validation</span>
<span class="section-subtitle">Validate Finance reports and export per your site's SOP</span>
</span>
<span class="section-badge" id="badge-sec-5" aria-hidden="true">0 / 5</span>
<span class="section-chevron" aria-hidden="true">▼</span>
</button>
<div class="section-body" id="body-sec-5" role="group" aria-labelledby="hdr-sec-5">
<div class="check-item" id="c-5-0" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-5-0')" onkeydown="handleKey(event,'c-5-0')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text"><strong>Validate Finance reports</strong> to confirm the following. For more, see the <strong>Report Dictionary</strong> guide.</span>
</div>
<div class="sub-items" role="group" aria-label="Finance report validation items">
<div class="sub-item" id="c-5-1" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-5-1')" onkeydown="handleKey(event,'c-5-1')">
<span class="sub-box" aria-hidden="true"><span class="sub-tick">✓</span></span>
<span class="sub-text">Applicable revenue and payments are accurate.</span>
</div>
<div class="sub-item" id="c-5-2" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-5-2')" onkeydown="handleKey(event,'c-5-2')">
<span class="sub-box" aria-hidden="true"><span class="sub-tick">✓</span></span>
<span class="sub-text">No outstanding AR.</span>
</div>
<div class="sub-item" id="c-5-3" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-5-3')" onkeydown="handleKey(event,'c-5-3')">
<span class="sub-box" aria-hidden="true"><span class="sub-tick">✓</span></span>
<span class="sub-text">All payments have been fully logged and allocated correctly.</span>
</div>
<div class="sub-item" id="c-5-4" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-5-4')" onkeydown="handleKey(event,'c-5-4')">
<span class="sub-box" aria-hidden="true"><span class="sub-tick">✓</span></span>
<span class="sub-text">Budget end dates align with reconciled Finance, or update per SOP if left open for closeout fees.</span>
</div>
</div>
<div class="check-item" id="c-5-5" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-5-5')" onkeydown="handleKey(event,'c-5-5')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text"><strong>Export required reports</strong> per your site's internal SOP.</span>
</div>
</div>
</div>
<!-- ── Section 6: Archive & communicate ── -->
<div class="section-card" id="sec-6">
<button class="section-header" onclick="toggleSection('sec-6')" aria-expanded="true" aria-controls="body-sec-6" id="hdr-sec-6">
<span class="section-num" aria-hidden="true">6</span>
<span class="section-title-wrap">
<span class="section-title">Archive and communicate closeout</span>
<span class="section-subtitle">Final step — once all above sections are complete</span>
</span>
<span class="section-badge" id="badge-sec-6" aria-hidden="true">0 / 2</span>
<span class="section-chevron" aria-hidden="true">▼</span>
</button>
<div class="section-body" id="body-sec-6" role="group" aria-labelledby="hdr-sec-6">
<div class="check-item" id="c-6-1" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-6-1')" onkeydown="handleKey(event,'c-6-1')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text"><strong>Archive study documents</strong> by ensuring all documents are stored in accordance with site and sponsor policies.</span>
</div>
<div class="check-item" id="c-6-2" role="checkbox" aria-checked="false" tabindex="0" onclick="toggle('c-6-2')" onkeydown="handleKey(event,'c-6-2')">
<span class="check-box" aria-hidden="true"><span class="check-tick">✓</span></span>
<span class="check-text"><strong>Notify stakeholders</strong> by communicating study closure to relevant site, sponsor, and Site CTMS stakeholders.</span>
</div>
</div>
</div>
</div>
<script>
/* ── Section map: which item IDs belong to each section ── */
const SECTIONS = {
'sec-1': ['c-1-1','c-1-2','c-1-3','c-1-4','c-1-5','c-1-6'],
'sec-2': ['c-2-1','c-2-2','c-2-3','c-2-4','c-2-5'],
'sec-3': ['c-3-0','c-3-1','c-3-2','c-3-3','c-3-4'],
'sec-4': ['c-4-1','c-4-2'],
'sec-5': ['c-5-0','c-5-1','c-5-2','c-5-3','c-5-4','c-5-5'],
'sec-6': ['c-6-1','c-6-2']
};
const ALL_IDS = Object.values(SECTIONS).flat();
const TOTAL = ALL_IDS.length;
/* Toggle a checkbox item */
function toggle(id) {
const el = document.getElementById(id);
const isChecked = el.classList.toggle('checked');
el.setAttribute('aria-checked', isChecked ? 'true' : 'false');
updateProgress();
}
/* Keyboard support: Space/Enter activate the checkbox */
function handleKey(event, id) {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault();
toggle(id);
}
}
/* Toggle section expand/collapse */
function toggleSection(secId) {
const card = document.getElementById(secId);
const btn = card.querySelector('.section-header');
const body = card.querySelector('.section-body');
const isOpen = !card.classList.contains('collapsed');
card.classList.toggle('collapsed', isOpen);
btn.setAttribute('aria-expanded', isOpen ? 'false' : 'true');
body.hidden = isOpen;
}
function countChecked(ids) {
return ids.filter(id => document.getElementById(id).classList.contains('checked')).length;
}
function updateProgress() {
const done = countChecked(ALL_IDS);
const pct = TOTAL > 0 ? Math.round((done / TOTAL) * 100) : 0;
/* Overall bar */
document.getElementById('progress-fill').style.width = pct + '%';
document.getElementById('progress-count').textContent = done + ' / ' + TOTAL;
/* Update progressbar ARIA attributes */
const bar = document.getElementById('progress-bar');
bar.setAttribute('aria-valuenow', pct);
bar.setAttribute('aria-valuetext', done + ' of ' + TOTAL + ' steps completed');
/* Per-section badges and done state */
Object.entries(SECTIONS).forEach(([secId, ids]) => {
const secDone = countChecked(ids);
const secTotal = ids.length;
const badge = document.getElementById('badge-' + secId);
const card = document.getElementById(secId);
badge.textContent = secDone + ' / ' + secTotal;
if (secDone === secTotal) {
card.classList.add('all-done');
} else {
card.classList.remove('all-done');
}
});
/* Completion banner */
const banner = document.getElementById('completion-banner');
if (done === TOTAL) {
banner.classList.add('show');
banner.removeAttribute('hidden');
} else {
banner.classList.remove('show');
}
}
function resetAll() {
ALL_IDS.forEach(id => {
const el = document.getElementById(id);
el.classList.remove('checked');
el.setAttribute('aria-checked', 'false');
});
updateProgress();
}
/* Initialise counts */
updateProgress();
</script>
</body>
</html>