<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Digital Ticket</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.160.0/three.min.js"></script>
<style>
:root {
--bg-color: #f4f7f9;
--ticket-bg: #ffffff;
--text-main: #000000;
--text-muted: #8e8e93;
--divider-color: #e5e5ea;
}
body {
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: var(--bg-color);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
/* Ticket Container */
.ticket-wrapper {
position: relative;
width: 360px;
filter: drop-shadow(0 20px 30px rgba(0,0,0,0.08));
transition: transform 0.1s ease-out;
perspective: 1000px;
}
.ticket {
background: var(--ticket-bg);
border-radius: 24px;
overflow: hidden;
display: flex;
flex-direction: column;
/* The wavy bottom edge mask */
-webkit-mask-image: radial-gradient(circle at 15px 100%, transparent 15px, white 15px);
-webkit-mask-size: 30px 100%;
-webkit-mask-position: -15px 0;
mask-image: radial-gradient(circle at 15px 100%, transparent 15px, white 15px);
mask-size: 30px 100%;
mask-position: -15px 0;
}
/* WebGL Overlay Canvas */
#gl-canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 10;
mix-blend-mode: overlay;
opacity: 0.4;
}
.section {
padding: 32px 24px;
text-align: center;
}
/* Header Section */
.header h1 {
font-size: 24px;
margin: 12px 0 4px 0;
font-weight: 700;
}
.header p {
color: var(--text-muted);
font-size: 14px;
margin: 0;
}
.emoji { font-size: 40px; }
/* Divider with side cutouts */
.divider {
height: 2px;
border-top: 2px dashed var(--divider-color);
margin: 0 30px;
position: relative;
}
.divider::before, .divider::after {
content: '';
position: absolute;
width: 24px;
height: 24px;
background-color: var(--bg-color);
border-radius: 50%;
top: -13px;
}
.divider::before { left: -43px; }
.divider::after { right: -43px; }
/* Info Section */
.info-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
text-align: left;
padding: 24px;
}
.label {
color: var(--text-muted);
text-transform: uppercase;
font-size: 11px;
letter-spacing: 0.5px;
display: block;
margin-bottom: 4px;
}
.value {
font-weight: 600;
font-size: 15px;
}
.full-width { grid-column: span 2; }
/* Payment Card UI */
.payment-pill {
background: #f8f8f8;
border-radius: 12px;
padding: 12px 16px;
display: flex;
align-items: center;
margin: 0 24px 24px 24px;
}
.mc-logo {
width: 32px;
height: 20px;
background: linear-gradient(90deg, #eb001b 50%, #ff5f00 50%);
border-radius: 4px;
margin-right: 12px;
position: relative;
}
.mc-logo::after {
content: '';
position: absolute;
left: 10px;
width: 12px;
height: 20px;
background: #ff5f00;
border-radius: 50%;
opacity: 0.8;
}
.payment-info { text-align: left; }
.payment-info div { font-size: 14px; font-weight: 600; }
.payment-info span { font-size: 12px; color: var(--text-muted); }
/* Barcode Section */
.barcode-container {
padding: 20px 40px 40px 40px;
}
.barcode-svg {
width: 100%;
height: 80px;
}
</style>
</head>
<body>
<div class="ticket-wrapper" id="wrapper">
<canvas id="gl-canvas"></canvas>
<div class="ticket">
<div class="section header">
<div class="emoji">🎉</div>
<h1>Thank you!</h1>
<p>Your ticket has been issued successfully</p>
</div>
<div class="divider"></div>
<div class="info-grid">
<div>
<span class="label">Ticket ID</span>
<span class="value">0120034399434</span>
</div>
<div style="text-align: right;">
<span class="label">Amount</span>
<span class="value">$35.00</span>
</div>
<div class="full-width">
<span class="label">Date & Time</span>
<span class="value">19 Jun 2025 • 10:15</span>
</div>
</div>
<div class="payment-pill">
<div class="mc-logo"></div>
<div class="payment-info">
<div>Liana Tudakova</div>
<span>•••• 8237</span>
</div>
</div>
<div class="divider"></div>
<div class="barcode-container">
<svg class="barcode-svg" preserveAspectRatio="none" viewBox="0 0 100 40">
<rect x="0" width="2" height="40" fill="black"/>
<rect x="5" width="1" height="40" fill="black"/>
<rect x="8" width="3" height="40" fill="black"/>
<rect x="13" width="1" height="40" fill="black"/>
<rect x="17" width="4" height="40" fill="black"/>
<rect x="25" width="2" height="40" fill="black"/>
<rect x="30" width="1" height="40" fill="black"/>
<rect x="35" width="3" height="40" fill="black"/>
<rect x="42" width="2" height="40" fill="black"/>
<rect x="48" width="1" height="40" fill="black"/>
<rect x="55" width="4" height="40" fill="black"/>
<rect x="62" width="2" height="40" fill="black"/>
<rect x="70" width="1" height="40" fill="black"/>
<rect x="75" width="3" height="40" fill="black"/>
<rect x="85" width="2" height="40" fill="black"/>
<rect x="92" width="4" height="40" fill="black"/>
<rect x="98" width="2" height="40" fill="black"/>
</svg>
<div style="font-size: 10px; letter-spacing: 4px; margin-top: 8px; color: #000; text-align: center;">
2 8937261 273610
</div>
</div>
</div>
</div>
<script>
// --- WebGL Holographic Effect ---
const canvas = document.getElementById('gl-canvas');
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
const renderer = new THREE.WebGLRenderer({ canvas, alpha: true });
const geometry = new THREE.PlaneGeometry(2, 2);
const material = new THREE.ShaderMaterial({
uniforms: {
uMouse: { value: new THREE.Vector2(0.5, 0.5) },
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4(position, 1.0);
}
`,
fragmentShader: `
varying vec2 vUv;
uniform vec2 uMouse;
void main() {
float dist = distance(vUv, uMouse);
float edge = smoothstep(0.4, 0.0, dist);
vec3 color = vec3(0.8, 0.9, 1.0) * edge;
gl_FragColor = vec4(color, edge * 0.5);
}
`
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
function resize() {
const rect = canvas.parentNode.getBoundingClientRect();
renderer.setSize(rect.width, rect.height);
}
window.addEventListener('resize', resize);
resize();
// --- Interactivity ---
const wrapper = document.getElementById('wrapper');
document.addEventListener('mousemove', (e) => {
const rect = wrapper.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width;
const y = 1.0 - (e.clientY - rect.top) / rect.height;
// Update WebGL Uniform
material.uniforms.uMouse.value.set(x, y);
// Subtle 3D Tilt
const rotateX = (y - 0.5) * 10;
const rotateY = (x - 0.5) * -10;
wrapper.style.transform = `rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
});
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>“Create a "Interactive Digital Ticket" component. Use Three.js for 3D WebGL rendering. Implement custom GLSL shaders for visual effects. Apply gradients, 3D CSS perspective, blend modes. Color palette: #f4f7f9, #ffffff, #000000, #8e8e93, #e5e5ea. Layout: CSS Grid, Flexbox, full-viewport sizing. Interactivity: mouse tracking, continuous animation loop, responsive resize handling.”