Andrea di Tuoro
Developer
Web Designer
Home
Portfolio
Code & Samples
Templates
Blog
Contatti
Instagram
@andrew_webdeveloper
Dark
Dark
Navigazione
Menu rapido
Home
Ingresso
Portfolio
Lavori
Code & Samples
Pagina attuale
Templates
Modelli
Blog
Articoli
Contatti
Scrivimi
Instagram
@andrew_webdeveloper
HTML
<main class="scene"> <div class="ambient-grid"></div> <div class="light-haze"></div> <section class="arena"> <div class="stands"></div> <div class="runoff"></div> <div class="court-wrap"> <div class="court"></div> </div> <div class="net"></div> </section> <header class="hud"> <div class="chip">Pure HTML + CSS</div> <div class="scoreboard"> <div class="team a"><span class="dot"></span> Team A</div> <div class="score">40 : 30</div> <div class="team b"><span class="dot"></span> Team B</div> </div> </header> <div class="ball-layer"> <div class="path-glow"></div> <div class="hit-ring"></div> <div class="ball-shadow"></div> <div class="racket" aria-hidden="true"> <div class="head"></div> <div class="throat"></div> <div class="handle"></div> <div class="cap"></div> </div> <div class="ball" aria-hidden="true"></div> </div> <div class="copy"> <div class="eyebrow">Padel Motion Concept</div> <div class="headline">Court <span>Pulse</span></div> <div class="subcopy"> Animazione Padel/Tennis </div> </div> <div class="badge">Refined impact timing</div> <div class="vignette"></div> </main> <script src="script.js"></script>
CSS
:root { --bg-top: #071321; --bg-bottom: #0b1a2d; --glass: rgba(255, 255, 255, 0.06); --glass-strong: rgba(255, 255, 255, 0.09); --text: #eef7ff; --muted: rgba(238, 247, 255, 0.68); --cyan: #7ef6ff; --mint: #b9ff8c; --court-1: #14365a; --court-2: #0d2946; --court-line: rgba(255, 255, 255, 0.82); --shadow: 0 28px 80px rgba(0, 0, 0, 0.42); --loop: 7.8s; --scene-radius: clamp(20px, 2vw, 34px); --hud-gap: clamp(10px, 1.6vw, 18px); --pad-x: clamp(16px, 2vw, 28px); --pad-y: clamp(16px, 2vw, 24px); } *, *::before, *::after { box-sizing: border-box; } html, body { margin: 0; min-height: 100%; font-family: Inter, ui-sans-serif, system-ui, sans-serif; color: var(--text); background: linear-gradient(180deg, var(--bg-top), var(--bg-bottom)); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } body { display: grid; place-items: center; overflow: hidden; background: radial-gradient(circle at 20% 18%, rgba(126, 246, 255, 0.12), transparent 24%), radial-gradient(circle at 80% 12%, rgba(185, 255, 140, 0.08), transparent 26%), radial-gradient(circle at 50% 120%, rgba(255, 255, 255, 0.05), transparent 35%), linear-gradient(180deg, var(--bg-top), var(--bg-bottom)); } .scene { position: relative; width: 100%; max-width: 100%; min-width: 0; aspect-ratio: 16 / 9; overflow: hidden; border-radius: var(--scene-radius); border: 1px solid rgba(255, 255, 255, 0.08); background: linear-gradient(180deg, rgba(255, 255, 255, 0.03), rgba(255, 255, 255, 0.01)), linear-gradient(180deg, #10243d 0%, #0b1a2d 42%, #081321 100%); box-shadow: var(--shadow); isolation: isolate; container-type: inline-size; } .scene, .scene * { backface-visibility: hidden; transform-style: preserve-3d; } .scene::before, .scene::after { content: ""; position: absolute; pointer-events: none; z-index: 0; } .scene::before { top: -28%; left: -16%; width: 64%; height: 70%; background: radial-gradient(circle, rgba(255, 255, 255, 0.12), transparent 58%); filter: blur(18px); animation: beamLeft 10s ease-in-out infinite; } .scene::after { top: -25%; right: -14%; width: 58%; height: 64%; background: radial-gradient(circle, rgba(126, 246, 255, 0.14), transparent 56%); filter: blur(20px); animation: beamRight 10s ease-in-out infinite; } .ambient-grid, .light-haze, .vignette { position: absolute; inset: 0; pointer-events: none; } .ambient-grid { z-index: 1; opacity: 0.55; background: linear-gradient(to right, transparent 49.7%, rgba(255, 255, 255, 0.06) 49.7% 50.3%, transparent 50.3%), repeating-linear-gradient(to right, transparent 0 8%, rgba(255, 255, 255, 0.018) 8% 8.16%), repeating-linear-gradient(to bottom, transparent 0 12%, rgba(255, 255, 255, 0.015) 12% 12.18%); } .light-haze { z-index: 2; background: radial-gradient(circle at 50% 28%, rgba(126, 246, 255, 0.12), transparent 28%), radial-gradient(circle at 50% 92%, rgba(185, 255, 140, 0.08), transparent 32%); animation: hazePulse 6s ease-in-out infinite; } .vignette { z-index: 8; background: radial-gradient(circle at 50% 45%, transparent 42%, rgba(0, 0, 0, 0.14) 72%, rgba(0, 0, 0, 0.34) 100%); } .arena { position: absolute; inset: 7.5% 5% 10%; z-index: 2; border-radius: calc(var(--scene-radius) - 2px); border: 1px solid rgba(255, 255, 255, 0.08); box-shadow: inset 0 0 0 1px rgba(126, 246, 255, 0.03); overflow: hidden; } .stands { position: absolute; inset: 0 0 52% 0; background: linear-gradient(180deg, rgba(255, 255, 255, 0.04), transparent 78%), linear-gradient(180deg, rgba(255, 255, 255, 0.03), rgba(255, 255, 255, 0.01)); } .stands::before, .stands::after { content: ""; position: absolute; inset: 10% 4% 8%; background: radial-gradient(circle at 4% 38%, rgba(255, 255, 255, 0.12) 0 1.2px, transparent 2px), radial-gradient(circle at 12% 62%, rgba(126, 246, 255, 0.18) 0 1.1px, transparent 2px), radial-gradient(circle at 20% 34%, rgba(255, 255, 255, 0.11) 0 1.1px, transparent 2px), radial-gradient(circle at 28% 60%, rgba(185, 255, 140, 0.15) 0 1.1px, transparent 2px), radial-gradient(circle at 38% 36%, rgba(255, 255, 255, 0.1) 0 1.1px, transparent 2px), radial-gradient(circle at 48% 64%, rgba(126, 246, 255, 0.18) 0 1.1px, transparent 2px), radial-gradient(circle at 58% 40%, rgba(255, 255, 255, 0.1) 0 1.1px, transparent 2px), radial-gradient(circle at 68% 58%, rgba(185, 255, 140, 0.14) 0 1.1px, transparent 2px), radial-gradient(circle at 78% 34%, rgba(255, 255, 255, 0.1) 0 1.1px, transparent 2px), radial-gradient(circle at 88% 62%, rgba(126, 246, 255, 0.17) 0 1.1px, transparent 2px), radial-gradient(circle at 96% 40%, rgba(255, 255, 255, 0.1) 0 1.1px, transparent 2px); background-size: 160px 72px; opacity: 0.72; animation: crowdGlow 3.8s ease-in-out infinite alternate; } .stands::after { filter: blur(1.2px); opacity: 0.28; transform: translateY(9px) scale(1.015); } .court-wrap { position: absolute; left: 50%; bottom: 7%; width: 88%; height: 56%; transform: translateX(-50%); perspective: 1200px; z-index: 3; } .court { position: absolute; inset: 0; border-radius: 20px 20px 34px 34px; overflow: hidden; background: linear-gradient(180deg, rgba(255, 255, 255, 0.02), rgba(255, 255, 255, 0)), linear-gradient(180deg, var(--court-1), var(--court-2)); border: 1px solid rgba(255, 255, 255, 0.1); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03), inset 0 -30px 60px rgba(0, 0, 0, 0.16); transform: rotateX(58deg); transform-origin: center bottom; } .court::before { content: ""; position: absolute; inset: 0; background: linear-gradient(to right, transparent 49.7%, var(--court-line) 49.7% 50.3%, transparent 50.3%), linear-gradient(to bottom, transparent 49.6%, var(--court-line) 49.6% 50.4%, transparent 50.4%), linear-gradient(to right, transparent 23.4%, rgba(255, 255, 255, 0.52) 23.4% 23.8%, transparent 23.8%, transparent 76.2%, rgba(255, 255, 255, 0.52) 76.2% 76.6%, transparent 76.6%), linear-gradient(to bottom, transparent 17.5%, rgba(255, 255, 255, 0.56) 17.5% 17.9%, transparent 17.9%, transparent 82.1%, rgba(255, 255, 255, 0.56) 82.1% 82.5%, transparent 82.5%); opacity: 0.9; } .court::after { content: ""; position: absolute; inset: 0; background: repeating-linear-gradient(to right, rgba(255, 255, 255, 0.02) 0 5.5%, rgba(255, 255, 255, 0.01) 5.5% 11%), radial-gradient(circle at 50% 40%, rgba(126, 246, 255, 0.18), transparent 42%); mix-blend-mode: screen; opacity: 0.65; } .runoff { position: absolute; left: 50%; bottom: 2%; width: 94%; height: 10%; transform: translateX(-50%) rotateX(72deg); border-radius: 20px; background: linear-gradient(180deg, rgba(227, 194, 141, 0.28), rgba(227, 194, 141, 0.12)); filter: blur(0.3px); z-index: 2; } .glass-back, .glass-front, .glass-side-left, .glass-side-right { position: absolute; border: 1px solid rgba(255, 255, 255, 0.1); background: linear-gradient(180deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02)); box-shadow: inset 0 0 24px rgba(126, 246, 255, 0.04); z-index: 4; } .glass-back { left: 7%; right: 7%; top: 18%; height: 16%; border-radius: 14px 14px 0 0; } .glass-front { left: 10%; right: 10%; bottom: 10%; height: 8%; border-radius: 0 0 16px 16px; opacity: 0.72; } .glass-side-left, .glass-side-right { top: 24%; bottom: 16%; width: 6%; opacity: 0.8; } .glass-side-left { left: 8.6%; border-radius: 12px 0 0 12px; } .glass-side-right { right: 8.6%; border-radius: 0 12px 12px 0; } .net { position: absolute; left: 50%; bottom: 25.4%; width: 70%; height: 5.2%; transform: translateX(-50%); z-index: 5; background: linear-gradient(180deg, rgba(255, 255, 255, 0.92), rgba(255, 255, 255, 0.68) 12%, transparent 12%), repeating-linear-gradient(to right, rgba(255, 255, 255, 0.12) 0 2px, transparent 2px 11px), repeating-linear-gradient(to bottom, rgba(255, 255, 255, 0.08) 0 2px, transparent 2px 8px); border-radius: 4px; filter: drop-shadow(0 10px 12px rgba(0, 0, 0, 0.18)); opacity: 0.9; } .hud { position: absolute; top: var(--pad-y); left: var(--pad-x); right: var(--pad-x); z-index: 9; display: flex; justify-content: space-between; align-items: center; gap: var(--hud-gap); } .chip, .scoreboard, .badge { backdrop-filter: blur(14px); background: var(--glass); border: 1px solid rgba(255, 255, 255, 0.1); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); } .chip, .badge { padding: 10px 14px; border-radius: 999px; font-size: 12px; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(238, 247, 255, 0.84); white-space: nowrap; } .scoreboard { display: flex; align-items: center; gap: clamp(10px, 1.6vw, 18px); padding: clamp(10px, 1.4vw, 14px) clamp(12px, 1.8vw, 18px); border-radius: 18px; } .team { display: flex; align-items: center; gap: 10px; font-size: clamp(12px, 1.2vw, 14px); font-weight: 600; color: rgba(238, 247, 255, 0.92); } .dot { width: 10px; height: 10px; border-radius: 999px; box-shadow: 0 0 18px currentColor; } .team.a .dot { color: var(--cyan); background: var(--cyan); } .team.b .dot { color: var(--mint); background: var(--mint); } .score { min-width: 86px; text-align: center; font-size: clamp(20px, 2.8vw, 34px); line-height: 1; font-weight: 800; letter-spacing: 0.08em; animation: scoreBreath var(--loop) ease-in-out infinite; } .copy { position: absolute; left: clamp(18px, 2vw, 34px); bottom: clamp(18px, 2vw, 30px); z-index: 9; display: grid; gap: 8px; max-width: min(430px, 42vw); } .eyebrow { font-size: 12px; letter-spacing: 0.24em; text-transform: uppercase; color: rgba(238, 247, 255, 0.66); } .headline { font-size: clamp(30px, 4.4vw, 58px); line-height: 0.92; letter-spacing: -0.05em; text-transform: uppercase; font-weight: 800; text-shadow: 0 10px 30px rgba(0, 0, 0, 0.26); max-width: 8ch; } .headline span { color: var(--mint); filter: drop-shadow(0 0 18px rgba(185, 255, 140, 0.22)); } .subcopy { font-size: clamp(13px, 1.05vw, 14px); line-height: 1.5; color: var(--muted); max-width: 35ch; } .badge { position: absolute; right: clamp(18px, 2vw, 28px); bottom: clamp(18px, 2vw, 28px); z-index: 9; color: rgba(238, 247, 255, 0.76); letter-spacing: 0.1em; } .ball-layer { position: absolute; inset: 0; z-index: 7; pointer-events: none; } .path-glow, .hit-ring, .ball-shadow, .ball, .racket { will-change: left, top, transform, opacity; } .path-glow { position: absolute; width: 15.25%; height: 3.3%; border-radius: 999px; background: linear-gradient(90deg, rgba(126, 246, 255, 0), rgba(126, 246, 255, 0.22), rgba(185, 255, 140, 0.72)); filter: blur(10px); opacity: 0; animation: trailArc var(--loop) linear infinite; transform-origin: center; } .hit-ring { position: absolute; width: 13.2%; aspect-ratio: 1; border-radius: 50%; border: 1px solid rgba(185, 255, 140, 0.42); box-shadow: 0 0 26px rgba(185, 255, 140, 0.18), inset 0 0 20px rgba(255, 255, 255, 0.06); opacity: 0; animation: impactRing var(--loop) linear infinite; } .ball-shadow { position: absolute; width: 10.2%; height: 5.4%; border-radius: 50%; background: radial-gradient(circle, rgba(0, 0, 0, 0.42), transparent 70%); filter: blur(10px); animation: shadowArc var(--loop) linear infinite; } .ball { position: absolute; width: 4.9%; aspect-ratio: 1; min-width: 20px; border-radius: 50%; background: radial-gradient(circle at 30% 26%, rgba(255, 255, 255, 0.98) 0 8%, rgba(255, 255, 255, 0.52) 8% 14%, transparent 14%), radial-gradient(circle at 38% 34%, #eefb93 0 24%, #d8f15c 36%, #b8dd25 68%, #97be16 100%); box-shadow: inset -8px -10px 12px rgba(83, 112, 8, 0.26), inset 8px 10px 10px rgba(255, 255, 255, 0.22), 0 18px 28px rgba(0, 0, 0, 0.26), 0 0 26px rgba(185, 255, 140, 0.1); animation: ballArc var(--loop) linear infinite; transform-origin: center; overflow: hidden; } .ball::before { content: ""; position: absolute; inset: 0; border-radius: 50%; background: radial-gradient(circle at 2% 50%, transparent 0 32%, rgba(255, 255, 255, 0.98) 33.2% 38.6%, transparent 40%), radial-gradient(circle at 98% 50%, transparent 0 32%, rgba(255, 255, 255, 0.98) 33.2% 38.6%, transparent 40%); opacity: 0.98; transform: rotate(24deg); } .ball::after { content: ""; position: absolute; inset: 0; border-radius: 50%; background: radial-gradient(circle at 28% 24%, rgba(255, 255, 255, 0.28), transparent 22%), radial-gradient(circle at 72% 76%, rgba(0, 0, 0, 0.08), transparent 30%), radial-gradient(circle at 56% 52%, rgba(255, 255, 255, 0.06), transparent 48%); mix-blend-mode: screen; } .racket { position: absolute; width: 16.1%; aspect-ratio: 190 / 266; min-width: 78px; animation: racketMove var(--loop) linear infinite; filter: drop-shadow(0 18px 22px rgba(0, 0, 0, 0.26)); } .racket .head { position: absolute; left: 0; top: 0; width: 100%; height: 71.5%; border-radius: 48% 48% 44% 44%; background: radial-gradient(circle at 50% 42%, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.01)); border: 10px solid rgba(22, 28, 38, 0.96); box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.05); } .racket .head::before { content: ""; position: absolute; inset: 10%; border-radius: 44% 44% 40% 40%; background: repeating-linear-gradient(to right, rgba(255, 255, 255, 0.16) 0 2px, transparent 2px 14px), repeating-linear-gradient(to bottom, rgba(255, 255, 255, 0.14) 0 2px, transparent 2px 14px); opacity: 0.7; } .racket .head::after { content: ""; position: absolute; width: 9.5%; aspect-ratio: 1; border-radius: 50%; background: rgba(255, 255, 255, 0.12); top: 11.5%; left: 50%; transform: translateX(-50%); box-shadow: -48px 22px 0 rgba(255, 255, 255, 0.1), 48px 22px 0 rgba(255, 255, 255, 0.1), -66px 64px 0 rgba(255, 255, 255, 0.08), 66px 64px 0 rgba(255, 255, 255, 0.08), 0 76px 0 rgba(255, 255, 255, 0.08); opacity: 0.85; } .racket .throat { position: absolute; left: 50%; top: 53.4%; width: 30.5%; height: 12.8%; transform: translateX(-50%); background: linear-gradient(180deg, rgba(20, 26, 38, 1), rgba(29, 40, 58, 0.92)); clip-path: polygon(22% 0, 78% 0, 100% 100%, 0 100%); border-radius: 0 0 14px 14px; } .racket .handle { position: absolute; left: 50%; top: 62.4%; width: 14.7%; height: 36.1%; transform: translateX(-50%); background: repeating-linear-gradient(135deg, #f6f8fb 0 6px, #d5dce5 6px 12px); border-radius: 0 0 18px 18px; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08); } .racket .cap { position: absolute; left: 50%; top: 93.2%; width: 21%; height: 6.8%; transform: translateX(-50%); border-radius: 14px; background: linear-gradient(180deg, #111822, #0a1119); } @keyframes ballArc { 0% { left: 2.4%; top: 78.6%; transform: scale(0.82) rotate(0deg); } 10% { left: 7.8%; top: 70.8%; transform: scale(0.88) rotate(42deg); } 22% { left: 15.9%; top: 59%; transform: scale(0.96) rotate(98deg); } 36% { left: 26.6%; top: 44.9%; transform: scale(1.05) rotate(160deg); } 50% { left: 38.5%; top: 32.5%; transform: scale(1.12) rotate(220deg); } 62% { left: 47.8%; top: 26.5%; transform: scale(1.16) rotate(270deg); } 74% { left: 62.9%; top: 25.6%; transform: scale(1.18) rotate(326deg); } 80% { left: 72.4%; top: 27.4%; transform: scale(1.2) rotate(348deg); } 82% { left: 74.9%; top: 28%; transform: scale(1.18) rotate(356deg); } 84% { left: 71.7%; top: 31.6%; transform: scale(1.16) rotate(372deg); } 90% { left: 55.1%; top: 47.6%; transform: scale(1.02) rotate(420deg); } 96% { left: 26.9%; top: 68.1%; transform: scale(0.88) rotate(462deg); } 100% { left: -8.8%; top: 94.3%; transform: scale(0.74) rotate(492deg); } } @keyframes shadowArc { 0% { left: 1.2%; top: 91.6%; transform: scale(0.72); opacity: 0.26; } 10% { left: 6.8%; top: 86.4%; transform: scale(0.78); opacity: 0.30; } 22% { left: 14.9%; top: 78.6%; transform: scale(0.84); opacity: 0.34; } 36% { left: 25.6%; top: 69%; transform: scale(0.92); opacity: 0.38; } 50% { left: 37.5%; top: 60.5%; transform: scale(1); opacity: 0.42; } 62% { left: 46.9%; top: 56.3%; transform: scale(1.04); opacity: 0.44; } 74% { left: 62%; top: 55.4%; transform: scale(1.06); opacity: 0.46; } 80% { left: 71.4%; top: 56.6%; transform: scale(1.02); opacity: 0.44; } 82% { left: 74.1%; top: 57.5%; transform: scale(1); opacity: 0.42; } 84% { left: 70.7%; top: 59.9%; transform: scale(0.98); opacity: 0.40; } 90% { left: 54.1%; top: 71.4%; transform: scale(0.9); opacity: 0.32; } 96% { left: 25.9%; top: 84.6%; transform: scale(0.8); opacity: 0.24; } 100% { left: -8.1%; top: 98.5%; transform: scale(0.7); opacity: 0.18; } } @keyframes trailArc { 0%, 6% { left: -3.4%; top: 83.7%; transform: rotate(-36deg); opacity: 0; } 14% { left: 2.5%; top: 75.3%; transform: rotate(-30deg); opacity: 0.34; } 28% { left: 11.7%; top: 62.7%; transform: rotate(-22deg); opacity: 0.56; } 42% { left: 23.4%; top: 47.3%; transform: rotate(-10deg); opacity: 0.7; } 56% { left: 36.4%; top: 34%; transform: rotate(-2deg); opacity: 0.78; } 68% { left: 50.5%; top: 27.4%; transform: rotate(3deg); opacity: 0.82; } 78% { left: 67.3%; top: 26.8%; transform: rotate(6deg); opacity: 0.9; } 82% { left: 75.4%; top: 28.6%; transform: rotate(10deg); opacity: 0.94; } 86% { left: 68.6%; top: 35.5%; transform: rotate(18deg); opacity: 0.8; } 92% { left: 47.6%; top: 57.2%; transform: rotate(30deg); opacity: 0.52; } 100% { left: -3.4%; top: 92.2%; transform: rotate(42deg); opacity: 0; } } @keyframes impactRing { 0%, 79% { left: 72.9%; top: 20.5%; transform: scale(0.06); opacity: 0; } 80% { left: 72.9%; top: 20.5%; transform: scale(0.18); opacity: 0.98; } 81% { left: 72.9%; top: 20.5%; transform: scale(0.26); opacity: 0.94; } 82% { left: 72.9%; top: 20.5%; transform: scale(0.48); opacity: 0.82; } 84% { left: 72.9%; top: 20.5%; transform: scale(0.88); opacity: 0.24; } 100% { left: 72.9%; top: 20.5%; transform: scale(1.32); opacity: 0; } } @keyframes racketMove { 0%, 72% { left: 82.4%; top: 37.7%; transform: rotate(18deg) scale(0.76); opacity: 0; } 76% { left: 79.8%; top: 33.4%; transform: rotate(8deg) scale(0.8); opacity: 0.82; } 79% { left: 77.3%; top: 29.8%; transform: rotate(-4deg) scale(0.86); opacity: 1; } 80% { left: 75.8%; top: 27.4%; transform: rotate(-14deg) scale(0.9); opacity: 1; } 81% { left: 74.7%; top: 26.2%; transform: rotate(-24deg) scale(0.95); opacity: 1; } 82% { left: 73.7%; top: 25.6%; transform: rotate(-30deg) scale(1); opacity: 1; } 82.5% { left: 73.2%; top: 25.3%; transform: rotate(-34deg) scale(1.03); opacity: 1; } 83% { left: 74.1%; top: 25.9%; transform: rotate(-24deg) scale(0.99); opacity: 1; } 86% { left: 77.5%; top: 31%; transform: rotate(-8deg) scale(0.9); opacity: 0.96; } 92% { left: 82%; top: 40.4%; transform: rotate(10deg) scale(0.82); opacity: 0.7; } 100% { left: 87.6%; top: 51.8%; transform: rotate(18deg) scale(0.72); opacity: 0; } } @keyframes crowdGlow { from { opacity: 0.48; transform: translateY(0); } to { opacity: 0.74; transform: translateY(4px); } } @keyframes beamLeft { 0%, 100% { transform: translateX(0) rotate(8deg); opacity: 0.24; } 50% { transform: translateX(5%) rotate(14deg); opacity: 0.4; } } @keyframes beamRight { 0%, 100% { transform: translateX(0) rotate(-8deg); opacity: 0.16; } 50% { transform: translateX(-5%) rotate(-14deg); opacity: 0.32; } } @keyframes hazePulse { 0%, 100% { opacity: 0.58; } 50% { opacity: 0.82; } } @keyframes scoreBreath { 0%, 100% { transform: scale(1); opacity: 0.94; } 50% { transform: scale(1.05); opacity: 1; } } @media (max-width: 980px) { .scene { width: 100%; max-width: 100%; } .hud { top: 16px; left: 16px; right: 16px; } .scoreboard { gap: 12px; padding: 10px 12px; } .team { font-size: 12px; } .copy { left: 18px; bottom: 18px; max-width: min(360px, 46vw); } .badge { right: 18px; bottom: 18px; font-size: 11px; } .headline { max-width: 10ch; } } @container (max-width: 640px) { .hud { top: 14px; left: 14px; right: 14px; align-items: flex-start; flex-wrap: wrap; gap: 10px; } .chip { font-size: 10px; padding: 8px 10px; } .scoreboard { margin-left: auto; gap: 10px; padding: 10px 12px; } .score { min-width: auto; font-size: 20px; } .team { gap: 8px; font-size: 11px; } .copy { left: 16px; right: 16px; bottom: 18px; max-width: 290px; } .headline { font-size: clamp(34px, 10vw, 58px); } .subcopy { max-width: 24ch; font-size: 13px; } .badge { display: none; } .court-wrap { width: 124%; height: 42%; bottom: 18%; } .glass-back { top: 25%; height: 12%; } .glass-front { bottom: 16%; height: 6%; } .glass-side-left, .glass-side-right { top: 30%; bottom: 22%; width: 8%; } .net { width: 84%; bottom: 28%; } .path-glow { width: 20%; height: 3.8%; } .hit-ring { width: 18%; } .ball-shadow { width: 14%; height: 6%; } .ball { width: 7%; min-width: 16px; } .racket { width: 21%; min-width: 64px; } }
JS
Padel/Tennis Match