Open demo

CSS code

HTML
<div><span class="lbl">Subgrid rows and a :has() selection</span>
<section class="mc" aria-labelledby="cg-title">
  <p class="mc-kicker">Cartograph maps API</p><h2 class="mc-title" id="cg-title">Choose a plan</h2><p class="mc-sub">Every row lines up across the cards, however long the text in it.</p>
  <fieldset class="mc-fs"><legend class="sr-only">Plan</legend>
  <div class="mc-grid">
    <article class="mc-card" aria-labelledby="cg-starter">
      <div class="mc-top"><h3 id="cg-starter">Starter</h3></div>
      <p class="mc-desc">For prototypes and personal maps.</p>
      <p class="mc-price"><span class="mc-amt">$0</span><span class="mc-per">free forever</span></p>
      <ul class="mc-feats">
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Map loads</span>25,000 a month</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Geocoding</span>1,000 lookups a month</span></li>
        <li class="no"><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true" focusable="false"><path d="M6 6l8 8M14 6l-8 8"/></svg><span><span class="mc-k">Offline tiles</span>Not included</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Map styles</span>1 custom style</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Support</span>Community forum</span></li>
      </ul>
      <label class="mc-pick"><input type="radio" name="cg-plan" value="starter"><span><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg>Choose Starter</span></label>
    </article>
    <article class="mc-card" aria-labelledby="cg-growth">
      <div class="mc-top"><h3 id="cg-growth">Growth</h3><p class="mc-badge">Recommended</p></div>
      <p class="mc-desc">For apps with steady traffic and a few thousand people using the map every day.</p>
      <p class="mc-price"><span class="mc-amt">$49</span><span class="mc-per">per month</span></p>
      <ul class="mc-feats">
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Map loads</span>250,000 a month</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Geocoding</span>50,000 lookups a month, plus batch geocoding from CSV files</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Offline tiles</span>iOS and Android</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Map styles</span>10 custom styles</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Support</span>Email, next business day</span></li>
      </ul>
      <label class="mc-pick"><input type="radio" name="cg-plan" value="growth" checked><span><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg>Choose Growth</span></label>
    </article>
    <article class="mc-card" aria-labelledby="cg-fleet">
      <div class="mc-top"><h3 id="cg-fleet">Fleet</h3></div>
      <p class="mc-desc">For delivery and field teams.</p>
      <p class="mc-price"><span class="mc-amt">$299</span><span class="mc-per">per month</span></p>
      <ul class="mc-feats">
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Map loads</span>2.5 million a month</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Geocoding</span>Unlimited lookups</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Offline tiles</span>iOS, Android and custom regions</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Map styles</span>Unlimited styles and a private style editor</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Support</span>Named engineer and a 99.9% uptime SLA</span></li>
      </ul>
      <label class="mc-pick"><input type="radio" name="cg-plan" value="fleet"><span><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg>Choose Fleet</span></label>
    </article>
  </div>
  </fieldset>
</section></div>

<div class="cq-demo">
<div><span class="lbl">Container query: full width</span>
<div class="mc cq-slot">
  <article class="cq" aria-labelledby="tw-wide-title">
    <div><p class="mc-kicker">Tidewell Pro</p><h3 id="tw-wide-title">Grow your newsletter past 1,000 readers</h3><p class="cq-desc">Everything in Free, with room to grow and a way to get paid.</p></div>
    <ul class="cq-list">
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Up to 10,000 subscribers</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Your own domain</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Paid posts with no platform fee</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>No Tidewell branding</span></li>
    </ul>
    <div><p class="cq-price"><b>$15</b><span>per month</span></p><p class="cq-note">Billed yearly at $180.</p><a class="cq-btn" href="#">Upgrade to Pro</a></div>
  </article>
</div></div>
<div><span class="lbl">Same card in a wider column</span>
<div class="mc cq-slot">
  <article class="cq" aria-labelledby="tw-mid-title">
    <div><p class="mc-kicker">Tidewell Pro</p><h3 id="tw-mid-title">Grow your newsletter past 1,000 readers</h3><p class="cq-desc">Everything in Free, with room to grow and a way to get paid.</p></div>
    <ul class="cq-list">
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Up to 10,000 subscribers</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Your own domain</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Paid posts with no platform fee</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>No Tidewell branding</span></li>
    </ul>
    <div><p class="cq-price"><b>$15</b><span>per month</span></p><p class="cq-note">Billed yearly at $180.</p><a class="cq-btn" href="#">Upgrade to Pro</a></div>
  </article>
</div></div>
<div><span class="lbl">Same card in a sidebar</span>
<div class="mc cq-slot">
  <article class="cq" aria-labelledby="tw-side-title">
    <div><p class="mc-kicker">Tidewell Pro</p><h3 id="tw-side-title">Grow your newsletter past 1,000 readers</h3><p class="cq-desc">Everything in Free, with room to grow and a way to get paid.</p></div>
    <ul class="cq-list">
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Up to 10,000 subscribers</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Your own domain</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Paid posts with no platform fee</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>No Tidewell branding</span></li>
    </ul>
    <div><p class="cq-price"><b>$15</b><span>per month</span></p><p class="cq-note">Billed yearly at $180.</p><a class="cq-btn" href="#">Upgrade to Pro</a></div>
  </article>
</div></div>
</div>
CSS
.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}
/* Modern CSS pricing: subgrid lines up every row across the cards, :has() highlights the chosen plan,
   and a container query lays the upgrade card out by the width of its slot, not the viewport. No JavaScript. */
.mc{--mc-accent:#be123c;--mc-accent-dark:#9f1239;--mc-ink:#18181b;--mc-muted:#52525b;--mc-line:#e4e4e7;--mc-tint:#fff1f2;--mc-edge:#fda4af;--mc-radius:20px;color:var(--mc-ink)}
.mc *,.mc *::before,.mc *::after{box-sizing:border-box}
:where(.mc) h2,:where(.mc) h3,:where(.mc) p,:where(.mc) ul{margin:0}
.mc-kicker{font-size:.78rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--mc-accent)}
.mc-title{margin-top:8px;font-size:clamp(1.5rem,3.6vw,2rem);font-weight:800;line-height:1.15;letter-spacing:-.025em}
.mc-sub{margin-top:10px;font-size:.95rem;line-height:1.55;color:var(--mc-muted)}
/* 1. subgrid cards: each card spans 9 rows of the parent grid and the feature list spans 5 of them */
.mc-fs{min-width:0;margin:0;padding:0;border:0}
.mc-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));column-gap:20px;row-gap:0;margin-top:30px}
.mc-card{display:grid;grid-row:span 9;grid-template-rows:subgrid;row-gap:0;margin-bottom:20px;padding:26px 24px 24px;background:#fff;border:1.5px solid var(--mc-line);border-radius:var(--mc-radius);transition:border-color .2s,box-shadow .2s}
.mc-card:has(input:checked){border-color:var(--mc-accent);box-shadow:0 0 0 3px var(--mc-tint),0 24px 40px -24px rgba(190,18,60,.45)}
.mc-top{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}
.mc-card h3{font-size:1.15rem;font-weight:700}
.mc-badge{padding:4px 10px;border-radius:999px;background:var(--mc-ink);color:#fff;font-size:.7rem;font-weight:700;line-height:1.2;letter-spacing:.06em;text-transform:uppercase}
.mc-desc{padding-top:8px;font-size:.92rem;line-height:1.5;color:var(--mc-muted)}
.mc-price{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 8px;padding:20px 0}
.mc-amt{font-size:2.6rem;font-weight:800;line-height:1;letter-spacing:-.04em}
.mc-per{font-size:.88rem;color:var(--mc-muted)}
.mc-feats{display:grid;grid-row:span 5;grid-template-rows:subgrid;row-gap:0;padding:0;list-style:none;border-top:1px solid var(--mc-line)}
.mc-feats li{display:flex;align-items:flex-start;gap:10px;padding:12px 0;border-bottom:1px solid var(--mc-line);font-size:.9rem;line-height:1.4}
.mc-feats svg{flex:none;margin-top:1px;color:var(--mc-accent)}
.mc-feats .no{color:var(--mc-muted)}
.mc-feats .no svg{color:var(--mc-muted)}
.mc-k{display:block;font-size:.72rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--mc-muted)}
.mc-pick{position:relative;display:block;margin-top:20px;cursor:pointer}
.mc-pick input{position:absolute;width:1px;height:1px;margin:0;opacity:0;pointer-events:none}
.mc-pick span{display:flex;align-items:center;justify-content:center;gap:8px;padding:12px 16px;border:1.5px solid var(--mc-ink);border-radius:12px;font-size:.95rem;font-weight:700;line-height:1.3;transition:background-color .2s,color .2s}
.mc-pick svg{display:none}
.mc-pick:hover span{background:#f4f4f5}
.mc-pick input:checked+span{border-color:var(--mc-accent);background:var(--mc-accent);color:#fff}
.mc-pick input:checked+span svg{display:block}
.mc-pick input:focus-visible+span{outline:3px solid var(--mc-accent);outline-offset:3px}
/* 2. container query upgrade card */
.cq-slot{container-type:inline-size}
.cq{display:grid;gap:20px 28px;padding:26px;background:var(--mc-tint);border:1px solid var(--mc-edge);border-radius:var(--mc-radius)}
.cq h3{margin-top:6px;font-size:1.25rem;font-weight:800;line-height:1.25;letter-spacing:-.015em}
.cq-desc{margin-top:8px;font-size:.92rem;line-height:1.5;color:var(--mc-muted)}
.cq-list{display:grid;gap:9px;padding:0;list-style:none;font-size:.9rem;line-height:1.4}
.cq-list li{display:flex;align-items:flex-start;gap:9px}
.cq-list svg{flex:none;margin-top:1px;color:var(--mc-accent)}
.cq-price{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 8px}
.cq-price b{font-size:clamp(2rem,9cqi,2.6rem);font-weight:800;line-height:1;letter-spacing:-.04em}
.cq-price span{font-size:.88rem;color:var(--mc-muted)}
.cq-note{margin-top:6px;font-size:.82rem;color:var(--mc-muted)}
.cq-btn{display:block;margin-top:16px;padding:12px 22px;border-radius:12px;background:var(--mc-accent);color:#fff;font-size:.95rem;font-weight:700;line-height:1.3;text-align:center;text-decoration:none;white-space:nowrap;transition:background-color .2s}
.cq-btn:hover{background:var(--mc-accent-dark)}
.cq-btn:focus-visible{outline:3px solid var(--mc-accent);outline-offset:3px}
@container (min-width:440px){.cq{grid-template-columns:minmax(0,1fr) auto;align-items:start}.cq-list{grid-column:1/-1;grid-row:2}}
@container (min-width:700px){.cq{grid-template-columns:minmax(0,1.2fr) minmax(0,1fr) auto;align-items:center}.cq-list{grid-column:auto;grid-row:auto}}
@media (prefers-reduced-motion:reduce){.mc-card,.mc-pick span,.cq-btn{transition:none}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl">Subgrid rows and a :has() selection</span>
<section class="mc" aria-labelledby="cg-title">
  <p class="mc-kicker">Cartograph maps API</p><h2 class="mc-title" id="cg-title">Choose a plan</h2><p class="mc-sub">Every row lines up across the cards, however long the text in it.</p>
  <fieldset><legend class="visually-hidden">Plan</legend>
  <div class="mc-grid">
    <article class="card mc-card" aria-labelledby="cg-starter">
      <div class="mc-top d-flex flex-wrap align-items-center justify-content-between"><h3 id="cg-starter">Starter</h3></div>
      <p class="mc-desc">For prototypes and personal maps.</p>
      <p class="mc-price d-flex flex-wrap align-items-baseline"><span class="mc-amt">$0</span><span class="mc-per">free forever</span></p>
      <ul class="mc-feats list-unstyled">
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Map loads</span>25,000 a month</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Geocoding</span>1,000 lookups a month</span></li>
        <li class="no"><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true" focusable="false"><path d="M6 6l8 8M14 6l-8 8"/></svg><span><span class="mc-k">Offline tiles</span>Not included</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Map styles</span>1 custom style</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Support</span>Community forum</span></li>
      </ul>
      <div class="mc-pick"><input type="radio" class="btn-check" name="cg-plan" id="cg-pick-starter" value="starter"><label class="btn" for="cg-pick-starter"><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg>Choose Starter</label></div>
    </article>
    <article class="card mc-card" aria-labelledby="cg-growth">
      <div class="mc-top d-flex flex-wrap align-items-center justify-content-between"><h3 id="cg-growth">Growth</h3><p class="badge rounded-pill mc-badge">Recommended</p></div>
      <p class="mc-desc">For apps with steady traffic and a few thousand people using the map every day.</p>
      <p class="mc-price d-flex flex-wrap align-items-baseline"><span class="mc-amt">$49</span><span class="mc-per">per month</span></p>
      <ul class="mc-feats list-unstyled">
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Map loads</span>250,000 a month</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Geocoding</span>50,000 lookups a month, plus batch geocoding from CSV files</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Offline tiles</span>iOS and Android</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Map styles</span>10 custom styles</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Support</span>Email, next business day</span></li>
      </ul>
      <div class="mc-pick"><input type="radio" class="btn-check" name="cg-plan" id="cg-pick-growth" value="growth" checked><label class="btn" for="cg-pick-growth"><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg>Choose Growth</label></div>
    </article>
    <article class="card mc-card" aria-labelledby="cg-fleet">
      <div class="mc-top d-flex flex-wrap align-items-center justify-content-between"><h3 id="cg-fleet">Fleet</h3></div>
      <p class="mc-desc">For delivery and field teams.</p>
      <p class="mc-price d-flex flex-wrap align-items-baseline"><span class="mc-amt">$299</span><span class="mc-per">per month</span></p>
      <ul class="mc-feats list-unstyled">
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Map loads</span>2.5 million a month</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Geocoding</span>Unlimited lookups</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Offline tiles</span>iOS, Android and custom regions</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Map styles</span>Unlimited styles and a private style editor</span></li>
        <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="mc-k">Support</span>Named engineer and a 99.9% uptime SLA</span></li>
      </ul>
      <div class="mc-pick"><input type="radio" class="btn-check" name="cg-plan" id="cg-pick-fleet" value="fleet"><label class="btn" for="cg-pick-fleet"><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg>Choose Fleet</label></div>
    </article>
  </div>
  </fieldset>
</section></div>

<div class="cq-demo">
<div><span class="lbl">Container query: full width</span>
<div class="mc cq-slot">
  <article class="card cq" aria-labelledby="tw-wide-title">
    <div><p class="mc-kicker">Tidewell Pro</p><h3 id="tw-wide-title">Grow your newsletter past 1,000 readers</h3><p class="cq-desc">Everything in Free, with room to grow and a way to get paid.</p></div>
    <ul class="cq-list list-unstyled">
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="visually-hidden">Included: </span>Up to 10,000 subscribers</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="visually-hidden">Included: </span>Your own domain</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="visually-hidden">Included: </span>Paid posts with no platform fee</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="visually-hidden">Included: </span>No Tidewell branding</span></li>
    </ul>
    <div><p class="cq-price d-flex flex-wrap align-items-baseline"><b>$15</b><span>per month</span></p><p class="cq-note">Billed yearly at $180.</p><a class="btn cq-btn d-block" href="#">Upgrade to Pro</a></div>
  </article>
</div></div>
<div><span class="lbl">Same card in a wider column</span>
<div class="mc cq-slot">
  <article class="card cq" aria-labelledby="tw-mid-title">
    <div><p class="mc-kicker">Tidewell Pro</p><h3 id="tw-mid-title">Grow your newsletter past 1,000 readers</h3><p class="cq-desc">Everything in Free, with room to grow and a way to get paid.</p></div>
    <ul class="cq-list list-unstyled">
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="visually-hidden">Included: </span>Up to 10,000 subscribers</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="visually-hidden">Included: </span>Your own domain</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="visually-hidden">Included: </span>Paid posts with no platform fee</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="visually-hidden">Included: </span>No Tidewell branding</span></li>
    </ul>
    <div><p class="cq-price d-flex flex-wrap align-items-baseline"><b>$15</b><span>per month</span></p><p class="cq-note">Billed yearly at $180.</p><a class="btn cq-btn d-block" href="#">Upgrade to Pro</a></div>
  </article>
</div></div>
<div><span class="lbl">Same card in a sidebar</span>
<div class="mc cq-slot">
  <article class="card cq" aria-labelledby="tw-side-title">
    <div><p class="mc-kicker">Tidewell Pro</p><h3 id="tw-side-title">Grow your newsletter past 1,000 readers</h3><p class="cq-desc">Everything in Free, with room to grow and a way to get paid.</p></div>
    <ul class="cq-list list-unstyled">
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="visually-hidden">Included: </span>Up to 10,000 subscribers</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="visually-hidden">Included: </span>Your own domain</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="visually-hidden">Included: </span>Paid posts with no platform fee</span></li>
      <li><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="visually-hidden">Included: </span>No Tidewell branding</span></li>
    </ul>
    <div><p class="cq-price d-flex flex-wrap align-items-baseline"><b>$15</b><span>per month</span></p><p class="cq-note">Billed yearly at $180.</p><a class="btn cq-btn d-block" href="#">Upgrade to Pro</a></div>
  </article>
</div></div>
</div>
CSS
/* Modern CSS pricing with Bootstrap .card, .badge, .btn-check and .btn: subgrid aligns the rows, :has() marks the chosen plan,
   and a container query lays the upgrade card out by the width of its slot. */
.mc{--mc-accent:#be123c;--mc-accent-dark:#9f1239;--mc-ink:#18181b;--mc-muted:#52525b;--mc-line:#e4e4e7;--mc-tint:#fff1f2;--mc-edge:#fda4af;color:var(--mc-ink)}
:where(.mc) h2,:where(.mc) h3,:where(.mc) p,:where(.mc) ul{margin:0}
.mc-kicker{font-size:.78rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--mc-accent)}
.mc .mc-title{margin-top:8px;font-size:clamp(1.5rem,3.6vw,2rem);font-weight:800;line-height:1.15;letter-spacing:-.025em}
.mc .mc-sub{margin-top:10px;font-size:.95rem;line-height:1.55;color:var(--mc-muted)}
.mc-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));column-gap:20px;row-gap:0;margin-top:30px}
.mc-card{--bs-card-border-width:1.5px;--bs-card-border-color:var(--mc-line);--bs-card-border-radius:20px;--bs-card-color:var(--mc-ink);display:grid;grid-row:span 9;grid-template-rows:subgrid;row-gap:0;margin-bottom:20px;padding:26px 24px 24px;transition:border-color .2s,box-shadow .2s}
.mc-card:has(.btn-check:checked){--bs-card-border-color:var(--mc-accent);box-shadow:0 0 0 3px var(--mc-tint),0 24px 40px -24px rgba(190,18,60,.45)}
.mc-top{gap:8px}
.mc-card h3{font-size:1.15rem;font-weight:700}
.mc-badge{--bs-badge-padding-x:10px;--bs-badge-padding-y:4px;--bs-badge-font-size:.7rem;--bs-badge-font-weight:700;background:var(--mc-ink);line-height:1.2;letter-spacing:.06em;text-transform:uppercase}
.mc .mc-desc{padding-top:8px;font-size:.92rem;line-height:1.5;color:var(--mc-muted)}
.mc .mc-price{gap:4px 8px;padding:20px 0}
.mc-amt{font-size:2.6rem;font-weight:800;line-height:1;letter-spacing:-.04em}
.mc-per{font-size:.88rem;color:var(--mc-muted)}
.mc-feats{display:grid;grid-row:span 5;grid-template-rows:subgrid;row-gap:0;border-top:1px solid var(--mc-line)}
.mc-feats li{display:flex;align-items:flex-start;gap:10px;padding:12px 0;border-bottom:1px solid var(--mc-line);font-size:.9rem;line-height:1.4}
.mc-feats svg{flex:none;margin-top:1px;color:var(--mc-accent)}
.mc-feats .no,.mc-feats .no svg{color:var(--mc-muted)}
.mc-k{display:block;font-size:.72rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--mc-muted)}
.mc-pick{margin-top:20px}
.mc-pick .btn{--bs-btn-padding-y:12px;--bs-btn-padding-x:16px;--bs-btn-font-size:.95rem;--bs-btn-font-weight:700;--bs-btn-line-height:1.3;--bs-btn-border-width:1.5px;--bs-btn-border-radius:12px;--bs-btn-color:var(--mc-ink);--bs-btn-border-color:var(--mc-ink);
  --bs-btn-hover-color:var(--mc-ink);--bs-btn-hover-bg:#f4f4f5;--bs-btn-hover-border-color:var(--mc-ink);--bs-btn-active-color:#fff;--bs-btn-active-bg:var(--mc-accent);--bs-btn-active-border-color:var(--mc-accent);
  display:flex;align-items:center;justify-content:center;gap:8px;width:100%;transition:background-color .2s,color .2s}
.mc-pick .btn svg{display:none}
.mc-pick .btn-check:checked+.btn svg{display:block}
.mc-pick .btn-check:focus-visible+.btn{outline:3px solid var(--mc-accent);outline-offset:3px;box-shadow:none}
.cq-slot{container-type:inline-size}
.cq{--bs-card-bg:var(--mc-tint);--bs-card-border-color:var(--mc-edge);--bs-card-border-radius:20px;--bs-card-color:var(--mc-ink);display:grid;gap:20px 28px;padding:26px}
.cq h3{margin-top:6px;font-size:1.25rem;font-weight:800;line-height:1.25;letter-spacing:-.015em}
.mc .cq-desc{margin-top:8px;font-size:.92rem;line-height:1.5;color:var(--mc-muted)}
.cq-list{display:grid;gap:9px;font-size:.9rem;line-height:1.4}
.cq-list li{display:flex;align-items:flex-start;gap:9px}
.cq-list svg{flex:none;margin-top:1px;color:var(--mc-accent)}
.mc .cq-price{gap:4px 8px}
.cq-price b{font-size:clamp(2rem,9cqi,2.6rem);font-weight:800;line-height:1;letter-spacing:-.04em}
.cq-price span{font-size:.88rem;color:var(--mc-muted)}
.mc .cq-note{margin-top:6px;font-size:.82rem;color:var(--mc-muted)}
.cq-btn{--bs-btn-padding-y:12px;--bs-btn-padding-x:22px;--bs-btn-font-size:.95rem;--bs-btn-font-weight:700;--bs-btn-line-height:1.3;--bs-btn-border-width:0;--bs-btn-border-radius:12px;--bs-btn-color:#fff;--bs-btn-bg:var(--mc-accent);--bs-btn-hover-color:#fff;--bs-btn-hover-bg:var(--mc-accent-dark);--bs-btn-active-color:#fff;--bs-btn-active-bg:var(--mc-accent-dark);margin-top:16px;white-space:nowrap;transition:background-color .2s}
.cq-btn:focus-visible{outline:3px solid var(--mc-accent);outline-offset:3px;box-shadow:none}
@container (min-width:440px){.cq{grid-template-columns:minmax(0,1fr) auto;align-items:start}.cq-list{grid-column:1/-1;grid-row:2}}
@container (min-width:700px){.cq{grid-template-columns:minmax(0,1.2fr) minmax(0,1fr) auto;align-items:center}.cq-list{grid-column:auto;grid-row:auto}}
@media (prefers-reduced-motion:reduce){.mc-card,.mc-pick .btn,.cq-btn{transition:none}}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#52525b] uppercase">Subgrid rows and a :has() selection</span>
<section class="text-[#18181b]" aria-labelledby="cg-title">
  <p class="text-[.78rem] font-bold tracking-[.14em] text-[#be123c] uppercase">Cartograph maps API</p><h2 class="mt-2 text-[clamp(1.5rem,3.6vw,2rem)] leading-[1.15] font-extrabold tracking-[-.025em]" id="cg-title">Choose a plan</h2><p class="mt-2.5 text-[.95rem] leading-[1.55] text-[#52525b]">Every row lines up across the cards, however long the text in it.</p>
  <fieldset class="min-w-0"><legend class="sr-only">Plan</legend>
  <div class="mt-[30px] grid grid-cols-[repeat(auto-fit,minmax(250px,1fr))] gap-x-5 gap-y-0">
    <article class="row-span-9 mb-5 grid grid-rows-subgrid gap-y-0 rounded-[20px] border-[1.5px] border-[#e4e4e7] bg-white px-6 pt-[26px] pb-6 transition-[border-color,box-shadow] duration-200 has-checked:border-[#be123c] has-checked:shadow-[0_0_0_3px_#fff1f2,0_24px_40px_-24px_rgba(190,18,60,.45)] motion-reduce:transition-none" aria-labelledby="cg-starter">
      <div class="flex flex-wrap items-center justify-between gap-2"><h3 class="text-[1.15rem] font-bold" id="cg-starter">Starter</h3></div>
      <p class="pt-2 text-[.92rem] leading-normal text-[#52525b]">For prototypes and personal maps.</p>
      <p class="flex flex-wrap items-baseline gap-x-2 gap-y-1 py-5"><span class="text-[2.6rem] leading-none font-extrabold tracking-[-.04em]">$0</span><span class="text-[.88rem] text-[#52525b]">free forever</span></p>
      <ul class="row-span-5 grid grid-rows-subgrid gap-y-0 border-t border-[#e4e4e7]">
        <li class="flex items-start gap-2.5 border-b border-[#e4e4e7] py-3 text-[.9rem] leading-[1.4]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#52525b] uppercase">Map loads</span>25,000 a month</span></li>
        <li class="flex items-start gap-2.5 border-b border-[#e4e4e7] py-3 text-[.9rem] leading-[1.4]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#52525b] uppercase">Geocoding</span>1,000 lookups a month</span></li>
        <li class="flex items-start gap-2.5 border-b border-[#e4e4e7] py-3 text-[.9rem] leading-[1.4] text-[#52525b]"><svg class="mt-px flex-none" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true" focusable="false"><path d="M6 6l8 8M14 6l-8 8"/></svg><span><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#52525b] uppercase">Offline tiles</span>Not included</span></li>
        <li class="flex items-start gap-2.5 border-b border-[#e4e4e7] py-3 text-[.9rem] leading-[1.4]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#52525b] uppercase">Map styles</span>1 custom style</span></li>
        <li class="flex items-start gap-2.5 border-b border-[#e4e4e7] py-3 text-[.9rem] leading-[1.4]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#52525b] uppercase">Support</span>Community forum</span></li>
      </ul>
      <label class="relative mt-5 block cursor-pointer"><input class="peer sr-only" type="radio" name="cg-plan" value="starter"><span class="flex items-center justify-center gap-2 rounded-xl border-[1.5px] border-[#18181b] px-4 py-3 text-[.95rem] leading-[1.3] font-bold transition-[color,background-color,border-color] duration-200 hover:bg-[#f4f4f5] peer-checked:border-[#be123c] peer-checked:bg-[#be123c] peer-checked:text-white peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-[#be123c] motion-reduce:transition-none [&>svg]:hidden peer-checked:[&>svg]:block"><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg>Choose Starter</span></label>
    </article>
    <article class="row-span-9 mb-5 grid grid-rows-subgrid gap-y-0 rounded-[20px] border-[1.5px] border-[#e4e4e7] bg-white px-6 pt-[26px] pb-6 transition-[border-color,box-shadow] duration-200 has-checked:border-[#be123c] has-checked:shadow-[0_0_0_3px_#fff1f2,0_24px_40px_-24px_rgba(190,18,60,.45)] motion-reduce:transition-none" aria-labelledby="cg-growth">
      <div class="flex flex-wrap items-center justify-between gap-2"><h3 class="text-[1.15rem] font-bold" id="cg-growth">Growth</h3><p class="rounded-full bg-[#18181b] px-2.5 py-1 text-[.7rem] leading-[1.2] font-bold tracking-[.06em] text-white uppercase">Recommended</p></div>
      <p class="pt-2 text-[.92rem] leading-normal text-[#52525b]">For apps with steady traffic and a few thousand people using the map every day.</p>
      <p class="flex flex-wrap items-baseline gap-x-2 gap-y-1 py-5"><span class="text-[2.6rem] leading-none font-extrabold tracking-[-.04em]">$49</span><span class="text-[.88rem] text-[#52525b]">per month</span></p>
      <ul class="row-span-5 grid grid-rows-subgrid gap-y-0 border-t border-[#e4e4e7]">
        <li class="flex items-start gap-2.5 border-b border-[#e4e4e7] py-3 text-[.9rem] leading-[1.4]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#52525b] uppercase">Map loads</span>250,000 a month</span></li>
        <li class="flex items-start gap-2.5 border-b border-[#e4e4e7] py-3 text-[.9rem] leading-[1.4]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#52525b] uppercase">Geocoding</span>50,000 lookups a month, plus batch geocoding from CSV files</span></li>
        <li class="flex items-start gap-2.5 border-b border-[#e4e4e7] py-3 text-[.9rem] leading-[1.4]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#52525b] uppercase">Offline tiles</span>iOS and Android</span></li>
        <li class="flex items-start gap-2.5 border-b border-[#e4e4e7] py-3 text-[.9rem] leading-[1.4]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#52525b] uppercase">Map styles</span>10 custom styles</span></li>
        <li class="flex items-start gap-2.5 border-b border-[#e4e4e7] py-3 text-[.9rem] leading-[1.4]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#52525b] uppercase">Support</span>Email, next business day</span></li>
      </ul>
      <label class="relative mt-5 block cursor-pointer"><input class="peer sr-only" type="radio" name="cg-plan" value="growth" checked><span class="flex items-center justify-center gap-2 rounded-xl border-[1.5px] border-[#18181b] px-4 py-3 text-[.95rem] leading-[1.3] font-bold transition-[color,background-color,border-color] duration-200 hover:bg-[#f4f4f5] peer-checked:border-[#be123c] peer-checked:bg-[#be123c] peer-checked:text-white peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-[#be123c] motion-reduce:transition-none [&>svg]:hidden peer-checked:[&>svg]:block"><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg>Choose Growth</span></label>
    </article>
    <article class="row-span-9 mb-5 grid grid-rows-subgrid gap-y-0 rounded-[20px] border-[1.5px] border-[#e4e4e7] bg-white px-6 pt-[26px] pb-6 transition-[border-color,box-shadow] duration-200 has-checked:border-[#be123c] has-checked:shadow-[0_0_0_3px_#fff1f2,0_24px_40px_-24px_rgba(190,18,60,.45)] motion-reduce:transition-none" aria-labelledby="cg-fleet">
      <div class="flex flex-wrap items-center justify-between gap-2"><h3 class="text-[1.15rem] font-bold" id="cg-fleet">Fleet</h3></div>
      <p class="pt-2 text-[.92rem] leading-normal text-[#52525b]">For delivery and field teams.</p>
      <p class="flex flex-wrap items-baseline gap-x-2 gap-y-1 py-5"><span class="text-[2.6rem] leading-none font-extrabold tracking-[-.04em]">$299</span><span class="text-[.88rem] text-[#52525b]">per month</span></p>
      <ul class="row-span-5 grid grid-rows-subgrid gap-y-0 border-t border-[#e4e4e7]">
        <li class="flex items-start gap-2.5 border-b border-[#e4e4e7] py-3 text-[.9rem] leading-[1.4]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#52525b] uppercase">Map loads</span>2.5 million a month</span></li>
        <li class="flex items-start gap-2.5 border-b border-[#e4e4e7] py-3 text-[.9rem] leading-[1.4]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#52525b] uppercase">Geocoding</span>Unlimited lookups</span></li>
        <li class="flex items-start gap-2.5 border-b border-[#e4e4e7] py-3 text-[.9rem] leading-[1.4]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#52525b] uppercase">Offline tiles</span>iOS, Android and custom regions</span></li>
        <li class="flex items-start gap-2.5 border-b border-[#e4e4e7] py-3 text-[.9rem] leading-[1.4]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#52525b] uppercase">Map styles</span>Unlimited styles and a private style editor</span></li>
        <li class="flex items-start gap-2.5 border-b border-[#e4e4e7] py-3 text-[.9rem] leading-[1.4]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="block text-[.72rem] font-bold tracking-[.08em] text-[#52525b] uppercase">Support</span>Named engineer and a 99.9% uptime SLA</span></li>
      </ul>
      <label class="relative mt-5 block cursor-pointer"><input class="peer sr-only" type="radio" name="cg-plan" value="fleet"><span class="flex items-center justify-center gap-2 rounded-xl border-[1.5px] border-[#18181b] px-4 py-3 text-[.95rem] leading-[1.3] font-bold transition-[color,background-color,border-color] duration-200 hover:bg-[#f4f4f5] peer-checked:border-[#be123c] peer-checked:bg-[#be123c] peer-checked:text-white peer-focus-visible:outline-3 peer-focus-visible:outline-offset-3 peer-focus-visible:outline-[#be123c] motion-reduce:transition-none [&>svg]:hidden peer-checked:[&>svg]:block"><svg viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg>Choose Fleet</span></label>
    </article>
  </div>
  </fieldset>
</section></div>

<div class="grid items-start gap-x-6 gap-y-[72px] min-[860px]:grid-cols-[minmax(0,1.6fr)_minmax(0,1fr)] min-[860px]:[&>:first-child]:col-span-full">
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#52525b] uppercase">Container query: full width</span>
<div class="@container text-[#18181b]">
  <article class="grid gap-x-7 gap-y-5 rounded-[20px] border border-[#fda4af] bg-[#fff1f2] p-[26px] @min-[440px]:grid-cols-[minmax(0,1fr)_auto] @min-[440px]:items-start @min-[700px]:grid-cols-[minmax(0,1.2fr)_minmax(0,1fr)_auto] @min-[700px]:items-center" aria-labelledby="tw-wide-title">
    <div><p class="text-[.78rem] font-bold tracking-[.14em] text-[#be123c] uppercase">Tidewell Pro</p><h3 class="mt-1.5 text-[1.25rem] leading-[1.25] font-extrabold tracking-[-.015em]" id="tw-wide-title">Grow your newsletter past 1,000 readers</h3><p class="mt-2 text-[.92rem] leading-normal text-[#52525b]">Everything in Free, with room to grow and a way to get paid.</p></div>
    <ul class="grid gap-[9px] text-[.9rem] leading-[1.4] @min-[440px]:col-span-full @min-[440px]:row-start-2 @min-[700px]:col-auto @min-[700px]:row-auto">
      <li class="flex items-start gap-[9px]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Up to 10,000 subscribers</span></li>
      <li class="flex items-start gap-[9px]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Your own domain</span></li>
      <li class="flex items-start gap-[9px]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Paid posts with no platform fee</span></li>
      <li class="flex items-start gap-[9px]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>No Tidewell branding</span></li>
    </ul>
    <div><p class="flex flex-wrap items-baseline gap-x-2 gap-y-1"><b class="text-[clamp(2rem,9cqi,2.6rem)] leading-none font-extrabold tracking-[-.04em]">$15</b><span class="text-[.88rem] text-[#52525b]">per month</span></p><p class="mt-1.5 text-[.82rem] text-[#52525b]">Billed yearly at $180.</p><a class="mt-4 block rounded-xl bg-[#be123c] px-[22px] py-3 text-center text-[.95rem] leading-[1.3] font-bold whitespace-nowrap text-white no-underline transition-[color,background-color,border-color] duration-200 hover:bg-[#9f1239] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#be123c] motion-reduce:transition-none" href="#">Upgrade to Pro</a></div>
  </article>
</div></div>
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#52525b] uppercase">Same card in a wider column</span>
<div class="@container text-[#18181b]">
  <article class="grid gap-x-7 gap-y-5 rounded-[20px] border border-[#fda4af] bg-[#fff1f2] p-[26px] @min-[440px]:grid-cols-[minmax(0,1fr)_auto] @min-[440px]:items-start @min-[700px]:grid-cols-[minmax(0,1.2fr)_minmax(0,1fr)_auto] @min-[700px]:items-center" aria-labelledby="tw-mid-title">
    <div><p class="text-[.78rem] font-bold tracking-[.14em] text-[#be123c] uppercase">Tidewell Pro</p><h3 class="mt-1.5 text-[1.25rem] leading-[1.25] font-extrabold tracking-[-.015em]" id="tw-mid-title">Grow your newsletter past 1,000 readers</h3><p class="mt-2 text-[.92rem] leading-normal text-[#52525b]">Everything in Free, with room to grow and a way to get paid.</p></div>
    <ul class="grid gap-[9px] text-[.9rem] leading-[1.4] @min-[440px]:col-span-full @min-[440px]:row-start-2 @min-[700px]:col-auto @min-[700px]:row-auto">
      <li class="flex items-start gap-[9px]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Up to 10,000 subscribers</span></li>
      <li class="flex items-start gap-[9px]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Your own domain</span></li>
      <li class="flex items-start gap-[9px]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Paid posts with no platform fee</span></li>
      <li class="flex items-start gap-[9px]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>No Tidewell branding</span></li>
    </ul>
    <div><p class="flex flex-wrap items-baseline gap-x-2 gap-y-1"><b class="text-[clamp(2rem,9cqi,2.6rem)] leading-none font-extrabold tracking-[-.04em]">$15</b><span class="text-[.88rem] text-[#52525b]">per month</span></p><p class="mt-1.5 text-[.82rem] text-[#52525b]">Billed yearly at $180.</p><a class="mt-4 block rounded-xl bg-[#be123c] px-[22px] py-3 text-center text-[.95rem] leading-[1.3] font-bold whitespace-nowrap text-white no-underline transition-[color,background-color,border-color] duration-200 hover:bg-[#9f1239] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#be123c] motion-reduce:transition-none" href="#">Upgrade to Pro</a></div>
  </article>
</div></div>
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#52525b] uppercase">Same card in a sidebar</span>
<div class="@container text-[#18181b]">
  <article class="grid gap-x-7 gap-y-5 rounded-[20px] border border-[#fda4af] bg-[#fff1f2] p-[26px] @min-[440px]:grid-cols-[minmax(0,1fr)_auto] @min-[440px]:items-start @min-[700px]:grid-cols-[minmax(0,1.2fr)_minmax(0,1fr)_auto] @min-[700px]:items-center" aria-labelledby="tw-side-title">
    <div><p class="text-[.78rem] font-bold tracking-[.14em] text-[#be123c] uppercase">Tidewell Pro</p><h3 class="mt-1.5 text-[1.25rem] leading-[1.25] font-extrabold tracking-[-.015em]" id="tw-side-title">Grow your newsletter past 1,000 readers</h3><p class="mt-2 text-[.92rem] leading-normal text-[#52525b]">Everything in Free, with room to grow and a way to get paid.</p></div>
    <ul class="grid gap-[9px] text-[.9rem] leading-[1.4] @min-[440px]:col-span-full @min-[440px]:row-start-2 @min-[700px]:col-auto @min-[700px]:row-auto">
      <li class="flex items-start gap-[9px]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Up to 10,000 subscribers</span></li>
      <li class="flex items-start gap-[9px]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Your own domain</span></li>
      <li class="flex items-start gap-[9px]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>Paid posts with no platform fee</span></li>
      <li class="flex items-start gap-[9px]"><svg class="mt-px flex-none text-[#be123c]" viewBox="0 0 20 20" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M4.5 10.5l3.5 3.5 7.5-8"/></svg><span><span class="sr-only">Included: </span>No Tidewell branding</span></li>
    </ul>
    <div><p class="flex flex-wrap items-baseline gap-x-2 gap-y-1"><b class="text-[clamp(2rem,9cqi,2.6rem)] leading-none font-extrabold tracking-[-.04em]">$15</b><span class="text-[.88rem] text-[#52525b]">per month</span></p><p class="mt-1.5 text-[.82rem] text-[#52525b]">Billed yearly at $180.</p><a class="mt-4 block rounded-xl bg-[#be123c] px-[22px] py-3 text-center text-[.95rem] leading-[1.3] font-bold whitespace-nowrap text-white no-underline transition-[color,background-color,border-color] duration-200 hover:bg-[#9f1239] focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#be123c] motion-reduce:transition-none" href="#">Upgrade to Pro</a></div>
  </article>
</div></div>
</div>

About this set

Two pricing layouts that use newer CSS to do what usually takes JavaScript or fixed heights. Subgrid rows and a :has() selection is a maps API with three plans whose descriptions and feature values are different lengths, yet every row lines up across the cards: each card spans nine rows of the parent grid with grid-template-rows: subgrid, and its feature list is a nested subgrid of five rows, so the price, every feature and the button sit on one line in all three cards. Each card ends in a Choose button that is a radio button, and the chosen card gets an accent border and ring through :has(). Container query upgrade card is one in-app upgrade card for a newsletter platform, shown at three widths: stacked in a narrow sidebar, two columns in a wider column, and three columns at full width. The layout follows the width of the card’s container, not the window, and the price size scales with cqi units. There is no JavaScript in either layout.

What’s included

  • Subgrid aligns the price, every feature row and the button across cards
  • Choose buttons are a native radio group, with :has() marking the chosen card
  • Container query card with stacked, two-column and three-column layouts
  • Price size scales with the container through cqi units
  • No JavaScript in any of the three versions

Accessibility

The plan choice is a fieldset of native radio buttons labelled Choose Starter, Choose Growth and Choose Fleet, so the arrow keys move between plans and the selected one is announced. Each feature starts with its row name in visible text, such as Offline tiles, followed by the value, such as Not included. Focus shows a 3px outline on the visible button, and card and button transitions stop under prefers-reduced-motion.

Customise it

Change --mc-accent, --mc-tint and --mc-radius on .mc, and the 440px and 700px @container breakpoints. In Tailwind the same breakpoints are the @min-[440px] and @min-[700px] variants, and the subgrid is row-span-9 with grid-rows-subgrid.