Book a callGitHub10

Brindlecup Rewards

Silver member

Points balance

1,240 pts

760 points to Gold1,240 / 2,000

Wairimu NjorogeScan at the till to earn and pay4417 2208 9631

Offers for you

  • Sliced fresh fruit

    Free fruit cup with any drinkEnds Sunday

  • Cappuccino with latte art

    Double points on coffee3 days left · any size

It is live: hover, focus and its own controls respond. Actions that would change data (approve, send, delete) are for your app to wire. The width is a real 390 px, 768 px or 1280 px box, shrunk to fit your screen.

Source
<!-- Icons: Lucide (lucide.dev), ISC licence -->
<style>
.odl-rewards-card { box-sizing: border-box; inline-size: 100%; max-inline-size: 30rem; margin-inline: auto; container-type: inline-size; color: var(--ds-color-text-primary); font: var(--ds-text-body-md); text-wrap: pretty; }
.odl-rewards-card *, .odl-rewards-card *::before, .odl-rewards-card *::after { box-sizing: border-box; }
.odl-rewards-card .odl-wrap { --odl-tap: var(--ds-size-target-touch); display: grid; gap: var(--ds-space-stack-xl); }
/* The member card: a lightly tinted surface so it reads as a card, not a settings panel. Accent fill only on the progress and the primary action. */
.odl-rewards-card .odl-face { display: grid; gap: var(--ds-space-stack-lg); padding: var(--ds-space-inset-xl); border: var(--ds-border-width-default) solid var(--ds-color-border-subtle); border-radius: var(--ds-radius-container);
  background: var(--ds-color-bg-accent-subtle); }
.odl-rewards-card .odl-brand { display: flex; align-items: center; justify-content: space-between; gap: var(--ds-space-inline-sm); }
.odl-rewards-card .odl-brand p { display: flex; align-items: center; gap: var(--ds-space-inline-md); margin: 0; font: var(--ds-text-label-lg); }
.odl-rewards-card .odl-brand svg { inline-size: var(--ds-size-icon-md); block-size: var(--ds-size-icon-md); stroke-width: var(--ds-icon-stroke-md); color: var(--ds-color-text-secondary); }
.odl-rewards-card .odl-tier { display: inline-flex; align-items: center; min-block-size: var(--ds-size-control-sm); padding: 0 var(--ds-space-inset-sm); border-radius: var(--ds-radius-control-sm);
  background: var(--ds-color-surface-raised); color: var(--ds-color-text-secondary); font: var(--ds-text-label-md); white-space: nowrap; }
.odl-rewards-card .odl-pts { display: grid; gap: var(--ds-space-stack-xs); }
.odl-rewards-card .odl-pts p { margin: 0; }
.odl-rewards-card .odl-lbl { color: var(--ds-color-text-secondary); font: var(--ds-text-label-md); }
.odl-rewards-card .odl-big { font: var(--ds-text-headline-sm); line-height: 1; font-variant-numeric: tabular-nums; }
.odl-rewards-card .odl-big small { font: var(--ds-text-label-lg); color: var(--ds-color-text-secondary); }
.odl-rewards-card .odl-next { display: grid; gap: var(--ds-space-stack-sm); }
.odl-rewards-card .odl-next p { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--ds-space-inline-sm); margin: 0; font: var(--ds-text-label-md); color: var(--ds-color-text-secondary); font-variant-numeric: tabular-nums; }
.odl-rewards-card .odl-next b { color: var(--ds-color-text-primary); font-weight: var(--ds-font-weight-label); }
.odl-rewards-card .odl-track { position: relative; block-size: var(--ds-space-8); border-radius: var(--ds-radius-full); background: var(--ds-color-surface-raised); }
.odl-rewards-card .odl-track i { position: absolute; inset-block: 0; inset-inline-start: 0; inline-size: 62%; border-radius: var(--ds-radius-full); background: var(--ds-color-bg-accent-bold); }
/* The code: always dark on white so it scans in dark mode too. */
.odl-rewards-card .odl-code { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: var(--ds-space-inline-md); padding: var(--ds-space-inset-md); border: var(--ds-border-width-default) solid var(--ds-color-border-subtle);
  border-radius: var(--ds-radius-nested); background: var(--ds-color-white); color: var(--ds-color-black); }
.odl-rewards-card .odl-qr { inline-size: calc(var(--ds-size-control-lg) * 2); aspect-ratio: 1; }
.odl-rewards-card .odl-qr svg { display: block; inline-size: 100%; block-size: 100%; shape-rendering: crispEdges; }
.odl-rewards-card .odl-qr path, .odl-rewards-card .odl-qr .odl-eye { fill: var(--ds-color-black); }
.odl-rewards-card .odl-qr .odl-eye-in { fill: var(--ds-color-white); }
.odl-rewards-card .odl-code p { display: grid; gap: var(--ds-space-stack-xs); margin: 0; min-inline-size: 0; }
.odl-rewards-card .odl-code b { font: var(--ds-text-label-lg); }
.odl-rewards-card .odl-code span { color: var(--ds-color-neutral-light-11); font: var(--ds-text-label-md); }
.odl-rewards-card .odl-num { font: var(--ds-text-code-sm); letter-spacing: var(--ds-text-label-sm-tracking); color: var(--ds-color-neutral-light-12); font-variant-numeric: tabular-nums; }
/* Offers */
.odl-rewards-card .odl-offers { display: grid; gap: var(--ds-space-stack-md); }
.odl-rewards-card h3 { margin: 0; font: var(--ds-text-title-sm); }
.odl-rewards-card ul { display: grid; gap: var(--ds-space-stack-sm); margin: 0; padding: 0; list-style: none; }
.odl-rewards-card li { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--ds-space-inline-md); padding: var(--ds-space-inset-md);
  border: var(--ds-border-width-default) solid var(--ds-color-border-subtle); border-radius: var(--ds-radius-container); background: var(--ds-color-surface-raised); }
.odl-rewards-card .odl-ph { display: block; inline-size: calc(var(--ds-size-control-lg) * 1.5); block-size: calc(var(--ds-size-control-lg) * 1.5); border-radius: max(var(--ds-radius-2), calc(var(--ds-radius-container) - var(--ds-space-inset-md) - var(--ds-border-width-default))); object-fit: cover; background: var(--ds-color-bg-neutral-subtle); }
.odl-rewards-card .odl-offer { display: grid; gap: var(--ds-space-stack-xs); margin: 0; min-inline-size: 0; }
.odl-rewards-card .odl-offer b { font: var(--ds-text-label-lg); text-wrap: wrap; }
.odl-rewards-card .odl-offer span { color: var(--ds-color-text-secondary); font: var(--ds-text-label-md); }
.odl-rewards-card .odl-act { display: inline-flex; align-items: center; justify-content: center; gap: var(--ds-space-inline-xs); min-block-size: var(--odl-tap); padding: 0 var(--ds-space-inset-md); border: 0; border-radius: var(--ds-radius-control);
  background: var(--ds-color-bg-action-primary); color: var(--ds-color-text-on-action); font: var(--ds-text-label-md); white-space: nowrap; cursor: pointer;
  transition: background-color var(--ds-motion-duration-short) var(--ds-motion-easing-standard); }
.odl-rewards-card .odl-act:hover { background: var(--ds-color-bg-action-primary-hover); }
.odl-rewards-card .odl-act svg { display: none; inline-size: var(--ds-size-icon-sm); block-size: var(--ds-size-icon-sm); stroke-width: var(--ds-icon-stroke-md); }
.odl-rewards-card .odl-act[aria-pressed="true"] { background: var(--ds-color-bg-neutral-subtle); color: var(--ds-color-text-primary); }
.odl-rewards-card .odl-act[aria-pressed="true"] svg { display: block; color: var(--ds-color-text-success); }
.odl-rewards-card button:focus-visible { outline: var(--ds-focus-ring-width) solid var(--ds-color-border-focus); outline-offset: var(--ds-focus-ring-offset); }
.odl-rewards-card .odl-sr { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* Phone: a little less padding, and the button goes under the offer text so a title never squeezes beside it. */
@container (max-width: 24rem) { .odl-rewards-card .odl-face { padding: var(--ds-space-inset-lg); } }
@container (max-width: 23rem) { .odl-rewards-card li { grid-template-columns: auto minmax(0, 1fr); row-gap: var(--ds-space-stack-sm); }
  .odl-rewards-card .odl-ph { grid-row: span 2; align-self: start; }
  .odl-rewards-card .odl-act { grid-column: 2; justify-self: start; } }
@media (prefers-reduced-motion: reduce) { .odl-rewards-card, .odl-rewards-card *, .odl-rewards-card *::before { transition: none !important; animation: none !important; } }
</style>
<section class="odl-rewards-card" aria-label="Brindlecup Rewards card">
  <div class="odl-wrap">
    <div class="odl-face">
      <div class="odl-brand"><p><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10 2v2"/><path d="M14 2v2"/><path d="M16 8a1 1 0 0 1 1 1v8a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1h14a4 4 0 1 1 0 8h-1"/><path d="M6 2v2"/></svg>Brindlecup Rewards</p><span class="odl-tier">Silver member</span></div>
      <div class="odl-pts"><p class="odl-lbl">Points balance</p><p class="odl-big">1,240 <small>pts</small></p></div>
      <div class="odl-next">
        <p><span><b>760 points</b> to Gold</span><span>1,240 / 2,000</span></p>
        <div class="odl-track" role="progressbar" aria-label="Progress to Gold" aria-valuemin="0" aria-valuemax="2000" aria-valuenow="1240" aria-valuetext="1,240 of 2,000 points"><i></i></div>
      </div>
      <div class="odl-code">
        <div class="odl-qr" role="img" aria-label="Member code to scan">
          <svg viewBox="-1 -1 27 27" aria-hidden="true">
            <path d="M8 0h1v1h-1zM9 0h1v1h-1zM10 0h1v1h-1zM11 0h1v1h-1zM12 0h1v1h-1zM14 0h1v1h-1zM15 0h1v1h-1zM8 1h1v1h-1zM9 1h1v1h-1zM10 1h1v1h-1zM12 1h1v1h-1zM13 1h1v1h-1zM15 1h1v1h-1zM16 1h1v1h-1zM11 2h1v1h-1zM15 2h1v1h-1zM9 3h1v1h-1zM10 3h1v1h-1zM11 3h1v1h-1zM13 3h1v1h-1zM14 3h1v1h-1zM8 4h1v1h-1zM15 4h1v1h-1zM8 5h1v1h-1zM9 5h1v1h-1zM12 5h1v1h-1zM13 5h1v1h-1zM14 5h1v1h-1zM15 5h1v1h-1zM16 5h1v1h-1zM12 6h1v1h-1zM13 6h1v1h-1zM14 6h1v1h-1zM10 7h1v1h-1zM14 7h1v1h-1zM15 7h1v1h-1zM16 7h1v1h-1zM0 8h1v1h-1zM5 8h1v1h-1zM6 8h1v1h-1zM8 8h1v1h-1zM11 8h1v1h-1zM12 8h1v1h-1zM15 8h1v1h-1zM16 8h1v1h-1zM17 8h1v1h-1zM20 8h1v1h-1zM24 8h1v1h-1zM1 9h1v1h-1zM2 9h1v1h-1zM7 9h1v1h-1zM10 9h1v1h-1zM11 9h1v1h-1zM12 9h1v1h-1zM13 9h1v1h-1zM15 9h1v1h-1zM16 9h1v1h-1zM17 9h1v1h-1zM19 9h1v1h-1zM20 9h1v1h-1zM23 9h1v1h-1zM3 10h1v1h-1zM4 10h1v1h-1zM5 10h1v1h-1zM6 10h1v1h-1zM8 10h1v1h-1zM9 10h1v1h-1zM12 10h1v1h-1zM16 10h1v1h-1zM18 10h1v1h-1zM19 10h1v1h-1zM0 11h1v1h-1zM5 11h1v1h-1zM7 11h1v1h-1zM12 11h1v1h-1zM16 11h1v1h-1zM17 11h1v1h-1zM18 11h1v1h-1zM19 11h1v1h-1zM20 11h1v1h-1zM21 11h1v1h-1zM0 12h1v1h-1zM3 12h1v1h-1zM6 12h1v1h-1zM8 12h1v1h-1zM12 12h1v1h-1zM13 12h1v1h-1zM15 12h1v1h-1zM16 12h1v1h-1zM17 12h1v1h-1zM19 12h1v1h-1zM21 12h1v1h-1zM22 12h1v1h-1zM23 12h1v1h-1zM1 13h1v1h-1zM5 13h1v1h-1zM6 13h1v1h-1zM7 13h1v1h-1zM9 13h1v1h-1zM10 13h1v1h-1zM11 13h1v1h-1zM14 13h1v1h-1zM15 13h1v1h-1zM19 13h1v1h-1zM20 13h1v1h-1zM22 13h1v1h-1zM23 13h1v1h-1zM2 14h1v1h-1zM4 14h1v1h-1zM6 14h1v1h-1zM7 14h1v1h-1zM10 14h1v1h-1zM11 14h1v1h-1zM13 14h1v1h-1zM14 14h1v1h-1zM15 14h1v1h-1zM16 14h1v1h-1zM17 14h1v1h-1zM18 14h1v1h-1zM19 14h1v1h-1zM21 14h1v1h-1zM23 14h1v1h-1zM24 14h1v1h-1zM0 15h1v1h-1zM1 15h1v1h-1zM2 15h1v1h-1zM5 15h1v1h-1zM6 15h1v1h-1zM8 15h1v1h-1zM10 15h1v1h-1zM13 15h1v1h-1zM17 15h1v1h-1zM21 15h1v1h-1zM22 15h1v1h-1zM23 15h1v1h-1zM24 15h1v1h-1zM0 16h1v1h-1zM2 16h1v1h-1zM3 16h1v1h-1zM4 16h1v1h-1zM8 16h1v1h-1zM9 16h1v1h-1zM10 16h1v1h-1zM11 16h1v1h-1zM12 16h1v1h-1zM13 16h1v1h-1zM14 16h1v1h-1zM18 16h1v1h-1zM20 16h1v1h-1zM21 16h1v1h-1zM22 16h1v1h-1zM23 16h1v1h-1zM24 16h1v1h-1zM8 17h1v1h-1zM9 17h1v1h-1zM10 17h1v1h-1zM17 17h1v1h-1zM18 17h1v1h-1zM20 17h1v1h-1zM23 17h1v1h-1zM14 18h1v1h-1zM15 18h1v1h-1zM16 18h1v1h-1zM17 18h1v1h-1zM18 18h1v1h-1zM8 19h1v1h-1zM9 19h1v1h-1zM10 19h1v1h-1zM12 19h1v1h-1zM16 19h1v1h-1zM17 19h1v1h-1zM22 19h1v1h-1zM23 19h1v1h-1zM24 19h1v1h-1zM9 20h1v1h-1zM11 20h1v1h-1zM12 20h1v1h-1zM13 20h1v1h-1zM15 20h1v1h-1zM18 20h1v1h-1zM19 20h1v1h-1zM22 20h1v1h-1zM23 20h1v1h-1zM24 20h1v1h-1zM11 21h1v1h-1zM14 21h1v1h-1zM15 21h1v1h-1zM17 21h1v1h-1zM18 21h1v1h-1zM19 21h1v1h-1zM20 21h1v1h-1zM21 21h1v1h-1zM23 21h1v1h-1zM10 22h1v1h-1zM11 22h1v1h-1zM12 22h1v1h-1zM13 22h1v1h-1zM14 22h1v1h-1zM16 22h1v1h-1zM18 22h1v1h-1zM19 22h1v1h-1zM21 22h1v1h-1zM22 22h1v1h-1zM8 23h1v1h-1zM11 23h1v1h-1zM12 23h1v1h-1zM14 23h1v1h-1zM15 23h1v1h-1zM16 23h1v1h-1zM17 23h1v1h-1zM20 23h1v1h-1zM22 23h1v1h-1zM24 23h1v1h-1zM8 24h1v1h-1zM9 24h1v1h-1zM10 24h1v1h-1zM11 24h1v1h-1zM12 24h1v1h-1zM13 24h1v1h-1zM14 24h1v1h-1zM15 24h1v1h-1zM19 24h1v1h-1zM20 24h1v1h-1zM22 24h1v1h-1zM23 24h1v1h-1zM24 24h1v1h-1z"/>
            <rect class="odl-eye" x="0" y="0" width="7" height="7"/><rect class="odl-eye-in" x="1" y="1" width="5" height="5"/><rect class="odl-eye" x="2" y="2" width="3" height="3"/>
            <rect class="odl-eye" x="18" y="0" width="7" height="7"/><rect class="odl-eye-in" x="19" y="1" width="5" height="5"/><rect class="odl-eye" x="20" y="2" width="3" height="3"/>
            <rect class="odl-eye" x="0" y="18" width="7" height="7"/><rect class="odl-eye-in" x="1" y="19" width="5" height="5"/><rect class="odl-eye" x="2" y="20" width="3" height="3"/>
          </svg>
        </div>
        <p><b>Wairimu Njoroge</b><span>Scan at the till to earn and pay</span><span class="odl-num">4417 2208 9631</span></p>
      </div>
    </div>
    <div class="odl-offers">
      <h3>Offers for you</h3>
      <ul>
        <li>
          <img class="odl-ph" src="https://images.unsplash.com/photo-1490818387583-1baba5e638af?w=144&amp;h=144&amp;fit=crop&amp;crop=focalpoint&amp;fp-x=0.18&amp;fp-y=0.45&amp;fp-z=1.5&amp;auto=format&amp;q=70" alt="Sliced fresh fruit" width="72" height="72" loading="lazy" decoding="async">
          <p class="odl-offer"><b>Free fruit cup with any drink</b><span>Ends Sunday</span></p>
          <button type="button" class="odl-act" aria-pressed="false"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg><span class="odl-l">Activate</span><span class="odl-sr"> free fruit cup offer</span></button>
        </li>
        <li>
          <img class="odl-ph" src="https://images.unsplash.com/photo-1563311977-d285756282dc?w=144&amp;h=144&amp;fit=crop&amp;crop=focalpoint&amp;fp-x=0.8&amp;fp-y=0.72&amp;fp-z=1.4&amp;auto=format&amp;q=70" alt="Cappuccino with latte art" width="72" height="72" loading="lazy" decoding="async">
          <p class="odl-offer"><b>Double points on coffee</b><span>3 days left · any size</span></p>
          <button type="button" class="odl-act" aria-pressed="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg><span class="odl-l">Active</span><span class="odl-sr"> double points offer</span></button>
        </li>
      </ul>
    </div>
  </div>
</section>
<script>
document.querySelectorAll(".odl-rewards-card").forEach((root) => {
  if (root.dataset.odlReady) return; // wire once, even if the file is pasted twice
  root.dataset.odlReady = "1";
  root.querySelectorAll(".odl-act").forEach((b) => b.addEventListener("click", () => {
    const on = b.getAttribute("aria-pressed") !== "true";
    b.setAttribute("aria-pressed", String(on)); b.querySelector(".odl-l").textContent = on ? "Active" : "Activate";
  }));
});
</script>

More like this

ConsumerFriendly · Travel

Stay card

A holiday rental or hotel listing: a swipeable photo carousel with dots, a favourite heart, the place, host and dates, the rating, and the price per night with the total.

B2BFriendly · SaaS

Plan picker

Three plans as cards you select, with a monthly or yearly switch that changes the prices and one plan marked as the common choice.

Your kit

Nothing here yet. Add parts with Add to kit, and a look if you want the whole system.

    Parts
    0
    Files to fetch
    0 KB
    Licence
    MIT
    Total
    Free, now and later

    How do you want it?

    Your prompt

    No sign-up. Nothing leaves your browser until you paste it.

    Free