Open demo

CSS code

HTML
<div><span class="lbl">Weekly habit tracker</span>
<section class="hb" data-tallies aria-labelledby="habits-title">
  <div class="hb-head"><h2 id="habits-title">Habits this week</h2><p class="hb-sub">Monday 8 to Sunday 14 June</p></div>
  <div class="hb-habits">
    <div class="hb-row" role="group" aria-labelledby="habit-1" data-tally="Read 20 pages" data-unit="days this week">
      <div><p class="hb-n" id="habit-1">Read 20 pages</p><p class="hb-goal">Goal: 5 days a week</p></div>
      <div class="hb-days"><label class="hb-day"><input class="hb-dot" type="checkbox" checked><span class="hb-dname">Mon</span></label><label class="hb-day"><input class="hb-dot" type="checkbox" checked><span class="hb-dname">Tue</span></label><label class="hb-day"><input class="hb-dot" type="checkbox"><span class="hb-dname">Wed</span></label><label class="hb-day is-today"><input class="hb-dot" type="checkbox" checked><span class="hb-dname">Thu<span class="sr-only">, today</span></span></label><label class="hb-day"><input class="hb-dot" type="checkbox"><span class="hb-dname">Fri</span></label><label class="hb-day"><input class="hb-dot" type="checkbox"><span class="hb-dname">Sat</span></label><label class="hb-day"><input class="hb-dot" type="checkbox"><span class="hb-dname">Sun</span></label></div>
      <p class="hb-tally"><span data-tally-out>3 of 7</span><span>days</span></p>
    </div>
    <div class="hb-row" role="group" aria-labelledby="habit-2" data-tally="Walk 8,000 steps" data-unit="days this week">
      <div><p class="hb-n" id="habit-2">Walk 8,000 steps</p><p class="hb-goal">Goal: every day</p></div>
      <div class="hb-days"><label class="hb-day"><input class="hb-dot" type="checkbox" checked><span class="hb-dname">Mon</span></label><label class="hb-day"><input class="hb-dot" type="checkbox" checked><span class="hb-dname">Tue</span></label><label class="hb-day"><input class="hb-dot" type="checkbox" checked><span class="hb-dname">Wed</span></label><label class="hb-day is-today"><input class="hb-dot" type="checkbox"><span class="hb-dname">Thu<span class="sr-only">, today</span></span></label><label class="hb-day"><input class="hb-dot" type="checkbox"><span class="hb-dname">Fri</span></label><label class="hb-day"><input class="hb-dot" type="checkbox"><span class="hb-dname">Sat</span></label><label class="hb-day"><input class="hb-dot" type="checkbox"><span class="hb-dname">Sun</span></label></div>
      <p class="hb-tally"><span data-tally-out>3 of 7</span><span>days</span></p>
    </div>
    <div class="hb-row" role="group" aria-labelledby="habit-3" data-tally="No phone after 22:00" data-unit="days this week">
      <div><p class="hb-n" id="habit-3">No phone after 22:00</p><p class="hb-goal">Goal: 4 days a week</p></div>
      <div class="hb-days"><label class="hb-day"><input class="hb-dot" type="checkbox"><span class="hb-dname">Mon</span></label><label class="hb-day"><input class="hb-dot" type="checkbox" checked><span class="hb-dname">Tue</span></label><label class="hb-day"><input class="hb-dot" type="checkbox" checked><span class="hb-dname">Wed</span></label><label class="hb-day is-today"><input class="hb-dot" type="checkbox" checked><span class="hb-dname">Thu<span class="sr-only">, today</span></span></label><label class="hb-day"><input class="hb-dot" type="checkbox"><span class="hb-dname">Fri</span></label><label class="hb-day"><input class="hb-dot" type="checkbox"><span class="hb-dname">Sat</span></label><label class="hb-day"><input class="hb-dot" type="checkbox"><span class="hb-dname">Sun</span></label></div>
      <p class="hb-tally"><span data-tally-out>3 of 7</span><span>days</span></p>
    </div>
    <div class="hb-row" role="group" aria-labelledby="habit-4" data-tally="Practise Spanish for 15 minutes" data-unit="days this week">
      <div><p class="hb-n" id="habit-4">Practise Spanish for 15 minutes</p><p class="hb-goal">Goal: 5 days a week</p></div>
      <div class="hb-days"><label class="hb-day"><input class="hb-dot" type="checkbox" checked><span class="hb-dname">Mon</span></label><label class="hb-day"><input class="hb-dot" type="checkbox"><span class="hb-dname">Tue</span></label><label class="hb-day"><input class="hb-dot" type="checkbox" checked><span class="hb-dname">Wed</span></label><label class="hb-day is-today"><input class="hb-dot" type="checkbox"><span class="hb-dname">Thu<span class="sr-only">, today</span></span></label><label class="hb-day"><input class="hb-dot" type="checkbox"><span class="hb-dname">Fri</span></label><label class="hb-day"><input class="hb-dot" type="checkbox"><span class="hb-dname">Sat</span></label><label class="hb-day"><input class="hb-dot" type="checkbox"><span class="hb-dname">Sun</span></label></div>
      <p class="hb-tally"><span data-tally-out>2 of 7</span><span>days</span></p>
    </div>
  </div>
  <p class="sr-only" role="status" data-live></p>
</section></div>

<div><span class="lbl">Daily planner</span>
<section class="hb" data-tallies aria-labelledby="plan-title">
  <div data-tally="Thursday plan" data-unit="tasks done">
  <div class="hb-head"><h2 id="plan-title">Thursday 11 June</h2><p class="hb-count"><span data-tally-out>2 of 6</span> done</p></div>
  <ol class="hb-plan">
    <li class="hb-item"><time class="hb-time" datetime="08:30">08:30</time><div class="hb-card tag-routine"><input class="hb-box" type="checkbox" id="plan-1" checked><label for="plan-1">Plan the day and clear the inbox</label><span class="hb-tag">Routine</span></div></li>
    <li class="hb-item"><time class="hb-time" datetime="09:00">09:00</time><div class="hb-card tag-deep"><input class="hb-box" type="checkbox" id="plan-2" checked><label for="plan-2">Write the grant report draft</label><span class="hb-tag">Deep work</span></div></li>
    <li class="hb-item"><time class="hb-time" datetime="11:00">11:00</time><div class="hb-card tag-call"><span class="hb-now" aria-hidden="true"><b>Now 10:15</b></span><input class="hb-box" type="checkbox" id="plan-3"><label for="plan-3">Call the printer about paper stock</label><span class="hb-tag">Call</span></div></li>
    <li class="hb-item"><time class="hb-time" datetime="12:30">12:30</time><div class="hb-card tag-personal"><input class="hb-box" type="checkbox" id="plan-4"><label for="plan-4">Lunch with Sam at Marlow Café</label><span class="hb-tag">Personal</span></div></li>
    <li class="hb-item"><time class="hb-time" datetime="14:00">14:00</time><div class="hb-card tag-deep"><input class="hb-box" type="checkbox" id="plan-5"><label for="plan-5">Review three pull requests</label><span class="hb-tag">Deep work</span></div></li>
    <li class="hb-item"><time class="hb-time" datetime="16:30">16:30</time><div class="hb-card tag-personal"><input class="hb-box" type="checkbox" id="plan-6"><label for="plan-6">Pick up the kids from swimming</label><span class="hb-tag">Personal</span></div></li>
  </ol>
  </div>
  <p class="sr-only" role="status" data-live></p>
</section></div>
CSS
/* Habit tracker and daily planner: every day dot and every planner task is a real checkbox with a visible label.
   Each habit row is a group named by the habit, so a dot reads as "Read 20 pages, Mon, checkbox". The script keeps the tallies. */
.hb{--hb-ink:#1e1537;--hb-muted:#5b5175;--hb-line:#e7e1f6;--hb-box:#8a7fa9;--hb-accent:#6d28d9;--hb-accent-dark:#5b21b6;--hb-tint:#f1ecfd;
  background:#fff;color:var(--hb-ink);border:1px solid var(--hb-line);border-radius:20px;padding:24px 26px;box-shadow:0 20px 44px -30px rgba(30,21,55,.45)}
.hb :where(h2,p,ol){margin:0;padding:0}
.hb ol{list-style:none}
.hb-head{display:flex;align-items:baseline;justify-content:space-between;gap:4px 16px;flex-wrap:wrap}
.hb h2{font-size:1.2rem;font-weight:800;letter-spacing:-.015em}
.hb-sub{font-size:.86rem;color:var(--hb-muted)}
.hb-habits{margin-top:14px}
.hb-row{display:grid;grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:10px 18px;padding:14px 0;border-top:1px solid var(--hb-line)}
.hb-n{font-size:1rem;font-weight:700;line-height:1.35}
.hb-goal{margin-top:2px!important;font-size:.8rem;color:var(--hb-muted)}
.hb-days{display:flex;gap:6px}
.hb-day{display:flex;flex-direction:column;align-items:center;gap:5px;cursor:pointer}
.hb-dot{appearance:none;width:30px;height:30px;margin:0;border:2px solid var(--hb-box);border-radius:50%;background:#fff center/15px no-repeat;cursor:pointer;
  transition:background-color .15s,border-color .15s,transform .15s}
.hb-dot:hover{border-color:var(--hb-accent)}
.hb-dot:checked{background-color:var(--hb-accent);border-color:var(--hb-accent);background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5l3 3 6-7'/%3E%3C/svg%3E")}
.hb-dot:active{transform:scale(.92)}
.hb-dot:focus-visible{outline:3px solid var(--hb-accent);outline-offset:2px}
.hb-dname{font-size:.7rem;font-weight:600;color:var(--hb-muted)}
.hb-day.is-today .hb-dot{box-shadow:0 0 0 3px #fff,0 0 0 5px #c4b5fd}
.hb-day.is-today .hb-dname{color:var(--hb-accent-dark);font-weight:800}
.hb-tally{min-width:58px;text-align:right;font-size:1.05rem;font-weight:800;font-variant-numeric:tabular-nums;color:var(--hb-accent-dark);line-height:1.2}
.hb-tally span:last-child{display:block;font-size:.72rem;font-weight:600;color:var(--hb-muted)}
/* daily planner */
.hb-count{font-size:.9rem;font-weight:700;color:var(--hb-accent-dark)}
.hb-plan{margin-top:16px!important;display:grid;gap:10px}
.hb-item{display:grid;grid-template-columns:52px minmax(0,1fr);gap:12px;align-items:start}
.hb-time{padding-top:13px;font-size:.85rem;font-weight:700;font-variant-numeric:tabular-nums;color:var(--hb-muted);text-align:right}
.hb-card{position:relative;display:flex;align-items:center;flex-wrap:wrap;gap:8px 12px;padding:11px 14px;border:1px solid var(--hb-line);border-left:4px solid var(--tag-bar);border-radius:12px;background:#fff;transition:background-color .15s}
.hb-card:has(:checked){background:#faf9fd}
.hb-box{appearance:none;flex:none;width:20px;height:20px;margin:0;border:2px solid var(--hb-box);border-radius:6px;background:#fff center/13px no-repeat;cursor:pointer;transition:background-color .15s,border-color .15s}
.hb-box:checked{background-color:var(--hb-accent);border-color:var(--hb-accent);background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5l3 3 6-7'/%3E%3C/svg%3E")}
.hb-box:focus-visible{outline:3px solid var(--hb-accent);outline-offset:2px}
.hb-card label{flex:1 1 180px;min-width:0;font-size:.98rem;font-weight:600;line-height:1.4;cursor:pointer}
.hb-box:checked+label{color:var(--hb-muted);text-decoration:line-through;font-weight:500}
.hb-tag{margin-left:auto;font-size:.72rem;font-weight:700;padding:3px 9px;border-radius:999px;background:var(--tag-bg);color:var(--tag-ink);white-space:nowrap}
.tag-routine{--tag-ink:#475569;--tag-bg:#eef1f6;--tag-bar:#94a3b8}
.tag-deep{--tag-ink:#5b21b6;--tag-bg:#efe9fe;--tag-bar:#7c3aed}
.tag-call{--tag-ink:#1e40af;--tag-bg:#e5edfd;--tag-bar:#3b82f6}
.tag-personal{--tag-ink:#166534;--tag-bg:#e3f4e8;--tag-bar:#22a352}
.hb-now{position:absolute;left:-4px;right:0;top:-8px;height:0;border-top:2px solid #e11d48}
.hb-now::after{content:"";position:absolute;left:-6px;top:-6px;width:10px;height:10px;border-radius:50%;background:#e11d48}
.hb-now b{position:absolute;right:10px;top:-10px;padding:1px 7px;border-radius:999px;background:#e11d48;color:#fff;font-size:.66rem;font-weight:800;line-height:1.4}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
@media (max-width:640px){.hb{padding:20px 16px}.hb-row{grid-template-columns:minmax(0,1fr) auto}.hb-days{grid-column:1/-1;grid-row:2;justify-content:space-between}
  .hb-item{grid-template-columns:44px minmax(0,1fr);gap:10px}}
@media (prefers-reduced-motion:reduce){.hb *{transition:none!important}}
JavaScript
/* Habit and planner tallies: count the ticked boxes in each [data-tally] group, write "4 of 7" into its
   [data-tally-out] and announce the new total politely. */
document.querySelectorAll('[data-tallies]').forEach((root) => {
  const live = root.querySelector('[data-live]');
  const paint = (group) => {
    const boxes = [...group.querySelectorAll('input[type=checkbox]')];
    const done = boxes.filter((b) => b.checked).length;
    group.querySelector('[data-tally-out]').textContent = done + ' of ' + boxes.length;
    return [done, boxes.length];
  };
  root.querySelectorAll('[data-tally]').forEach(paint);
  root.addEventListener('change', (e) => {
    const group = e.target.closest('[data-tally]');
    if (!group) return;
    const [done, total] = paint(group);
    live.textContent = group.dataset.tally + ': ' + done + ' of ' + total + ' ' + (group.dataset.unit || 'done') + '.';
  });
});

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl">Weekly habit tracker</span>
<section class="card hb" data-tallies aria-labelledby="habits-title">
  <div class="hb-head"><h2 class="mb-0" id="habits-title">Habits this week</h2><p class="hb-sub mb-0">Monday 8 to Sunday 14 June</p></div>
  <div class="hb-habits">
    <div class="hb-row" role="group" aria-labelledby="habit-1" data-tally="Read 20 pages" data-unit="days this week">
      <div><p class="hb-n mb-0" id="habit-1">Read 20 pages</p><p class="hb-goal mb-0">Goal: 5 days a week</p></div>
      <div class="hb-days"><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox" checked><span class="hb-dname">Mon</span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox" checked><span class="hb-dname">Tue</span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Wed</span></label><label class="hb-day is-today"><input class="form-check-input hb-dot" type="checkbox" checked><span class="hb-dname">Thu<span class="visually-hidden">, today</span></span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Fri</span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Sat</span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Sun</span></label></div>
      <p class="hb-tally mb-0"><span data-tally-out>3 of 7</span><span>days</span></p>
    </div>
    <div class="hb-row" role="group" aria-labelledby="habit-2" data-tally="Walk 8,000 steps" data-unit="days this week">
      <div><p class="hb-n mb-0" id="habit-2">Walk 8,000 steps</p><p class="hb-goal mb-0">Goal: every day</p></div>
      <div class="hb-days"><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox" checked><span class="hb-dname">Mon</span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox" checked><span class="hb-dname">Tue</span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox" checked><span class="hb-dname">Wed</span></label><label class="hb-day is-today"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Thu<span class="visually-hidden">, today</span></span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Fri</span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Sat</span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Sun</span></label></div>
      <p class="hb-tally mb-0"><span data-tally-out>3 of 7</span><span>days</span></p>
    </div>
    <div class="hb-row" role="group" aria-labelledby="habit-3" data-tally="No phone after 22:00" data-unit="days this week">
      <div><p class="hb-n mb-0" id="habit-3">No phone after 22:00</p><p class="hb-goal mb-0">Goal: 4 days a week</p></div>
      <div class="hb-days"><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Mon</span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox" checked><span class="hb-dname">Tue</span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox" checked><span class="hb-dname">Wed</span></label><label class="hb-day is-today"><input class="form-check-input hb-dot" type="checkbox" checked><span class="hb-dname">Thu<span class="visually-hidden">, today</span></span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Fri</span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Sat</span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Sun</span></label></div>
      <p class="hb-tally mb-0"><span data-tally-out>3 of 7</span><span>days</span></p>
    </div>
    <div class="hb-row" role="group" aria-labelledby="habit-4" data-tally="Practise Spanish for 15 minutes" data-unit="days this week">
      <div><p class="hb-n mb-0" id="habit-4">Practise Spanish for 15 minutes</p><p class="hb-goal mb-0">Goal: 5 days a week</p></div>
      <div class="hb-days"><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox" checked><span class="hb-dname">Mon</span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Tue</span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox" checked><span class="hb-dname">Wed</span></label><label class="hb-day is-today"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Thu<span class="visually-hidden">, today</span></span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Fri</span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Sat</span></label><label class="hb-day"><input class="form-check-input hb-dot" type="checkbox"><span class="hb-dname">Sun</span></label></div>
      <p class="hb-tally mb-0"><span data-tally-out>2 of 7</span><span>days</span></p>
    </div>
  </div>
  <p class="visually-hidden" role="status" data-live></p>
</section></div>

<div><span class="lbl">Daily planner</span>
<section class="card hb" data-tallies aria-labelledby="plan-title">
  <div data-tally="Thursday plan" data-unit="tasks done">
  <div class="hb-head"><h2 class="mb-0" id="plan-title">Thursday 11 June</h2><p class="hb-count mb-0"><span data-tally-out>2 of 6</span> done</p></div>
  <ol class="hb-plan">
    <li class="hb-item"><time class="hb-time" datetime="08:30">08:30</time><div class="hb-card tag-routine"><input class="form-check-input" type="checkbox" id="plan-1" checked><label for="plan-1">Plan the day and clear the inbox</label><span class="badge rounded-pill hb-tag">Routine</span></div></li>
    <li class="hb-item"><time class="hb-time" datetime="09:00">09:00</time><div class="hb-card tag-deep"><input class="form-check-input" type="checkbox" id="plan-2" checked><label for="plan-2">Write the grant report draft</label><span class="badge rounded-pill hb-tag">Deep work</span></div></li>
    <li class="hb-item"><time class="hb-time" datetime="11:00">11:00</time><div class="hb-card tag-call"><span class="hb-now" aria-hidden="true"><b>Now 10:15</b></span><input class="form-check-input" type="checkbox" id="plan-3"><label for="plan-3">Call the printer about paper stock</label><span class="badge rounded-pill hb-tag">Call</span></div></li>
    <li class="hb-item"><time class="hb-time" datetime="12:30">12:30</time><div class="hb-card tag-personal"><input class="form-check-input" type="checkbox" id="plan-4"><label for="plan-4">Lunch with Sam at Marlow Café</label><span class="badge rounded-pill hb-tag">Personal</span></div></li>
    <li class="hb-item"><time class="hb-time" datetime="14:00">14:00</time><div class="hb-card tag-deep"><input class="form-check-input" type="checkbox" id="plan-5"><label for="plan-5">Review three pull requests</label><span class="badge rounded-pill hb-tag">Deep work</span></div></li>
    <li class="hb-item"><time class="hb-time" datetime="16:30">16:30</time><div class="hb-card tag-personal"><input class="form-check-input" type="checkbox" id="plan-6"><label for="plan-6">Pick up the kids from swimming</label><span class="badge rounded-pill hb-tag">Personal</span></div></li>
  </ol>
  </div>
  <p class="visually-hidden" role="status" data-live></p>
</section></div>
CSS
/* Habit tracker and daily planner on Bootstrap: .card, .form-check-input and .badge, restyled through CSS variables. Every day dot and every planner task is a real checkbox with a visible label.
   Each habit row is a group named by the habit, so a dot reads as "Read 20 pages, Mon, checkbox". The script keeps the tallies. */
.hb{--bs-card-border-color:var(--hb-line);--bs-card-border-radius:20px;--hb-ink:#1e1537;--hb-muted:#5b5175;--hb-line:#e7e1f6;--hb-box:#8a7fa9;--hb-accent:#6d28d9;--hb-accent-dark:#5b21b6;--hb-tint:#f1ecfd;
  background:#fff;color:var(--hb-ink);border:1px solid var(--hb-line);border-radius:20px;padding:24px 26px;box-shadow:0 20px 44px -30px rgba(30,21,55,.45)}
.hb :where(h2,p,ol){margin:0;padding:0}
.hb label{margin:0}
.hb h2{line-height:normal}
.hb ol{list-style:none}
.hb-head{display:flex;align-items:baseline;justify-content:space-between;gap:4px 16px;flex-wrap:wrap}
.hb h2{font-size:1.2rem;font-weight:800;letter-spacing:-.015em}
.hb-sub{font-size:.86rem;color:var(--hb-muted)}
.hb-habits{margin-top:14px}
.hb-row{display:grid;grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:10px 18px;padding:14px 0;border-top:1px solid var(--hb-line)}
.hb-n{font-size:1rem;font-weight:700;line-height:1.35}
.hb-goal{margin-top:2px!important;font-size:.8rem;color:var(--hb-muted)}
.hb-days{display:flex;gap:6px}
.hb-day{display:flex;flex-direction:column;align-items:center;gap:5px;cursor:pointer}
.hb .hb-dot{width:30px;height:30px;margin:0;border:2px solid var(--hb-box);border-radius:50%;background-size:15px;cursor:pointer;
  transition:background-color .15s,border-color .15s,transform .15s}
.hb .hb-dot:hover{border-color:var(--hb-accent)}
.hb .form-check-input:checked{background-color:var(--hb-accent);border-color:var(--hb-accent)}
.hb .form-check-input:focus{box-shadow:none;border-color:var(--hb-box)}
.hb .form-check-input:checked:focus{border-color:var(--hb-accent)}
.hb .hb-dot:active{transform:scale(.92)}
.hb .form-check-input:focus-visible{outline:3px solid var(--hb-accent);outline-offset:2px}
.hb-dname{font-size:.7rem;font-weight:600;color:var(--hb-muted)}
.hb .hb-day.is-today .hb-dot{box-shadow:0 0 0 3px #fff,0 0 0 5px #c4b5fd}
.hb-day.is-today .hb-dname{color:var(--hb-accent-dark);font-weight:800}
.hb-tally{min-width:58px;text-align:right;font-size:1.05rem;font-weight:800;font-variant-numeric:tabular-nums;color:var(--hb-accent-dark);line-height:1.2}
.hb-tally span:last-child{display:block;font-size:.72rem;font-weight:600;color:var(--hb-muted)}
/* daily planner */
.hb-count{font-size:.9rem;font-weight:700;color:var(--hb-accent-dark)}
.hb-plan{margin-top:16px!important;display:grid;gap:10px}
.hb-item{display:grid;grid-template-columns:52px minmax(0,1fr);gap:12px;align-items:start}
.hb-time{padding-top:13px;font-size:.85rem;font-weight:700;font-variant-numeric:tabular-nums;color:var(--hb-muted);text-align:right}
.hb-card{position:relative;display:flex;align-items:center;flex-wrap:wrap;gap:8px 12px;padding:11px 14px;border:1px solid var(--hb-line);border-left:4px solid var(--tag-bar);border-radius:12px;background:#fff;transition:background-color .15s}
.hb-card:has(:checked){background:#faf9fd}
.hb-card .form-check-input{flex:none;width:20px;height:20px;margin:0;border:2px solid var(--hb-box);border-radius:6px;background-size:13px;cursor:pointer;transition:background-color .15s,border-color .15s}
.hb-card label{flex:1 1 180px;min-width:0;font-size:.98rem;font-weight:600;line-height:1.4;cursor:pointer}
.hb .form-check-input:checked+label{color:var(--hb-muted);text-decoration:line-through;font-weight:500}
.hb-tag{--bs-badge-font-size:.72rem;--bs-badge-font-weight:700;--bs-badge-padding-x:9px;--bs-badge-padding-y:3px;--bs-badge-color:var(--tag-ink);margin-left:auto;background:var(--tag-bg);line-height:normal}
.tag-routine{--tag-ink:#475569;--tag-bg:#eef1f6;--tag-bar:#94a3b8}
.tag-deep{--tag-ink:#5b21b6;--tag-bg:#efe9fe;--tag-bar:#7c3aed}
.tag-call{--tag-ink:#1e40af;--tag-bg:#e5edfd;--tag-bar:#3b82f6}
.tag-personal{--tag-ink:#166534;--tag-bg:#e3f4e8;--tag-bar:#22a352}
.hb-now{position:absolute;left:-4px;right:0;top:-8px;height:0;border-top:2px solid #e11d48}
.hb-now::after{content:"";position:absolute;left:-6px;top:-6px;width:10px;height:10px;border-radius:50%;background:#e11d48}
.hb-now b{position:absolute;right:10px;top:-10px;padding:1px 7px;border-radius:999px;background:#e11d48;color:#fff;font-size:.66rem;font-weight:800;line-height:1.4}
@media (max-width:640px){.hb{padding:20px 16px}.hb-row{grid-template-columns:minmax(0,1fr) auto}.hb-days{grid-column:1/-1;grid-row:2;justify-content:space-between}
  .hb-item{grid-template-columns:44px minmax(0,1fr);gap:10px}}
@media (prefers-reduced-motion:reduce){.hb *{transition:none!important}}
JavaScript
/* Habit and planner tallies: count the ticked boxes in each [data-tally] group, write "4 of 7" into its
   [data-tally-out] and announce the new total politely. */
document.querySelectorAll('[data-tallies]').forEach((root) => {
  const live = root.querySelector('[data-live]');
  const paint = (group) => {
    const boxes = [...group.querySelectorAll('input[type=checkbox]')];
    const done = boxes.filter((b) => b.checked).length;
    group.querySelector('[data-tally-out]').textContent = done + ' of ' + boxes.length;
    return [done, boxes.length];
  };
  root.querySelectorAll('[data-tally]').forEach(paint);
  root.addEventListener('change', (e) => {
    const group = e.target.closest('[data-tally]');
    if (!group) return;
    const [done, total] = paint(group);
    live.textContent = group.dataset.tally + ': ' + done + ' of ' + total + ' ' + (group.dataset.unit || 'done') + '.';
  });
});

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#5b5175] uppercase">Weekly habit tracker</span>
<section class="rounded-[20px] border border-[#e7e1f6] bg-white px-[26px] py-6 text-[#1e1537] shadow-[0_20px_44px_-30px_rgba(30,21,55,.45)] max-sm:px-4 max-sm:py-5" data-tallies aria-labelledby="habits-title">
  <div class="flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1"><h2 class="text-[1.2rem] font-extrabold tracking-[-.015em]" id="habits-title">Habits this week</h2><p class="text-[.86rem] text-[#5b5175]">Monday 8 to Sunday 14 June</p></div>
  <div class="mt-3.5">
    <div class="grid grid-cols-[minmax(0,1fr)_auto_auto] items-center gap-x-[18px] gap-y-2.5 border-t border-[#e7e1f6] py-3.5 max-sm:grid-cols-[minmax(0,1fr)_auto]" role="group" aria-labelledby="habit-1" data-tally="Read 20 pages" data-unit="days this week">
      <div><p class="text-base leading-[1.35] font-bold" id="habit-1">Read 20 pages</p><p class="mt-0.5 text-[.8rem] text-[#5b5175]">Goal: 5 days a week</p></div>
      <div class="flex gap-1.5 max-sm:col-span-full max-sm:row-start-2 max-sm:justify-between"><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" checked><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Mon</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" checked><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Tue</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Wed</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px] is-today"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" checked><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Thu<span class="sr-only">, today</span></span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Fri</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Sat</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Sun</span></label></div>
      <p class="min-w-[58px] text-right text-[1.05rem] leading-[1.2] font-extrabold text-[#5b21b6] tabular-nums"><span data-tally-out>3 of 7</span><span class="block text-[.72rem] font-semibold text-[#5b5175]">days</span></p>
    </div>
    <div class="grid grid-cols-[minmax(0,1fr)_auto_auto] items-center gap-x-[18px] gap-y-2.5 border-t border-[#e7e1f6] py-3.5 max-sm:grid-cols-[minmax(0,1fr)_auto]" role="group" aria-labelledby="habit-2" data-tally="Walk 8,000 steps" data-unit="days this week">
      <div><p class="text-base leading-[1.35] font-bold" id="habit-2">Walk 8,000 steps</p><p class="mt-0.5 text-[.8rem] text-[#5b5175]">Goal: every day</p></div>
      <div class="flex gap-1.5 max-sm:col-span-full max-sm:row-start-2 max-sm:justify-between"><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" checked><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Mon</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" checked><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Tue</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" checked><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Wed</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px] is-today"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Thu<span class="sr-only">, today</span></span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Fri</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Sat</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Sun</span></label></div>
      <p class="min-w-[58px] text-right text-[1.05rem] leading-[1.2] font-extrabold text-[#5b21b6] tabular-nums"><span data-tally-out>3 of 7</span><span class="block text-[.72rem] font-semibold text-[#5b5175]">days</span></p>
    </div>
    <div class="grid grid-cols-[minmax(0,1fr)_auto_auto] items-center gap-x-[18px] gap-y-2.5 border-t border-[#e7e1f6] py-3.5 max-sm:grid-cols-[minmax(0,1fr)_auto]" role="group" aria-labelledby="habit-3" data-tally="No phone after 22:00" data-unit="days this week">
      <div><p class="text-base leading-[1.35] font-bold" id="habit-3">No phone after 22:00</p><p class="mt-0.5 text-[.8rem] text-[#5b5175]">Goal: 4 days a week</p></div>
      <div class="flex gap-1.5 max-sm:col-span-full max-sm:row-start-2 max-sm:justify-between"><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Mon</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" checked><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Tue</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" checked><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Wed</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px] is-today"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" checked><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Thu<span class="sr-only">, today</span></span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Fri</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Sat</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Sun</span></label></div>
      <p class="min-w-[58px] text-right text-[1.05rem] leading-[1.2] font-extrabold text-[#5b21b6] tabular-nums"><span data-tally-out>3 of 7</span><span class="block text-[.72rem] font-semibold text-[#5b5175]">days</span></p>
    </div>
    <div class="grid grid-cols-[minmax(0,1fr)_auto_auto] items-center gap-x-[18px] gap-y-2.5 border-t border-[#e7e1f6] py-3.5 max-sm:grid-cols-[minmax(0,1fr)_auto]" role="group" aria-labelledby="habit-4" data-tally="Practise Spanish for 15 minutes" data-unit="days this week">
      <div><p class="text-base leading-[1.35] font-bold" id="habit-4">Practise Spanish for 15 minutes</p><p class="mt-0.5 text-[.8rem] text-[#5b5175]">Goal: 5 days a week</p></div>
      <div class="flex gap-1.5 max-sm:col-span-full max-sm:row-start-2 max-sm:justify-between"><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" checked><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Mon</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Tue</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" checked><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Wed</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px] is-today"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Thu<span class="sr-only">, today</span></span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Fri</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Sat</span></label><label class="group/day flex cursor-pointer flex-col items-center gap-[5px]"><input class="size-[30px] cursor-pointer appearance-none rounded-full border-2 border-[#8a7fa9] bg-white bg-[length:15px] bg-center bg-no-repeat transition-[background-color,border-color,transform] duration-150 hover:border-[#6d28d9] checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick active:scale-[.92] group-[.is-today]/day:shadow-[0_0_0_3px_#fff,0_0_0_5px_#c4b5fd] focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox"><span class="text-[.7rem] font-semibold text-[#5b5175] group-[.is-today]/day:font-extrabold group-[.is-today]/day:text-[#5b21b6]">Sun</span></label></div>
      <p class="min-w-[58px] text-right text-[1.05rem] leading-[1.2] font-extrabold text-[#5b21b6] tabular-nums"><span data-tally-out>2 of 7</span><span class="block text-[.72rem] font-semibold text-[#5b5175]">days</span></p>
    </div>
  </div>
  <p class="sr-only" role="status" data-live></p>
</section></div>

<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#5b5175] uppercase">Daily planner</span>
<section class="rounded-[20px] border border-[#e7e1f6] bg-white px-[26px] py-6 text-[#1e1537] shadow-[0_20px_44px_-30px_rgba(30,21,55,.45)] max-sm:px-4 max-sm:py-5" data-tallies aria-labelledby="plan-title">
  <div data-tally="Thursday plan" data-unit="tasks done">
  <div class="flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1"><h2 class="text-[1.2rem] font-extrabold tracking-[-.015em]" id="plan-title">Thursday 11 June</h2><p class="text-[.9rem] font-bold text-[#5b21b6]"><span data-tally-out>2 of 6</span> done</p></div>
  <ol class="mt-4 grid gap-2.5">
    <li class="grid grid-cols-[52px_minmax(0,1fr)] items-start gap-3 max-sm:grid-cols-[44px_minmax(0,1fr)] max-sm:gap-2.5"><time class="pt-[13px] text-right text-[.85rem] font-bold text-[#5b5175] tabular-nums" datetime="08:30">08:30</time><div class="relative flex flex-wrap items-center gap-x-3 gap-y-2 rounded-xl border border-l-4 border-[#e7e1f6] bg-white px-3.5 py-[11px] transition-colors duration-150 has-checked:bg-[#faf9fd] motion-reduce:transition-none border-l-[#94a3b8]"><input class="peer size-5 flex-none cursor-pointer appearance-none rounded-md border-2 border-[#8a7fa9] bg-white bg-[length:13px] bg-center bg-no-repeat transition-colors duration-150 checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" id="plan-1" checked><label class="min-w-0 flex-[1_1_180px] cursor-pointer text-[.98rem] leading-[1.4] font-semibold peer-checked:font-medium peer-checked:text-[#5b5175] peer-checked:line-through" for="plan-1">Plan the day and clear the inbox</label><span class="ml-auto whitespace-nowrap rounded-full px-[9px] py-[3px] text-[.72rem] font-bold bg-[#eef1f6] text-[#475569]">Routine</span></div></li>
    <li class="grid grid-cols-[52px_minmax(0,1fr)] items-start gap-3 max-sm:grid-cols-[44px_minmax(0,1fr)] max-sm:gap-2.5"><time class="pt-[13px] text-right text-[.85rem] font-bold text-[#5b5175] tabular-nums" datetime="09:00">09:00</time><div class="relative flex flex-wrap items-center gap-x-3 gap-y-2 rounded-xl border border-l-4 border-[#e7e1f6] bg-white px-3.5 py-[11px] transition-colors duration-150 has-checked:bg-[#faf9fd] motion-reduce:transition-none border-l-[#7c3aed]"><input class="peer size-5 flex-none cursor-pointer appearance-none rounded-md border-2 border-[#8a7fa9] bg-white bg-[length:13px] bg-center bg-no-repeat transition-colors duration-150 checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" id="plan-2" checked><label class="min-w-0 flex-[1_1_180px] cursor-pointer text-[.98rem] leading-[1.4] font-semibold peer-checked:font-medium peer-checked:text-[#5b5175] peer-checked:line-through" for="plan-2">Write the grant report draft</label><span class="ml-auto whitespace-nowrap rounded-full px-[9px] py-[3px] text-[.72rem] font-bold bg-[#efe9fe] text-[#5b21b6]">Deep work</span></div></li>
    <li class="grid grid-cols-[52px_minmax(0,1fr)] items-start gap-3 max-sm:grid-cols-[44px_minmax(0,1fr)] max-sm:gap-2.5"><time class="pt-[13px] text-right text-[.85rem] font-bold text-[#5b5175] tabular-nums" datetime="11:00">11:00</time><div class="relative flex flex-wrap items-center gap-x-3 gap-y-2 rounded-xl border border-l-4 border-[#e7e1f6] bg-white px-3.5 py-[11px] transition-colors duration-150 has-checked:bg-[#faf9fd] motion-reduce:transition-none border-l-[#3b82f6]"><span class="absolute -top-2 -left-1 right-0 h-0 border-t-2 border-[#e11d48] after:absolute after:-top-1.5 after:-left-1.5 after:size-2.5 after:rounded-full after:bg-[#e11d48]" aria-hidden="true"><b class="absolute -top-2.5 right-2.5 rounded-full bg-[#e11d48] px-[7px] py-px text-[.66rem] leading-[1.4] font-extrabold text-white">Now 10:15</b></span><input class="peer size-5 flex-none cursor-pointer appearance-none rounded-md border-2 border-[#8a7fa9] bg-white bg-[length:13px] bg-center bg-no-repeat transition-colors duration-150 checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" id="plan-3"><label class="min-w-0 flex-[1_1_180px] cursor-pointer text-[.98rem] leading-[1.4] font-semibold peer-checked:font-medium peer-checked:text-[#5b5175] peer-checked:line-through" for="plan-3">Call the printer about paper stock</label><span class="ml-auto whitespace-nowrap rounded-full px-[9px] py-[3px] text-[.72rem] font-bold bg-[#e5edfd] text-[#1e40af]">Call</span></div></li>
    <li class="grid grid-cols-[52px_minmax(0,1fr)] items-start gap-3 max-sm:grid-cols-[44px_minmax(0,1fr)] max-sm:gap-2.5"><time class="pt-[13px] text-right text-[.85rem] font-bold text-[#5b5175] tabular-nums" datetime="12:30">12:30</time><div class="relative flex flex-wrap items-center gap-x-3 gap-y-2 rounded-xl border border-l-4 border-[#e7e1f6] bg-white px-3.5 py-[11px] transition-colors duration-150 has-checked:bg-[#faf9fd] motion-reduce:transition-none border-l-[#22a352]"><input class="peer size-5 flex-none cursor-pointer appearance-none rounded-md border-2 border-[#8a7fa9] bg-white bg-[length:13px] bg-center bg-no-repeat transition-colors duration-150 checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" id="plan-4"><label class="min-w-0 flex-[1_1_180px] cursor-pointer text-[.98rem] leading-[1.4] font-semibold peer-checked:font-medium peer-checked:text-[#5b5175] peer-checked:line-through" for="plan-4">Lunch with Sam at Marlow Café</label><span class="ml-auto whitespace-nowrap rounded-full px-[9px] py-[3px] text-[.72rem] font-bold bg-[#e3f4e8] text-[#166534]">Personal</span></div></li>
    <li class="grid grid-cols-[52px_minmax(0,1fr)] items-start gap-3 max-sm:grid-cols-[44px_minmax(0,1fr)] max-sm:gap-2.5"><time class="pt-[13px] text-right text-[.85rem] font-bold text-[#5b5175] tabular-nums" datetime="14:00">14:00</time><div class="relative flex flex-wrap items-center gap-x-3 gap-y-2 rounded-xl border border-l-4 border-[#e7e1f6] bg-white px-3.5 py-[11px] transition-colors duration-150 has-checked:bg-[#faf9fd] motion-reduce:transition-none border-l-[#7c3aed]"><input class="peer size-5 flex-none cursor-pointer appearance-none rounded-md border-2 border-[#8a7fa9] bg-white bg-[length:13px] bg-center bg-no-repeat transition-colors duration-150 checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" id="plan-5"><label class="min-w-0 flex-[1_1_180px] cursor-pointer text-[.98rem] leading-[1.4] font-semibold peer-checked:font-medium peer-checked:text-[#5b5175] peer-checked:line-through" for="plan-5">Review three pull requests</label><span class="ml-auto whitespace-nowrap rounded-full px-[9px] py-[3px] text-[.72rem] font-bold bg-[#efe9fe] text-[#5b21b6]">Deep work</span></div></li>
    <li class="grid grid-cols-[52px_minmax(0,1fr)] items-start gap-3 max-sm:grid-cols-[44px_minmax(0,1fr)] max-sm:gap-2.5"><time class="pt-[13px] text-right text-[.85rem] font-bold text-[#5b5175] tabular-nums" datetime="16:30">16:30</time><div class="relative flex flex-wrap items-center gap-x-3 gap-y-2 rounded-xl border border-l-4 border-[#e7e1f6] bg-white px-3.5 py-[11px] transition-colors duration-150 has-checked:bg-[#faf9fd] motion-reduce:transition-none border-l-[#22a352]"><input class="peer size-5 flex-none cursor-pointer appearance-none rounded-md border-2 border-[#8a7fa9] bg-white bg-[length:13px] bg-center bg-no-repeat transition-colors duration-150 checked:border-[#6d28d9] checked:bg-[#6d28d9] checked:bg-tick focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-[#6d28d9] motion-reduce:transition-none" type="checkbox" id="plan-6"><label class="min-w-0 flex-[1_1_180px] cursor-pointer text-[.98rem] leading-[1.4] font-semibold peer-checked:font-medium peer-checked:text-[#5b5175] peer-checked:line-through" for="plan-6">Pick up the kids from swimming</label><span class="ml-auto whitespace-nowrap rounded-full px-[9px] py-[3px] text-[.72rem] font-bold bg-[#e3f4e8] text-[#166534]">Personal</span></div></li>
  </ol>
  </div>
  <p class="sr-only" role="status" data-live></p>
</section></div>
CSS
/* the white tick drawn inside a checked dot or box */
@utility bg-tick {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5l3 3 6-7'/%3E%3C/svg%3E");
}
JavaScript
/* Habit and planner tallies: count the ticked boxes in each [data-tally] group, write "4 of 7" into its
   [data-tally-out] and announce the new total politely. */
document.querySelectorAll('[data-tallies]').forEach((root) => {
  const live = root.querySelector('[data-live]');
  const paint = (group) => {
    const boxes = [...group.querySelectorAll('input[type=checkbox]')];
    const done = boxes.filter((b) => b.checked).length;
    group.querySelector('[data-tally-out]').textContent = done + ' of ' + boxes.length;
    return [done, boxes.length];
  };
  root.querySelectorAll('[data-tally]').forEach(paint);
  root.addEventListener('change', (e) => {
    const group = e.target.closest('[data-tally]');
    if (!group) return;
    const [done, total] = paint(group);
    live.textContent = group.dataset.tally + ': ' + done + ' of ' + total + ' ' + (group.dataset.unit || 'done') + '.';
  });
});

About this set

Two list layouts for routines rather than one-off tasks. Weekly habit tracker shows four habits, such as Read 20 pages and Walk 8,000 steps, each with a goal line, seven round day checkboxes labelled Mon to Sun, and a tally such as 3 of 7 days. Today’s dot has a ring and a bold label, and on a phone the dots move to their own row under the habit name. Each habit row is a group named by the habit, so a screen reader hears the habit and then the day for every dot. Daily planner is one day of time blocks: each row has a start time in a time element, a task checkbox and a category written as text, such as Deep work, Call or Personal, with a matching coloured edge. A red line marks the current time between two blocks, and a count at the top says how many blocks are done. A script of about twenty lines keeps the tallies and the count up to date and announces them politely. Finished planner rows are struck through and their card turns grey through :has().

What’s included

  • Seven labelled day checkboxes per habit, with today marked
  • Habit rows are groups named by the habit
  • Tallies such as 3 of 7 days, updated as dots are ticked
  • Time-blocked planner with categories written as text
  • Current-time line between blocks and a done count

Accessibility

Every day dot and planner task is a real checkbox with a visible label; each habit row has role="group" and is named by the habit, and today's dot carries visually hidden today text. Categories are written words, not only colours, and the decorative current-time line is hidden from assistive technology. A polite status region announces tallies such as Walk 8,000 steps: 4 of 7 days this week, controls show a visible focus outline, and transitions stop under prefers-reduced-motion.

Customise it

Change --hb-accent, --hb-accent-dark and --hb-box on .hb for the dots and boxes, and the --tag-ink, --tag-bg and --tag-bar values in the .tag-* rules for planner categories. Bootstrap uses the same variables on .form-check-input and .badge; in Tailwind swap the #6d28d9 and category colour utilities.