index.html
Copy
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Pay Sheet</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<main class="card">
<div class="sheet-title">Confirm payment</div>
<div class="credit-card">
<div class="card-top">
<div class="chip"></div>
<span class="brand">VISA</span>
</div>
<div class="card-number">**** **** **** 4242</div>
<div class="card-foot">
<span>Alex Morgan</span>
<span>08 / 28</span>
</div>
</div>
<div class="amount">
<span class="amount-label">Total due</span>
<span class="amount-value">$48.00</span>
</div>
<button class="confirm">Confirm payment</button>
</main>
<script src="script.js"></script>
</body>
</html>
styles.css
Copy
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
font-family: "Inter", sans-serif;
background: linear-gradient(180deg, #0a2018, #08070c 60%);
}
.card {
width: 360px;
padding: 24px;
border-radius: 28px;
border: 1px solid rgba(255, 255, 255, 0.08);
background: #0d1310;
}
.sheet-title {
margin-bottom: 18px;
font-size: 20px;
font-weight: 700;
color: #ecfdf5;
}
.credit-card {
padding: 22px;
border-radius: 18px;
background: linear-gradient(135deg, #10b981, #065f46);
}
.card-top {
display: flex;
justify-content: space-between;
}
.chip {
width: 42px;
height: 30px;
border-radius: 7px;
background: linear-gradient(135deg, #f4d27a, #c79a3c);
}
.brand {
font-size: 17px;
font-weight: 800;
font-style: italic;
color: #fff;
}
.card-number {
margin-top: 34px;
font-size: 21px;
font-weight: 600;
letter-spacing: 0.1em;
color: #f0fdf4;
}
.card-foot {
display: flex;
justify-content: space-between;
margin-top: 18px;
font-size: 13px;
font-weight: 600;
color: rgba(240, 253, 244, 0.85);
}
.amount {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20px;
padding: 16px 18px;
border-radius: 16px;
background: rgba(255, 255, 255, 0.04);
font-size: 14px;
color: rgba(220, 244, 234, 0.55);
}
.amount-value {
font-size: 24px;
font-weight: 800;
color: #ecfdf5;
}
.confirm {
width: 100%;
margin-top: 18px;
padding: 17px 0;
border: none;
border-radius: 16px;
font-family: inherit;
font-size: 15px;
font-weight: 700;
color: #022c22;
background: linear-gradient(135deg, #34d399, #059669);
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% {
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.5);
}
50% {
box-shadow: 0 0 0 10px rgba(16, 185, 129, 0);
}
}
script.js
Copy
// Confirm-to-paid interaction for the payment sheet.
//
// Ships in the downloadable repo. The Remotion video renders a sandboxed iframe
// where this never runs, so the exported video shows the static sheet (the only
// motion there is the pure-CSS card sheen).
(() => {
const button = document.querySelector(".confirm");
if (!button) return;
let settled = false;
button.style.cursor = "pointer";
button.addEventListener("click", () => {
if (settled) return;
settled = true;
button.textContent = "✓ Payment confirmed";
button.style.animation = "none";
button.style.background = "linear-gradient(135deg, #6ee7b7, #34d399)";
button.style.boxShadow = "0 14px 32px rgba(16, 185, 129, 0.4)";
});
})();