Skip to content

Redline Supply · storefront

site/examples/store.html

generated assetworking cartlight
<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>VERSEVA Design · Example: storefront</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Archivo:wght@500..700&family=Manrope:wght@400..700&family=JetBrains+Mono:wght@400..600&display=swap">
<link rel="stylesheet" href="../../tokens.css?v=1p3">
<link rel="stylesheet" href="../../components.css?v=1p3">
<style>
  * { margin: 0; box-sizing: border-box; }
  body { background: var(--bg); color: var(--text-1); font-family: var(--font-sans); font-size: 15px; line-height: 1.6; }
  .crumb { position: sticky; top: 0; z-index: 10; background: var(--bg); display: flex; align-items: center; gap: var(--s-3); padding: var(--s-3) var(--s-5); border-bottom: 1px solid var(--hairline); font-size: 12.5px; color: var(--text-3); }
  .crumb a { color: var(--text-2); text-decoration: none; font-family: var(--font-display); font-weight: var(--display-weight); }
  .shopbar { display: flex; align-items: center; gap: var(--s-5); max-width: 68rem; margin: 0 auto; padding: var(--s-4) var(--s-5); }
  .shopbar .mark { font-family: var(--font-display); font-weight: var(--display-weight); font-size: 16px; }
  .shopbar nav { flex: 1; display: flex; gap: var(--s-4); }
  .shopbar nav a { font-size: 13.5px; color: var(--text-2); text-decoration: none; }
  .pdp { max-width: 68rem; margin: 0 auto; padding: var(--s-6) var(--s-5) var(--s-8); display: grid; grid-template-columns: 1.05fr 1fr; gap: var(--s-7); align-items: start; }
  .shot { background: var(--surface-2); border: 1px solid var(--hairline); border-radius: var(--r-lg); overflow: hidden; }
  .shot img { display: block; width: 100%; height: auto; }
  .buy { display: grid; gap: var(--s-4); }
  .buy h1 { font-family: var(--font-display); font-weight: var(--display-weight); font-size: clamp(28px, 4vw, 40px); letter-spacing: -0.02em; line-height: 1.08; }
  .price { font-family: var(--font-display); font-weight: var(--display-weight); font-size: 24px; font-variant-numeric: tabular-nums; }
  .price span { font-size: 13px; color: var(--text-3); font-family: var(--font-sans); font-weight: 400; }
  .flavors { display: flex; gap: var(--s-2); flex-wrap: wrap; }
  .qtyrow { display: flex; gap: var(--s-3); align-items: center; }
  .qty { display: inline-flex; align-items: center; border: 1px solid var(--hairline); border-radius: var(--r-btn); overflow: hidden; }
  .qty button { border: 0; background: var(--surface); color: var(--text-1); font: inherit; font-size: 16px; width: 40px; height: 40px; cursor: pointer; }
  .qty button:hover { background: var(--surface-2); }
  .qty output { min-width: 44px; text-align: center; font-variant-numeric: tabular-nums; font-weight: 600; }
  .qtyrow .btn { flex: 1; justify-content: center; }
  details.spec { border: 1px solid var(--hairline); border-radius: var(--r-md); background: var(--surface); }
  details.spec summary { cursor: pointer; padding: var(--s-3) var(--s-4); font-weight: 600; font-size: 14px; list-style: none; display: flex; justify-content: space-between; }
  details.spec summary::after { content: "+"; color: var(--text-3); }
  details.spec[open] summary::after { content: "–"; }
  details.spec .body { padding: 0 var(--s-4) var(--s-4); color: var(--text-2); font-size: 13.5px; }
  .reviews { max-width: 68rem; margin: 0 auto; padding: 0 var(--s-5) var(--s-8); display: grid; gap: var(--s-4); }
  .reviews h2 { font-family: var(--font-display); font-weight: var(--heading-weight); font-size: 22px; letter-spacing: -0.015em; }
  footer { max-width: 68rem; margin: 0 auto; padding: 0 var(--s-5) var(--s-7); display: flex; justify-content: space-between; flex-wrap: wrap; gap: var(--s-3); color: var(--text-3); font-size: 12.5px; }
  .badge-line { font-family: var(--font-display); font-weight: var(--display-weight); font-size: 13px; color: var(--text-2); }
  #toastwrap .toast { position: fixed; right: var(--s-5); bottom: var(--s-5); z-index: 9; }
  @media (max-width: 820px) { .pdp { grid-template-columns: 1fr; } }
  .crumb a { display: inline-flex; align-items: center; gap: 8px; }
  .crumb .vmark { width: 16px; height: 16px; flex: none; }
  .crumb .codelink { margin-left: auto; }
</style>
</head>
<body>
<div class="crumb"><a href="../index.html"><svg class="vmark" viewBox="0 0 768 775.92" aria-hidden="true"><defs><clipPath id="vmk-a"><path d="M400 277h358v396.4H400z"/></clipPath><clipPath id="vmk-b"><path d="M10 97h550v576.4H10z"/></clipPath><clipPath id="vmk-c"><path d="M10 94.5h358V491H10z"/></clipPath><clipPath id="vmk-d"><path d="M208 94.5h550V671H208z"/></clipPath></defs><g clip-path="url(#vmk-a)"><path fill="currentColor" opacity=".55" d="M 558.605469 278.128906 C 555.410156 277.984375 552.164062 277.90625 548.96875 277.90625 C 466.261719 277.90625 407.433594 327.675781 401.222656 333.144531 L 400.800781 333.59375 C 400.800781 333.59375 587.386719 406.570312 718.046875 673.386719 C 718.046875 673.386719 767.757812 550.011719 756.207031 509.574219 C 740.042969 453 663.917969 362.328125 584.683594 279.359375 L 558.605469 278.128906"/></g><g clip-path="url(#vmk-b)"><path fill="currentColor" d="M 49.953125 673.386719 C 49.953125 673.386719 262.128906 253.59375 559.761719 253.59375 C 497.894531 190.457031 437.765625 134.679688 406.402344 106.136719 C 393.699219 94.574219 374.308594 94.574219 361.601562 106.136719 C 285.859375 175.0625 42.257812 402.917969 11.796875 509.574219 C 0.242188 550.011719 49.953125 673.386719 49.953125 673.386719"/></g><g clip-path="url(#vmk-c)"><path fill="currentColor" opacity=".55" d="M 209.394531 489.785156 C 212.589844 489.929688 215.835938 490.007812 219.03125 490.007812 C 301.738281 490.007812 360.566406 440.238281 366.777344 434.765625 L 367.199219 434.316406 C 367.199219 434.316406 180.613281 361.34375 49.953125 94.523438 C 49.953125 94.523438 0.242188 217.902344 11.792969 258.335938 C 27.957031 314.914062 104.082031 405.585938 183.316406 488.554688 L 209.394531 489.785156"/></g><g clip-path="url(#vmk-d)"><path fill="currentColor" d="M 718.046875 94.523438 C 718.046875 94.523438 505.871094 514.316406 208.238281 514.316406 C 270.105469 577.453125 330.234375 633.230469 361.597656 661.773438 C 374.300781 673.335938 393.691406 673.335938 406.398438 661.773438 C 482.140625 592.847656 725.742188 364.992188 756.203125 258.335938 C 767.757812 217.902344 718.046875 94.523438 718.046875 94.523438"/></g></svg><span>VERSEVA Design</span></a><span>examples</span><span>storefront</span><a class="btn btn-secondary sm codelink" href="../code.html?f=examples/store.html">Code</a></div>
<header class="shopbar">
  <span class="mark">Redline Supply</span>
  <nav><a href="#shop">Shop</a><a href="#story">Story</a><a href="#reviews">Reviews</a></nav>
  <button class="btn btn-secondary sm" type="button" id="cartbtn">Cart · <output id="cartcount">0</output></button>
</header>

<main class="pdp" id="shop">
  <figure class="shot"><img src="assets/product-bottle.png" alt="Matte black supplement bottle with a red label band"></figure>
  <div class="buy">
    <div><span class="badge ok">In stock · ships in 48h</span></div>
    <h1>Creatine, held to the decimal</h1>
    <p class="price" id="price">$38.00 <span>/ 60 servings</span></p>
    <div>
      <div class="chiprow flavors" id="flavors">
        <button class="fchip" type="button" aria-pressed="true">Unflavored</button>
        <button class="fchip" type="button" aria-pressed="false">Cherry</button>
        <button class="fchip" type="button" aria-pressed="false">Citrus</button>
      </div>
    </div>
    <div class="qtyrow">
      <div class="qty">
        <button type="button" id="qminus" aria-label="Decrease quantity">−</button>
        <output id="qty">1</output>
        <button type="button" id="qplus" aria-label="Increase quantity">+</button>
      </div>
      <button class="btn btn-primary lg" type="button" id="addcart">Add to cart · <span id="linetotal">$38.00</span></button>
    </div>
    <details class="spec"><summary>Every batch, assayed</summary><div class="body">Each lot ships with its assay: stated dose vs measured dose, to two decimals. The number on the label is the number in the scoop.</div></details>
    <details class="spec"><summary>Dosing</summary><div class="body">5 g daily, any time. Consistency beats timing; the streak matters more than the clock.</div></details>
    <details class="spec"><summary>Shipping + returns</summary><div class="body">Free over $40. Unopened tubs return free for 30 days; opened tubs get a straight answer instead.</div></details>
  </div>
</main>

<section class="reviews" id="reviews">
  <h2>Reviews</h2>
  <div class="lrows">
    <div class="lrow"><span class="avc">MK</span><span class="tx"><b>Finally a label that survives an assay</b><span class="metaline">Verified buyer · 5.0</span></span></div>
    <div class="lrow"><span class="avc">JT</span><span class="tx"><b>Dissolves clean, zero grit</b><span class="metaline">Verified buyer · 4.8</span></span></div>
    <div class="lrow"><span class="avc">RS</span><span class="tx"><b>The streak counter got me to day 90</b><span class="metaline">Verified buyer · 5.0</span></span></div>
  </div>
</section>

<footer>
  <span>Redline Supply is fictional; this page is a VERSEVA Design example.</span>
  <span class="badge-line">Built on VERSEVA Design</span>
</footer>

<div id="toastwrap"></div>
<script>
  const UNIT = 38;
  let qty = 1, cart = 0;
  const $ = (id) => document.getElementById(id);
  const money = (n) => '$' + n.toFixed(2);
  function paint() {
    $('qty').textContent = qty;
    $('linetotal').textContent = money(UNIT * qty);
  }
  $('qplus').addEventListener('click', () => { qty = Math.min(9, qty + 1); paint(); });
  $('qminus').addEventListener('click', () => { qty = Math.max(1, qty - 1); paint(); });
  $('flavors').addEventListener('click', (e) => {
    const chip = e.target.closest('.fchip');
    if (!chip) return;
    document.querySelectorAll('#flavors .fchip').forEach((c) => c.setAttribute('aria-pressed', c === chip ? 'true' : 'false'));
  });
  $('addcart').addEventListener('click', () => {
    cart += qty;
    $('cartcount').textContent = cart;
    const flavor = document.querySelector('#flavors .fchip[aria-pressed="true"]').textContent;
    const wrap = $('toastwrap');
    wrap.replaceChildren();
    const toast = document.createElement('div');
    toast.className = 'toast ok';
    toast.innerHTML = '<span class="dot"></span>Added ' + qty + ' × ' + flavor + ' · ' + money(UNIT * qty);
    wrap.append(toast);
    setTimeout(() => toast.remove(), 2400);
  });
</script>
</body>
</html>