Open demo

CSS code

HTML
<div><span class="lbl">Race entry with ticket cards</span>
<form class="ev" action="#" method="post" aria-labelledby="rh-title">
  <div class="ev-head">
    <p class="ev-kicker">Entries open until 1 April</p>
    <h2 class="ev-title" id="rh-title">Riverside Half Marathon 2026</h2>
    <ul class="ev-meta"><li>Sunday 19 April 2026</li><li>Start 9:00, Riverside Park</li><li>Chip timed</li></ul>
  </div>
  <div class="ev-body">
    <p class="ev-note"><span class="ev-req" aria-hidden="true">*</span> Required field</p>
    <fieldset class="ev-set">
      <legend><span class="ev-num" aria-hidden="true">1</span>Choose your race</legend>
      <div class="ev-tickets">
        <label class="ev-ticket"><input class="ev-dot" type="radio" name="race" value="half" checked><b>Half marathon</b><small>21.1 km, two laps</small><span class="ev-price">£42</span></label>
        <label class="ev-ticket"><input class="ev-dot" type="radio" name="race" value="10k"><b>10K</b><small>One lap, flat course</small><span class="ev-price">£28</span></label>
        <label class="ev-ticket"><input class="ev-dot" type="radio" name="race" value="3k"><b>Family 3K</b><small>Under 12s run free</small><span class="ev-price">£12</span></label>
      </div>
    </fieldset>
    <fieldset class="ev-set">
      <legend><span class="ev-num" aria-hidden="true">2</span>Runner details</legend>
      <div class="ev-grid">
        <div class="ev-field">
          <label class="ev-label" for="rh-first">First name <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="ev-input" id="rh-first" name="given-name" type="text" autocomplete="given-name" required>
        </div>
        <div class="ev-field">
          <label class="ev-label" for="rh-last">Last name <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="ev-input" id="rh-last" name="family-name" type="text" autocomplete="family-name" required>
        </div>
        <div class="ev-field">
          <label class="ev-label" for="rh-email">Email <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="ev-input" id="rh-email" name="email" type="email" autocomplete="email" required aria-describedby="rh-email-hint">
          <p class="ev-hint" id="rh-email-hint">Your bib number arrives here a week before.</p>
        </div>
        <div class="ev-field">
          <label class="ev-label" for="rh-dob">Date of birth <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="ev-input" id="rh-dob" name="bday" type="date" autocomplete="bday" required aria-describedby="rh-dob-hint">
          <p class="ev-hint" id="rh-dob-hint">Half marathon runners must be 17 or over on race day.</p>
        </div>
        <div class="ev-field">
          <label class="ev-label" for="rh-shirt">T-shirt size <span class="ev-req" aria-hidden="true">*</span></label>
          <select class="ev-input" id="rh-shirt" name="shirt" required>
            <option value="">Choose a size</option>
            <option>XS</option><option>S</option><option>M</option><option>L</option><option>XL</option><option>XXL</option>
          </select>
        </div>
        <div class="ev-field">
          <label class="ev-label" for="rh-club">Running club (optional)</label>
          <input class="ev-input" id="rh-club" name="club" type="text" autocomplete="off">
        </div>
      </div>
    </fieldset>
    <fieldset class="ev-set">
      <legend><span class="ev-num" aria-hidden="true">3</span>Emergency contact</legend>
      <div class="ev-grid">
        <div class="ev-field">
          <label class="ev-label" for="rh-ice-name">Contact name <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="ev-input" id="rh-ice-name" name="ice-name" type="text" autocomplete="off" required>
        </div>
        <div class="ev-field">
          <label class="ev-label" for="rh-ice-tel">Contact phone <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="ev-input" id="rh-ice-tel" name="ice-tel" type="tel" autocomplete="off" required>
        </div>
      </div>
    </fieldset>
    <label class="ev-confirm"><input class="ev-box" type="checkbox" name="fit" required><span>I confirm I am fit to take part and have read the <a href="#">race rules</a>. <span class="ev-req" aria-hidden="true">*</span></span></label>
    <div class="ev-foot">
      <p class="ev-total">Entry fees are non-refundable but can be transferred until 5 April.</p>
      <button class="ev-btn" type="submit">Continue to payment</button>
    </div>
  </div>
</form>
</div>
<div><span class="lbl">Course booking with dietary needs</span>
<form class="ev ev--bake" action="#" method="post" aria-labelledby="hb-course-title">
  <div class="ev-head">
    <p class="ev-kicker">Hollow Oak Bakehouse</p>
    <h2 class="ev-title" id="hb-course-title">Weekend Sourdough Course</h2>
    <ul class="ev-meta"><li>Saturdays, 10:00 to 16:00</li><li>8 places per class</li><li>Lunch included</li></ul>
  </div>
  <div class="ev-body">
    <p class="ev-note"><span class="ev-req" aria-hidden="true">*</span> Required field</p>
    <fieldset class="ev-set">
      <legend><span class="ev-num" aria-hidden="true">1</span>Places and date</legend>
      <div class="ev-tickets">
        <label class="ev-ticket"><input class="ev-dot" type="radio" name="ticket" value="one" checked><b>One place</b><small>Starter and tin to take home</small><span class="ev-price">£95</span></label>
        <label class="ev-ticket"><input class="ev-dot" type="radio" name="ticket" value="two"><b>Two places</b><small>Bring a friend</small><span class="ev-price">£180</span></label>
        <label class="ev-ticket"><input class="ev-dot" type="radio" name="ticket" value="gift"><b>Gift voucher</b><small>Valid for 12 months</small><span class="ev-price">£95</span></label>
      </div>
      <div class="ev-grid">
        <div class="ev-field">
          <label class="ev-label" for="hb-date">Course date <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="ev-input" id="hb-date" name="course-date" type="date" min="2026-01-10" max="2026-06-27" step="7" value="2026-03-14" required aria-describedby="hb-date-hint">
          <p class="ev-hint" id="hb-date-hint">Saturdays from 10 January to 27 June 2026.</p>
        </div>
        <div class="ev-field">
          <label class="ev-label" for="hb-level">Baking experience</label>
          <select class="ev-input" id="hb-level" name="level">
            <option>I've never baked bread</option>
            <option>I bake yeasted bread</option>
            <option>I've tried sourdough before</option>
          </select>
        </div>
      </div>
    </fieldset>
    <fieldset class="ev-set">
      <legend><span class="ev-num" aria-hidden="true">2</span>Lunch and dietary needs</legend>
      <div class="ev-checks">
        <label class="ev-chip"><input class="ev-box" type="checkbox" name="diet" value="vegetarian">Vegetarian</label>
        <label class="ev-chip"><input class="ev-box" type="checkbox" name="diet" value="vegan">Vegan</label>
        <label class="ev-chip"><input class="ev-box" type="checkbox" name="diet" value="dairy-free">Dairy-free</label>
        <label class="ev-chip"><input class="ev-box" type="checkbox" name="diet" value="nut-allergy">Nut allergy</label>
        <label class="ev-chip"><input class="ev-box" type="checkbox" name="diet" value="coeliac">Coeliac</label>
      </div>
      <div class="ev-field">
        <label class="ev-label" for="hb-notes">Anything else we should know? (optional)</label>
        <textarea class="ev-input" id="hb-notes" name="notes" rows="3"></textarea>
      </div>
    </fieldset>
    <fieldset class="ev-set">
      <legend><span class="ev-num" aria-hidden="true">3</span>Your details</legend>
      <div class="ev-grid">
        <div class="ev-field">
          <label class="ev-label" for="hb-name">Full name <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="ev-input" id="hb-name" name="name" type="text" autocomplete="name" required>
        </div>
        <div class="ev-field">
          <label class="ev-label" for="hb-email">Email <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="ev-input" id="hb-email" name="email" type="email" autocomplete="email" required>
        </div>
      </div>
    </fieldset>
    <div class="ev-foot ev-foot--gap">
      <p class="ev-total">Flour, aprons and lunch included. <a href="#">Cancellation policy</a></p>
      <button class="ev-btn" type="submit">Book my place</button>
    </div>
  </div>
</form>
</div>
CSS
/* Event and course registration. Each group of fields is a fieldset with a legend, so screen readers announce
   "Runner details" before its fields; radio cards light up with :has(:checked). No JavaScript. */
.ev{--ev-accent:#0369a1;--ev-accent-dark:#075985;--ev-ring:rgba(3,105,161,.22);--ev-soft:#e0f2fe;--ev-ink:#0f1c2b;--ev-muted:#4b5a6a;--ev-line:#7a8896;--ev-rule:#dbe3ea;--ev-error:#b91c1c;
  background:#fff;color:var(--ev-ink);border-radius:20px;overflow:hidden;font-size:.92rem;line-height:1.45;
  box-shadow:0 1px 2px rgba(15,28,43,.06),0 18px 40px -18px rgba(15,28,43,.28)}
.ev--bake{--ev-accent:#9a3412;--ev-accent-dark:#7c2d12;--ev-ring:rgba(154,52,18,.22);--ev-soft:#fff1e6}
.ev-head{background:#0c3555;color:#fff;padding:28px 34px 26px}
.ev--bake .ev-head{background:#43261a}
.ev-kicker{font-size:.72rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:#9fd6f7}
.ev--bake .ev-kicker{color:#f8c9a4}
.ev-title{font-size:1.55rem;font-weight:750;letter-spacing:-.02em;line-height:1.2;margin:4px 0 12px}
.ev-meta{list-style:none;display:flex;flex-wrap:wrap;gap:8px}
.ev-meta li{font-size:.8rem;padding:4px 11px;border-radius:999px;background:rgba(255,255,255,.12);color:#e8f1f8}
.ev-body{padding:26px 34px 32px}
.ev-note{font-size:.8rem;color:var(--ev-muted)}
.ev-req{color:var(--ev-accent);font-weight:700}
.ev-set{border:0;padding:22px 0 6px;border-bottom:1px solid var(--ev-rule);margin:0;min-width:0}
.ev-set legend{float:left;width:100%;display:flex;align-items:center;gap:10px;font-size:1.02rem;font-weight:700;margin-bottom:14px}
.ev-set legend+*{clear:left}
.ev-num{display:grid;place-items:center;width:24px;height:24px;border-radius:50%;background:var(--ev-soft);color:var(--ev-accent-dark);font-size:.78rem;font-weight:800}
.ev-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 16px}
.ev-field{margin-bottom:16px;min-width:0}
.ev-label{display:block;font-size:.84rem;font-weight:600;margin-bottom:6px}
.ev-input{display:block;width:100%;min-height:44px;font:inherit;color:inherit;background:#fff;border:1px solid var(--ev-line);border-radius:10px;padding:10px 12px;
  transition:border-color .15s,box-shadow .15s}
select.ev-input{appearance:none;padding-right:38px;cursor:pointer;background:#fff no-repeat right 12px center/16px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%234b5a6a' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")}
textarea.ev-input{min-height:84px;resize:vertical}
.ev-input:focus{outline:none;border-color:var(--ev-accent);box-shadow:0 0 0 3px var(--ev-ring)}
.ev-input:user-invalid{border-color:var(--ev-error)}
.ev-hint{font-size:.8rem;color:var(--ev-muted);margin-top:6px}
/* radio cards */
.ev-tickets{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:18px}
.ev-ticket{position:relative;display:grid;grid-template-columns:auto 1fr;gap:2px 10px;align-items:start;padding:14px;border:1px solid var(--ev-line);border-radius:12px;cursor:pointer;
  transition:border-color .15s,background-color .15s,box-shadow .15s}
.ev-ticket:hover{border-color:var(--ev-accent)}
.ev-ticket:has(input:checked){border-color:var(--ev-accent);background:var(--ev-soft);box-shadow:inset 0 0 0 1px var(--ev-accent)}
.ev-ticket b{font-weight:650}
.ev-ticket small{grid-column:2;font-size:.78rem;color:var(--ev-muted)}
.ev-price{grid-column:2;font-weight:750;font-size:1.05rem;margin-top:6px;color:var(--ev-accent-dark)}
.ev-dot,.ev-box{appearance:none;width:18px;height:18px;margin-top:1px;border:1.5px solid var(--ev-line);background:#fff center/12px no-repeat;cursor:pointer;
  grid-row:span 3;transition:border-color .15s,background-color .15s}
.ev-dot{border-radius:50%}
.ev-dot:checked{border:5px solid var(--ev-accent)}
.ev-box{flex:none;border-radius:5px}
.ev-box:checked{background-color:var(--ev-accent);border-color:var(--ev-accent);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.5l3 3 6-7' fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")}
.ev-dot:focus-visible,.ev-box:focus-visible{outline:2px solid var(--ev-accent);outline-offset:2px}
/* checkbox chips for dietary needs */
.ev-checks{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:16px}
.ev-chip{display:flex;align-items:center;gap:8px;padding:8px 13px 8px 10px;border:1px solid var(--ev-line);border-radius:999px;cursor:pointer;font-size:.86rem;
  transition:border-color .15s,background-color .15s}
.ev-chip:has(input:checked){border-color:var(--ev-accent);background:var(--ev-soft)}
.ev-confirm{display:flex;gap:10px;align-items:flex-start;margin:20px 0 18px;font-size:.86rem;cursor:pointer}
.ev-foot{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap}
.ev-foot--gap{margin-top:22px}
.ev-total{font-size:.84rem;color:var(--ev-muted)}
.ev-total b{display:block;font-size:1.25rem;color:var(--ev-ink)}
.ev-btn{font:inherit;font-weight:600;color:#fff;background:var(--ev-accent);border:0;border-radius:10px;padding:12px 22px;cursor:pointer;transition:background-color .15s}
.ev-btn:hover{background:var(--ev-accent-dark)}
.ev-btn:focus-visible{outline:2px solid var(--ev-accent);outline-offset:3px}
.ev a{color:var(--ev-accent);text-decoration:underline;text-underline-offset:2px}
.ev a:focus-visible{outline:2px solid var(--ev-accent);outline-offset:2px;border-radius:3px}
@media (max-width:575px){.ev-head{padding:24px 20px}.ev-body{padding:20px 20px 26px}.ev-grid,.ev-tickets{grid-template-columns:1fr}
  .ev-btn{width:100%}}
@media (prefers-reduced-motion:reduce){.ev-input,.ev-ticket,.ev-dot,.ev-box,.ev-chip,.ev-btn{transition:none}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl">Race entry with ticket cards</span>
<form class="card ev" action="#" method="post" aria-labelledby="rh-title">
  <div class="ev-head">
    <p class="ev-kicker">Entries open until 1 April</p>
    <h2 class="ev-title" id="rh-title">Riverside Half Marathon 2026</h2>
    <ul class="list-unstyled ev-meta"><li class="badge rounded-pill">Sunday 19 April 2026</li><li class="badge rounded-pill">Start 9:00, Riverside Park</li><li class="badge rounded-pill">Chip timed</li></ul>
  </div>
  <div class="ev-body">
    <p class="ev-note"><span class="ev-req" aria-hidden="true">*</span> Required field</p>
    <fieldset class="ev-set">
      <legend><span class="ev-num" aria-hidden="true">1</span>Choose your race</legend>
      <div class="row g-2 mb-3">
        <div class="col-sm-4"><label class="ev-ticket"><input class="form-check-input" type="radio" name="race" value="half" checked><b>Half marathon</b><small>21.1 km, two laps</small><span class="ev-price">£42</span></label></div>
        <div class="col-sm-4"><label class="ev-ticket"><input class="form-check-input" type="radio" name="race" value="10k"><b>10K</b><small>One lap, flat course</small><span class="ev-price">£28</span></label></div>
        <div class="col-sm-4"><label class="ev-ticket"><input class="form-check-input" type="radio" name="race" value="3k"><b>Family 3K</b><small>Under 12s run free</small><span class="ev-price">£12</span></label></div>
      </div>
    </fieldset>
    <fieldset class="ev-set">
      <legend><span class="ev-num" aria-hidden="true">2</span>Runner details</legend>
      <div class="row gx-3">
        <div class="col-sm-6 mb-3">
          <label class="form-label" for="rh-first">First name <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="form-control" id="rh-first" name="given-name" type="text" autocomplete="given-name" required>
        </div>
        <div class="col-sm-6 mb-3">
          <label class="form-label" for="rh-last">Last name <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="form-control" id="rh-last" name="family-name" type="text" autocomplete="family-name" required>
        </div>
        <div class="col-sm-6 mb-3">
          <label class="form-label" for="rh-email">Email <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="form-control" id="rh-email" name="email" type="email" autocomplete="email" required aria-describedby="rh-email-hint">
          <p class="form-text" id="rh-email-hint">Your bib number arrives here a week before.</p>
        </div>
        <div class="col-sm-6 mb-3">
          <label class="form-label" for="rh-dob">Date of birth <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="form-control" id="rh-dob" name="bday" type="date" autocomplete="bday" required aria-describedby="rh-dob-hint">
          <p class="form-text" id="rh-dob-hint">Half marathon runners must be 17 or over on race day.</p>
        </div>
        <div class="col-sm-6 mb-3">
          <label class="form-label" for="rh-shirt">T-shirt size <span class="ev-req" aria-hidden="true">*</span></label>
          <select class="form-select" id="rh-shirt" name="shirt" required>
            <option value="">Choose a size</option>
            <option>XS</option><option>S</option><option>M</option><option>L</option><option>XL</option><option>XXL</option>
          </select>
        </div>
        <div class="col-sm-6 mb-3">
          <label class="form-label" for="rh-club">Running club (optional)</label>
          <input class="form-control" id="rh-club" name="club" type="text" autocomplete="off">
        </div>
      </div>
    </fieldset>
    <fieldset class="ev-set">
      <legend><span class="ev-num" aria-hidden="true">3</span>Emergency contact</legend>
      <div class="row gx-3">
        <div class="col-sm-6 mb-3">
          <label class="form-label" for="rh-ice-name">Contact name <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="form-control" id="rh-ice-name" name="ice-name" type="text" autocomplete="off" required>
        </div>
        <div class="col-sm-6 mb-3">
          <label class="form-label" for="rh-ice-tel">Contact phone <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="form-control" id="rh-ice-tel" name="ice-tel" type="tel" autocomplete="off" required>
        </div>
      </div>
    </fieldset>
    <div class="form-check ev-confirm"><input class="form-check-input" id="rh-fit" type="checkbox" name="fit" required><label class="form-check-label" for="rh-fit">I confirm I am fit to take part and have read the <a href="#">race rules</a>. <span class="ev-req" aria-hidden="true">*</span></label></div>
    <div class="ev-foot">
      <p class="ev-total">Entry fees are non-refundable but can be transferred until 5 April.</p>
      <button class="btn btn-primary" type="submit">Continue to payment</button>
    </div>
  </div>
</form>
</div>
<div><span class="lbl">Course booking with dietary needs</span>
<form class="card ev ev--bake" action="#" method="post" aria-labelledby="hb-course-title">
  <div class="ev-head">
    <p class="ev-kicker">Hollow Oak Bakehouse</p>
    <h2 class="ev-title" id="hb-course-title">Weekend Sourdough Course</h2>
    <ul class="list-unstyled ev-meta"><li class="badge rounded-pill">Saturdays, 10:00 to 16:00</li><li class="badge rounded-pill">8 places per class</li><li class="badge rounded-pill">Lunch included</li></ul>
  </div>
  <div class="ev-body">
    <p class="ev-note"><span class="ev-req" aria-hidden="true">*</span> Required field</p>
    <fieldset class="ev-set">
      <legend><span class="ev-num" aria-hidden="true">1</span>Places and date</legend>
      <div class="row g-2 mb-3">
        <div class="col-sm-4"><label class="ev-ticket"><input class="form-check-input" type="radio" name="ticket" value="one" checked><b>One place</b><small>Starter and tin to take home</small><span class="ev-price">£95</span></label></div>
        <div class="col-sm-4"><label class="ev-ticket"><input class="form-check-input" type="radio" name="ticket" value="two"><b>Two places</b><small>Bring a friend</small><span class="ev-price">£180</span></label></div>
        <div class="col-sm-4"><label class="ev-ticket"><input class="form-check-input" type="radio" name="ticket" value="gift"><b>Gift voucher</b><small>Valid for 12 months</small><span class="ev-price">£95</span></label></div>
      </div>
      <div class="row gx-3">
        <div class="col-sm-6 mb-3">
          <label class="form-label" for="hb-date">Course date <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="form-control" id="hb-date" name="course-date" type="date" min="2026-01-10" max="2026-06-27" step="7" value="2026-03-14" required aria-describedby="hb-date-hint">
          <p class="form-text" id="hb-date-hint">Saturdays from 10 January to 27 June 2026.</p>
        </div>
        <div class="col-sm-6 mb-3">
          <label class="form-label" for="hb-level">Baking experience</label>
          <select class="form-select" id="hb-level" name="level">
            <option>I've never baked bread</option>
            <option>I bake yeasted bread</option>
            <option>I've tried sourdough before</option>
          </select>
        </div>
      </div>
    </fieldset>
    <fieldset class="ev-set">
      <legend><span class="ev-num" aria-hidden="true">2</span>Lunch and dietary needs</legend>
      <div class="ev-checks">
        <label class="ev-chip"><input class="form-check-input" type="checkbox" name="diet" value="vegetarian">Vegetarian</label>
        <label class="ev-chip"><input class="form-check-input" type="checkbox" name="diet" value="vegan">Vegan</label>
        <label class="ev-chip"><input class="form-check-input" type="checkbox" name="diet" value="dairy-free">Dairy-free</label>
        <label class="ev-chip"><input class="form-check-input" type="checkbox" name="diet" value="nut-allergy">Nut allergy</label>
        <label class="ev-chip"><input class="form-check-input" type="checkbox" name="diet" value="coeliac">Coeliac</label>
      </div>
      <div class="mb-3">
        <label class="form-label" for="hb-notes">Anything else we should know? (optional)</label>
        <textarea class="form-control" id="hb-notes" name="notes" rows="3"></textarea>
      </div>
    </fieldset>
    <fieldset class="ev-set">
      <legend><span class="ev-num" aria-hidden="true">3</span>Your details</legend>
      <div class="row gx-3">
        <div class="col-sm-6 mb-3">
          <label class="form-label" for="hb-name">Full name <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="form-control" id="hb-name" name="name" type="text" autocomplete="name" required>
        </div>
        <div class="col-sm-6 mb-3">
          <label class="form-label" for="hb-email">Email <span class="ev-req" aria-hidden="true">*</span></label>
          <input class="form-control" id="hb-email" name="email" type="email" autocomplete="email" required>
        </div>
      </div>
    </fieldset>
    <div class="ev-foot ev-foot--gap">
      <p class="ev-total">Flour, aprons and lunch included. <a href="#">Cancellation policy</a></p>
      <button class="btn btn-primary" type="submit">Book my place</button>
    </div>
  </div>
</form>
</div>
CSS
/* Bootstrap .card, .row, .form-control, .form-select, .form-check-input and .btn-primary, recoloured through
   Bootstrap's CSS variables. Each group of fields is a fieldset with a legend; radio cards light up with :has(:checked).
   No JavaScript. */
.ev{--ev-accent:#0369a1;--ev-accent-dark:#075985;--ev-ring:rgba(3,105,161,.22);--ev-soft:#e0f2fe;--ev-ink:#0f1c2b;--ev-muted:#4b5a6a;--ev-line:#7a8896;--ev-rule:#dbe3ea;--ev-error:#b91c1c;
  --bs-card-border-width:0;--bs-card-border-radius:20px;--bs-border-color:var(--ev-line);--bs-border-radius:10px;--bs-body-color:var(--ev-ink);
  --bs-link-color-rgb:3,105,161;--bs-link-hover-color-rgb:7,89,133;
  overflow:hidden;color:var(--ev-ink);font-size:.92rem;line-height:1.45;box-shadow:0 1px 2px rgba(15,28,43,.06),0 18px 40px -18px rgba(15,28,43,.28)}
.ev--bake{--ev-accent:#9a3412;--ev-accent-dark:#7c2d12;--ev-ring:rgba(154,52,18,.22);--ev-soft:#fff1e6;--bs-link-color-rgb:154,52,18;--bs-link-hover-color-rgb:124,45,18}
.ev p,.ev h2,.ev ul{margin:0}
.ev .ev-head{background:#0c3555;color:#fff;padding:28px 34px 26px}
.ev--bake .ev-head{background:#43261a}
.ev .ev-kicker{font-size:.72rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:#9fd6f7}
.ev--bake .ev-kicker{color:#f8c9a4}
.ev .ev-title{font-size:1.55rem;font-weight:750;letter-spacing:-.02em;line-height:1.2;margin:4px 0 12px}
.ev .ev-meta{display:flex;flex-wrap:wrap;gap:8px}
.ev .ev-meta .badge{--bs-badge-font-size:.8rem;--bs-badge-font-weight:400;--bs-badge-padding-x:11px;--bs-badge-padding-y:4px;background:rgba(255,255,255,.12);color:#e8f1f8;line-height:1.45}
.ev .ev-body{padding:26px 34px 32px}
.ev .ev-note{font-size:.8rem;color:var(--ev-muted)}
.ev .ev-req{color:var(--ev-accent);font-weight:700}
.ev .ev-set{padding:22px 0 6px;border-bottom:1px solid var(--ev-rule);min-width:0}
.ev .ev-set legend{float:left;width:100%;display:flex;align-items:center;gap:10px;font-size:1.02rem;font-weight:700;line-height:1.45;margin-bottom:14px;padding:0}
.ev .ev-set legend+*{clear:left}
.ev .ev-num{display:grid;place-items:center;width:24px;height:24px;border-radius:50%;background:var(--ev-soft);color:var(--ev-accent-dark);font-size:.78rem;font-weight:800}
.ev .form-label{display:block;font-size:.84rem;font-weight:600;margin-bottom:6px}
.ev .form-control,.ev .form-select{min-height:44px;font-size:inherit;line-height:inherit;color:var(--ev-ink);padding:10px 12px;transition:border-color .15s,box-shadow .15s}
.ev textarea.form-control{min-height:84px}
.ev .form-select{padding-right:38px;cursor:pointer;background-position:right 12px center;background-size:16px;
  --bs-form-select-bg-img:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%234b5a6a' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")}
.ev .form-control:focus,.ev .form-select:focus{border-color:var(--ev-accent);box-shadow:0 0 0 3px var(--ev-ring)}
.ev .form-control:user-invalid,.ev .form-select:user-invalid{border-color:var(--ev-error)}
.ev .form-text{font-size:.8rem;color:var(--ev-muted);margin-top:6px}
/* radio cards and checkbox chips built on .form-check-input */
.ev .form-check-input{flex:none;width:18px;height:18px;margin:1px 0 0;border:1.5px solid var(--ev-line);cursor:pointer;--bs-form-check-bg-image:none;
  transition:border-color .15s,background-color .15s}
.ev .form-check-input:focus{box-shadow:none;border-color:var(--ev-line)}
.ev .form-check-input:focus-visible{outline:2px solid var(--ev-accent);outline-offset:2px}
.ev .form-check-input[type=radio]:checked{background-color:#fff;border:5px solid var(--ev-accent)}
.ev .form-check-input[type=checkbox]{border-radius:5px}
.ev .form-check-input[type=checkbox]:checked{background-color:var(--ev-accent);border-color:var(--ev-accent);background-size:12px;
  --bs-form-check-bg-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.5l3 3 6-7' fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")}
.ev .ev-ticket{height:100%;display:grid;grid-template-columns:auto 1fr;gap:2px 10px;align-items:start;padding:14px;border:1px solid var(--ev-line);border-radius:12px;cursor:pointer;
  transition:border-color .15s,background-color .15s,box-shadow .15s}
.ev .ev-ticket .form-check-input{grid-row:span 3}
.ev .ev-ticket:hover{border-color:var(--ev-accent)}
.ev .ev-ticket:has(:checked){border-color:var(--ev-accent);background:var(--ev-soft);box-shadow:inset 0 0 0 1px var(--ev-accent)}
.ev .ev-ticket b{font-weight:650}
.ev .ev-ticket small{grid-column:2;font-size:.78rem;color:var(--ev-muted)}
.ev .ev-price{grid-column:2;font-weight:750;font-size:1.05rem;margin-top:6px;color:var(--ev-accent-dark)}
.ev .ev-checks{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:16px}
.ev .ev-chip{display:flex;align-items:center;gap:8px;padding:8px 13px 8px 10px;margin:0;border:1px solid var(--ev-line);border-radius:999px;cursor:pointer;font-size:.86rem;
  transition:border-color .15s,background-color .15s}
.ev .ev-chip .form-check-input{margin:0}
.ev .ev-chip:has(:checked){border-color:var(--ev-accent);background:var(--ev-soft)}
.ev .form-check.ev-confirm{display:flex;gap:10px;align-items:flex-start;padding:0;margin:20px 0 18px;min-height:0;font-size:.86rem}
.ev .form-check.ev-confirm .form-check-input{float:none;margin:1px 0 0}
.ev .ev-foot{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap}
.ev .ev-foot--gap{margin-top:22px}
.ev .ev-total{font-size:.84rem;color:var(--ev-muted)}
.ev .btn-primary{--bs-btn-bg:var(--ev-accent);--bs-btn-border-color:var(--ev-accent);--bs-btn-hover-bg:var(--ev-accent-dark);--bs-btn-hover-border-color:var(--ev-accent-dark);
  --bs-btn-active-bg:var(--ev-accent-dark);--bs-btn-active-border-color:var(--ev-accent-dark);--bs-btn-focus-box-shadow:none;
  --bs-btn-font-weight:600;--bs-btn-padding-y:11px;--bs-btn-padding-x:22px;--bs-btn-font-size:.92rem;--bs-btn-border-radius:10px;line-height:1.45}
.ev .btn-primary:focus-visible{outline:2px solid var(--ev-accent);outline-offset:3px}
.ev a{text-underline-offset:2px}
.ev a:focus-visible{outline:2px solid var(--ev-accent);outline-offset:2px;border-radius:3px}
.card.ev{display:block} /* plain block flow, so vertical margins match the CSS version */
@media (max-width:575px){.ev .ev-head{padding:24px 20px}.ev .ev-body{padding:20px 20px 26px}.ev .btn-primary{width:100%}}
@media (prefers-reduced-motion:reduce){.ev .form-control,.ev .form-select,.ev .form-check-input,.ev .ev-ticket,.ev .ev-chip,.ev .btn{transition:none}}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#4f5d6c] uppercase">Race entry with ticket cards</span>
<form class="overflow-hidden rounded-[20px] bg-white text-[.92rem] leading-[1.45] text-ev-ink shadow-[0_1px_2px_rgba(15,28,43,.06),0_18px_40px_-18px_rgba(15,28,43,.28)] [--ev-accent:#0369a1] [--ev-accent-dark:#075985] [--ev-ring:rgba(3,105,161,.22)] [--ev-soft:#e0f2fe]" action="#" method="post" aria-labelledby="rh-title">
  <div class="px-[34px] pt-7 pb-[26px] text-white max-sm:px-5 max-sm:py-6 bg-[#0c3555]">
    <p class="text-[.72rem] font-bold tracking-[.12em] uppercase text-[#9fd6f7]">Entries open until 1 April</p>
    <h2 class="mt-1 mb-3 text-[1.55rem] leading-[1.2] font-[750] tracking-[-.02em]" id="rh-title">Riverside Half Marathon 2026</h2>
    <ul class="flex flex-wrap gap-2"><li class="rounded-full bg-white/12 px-[11px] py-1 text-[.8rem] text-[#e8f1f8]">Sunday 19 April 2026</li><li class="rounded-full bg-white/12 px-[11px] py-1 text-[.8rem] text-[#e8f1f8]">Start 9:00, Riverside Park</li><li class="rounded-full bg-white/12 px-[11px] py-1 text-[.8rem] text-[#e8f1f8]">Chip timed</li></ul>
  </div>
  <div class="px-[34px] pt-[26px] pb-8 max-sm:px-5 max-sm:pt-5 max-sm:pb-[26px]">
    <p class="text-[.8rem] text-ev-muted"><span class="font-bold text-(--ev-accent)" aria-hidden="true">*</span> Required field</p>
    <fieldset class="m-0 min-w-0 border-0 border-b border-ev-rule pt-[22px] pb-1.5">
      <legend class="float-left mb-3.5 flex w-full items-center gap-2.5 text-[1.02rem] font-bold"><span class="grid size-6 place-items-center rounded-full bg-(--ev-soft) text-[.78rem] font-extrabold text-(--ev-accent-dark)" aria-hidden="true">1</span>Choose your race</legend>
      <div class="clear-left mb-[18px] grid grid-cols-3 gap-2.5 max-sm:grid-cols-1">
        <label class="grid cursor-pointer grid-cols-[auto_1fr] items-start gap-x-2.5 gap-y-0.5 rounded-xl border border-ev-line p-3.5 transition-[border-color,background-color,box-shadow] duration-150 hover:border-(--ev-accent) has-checked:border-(--ev-accent) has-checked:bg-(--ev-soft) has-checked:shadow-[inset_0_0_0_1px_var(--ev-accent)] motion-reduce:transition-none"><input class="row-span-3 mt-px size-[18px] cursor-pointer appearance-none rounded-full border-[1.5px] border-ev-line bg-white transition-[background-color,border-color,color] duration-150 checked:border-[5px] checked:border-(--ev-accent) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ev-accent) motion-reduce:transition-none" type="radio" name="race" value="half" checked><b class="font-[650]">Half marathon</b><small class="col-start-2 text-[.78rem] text-ev-muted">21.1 km, two laps</small><span class="col-start-2 mt-1.5 text-[1.05rem] font-[750] text-(--ev-accent-dark)">£42</span></label>
        <label class="grid cursor-pointer grid-cols-[auto_1fr] items-start gap-x-2.5 gap-y-0.5 rounded-xl border border-ev-line p-3.5 transition-[border-color,background-color,box-shadow] duration-150 hover:border-(--ev-accent) has-checked:border-(--ev-accent) has-checked:bg-(--ev-soft) has-checked:shadow-[inset_0_0_0_1px_var(--ev-accent)] motion-reduce:transition-none"><input class="row-span-3 mt-px size-[18px] cursor-pointer appearance-none rounded-full border-[1.5px] border-ev-line bg-white transition-[background-color,border-color,color] duration-150 checked:border-[5px] checked:border-(--ev-accent) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ev-accent) motion-reduce:transition-none" type="radio" name="race" value="10k"><b class="font-[650]">10K</b><small class="col-start-2 text-[.78rem] text-ev-muted">One lap, flat course</small><span class="col-start-2 mt-1.5 text-[1.05rem] font-[750] text-(--ev-accent-dark)">£28</span></label>
        <label class="grid cursor-pointer grid-cols-[auto_1fr] items-start gap-x-2.5 gap-y-0.5 rounded-xl border border-ev-line p-3.5 transition-[border-color,background-color,box-shadow] duration-150 hover:border-(--ev-accent) has-checked:border-(--ev-accent) has-checked:bg-(--ev-soft) has-checked:shadow-[inset_0_0_0_1px_var(--ev-accent)] motion-reduce:transition-none"><input class="row-span-3 mt-px size-[18px] cursor-pointer appearance-none rounded-full border-[1.5px] border-ev-line bg-white transition-[background-color,border-color,color] duration-150 checked:border-[5px] checked:border-(--ev-accent) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ev-accent) motion-reduce:transition-none" type="radio" name="race" value="3k"><b class="font-[650]">Family 3K</b><small class="col-start-2 text-[.78rem] text-ev-muted">Under 12s run free</small><span class="col-start-2 mt-1.5 text-[1.05rem] font-[750] text-(--ev-accent-dark)">£12</span></label>
      </div>
    </fieldset>
    <fieldset class="m-0 min-w-0 border-0 border-b border-ev-rule pt-[22px] pb-1.5">
      <legend class="float-left mb-3.5 flex w-full items-center gap-2.5 text-[1.02rem] font-bold"><span class="grid size-6 place-items-center rounded-full bg-(--ev-soft) text-[.78rem] font-extrabold text-(--ev-accent-dark)" aria-hidden="true">2</span>Runner details</legend>
      <div class="clear-left grid grid-cols-2 gap-x-4 max-sm:grid-cols-1">
        <div class="mb-4 min-w-0">
          <label class="mb-1.5 block text-[.84rem] font-semibold" for="rh-first">First name <span class="font-bold text-(--ev-accent)" aria-hidden="true">*</span></label>
          <input class="block min-h-11 w-full rounded-[10px] border border-ev-line bg-white px-3 py-2.5 transition-[border-color,box-shadow] duration-150 focus:border-(--ev-accent) focus:shadow-[0_0_0_3px_var(--ev-ring)] focus:outline-none user-invalid:border-ev-error motion-reduce:transition-none" id="rh-first" name="given-name" type="text" autocomplete="given-name" required>
        </div>
        <div class="mb-4 min-w-0">
          <label class="mb-1.5 block text-[.84rem] font-semibold" for="rh-last">Last name <span class="font-bold text-(--ev-accent)" aria-hidden="true">*</span></label>
          <input class="block min-h-11 w-full rounded-[10px] border border-ev-line bg-white px-3 py-2.5 transition-[border-color,box-shadow] duration-150 focus:border-(--ev-accent) focus:shadow-[0_0_0_3px_var(--ev-ring)] focus:outline-none user-invalid:border-ev-error motion-reduce:transition-none" id="rh-last" name="family-name" type="text" autocomplete="family-name" required>
        </div>
        <div class="mb-4 min-w-0">
          <label class="mb-1.5 block text-[.84rem] font-semibold" for="rh-email">Email <span class="font-bold text-(--ev-accent)" aria-hidden="true">*</span></label>
          <input class="block min-h-11 w-full rounded-[10px] border border-ev-line bg-white px-3 py-2.5 transition-[border-color,box-shadow] duration-150 focus:border-(--ev-accent) focus:shadow-[0_0_0_3px_var(--ev-ring)] focus:outline-none user-invalid:border-ev-error motion-reduce:transition-none" id="rh-email" name="email" type="email" autocomplete="email" required aria-describedby="rh-email-hint">
          <p class="mt-1.5 text-[.8rem] text-ev-muted" id="rh-email-hint">Your bib number arrives here a week before.</p>
        </div>
        <div class="mb-4 min-w-0">
          <label class="mb-1.5 block text-[.84rem] font-semibold" for="rh-dob">Date of birth <span class="font-bold text-(--ev-accent)" aria-hidden="true">*</span></label>
          <input class="block min-h-11 w-full rounded-[10px] border border-ev-line bg-white px-3 py-2.5 transition-[border-color,box-shadow] duration-150 focus:border-(--ev-accent) focus:shadow-[0_0_0_3px_var(--ev-ring)] focus:outline-none user-invalid:border-ev-error motion-reduce:transition-none" id="rh-dob" name="bday" type="date" autocomplete="bday" required aria-describedby="rh-dob-hint">
          <p class="mt-1.5 text-[.8rem] text-ev-muted" id="rh-dob-hint">Half marathon runners must be 17 or over on race day.</p>
        </div>
        <div class="mb-4 min-w-0">
          <label class="mb-1.5 block text-[.84rem] font-semibold" for="rh-shirt">T-shirt size <span class="font-bold text-(--ev-accent)" aria-hidden="true">*</span></label>
          <select class="block min-h-11 w-full rounded-[10px] border border-ev-line bg-white px-3 py-2.5 transition-[border-color,box-shadow] duration-150 focus:border-(--ev-accent) focus:shadow-[0_0_0_3px_var(--ev-ring)] focus:outline-none user-invalid:border-ev-error motion-reduce:transition-none cursor-pointer appearance-none bg-[length:16px] bg-[right_12px_center] bg-no-repeat pr-[38px] ev-chevron" id="rh-shirt" name="shirt" required>
            <option value="">Choose a size</option>
            <option>XS</option><option>S</option><option>M</option><option>L</option><option>XL</option><option>XXL</option>
          </select>
        </div>
        <div class="mb-4 min-w-0">
          <label class="mb-1.5 block text-[.84rem] font-semibold" for="rh-club">Running club (optional)</label>
          <input class="block min-h-11 w-full rounded-[10px] border border-ev-line bg-white px-3 py-2.5 transition-[border-color,box-shadow] duration-150 focus:border-(--ev-accent) focus:shadow-[0_0_0_3px_var(--ev-ring)] focus:outline-none user-invalid:border-ev-error motion-reduce:transition-none" id="rh-club" name="club" type="text" autocomplete="off">
        </div>
      </div>
    </fieldset>
    <fieldset class="m-0 min-w-0 border-0 border-b border-ev-rule pt-[22px] pb-1.5">
      <legend class="float-left mb-3.5 flex w-full items-center gap-2.5 text-[1.02rem] font-bold"><span class="grid size-6 place-items-center rounded-full bg-(--ev-soft) text-[.78rem] font-extrabold text-(--ev-accent-dark)" aria-hidden="true">3</span>Emergency contact</legend>
      <div class="clear-left grid grid-cols-2 gap-x-4 max-sm:grid-cols-1">
        <div class="mb-4 min-w-0">
          <label class="mb-1.5 block text-[.84rem] font-semibold" for="rh-ice-name">Contact name <span class="font-bold text-(--ev-accent)" aria-hidden="true">*</span></label>
          <input class="block min-h-11 w-full rounded-[10px] border border-ev-line bg-white px-3 py-2.5 transition-[border-color,box-shadow] duration-150 focus:border-(--ev-accent) focus:shadow-[0_0_0_3px_var(--ev-ring)] focus:outline-none user-invalid:border-ev-error motion-reduce:transition-none" id="rh-ice-name" name="ice-name" type="text" autocomplete="off" required>
        </div>
        <div class="mb-4 min-w-0">
          <label class="mb-1.5 block text-[.84rem] font-semibold" for="rh-ice-tel">Contact phone <span class="font-bold text-(--ev-accent)" aria-hidden="true">*</span></label>
          <input class="block min-h-11 w-full rounded-[10px] border border-ev-line bg-white px-3 py-2.5 transition-[border-color,box-shadow] duration-150 focus:border-(--ev-accent) focus:shadow-[0_0_0_3px_var(--ev-ring)] focus:outline-none user-invalid:border-ev-error motion-reduce:transition-none" id="rh-ice-tel" name="ice-tel" type="tel" autocomplete="off" required>
        </div>
      </div>
    </fieldset>
    <label class="mt-5 mb-[18px] flex cursor-pointer items-start gap-2.5 text-[.86rem]"><input class="mt-px size-[18px] flex-none cursor-pointer appearance-none rounded-[5px] border-[1.5px] border-ev-line bg-white bg-[length:12px_12px] bg-center bg-no-repeat transition-[background-color,border-color,color] duration-150 checked:border-(--ev-accent) checked:bg-(--ev-accent) checked:ev-tick focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ev-accent) motion-reduce:transition-none" type="checkbox" name="fit" required><span>I confirm I am fit to take part and have read the <a class="text-(--ev-accent) underline underline-offset-2 hover:text-(--ev-accent-dark) focus-visible:rounded-[3px] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ev-accent)" href="#">race rules</a>. <span class="font-bold text-(--ev-accent)" aria-hidden="true">*</span></span></label>
    <div class="flex flex-wrap items-center justify-between gap-4">
      <p class="text-[.84rem] text-ev-muted">Entry fees are non-refundable but can be transferred until 5 April.</p>
      <button class="cursor-pointer rounded-[10px] bg-(--ev-accent) px-[22px] py-3 font-semibold text-white transition-[background-color,border-color,color] duration-150 hover:bg-(--ev-accent-dark) focus-visible:outline-2 focus-visible:outline-offset-3 focus-visible:outline-(--ev-accent) motion-reduce:transition-none max-sm:w-full" type="submit">Continue to payment</button>
    </div>
  </div>
</form>
</div>
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#4f5d6c] uppercase">Course booking with dietary needs</span>
<form class="overflow-hidden rounded-[20px] bg-white text-[.92rem] leading-[1.45] text-ev-ink shadow-[0_1px_2px_rgba(15,28,43,.06),0_18px_40px_-18px_rgba(15,28,43,.28)] [--ev-accent:#9a3412] [--ev-accent-dark:#7c2d12] [--ev-ring:rgba(154,52,18,.22)] [--ev-soft:#fff1e6]" action="#" method="post" aria-labelledby="hb-course-title">
  <div class="px-[34px] pt-7 pb-[26px] text-white max-sm:px-5 max-sm:py-6 bg-[#43261a]">
    <p class="text-[.72rem] font-bold tracking-[.12em] uppercase text-[#f8c9a4]">Hollow Oak Bakehouse</p>
    <h2 class="mt-1 mb-3 text-[1.55rem] leading-[1.2] font-[750] tracking-[-.02em]" id="hb-course-title">Weekend Sourdough Course</h2>
    <ul class="flex flex-wrap gap-2"><li class="rounded-full bg-white/12 px-[11px] py-1 text-[.8rem] text-[#e8f1f8]">Saturdays, 10:00 to 16:00</li><li class="rounded-full bg-white/12 px-[11px] py-1 text-[.8rem] text-[#e8f1f8]">8 places per class</li><li class="rounded-full bg-white/12 px-[11px] py-1 text-[.8rem] text-[#e8f1f8]">Lunch included</li></ul>
  </div>
  <div class="px-[34px] pt-[26px] pb-8 max-sm:px-5 max-sm:pt-5 max-sm:pb-[26px]">
    <p class="text-[.8rem] text-ev-muted"><span class="font-bold text-(--ev-accent)" aria-hidden="true">*</span> Required field</p>
    <fieldset class="m-0 min-w-0 border-0 border-b border-ev-rule pt-[22px] pb-1.5">
      <legend class="float-left mb-3.5 flex w-full items-center gap-2.5 text-[1.02rem] font-bold"><span class="grid size-6 place-items-center rounded-full bg-(--ev-soft) text-[.78rem] font-extrabold text-(--ev-accent-dark)" aria-hidden="true">1</span>Places and date</legend>
      <div class="clear-left mb-[18px] grid grid-cols-3 gap-2.5 max-sm:grid-cols-1">
        <label class="grid cursor-pointer grid-cols-[auto_1fr] items-start gap-x-2.5 gap-y-0.5 rounded-xl border border-ev-line p-3.5 transition-[border-color,background-color,box-shadow] duration-150 hover:border-(--ev-accent) has-checked:border-(--ev-accent) has-checked:bg-(--ev-soft) has-checked:shadow-[inset_0_0_0_1px_var(--ev-accent)] motion-reduce:transition-none"><input class="row-span-3 mt-px size-[18px] cursor-pointer appearance-none rounded-full border-[1.5px] border-ev-line bg-white transition-[background-color,border-color,color] duration-150 checked:border-[5px] checked:border-(--ev-accent) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ev-accent) motion-reduce:transition-none" type="radio" name="ticket" value="one" checked><b class="font-[650]">One place</b><small class="col-start-2 text-[.78rem] text-ev-muted">Starter and tin to take home</small><span class="col-start-2 mt-1.5 text-[1.05rem] font-[750] text-(--ev-accent-dark)">£95</span></label>
        <label class="grid cursor-pointer grid-cols-[auto_1fr] items-start gap-x-2.5 gap-y-0.5 rounded-xl border border-ev-line p-3.5 transition-[border-color,background-color,box-shadow] duration-150 hover:border-(--ev-accent) has-checked:border-(--ev-accent) has-checked:bg-(--ev-soft) has-checked:shadow-[inset_0_0_0_1px_var(--ev-accent)] motion-reduce:transition-none"><input class="row-span-3 mt-px size-[18px] cursor-pointer appearance-none rounded-full border-[1.5px] border-ev-line bg-white transition-[background-color,border-color,color] duration-150 checked:border-[5px] checked:border-(--ev-accent) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ev-accent) motion-reduce:transition-none" type="radio" name="ticket" value="two"><b class="font-[650]">Two places</b><small class="col-start-2 text-[.78rem] text-ev-muted">Bring a friend</small><span class="col-start-2 mt-1.5 text-[1.05rem] font-[750] text-(--ev-accent-dark)">£180</span></label>
        <label class="grid cursor-pointer grid-cols-[auto_1fr] items-start gap-x-2.5 gap-y-0.5 rounded-xl border border-ev-line p-3.5 transition-[border-color,background-color,box-shadow] duration-150 hover:border-(--ev-accent) has-checked:border-(--ev-accent) has-checked:bg-(--ev-soft) has-checked:shadow-[inset_0_0_0_1px_var(--ev-accent)] motion-reduce:transition-none"><input class="row-span-3 mt-px size-[18px] cursor-pointer appearance-none rounded-full border-[1.5px] border-ev-line bg-white transition-[background-color,border-color,color] duration-150 checked:border-[5px] checked:border-(--ev-accent) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ev-accent) motion-reduce:transition-none" type="radio" name="ticket" value="gift"><b class="font-[650]">Gift voucher</b><small class="col-start-2 text-[.78rem] text-ev-muted">Valid for 12 months</small><span class="col-start-2 mt-1.5 text-[1.05rem] font-[750] text-(--ev-accent-dark)">£95</span></label>
      </div>
      <div class="clear-left grid grid-cols-2 gap-x-4 max-sm:grid-cols-1">
        <div class="mb-4 min-w-0">
          <label class="mb-1.5 block text-[.84rem] font-semibold" for="hb-date">Course date <span class="font-bold text-(--ev-accent)" aria-hidden="true">*</span></label>
          <input class="block min-h-11 w-full rounded-[10px] border border-ev-line bg-white px-3 py-2.5 transition-[border-color,box-shadow] duration-150 focus:border-(--ev-accent) focus:shadow-[0_0_0_3px_var(--ev-ring)] focus:outline-none user-invalid:border-ev-error motion-reduce:transition-none" id="hb-date" name="course-date" type="date" min="2026-01-10" max="2026-06-27" step="7" value="2026-03-14" required aria-describedby="hb-date-hint">
          <p class="mt-1.5 text-[.8rem] text-ev-muted" id="hb-date-hint">Saturdays from 10 January to 27 June 2026.</p>
        </div>
        <div class="mb-4 min-w-0">
          <label class="mb-1.5 block text-[.84rem] font-semibold" for="hb-level">Baking experience</label>
          <select class="block min-h-11 w-full rounded-[10px] border border-ev-line bg-white px-3 py-2.5 transition-[border-color,box-shadow] duration-150 focus:border-(--ev-accent) focus:shadow-[0_0_0_3px_var(--ev-ring)] focus:outline-none user-invalid:border-ev-error motion-reduce:transition-none cursor-pointer appearance-none bg-[length:16px] bg-[right_12px_center] bg-no-repeat pr-[38px] ev-chevron" id="hb-level" name="level">
            <option>I've never baked bread</option>
            <option>I bake yeasted bread</option>
            <option>I've tried sourdough before</option>
          </select>
        </div>
      </div>
    </fieldset>
    <fieldset class="m-0 min-w-0 border-0 border-b border-ev-rule pt-[22px] pb-1.5">
      <legend class="float-left mb-3.5 flex w-full items-center gap-2.5 text-[1.02rem] font-bold"><span class="grid size-6 place-items-center rounded-full bg-(--ev-soft) text-[.78rem] font-extrabold text-(--ev-accent-dark)" aria-hidden="true">2</span>Lunch and dietary needs</legend>
      <div class="clear-left mb-4 flex flex-wrap gap-2">
        <label class="flex cursor-pointer items-center gap-2 rounded-full border border-ev-line py-2 pr-[13px] pl-2.5 text-[.86rem] transition-[background-color,border-color,color] duration-150 has-checked:border-(--ev-accent) has-checked:bg-(--ev-soft) motion-reduce:transition-none"><input class="mt-px size-[18px] flex-none cursor-pointer appearance-none rounded-[5px] border-[1.5px] border-ev-line bg-white bg-[length:12px_12px] bg-center bg-no-repeat transition-[background-color,border-color,color] duration-150 checked:border-(--ev-accent) checked:bg-(--ev-accent) checked:ev-tick focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ev-accent) motion-reduce:transition-none" type="checkbox" name="diet" value="vegetarian">Vegetarian</label>
        <label class="flex cursor-pointer items-center gap-2 rounded-full border border-ev-line py-2 pr-[13px] pl-2.5 text-[.86rem] transition-[background-color,border-color,color] duration-150 has-checked:border-(--ev-accent) has-checked:bg-(--ev-soft) motion-reduce:transition-none"><input class="mt-px size-[18px] flex-none cursor-pointer appearance-none rounded-[5px] border-[1.5px] border-ev-line bg-white bg-[length:12px_12px] bg-center bg-no-repeat transition-[background-color,border-color,color] duration-150 checked:border-(--ev-accent) checked:bg-(--ev-accent) checked:ev-tick focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ev-accent) motion-reduce:transition-none" type="checkbox" name="diet" value="vegan">Vegan</label>
        <label class="flex cursor-pointer items-center gap-2 rounded-full border border-ev-line py-2 pr-[13px] pl-2.5 text-[.86rem] transition-[background-color,border-color,color] duration-150 has-checked:border-(--ev-accent) has-checked:bg-(--ev-soft) motion-reduce:transition-none"><input class="mt-px size-[18px] flex-none cursor-pointer appearance-none rounded-[5px] border-[1.5px] border-ev-line bg-white bg-[length:12px_12px] bg-center bg-no-repeat transition-[background-color,border-color,color] duration-150 checked:border-(--ev-accent) checked:bg-(--ev-accent) checked:ev-tick focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ev-accent) motion-reduce:transition-none" type="checkbox" name="diet" value="dairy-free">Dairy-free</label>
        <label class="flex cursor-pointer items-center gap-2 rounded-full border border-ev-line py-2 pr-[13px] pl-2.5 text-[.86rem] transition-[background-color,border-color,color] duration-150 has-checked:border-(--ev-accent) has-checked:bg-(--ev-soft) motion-reduce:transition-none"><input class="mt-px size-[18px] flex-none cursor-pointer appearance-none rounded-[5px] border-[1.5px] border-ev-line bg-white bg-[length:12px_12px] bg-center bg-no-repeat transition-[background-color,border-color,color] duration-150 checked:border-(--ev-accent) checked:bg-(--ev-accent) checked:ev-tick focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ev-accent) motion-reduce:transition-none" type="checkbox" name="diet" value="nut-allergy">Nut allergy</label>
        <label class="flex cursor-pointer items-center gap-2 rounded-full border border-ev-line py-2 pr-[13px] pl-2.5 text-[.86rem] transition-[background-color,border-color,color] duration-150 has-checked:border-(--ev-accent) has-checked:bg-(--ev-soft) motion-reduce:transition-none"><input class="mt-px size-[18px] flex-none cursor-pointer appearance-none rounded-[5px] border-[1.5px] border-ev-line bg-white bg-[length:12px_12px] bg-center bg-no-repeat transition-[background-color,border-color,color] duration-150 checked:border-(--ev-accent) checked:bg-(--ev-accent) checked:ev-tick focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ev-accent) motion-reduce:transition-none" type="checkbox" name="diet" value="coeliac">Coeliac</label>
      </div>
      <div class="mb-4 min-w-0">
        <label class="mb-1.5 block text-[.84rem] font-semibold" for="hb-notes">Anything else we should know? (optional)</label>
        <textarea class="block min-h-11 w-full rounded-[10px] border border-ev-line bg-white px-3 py-2.5 transition-[border-color,box-shadow] duration-150 focus:border-(--ev-accent) focus:shadow-[0_0_0_3px_var(--ev-ring)] focus:outline-none user-invalid:border-ev-error motion-reduce:transition-none min-h-[84px] resize-y" id="hb-notes" name="notes" rows="3"></textarea>
      </div>
    </fieldset>
    <fieldset class="m-0 min-w-0 border-0 border-b border-ev-rule pt-[22px] pb-1.5">
      <legend class="float-left mb-3.5 flex w-full items-center gap-2.5 text-[1.02rem] font-bold"><span class="grid size-6 place-items-center rounded-full bg-(--ev-soft) text-[.78rem] font-extrabold text-(--ev-accent-dark)" aria-hidden="true">3</span>Your details</legend>
      <div class="clear-left grid grid-cols-2 gap-x-4 max-sm:grid-cols-1">
        <div class="mb-4 min-w-0">
          <label class="mb-1.5 block text-[.84rem] font-semibold" for="hb-name">Full name <span class="font-bold text-(--ev-accent)" aria-hidden="true">*</span></label>
          <input class="block min-h-11 w-full rounded-[10px] border border-ev-line bg-white px-3 py-2.5 transition-[border-color,box-shadow] duration-150 focus:border-(--ev-accent) focus:shadow-[0_0_0_3px_var(--ev-ring)] focus:outline-none user-invalid:border-ev-error motion-reduce:transition-none" id="hb-name" name="name" type="text" autocomplete="name" required>
        </div>
        <div class="mb-4 min-w-0">
          <label class="mb-1.5 block text-[.84rem] font-semibold" for="hb-email">Email <span class="font-bold text-(--ev-accent)" aria-hidden="true">*</span></label>
          <input class="block min-h-11 w-full rounded-[10px] border border-ev-line bg-white px-3 py-2.5 transition-[border-color,box-shadow] duration-150 focus:border-(--ev-accent) focus:shadow-[0_0_0_3px_var(--ev-ring)] focus:outline-none user-invalid:border-ev-error motion-reduce:transition-none" id="hb-email" name="email" type="email" autocomplete="email" required>
        </div>
      </div>
    </fieldset>
    <div class="flex flex-wrap items-center justify-between gap-4 mt-[22px]">
      <p class="text-[.84rem] text-ev-muted">Flour, aprons and lunch included. <a class="text-(--ev-accent) underline underline-offset-2 hover:text-(--ev-accent-dark) focus-visible:rounded-[3px] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ev-accent)" href="#">Cancellation policy</a></p>
      <button class="cursor-pointer rounded-[10px] bg-(--ev-accent) px-[22px] py-3 font-semibold text-white transition-[background-color,border-color,color] duration-150 hover:bg-(--ev-accent-dark) focus-visible:outline-2 focus-visible:outline-offset-3 focus-visible:outline-(--ev-accent) motion-reduce:transition-none max-sm:w-full" type="submit">Book my place</button>
    </div>
  </div>
</form>
</div>
CSS
@theme {
  --color-ev-ink: #0f1c2b;
  --color-ev-muted: #4b5a6a;
  --color-ev-line: #7a8896;
  --color-ev-rule: #dbe3ea;
  --color-ev-error: #b91c1c;
}
/* select chevron and checkbox tick */
@utility ev-chevron {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%234b5a6a' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
@utility ev-tick {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.5l3 3 6-7' fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

About this set

Two longer registration forms for events and courses, split into numbered sections. Race entry with ticket cards signs runners up for a half marathon: a dark header with the date and start time as chips, then a race choice of three radio cards with distances and prices, runner details (first and last name, email, date of birth, a T-shirt size select and an optional running club), an emergency contact and a required fitness confirmation. Course booking with dietary needs books a sourdough course: three ticket cards, a date field limited to Saturdays through min, max and a seven-day step, an experience select, dietary checkboxes drawn as chips, an optional notes textarea and contact details. Use them for races, workshops, conferences or classes where people choose an option and give details in one go. Each section is a fieldset with a legend, so screen readers announce the group name with its fields, and the radio cards and chips are real inputs inside labels that light up through :has(:checked). Two-column field rows stack on phones and the button goes full width. There is no JavaScript.

What’s included

  • Numbered fieldsets with legends for each part of the form
  • Radio cards with descriptions and prices, highlighted with :has(:checked)
  • Date of birth and course date fields, the latter limited with min, max and step
  • Dietary needs as checkbox chips plus an optional notes textarea
  • Bootstrap version uses .row columns, .form-select, .form-check-input and .badge

Accessibility

Every group of choices is a fieldset with a legend, every input has a visible label, and hints such as the age rule are linked with aria-describedby. Required fields carry an asterisk with a written key, optional ones say optional. Personal fields use autocomplete (given-name, family-name, email, bday) while the emergency contact fields switch it off so the runner's own details are not filled in. Radio and checkbox focus rings are visible, and transitions switch off under prefers-reduced-motion.

Customise it

Set --ev-accent, --ev-accent-dark, --ev-ring and --ev-soft on .ev (.ev--bake is the second palette) and the header colour on .ev-head. In Bootstrap the ticket cards are .col-sm-4 columns; in Tailwind edit the [--ev-accent:…] properties and the header background class.