Back to CSS Pricing Sections Per-Seat Calculator Light JS
Share
.ps-cal {
  padding: clamp(28px, 5vw, 56px) clamp(20px, 4vw, 40px);
  min-height: 480px;
  background:
    radial-gradient(60% 80% at 80% 0%, rgba(99,102,241,0.18), transparent 60%),
    radial-gradient(60% 80% at 0% 100%, rgba(56,189,248,0.14), transparent 60%),
    #07091a;
  color: #e6e9ff;
  font-family: 'Inter', system-ui, sans-serif;
}
.ps-cal-head { text-align: center; margin-bottom: clamp(24px, 4vw, 36px); }
.ps-cal-eye {
  display: inline-block; font-size: 11px; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: #818cf8; padding: 5px 12px;
  background: rgba(129,140,248,0.12);
  border: 1px solid rgba(129,140,248,0.28);
  border-radius: 999px; margin-bottom: 14px;
}
.ps-cal-head h2 {
  font-size: clamp(22px, 3.4vw, 32px); font-weight: 700;
  letter-spacing: -0.02em; margin: 0 0 8px; color: #fff;
}
.ps-cal-head p { color: #9aa3c8; margin: 0; font-size: 14px; }
.ps-cal-card {
  display: grid; grid-template-columns: 1.1fr 1fr;
  gap: 0;
  max-width: 820px; margin: 0 auto;
  background: rgba(20,22,48,0.7);
  border: 1px solid rgba(129,140,248,0.2);
  border-radius: 18px;
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(0,0,0,0.35);
  backdrop-filter: blur(8px);
}
.ps-cal-controls {
  padding: clamp(22px, 4vw, 32px);
  border-right: 1px solid rgba(129,140,248,0.15);
  display: flex; flex-direction: column; gap: 22px;
}
.ps-cal-summary {
  padding: clamp(22px, 4vw, 32px);
  background: linear-gradient(180deg, rgba(99,102,241,0.1), rgba(56,189,248,0.06));
  display: flex; flex-direction: column;
}
.ps-cal-cycle {
  border: 1px solid rgba(129,140,248,0.2);
  border-radius: 10px; padding: 4px;
  display: grid; grid-template-columns: 1fr 1fr; gap: 0;
  background: rgba(7,9,26,0.4);
  margin: 0;
}
.ps-cal-sr {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.ps-cal-cycle input[type="radio"] { position: absolute; opacity: 0; pointer-events: none; }
.ps-cal-cycle label {
  text-align: center; padding: 9px 12px;
  font-size: 12.5px; font-weight: 600; color: #9aa3c8;
  cursor: pointer; border-radius: 7px;
  transition: background 0.18s, color 0.18s;
}
.ps-cal-cycle input:checked + label {
  background: linear-gradient(135deg, #6366f1, #38bdf8); color: #fff;
}
.ps-cal-cycle input:focus-visible + label { outline: 2px solid #818cf8; outline-offset: 2px; }
.ps-cal-stp-lbl {
  display: block; font-size: 11px; letter-spacing: 0.16em;
  text-transform: uppercase; color: #9aa3c8; margin-bottom: 8px;
}
.ps-cal-stp {
  display: grid; grid-template-columns: 44px 1fr 44px;
  border: 1px solid rgba(129,140,248,0.25);
  border-radius: 10px; overflow: hidden;
  background: rgba(7,9,26,0.5);
}
.ps-cal-btn {
  background: transparent; border: 0; cursor: pointer;
  font-size: 22px; font-weight: 700; color: #818cf8;
  font-family: inherit;
  transition: background 0.15s, color 0.15s;
}
.ps-cal-btn:hover { background: rgba(129,140,248,0.15); color: #fff; }
.ps-cal-btn:focus-visible { outline: 2px solid #818cf8; outline-offset: -2px; }
.ps-cal-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.ps-cal-stp input[type="number"] {
  background: transparent; border: 0; outline: 0;
  text-align: center; color: #fff;
  font-size: 22px; font-weight: 700; letter-spacing: -0.01em;
  font-family: inherit;
  border-left: 1px solid rgba(129,140,248,0.18);
  border-right: 1px solid rgba(129,140,248,0.18);
  -moz-appearance: textfield;
}
.ps-cal-stp input::-webkit-outer-spin-button,
.ps-cal-stp input::-webkit-inner-spin-button {
  -webkit-appearance: none; margin: 0;
}
.ps-cal-stp input:focus-visible { background: rgba(129,140,248,0.12); }
.ps-cal-stp-hint { display: block; font-size: 11.5px; color: #6c759b; margin-top: 8px; }
.ps-cal-row {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 10px 0;
  font-size: 13.5px;
}
.ps-cal-row span { color: #9aa3c8; }
.ps-cal-row strong { color: #fff; font-weight: 600; }
.ps-cal-summary hr { border: 0; border-top: 1px dashed rgba(129,140,248,0.25); margin: 4px 0; }
.ps-cal-total span { color: #93c5fd; font-size: 13px; letter-spacing: 0.04em; text-transform: uppercase; }
.ps-cal-total strong {
  font-size: clamp(28px, 4vw, 38px); font-weight: 800; letter-spacing: -0.02em;
  background: linear-gradient(90deg, #818cf8, #38bdf8);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.ps-cal-foot { font-size: 12px; color: #6c759b; margin: 4px 0 16px; }
.ps-cal-cta {
  display: block; text-align: center;
  padding: 12px 18px; border-radius: 10px;
  background: linear-gradient(135deg, #6366f1, #38bdf8);
  color: #fff; text-decoration: none;
  font-size: 14px; font-weight: 700;
  margin-top: auto;
  box-shadow: 0 10px 24px rgba(99,102,241,0.3);
  transition: transform 0.18s;
}
.ps-cal-cta:hover { transform: translateY(-1px); }
.ps-cal-cta:focus-visible { outline: 2px solid #818cf8; outline-offset: 3px; }
@media (max-width: 720px) {
  .ps-cal-card { grid-template-columns: 1fr; }
  .ps-cal-controls { border-right: 0; border-bottom: 1px solid rgba(129,140,248,0.15); }
}
@media (prefers-reduced-motion: reduce) {
  .ps-cal-cta, .ps-cal-btn, .ps-cal-cycle label { transition: none; }
}
<section class="ps-cal" aria-label="Per-seat calculator">
  <header class="ps-cal-head">
    <span class="ps-cal-eye">Build your plan</span>
    <h2>Per-seat pricing, calculated live.</h2>
    <p>One number to change. Everything else updates with you.</p>
  </header>
  <div class="ps-cal-card">
    <div class="ps-cal-controls">
      <fieldset class="ps-cal-cycle">
        <legend class="ps-cal-sr">Billing cycle</legend>
        <input type="radio" name="ps-cal-cycle" id="ps-cal-m" checked />
        <label for="ps-cal-m">Monthly</label>
        <input type="radio" name="ps-cal-cycle" id="ps-cal-y" />
        <label for="ps-cal-y">Yearly · save 25%</label>
      </fieldset>
      <div class="ps-cal-stepper">
        <span class="ps-cal-stp-lbl">Team size</span>
        <div class="ps-cal-stp">
          <button type="button" class="ps-cal-btn" id="ps-cal-dec" aria-label="Decrease team size">
            −
          </button>
          <input
            type="number"
            id="ps-cal-seats"
            value="5"
            min="1"
            max="500"
            inputmode="numeric"
            pattern="[0-9]*"
            aria-label="Number of team members"
          />
          <button type="button" class="ps-cal-btn" id="ps-cal-inc" aria-label="Increase team size">
            +
          </button>
        </div>
        <span class="ps-cal-stp-hint">Up to 500 seats. Above that, we’ll talk.</span>
      </div>
    </div>
    <div class="ps-cal-summary">
      <div class="ps-cal-row"><span>Seats</span><strong id="ps-cal-out-seats">5</strong></div>
      <div class="ps-cal-row">
        <span>Per seat</span><strong id="ps-cal-out-per">$12 /mo</strong>
      </div>
      <div class="ps-cal-row"><span>Cycle</span><strong id="ps-cal-out-cyc">Monthly</strong></div>
      <hr />
      <div class="ps-cal-row ps-cal-total">
        <span>Total today</span>
        <strong id="ps-cal-out-total">$60.00</strong>
      </div>
      <p class="ps-cal-foot" id="ps-cal-out-foot">Billed monthly · cancel any time</p>
      <a class="ps-cal-cta" href="#start">Start 14-day trial →</a>
    </div>
  </div>
</section>
(function () {
  var seats   = document.getElementById('ps-cal-seats');
  var dec     = document.getElementById('ps-cal-dec');
  var inc     = document.getElementById('ps-cal-inc');
  var rM      = document.getElementById('ps-cal-m');
  var rY      = document.getElementById('ps-cal-y');
  var outSeats= document.getElementById('ps-cal-out-seats');
  var outPer  = document.getElementById('ps-cal-out-per');
  var outCyc  = document.getElementById('ps-cal-out-cyc');
  var outTot  = document.getElementById('ps-cal-out-total');
  var outFoot = document.getElementById('ps-cal-out-foot');
  if (!seats || !inc) return;

  var BASE_MONTHLY = 12;       // $12 / seat / mo
  var YEARLY_DISC  = 0.25;     // 25% off when yearly

  function clamp(v) {
    if (isNaN(v) || v < 1) return 1;
    if (v > 500) return 500;
    return v;
  }
  function fmt(n) { return '$' + n.toFixed(2); }

  function update() {
    var n = clamp(parseInt(seats.value, 10));
    seats.value = n;
    var yearly = rY.checked;
    var per    = yearly ? BASE_MONTHLY * (1 - YEARLY_DISC) : BASE_MONTHLY;
    var months = yearly ? 12 : 1;
    var total  = per * n * months;

    outSeats.textContent = n + (n === 1 ? ' member' : ' members');
    outPer.textContent   = '$' + per.toFixed(2) + ' / mo';
    outCyc.textContent   = yearly ? 'Yearly (–25%)' : 'Monthly';
    outTot.textContent   = fmt(total);
    outFoot.textContent  = yearly
      ? 'Billed yearly · ' + fmt(total) + ' once, then renews annually'
      : 'Billed monthly · cancel any time';

    dec.disabled = n <= 1;
    inc.disabled = n >= 500;
  }

  dec.addEventListener('click', function () { seats.value = clamp(parseInt(seats.value, 10) - 1); update(); });
  inc.addEventListener('click', function () { seats.value = clamp(parseInt(seats.value, 10) + 1); update(); });
  seats.addEventListener('input', update);
  rM.addEventListener('change', update);
  rY.addEventListener('change', update);
  update();
})();
Live preview Edit any tab — preview updates live Ready