<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="#f5f4ef">
<title>What happens in the 2 seconds after you tap Pay?</title>
<style>
:root{--ink:#17231f;--muted:#66736d;--paper:#f5f4ef;--card:#fffefa;--line:#d9ded7;--green:#176b50;--lime:#c8f36a;--blue:#dceafa;--amber:#f7e7c8}
*{box-sizing:border-box}body{margin:0;background:var(--paper);color:var(--ink);font:16px/1.5 Inter,ui-sans-serif,system-ui,-apple-system,Segoe UI,sans-serif}main{max-width:900px;margin:auto;padding:30px 22px 56px}.kicker{font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--green);font-weight:800}.hero{padding:22px 0 26px;border-bottom:1px solid var(--line)}h1{font-size:clamp(38px,7vw,66px);line-height:.98;letter-spacing:-.055em;max-width:720px;margin:14px 0 18px}.dek{font-size:18px;color:var(--muted);max-width:660px}.byline{font-size:12px;color:var(--muted);font-weight:650;margin-top:22px}.takeaways{margin:24px 0;background:#e9eee6;border-radius:18px;padding:20px 22px}.takeaways h2,.section h2{font-size:20px;letter-spacing:-.03em;margin:0 0 12px}.takeaways ol{margin:0;padding-left:22px;display:grid;gap:8px}.takeaways li{padding-left:4px}.panel{background:var(--card);border:1px solid var(--line);border-radius:22px;padding:20px;margin:26px 0;box-shadow:0 10px 30px #17231f08}.panel-top{display:flex;justify-content:space-between;gap:12px;align-items:center;flex-wrap:wrap}.panel-top h2{font-size:22px;letter-spacing:-.035em;margin:0}.time{font-variant-numeric:tabular-nums;font-weight:800;color:var(--green);background:#e8f1e9;border-radius:99px;padding:6px 11px;font-size:13px}.sub{color:var(--muted);font-size:13px;margin:5px 0 18px}.track{position:relative;display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:8px;padding:14px 0 4px}.track:before{content:"";position:absolute;left:7%;right:7%;top:43px;height:2px;background:var(--line)}.node{position:relative;text-align:center;min-width:0}.node .symbol svg{width:26px;height:26px}.node .symbol{width:58px;height:58px;border:1px solid var(--line);background:#fff;border-radius:17px;margin:0 auto 10px;display:grid;place-items:center;font-size:24px;position:relative;z-index:1;transition:.25s}.node strong{display:block;font-size:12px;line-height:1.2}.node small{display:block;color:var(--muted);font-size:10px;margin-top:4px;line-height:1.25}.node.active .symbol{background:var(--lime);border-color:var(--green);box-shadow:0 0 0 5px #c8f36a55;transform:translateY(-3px)}.node.done .symbol{background:#e5f1e9;border-color:#9bbba7}.packet{height:30px;position:relative;margin:14px 7% 0;border-top:2px dashed #b9c5bb}.packet:after{content:"";position:absolute;top:-8px;left:calc(var(--progress,0%) - 7px);width:14px;height:14px;border-radius:50%;background:var(--green);box-shadow:0 0 0 5px #176b501c}.packet-label{font-size:11px;color:var(--muted);text-align:center;margin-top:-16px}.controls{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:14px}.play{border:0;background:var(--green);color:white;border-radius:999px;padding:12px 20px;font-weight:800;font-size:14px;cursor:pointer;min-height:46px}.play:hover{background:#0e523c}.secondary{border:1px solid var(--line);background:white;color:var(--ink);border-radius:999px;padding:11px 16px;font-weight:700;cursor:pointer;min-height:44px}.hint{font-size:12px;color:var(--muted);margin-left:auto}.detail{margin-top:16px;background:#f0f4ef;border-radius:15px;padding:16px;min-height:104px}.detail .stamp{font-size:11px;color:var(--green);font-weight:850;text-transform:uppercase;letter-spacing:.1em}.detail h3{margin:4px 0 5px;font-size:18px}.detail p{margin:0;color:#52615a;font-size:14px}.section{margin:30px 0}.section p{color:#52615a;max-width:740px}.split{display:grid;grid-template-columns:1fr 1fr;gap:12px}.mini{padding:17px;border-radius:16px;background:#fffefa;border:1px solid var(--line)}.mini h3{font-size:15px;margin:0 0 7px}.mini p{font-size:13px;margin:0}.foot{font-size:12px;color:var(--muted);border-top:1px solid var(--line);padding-top:18px;margin-top:34px}
@media(max-width:620px){main{padding:22px 15px 42px}.track{grid-template-columns:repeat(3,minmax(0,1fr));row-gap:18px}.track:before{display:none}.node .symbol{width:54px;height:54px}.packet{display:none}.packet-label{margin-top:12px}.hint{width:100%;margin-left:0}.split{grid-template-columns:1fr}.panel{padding:16px}}
@media(prefers-reduced-motion:reduce){*,*:before,*:after{transition:none!important;animation:none!important}}
</style></head>
<body><main>
<header class="hero"><div class="kicker">A tiny journey through modern payments</div><h1>What happens in the 2 seconds after you tap Pay?</h1><p class="dek">A checkout feels instant. Behind that tap, a short chain of systems asks a big question: can this payment be approved?</p><div class="byline">A quick field guide · Payments, explained</div></header>
<section class="takeaways"><h2>If you have two minutes</h2><ol><li>Your phone sends payment credentials securely; the shop does not simply receive your card number.</li><li>The request travels through payment systems to the bank that issued your card.</li><li>An approval comes back quickly — but approval is not the same as final settlement.</li></ol></section>
<section class="panel" aria-label="Animated payment journey">
<div class="panel-top"><h2>Follow the payment</h2><div class="time" id="clock">00.0 / 2.0 sec</div></div>
<p class="sub">Press play to send the authorisation request out — then watch the answer return.</p>
<div class="track" id="track">
<div class="node active" data-step="0"><div class="symbol"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="7" y="2.5" width="10" height="19" rx="2.5"/><path d="M11 18.5h2"/></svg></div><strong>Phone &amp; wallet</strong><small>Tap + authenticate</small></div>
<div class="node" data-step="1"><div class="symbol"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M5 8h14l-1.2 12.5H6.2z"/><path d="M9 8V6.5a3 3 0 0 1 6 0V8"/></svg></div><strong>Shop checkout</strong><small>Creates the request</small></div>
<div class="node" data-step="2"><div class="symbol"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="10.5" width="14" height="10" rx="2"/><path d="M8 10.5v-3a4 4 0 0 1 8 0v3"/><path d="M12 14.5v2"/></svg></div><strong>Payment provider</strong><small>Secures and routes it</small></div>
<div class="node" data-step="3"><div class="symbol"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M4 9.5 5.5 4h13L20 9.5"/><path d="M4 9.5h16"/><path d="M5 9.5V20h14V9.5"/><path d="M10 20v-5h4v5"/></svg></div><strong>Acquirer</strong><small>Merchant's bank side</small></div>
<div class="node" data-step="4"><div class="symbol"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M3 12h18"/><path d="M12 3c2.6 2.5 3.8 5.5 3.8 9s-1.2 6.5-3.8 9c-2.6-2.5-3.8-5.5-3.8-9S9.4 5.5 12 3z"/></svg></div><strong>Card network</strong><small>Finds the issuer</small></div>
<div class="node" data-step="5"><div class="symbol"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 9 12 4l8.5 5z"/><path d="M6 9.5v8M10 9.5v8M14 9.5v8M18 9.5v8"/><path d="M4 20h16"/></svg></div><strong>Issuing bank</strong><small>Checks and decides</small></div>
</div>
<div class="packet" id="packet" style="--progress:0%"></div><div class="packet-label" id="direction">Request travelling to the bank →</div>
<div class="detail" aria-live="polite"><div class="stamp" id="stamp">00.0s · START</div><h3 id="detailTitle">One tap starts the chain</h3><p id="detailText">Your wallet or card app confirms the payment method and may ask for biometric or device authentication.</p></div>
<div class="controls"><button class="play" id="play">▶ Play journey</button><button class="secondary" id="reset">↺ Start again</button><span class="hint">About 2 seconds · illustrative timing</span></div>
</section>
<section class="section"><h2>Then the answer comes back</h2><p>The issuer checks things such as available funds or credit, card status, security signals and risk rules. It sends an approve or decline response back through the network and payment chain. The checkout can then show confirmation or ask you to try another method.</p>
<div class="split"><div class="mini"><h3>✓ Approved</h3><p>The merchant gets an authorisation — a promise to honour the amount, subject to the payment process.</p></div><div class="mini"><h3>↗ Settled later</h3><p>Clearing and settlement move the funds between financial institutions later. That is a separate step from the quick approval.</p></div></div></section>
<section class="section"><h2>Why it can feel instantaneous</h2><p>These systems are built to exchange compact messages quickly and run in parallel with security checks. The exact route and timing vary by payment method, country, merchant setup and whether extra authentication is needed. The two-second journey is a useful illustration, not a service-level guarantee.</p></section>
<footer class="foot">The simplified card-payment path shown here is illustrative. Wallets, domestic payment rails and alternative payment methods can follow different routes.</footer>
</main>
<script>
(()=>{
const steps=[
{t:0,title:"One tap starts the chain",text:"Your wallet or card app confirms the payment method and may ask for biometric or device authentication.",stamp:"START"},
{t:.25,title:"The shop creates a payment request",text:"The checkout sends the amount, currency and transaction details to its payment provider. Sensitive card data is handled securely.",stamp:"REQUEST"},
{t:.55,title:"The provider protects and routes it",text:"The payment provider applies security checks and sends the authorisation request onward to the acquiring side.",stamp:"ROUTING"},
{t:.85,title:"The acquirer passes it on",text:"The acquirer — the merchant's bank or payment institution — routes the request into the relevant card network.",stamp:"NETWORK"},
{t:1.15,title:"The card network finds your bank",text:"The network identifies the issuing bank and carries the request to the institution that issued the card.",stamp:"ISSUER"},
{t:1.45,title:"Your bank makes the decision",text:"The issuer checks the card, account or credit availability, and risk signals. It returns an approval or decline.",stamp:"DECISION"},
{t:1.72,title:"The answer travels back",text:"The response returns through the network and payment chain to the provider and the shop's checkout.",stamp:"RESPONSE"},
{t:2,title:"The checkout confirms",text:"You see a success or decline message. If approved, the payment is authorised; settlement happens later.",stamp:"DONE"}
];
const clock=document.getElementById('clock'),title=document.getElementById('detailTitle'),body=document.getElementById('detailText'),stamp=document.getElementById('stamp'),packet=document.getElementById('packet'),direction=document.getElementById('direction'),play=document.getElementById('play'),reset=document.getElementById('reset'),nodes=[...document.querySelectorAll('.node')];
let start=0,raf=0,elapsed=0,running=false;
function render(t){elapsed=Math.min(2,t);clock.textContent=elapsed.toFixed(1).padStart(4,'0')+' / 2.0 sec';let s=steps[0];for(const x of steps){if(elapsed>=x.t)s=x}
title.textContent=s.title;body.textContent=s.text;stamp.textContent=elapsed.toFixed(2)+'s · '+s.stamp;
let outbound=elapsed<1.45;direction.textContent=elapsed>=2?'✓ Approval response received':outbound?'Request travelling to the bank →':elapsed<1.72?'The bank decides…':'← Response travelling back';
let p=outbound?Math.min(100,elapsed/1.45*100):Math.max(0,100-Math.max(0,elapsed-1.72)/.28*100);packet.style.setProperty('--progress',p+'%');
let active=outbound?(elapsed<.25?0:elapsed<.55?1:elapsed<.85?2:elapsed<1.15?3:elapsed<1.45?4:5):Math.round(p/20);
nodes.forEach((n,i)=>{n.classList.toggle('active',i===active);n.classList.toggle('done',outbound?i<active:i!==active)});
}
function tick(now){if(!running)return;render((now-start)/1000);if(elapsed>=2){running=false;play.textContent='▶ Play again';return}raf=requestAnimationFrame(tick)}
play.addEventListener('click',()=>{if(running)return;if(elapsed>=2)render(0);running=true;play.textContent='Playing…';start=performance.now()-elapsed*1000;raf=requestAnimationFrame(tick)});
reset.addEventListener('click',()=>{cancelAnimationFrame(raf);running=false;render(0);play.textContent='▶ Play journey'});
render(0);
})();
</script></body></html>