Exploding like buttonOne-line
MiniMax M3.1 Flash
by MiniMaxReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 2 min 4 s
- Cost
- $0.016
- Output tokens
- 26,161
- Spent thinking
- 15,830 tokens
- Speed
- 211.4 tok/s
- Console errors
- 0
- First token after
- 577 ms
- First visible text after
- 1 min 40 s
- Prompt tokens
- 528
- Code size
- 32.0 KB
- Finish reason
- stop
- Served by
- DigitalOcean
- Model id
minimax/minimax-m3.1-flash- Reasoning sent
{"effort":"max"}- Max output
- 64,000 tokens
- Generated
- Nov 11, 2026
What it was asked
The prompt
“a "like" button in pure CSS, no JavaScript, that does a crazy animation when you click it”
System prompt, sent with every prompt
You are generating a self-contained web demo. It will be rendered automatically in a sandboxed iframe and compared side by side with the output of other AI models given the exact same task. Output rules: - Reply with exactly ONE fenced code block containing the complete file: ```html (or ```svg when the task asks for an SVG). No text before or after the code block. - Everything must be inline: CSS in <style>, JavaScript in <script>. No external files, images, fonts or network requests, except the CDN URLs explicitly allowed by the task. - Do not use localStorage, sessionStorage, cookies, IndexedDB, alert(), confirm(), prompt() or window.open(): they are blocked in the sandbox and will throw. - The page must look right in a 1280×800 viewport and adapt gracefully down to 375px wide. No horizontal scrollbar. - Something meaningful must be visible on first paint: a screenshot is taken automatically about 3 seconds after load, without any interaction. - Everything that makes the demo interesting must be visible within the first seconds: nothing hidden behind a high score, a later level or a long play session. - Games must start in a self-playing demo mode (a simple AI plays) behind a "Click or press a key to start" message, so the game can be judged in action without playing. - The iframe only receives keyboard events after the user clicks it: if the demo uses the keyboard, display a clear "Click or press a key to start" message. - The code must run with zero errors in the console of the latest Chrome.
Code run-1.html · 1283 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Pure CSS Like Button</title>
<style>
:root {
color-scheme: dark;
--pink: #ff5c91;
--orange: #ffad70;
--purple: #c18aff;
--cream: #fff5f0;
--muted: #b8afc9;
}
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
min-height: 100%;
}
body {
overflow-x: hidden;
color: var(--cream);
font-family: ui-rounded, "SF Pro Rounded", "Segoe UI", system-ui, -apple-system, sans-serif;
background:
radial-gradient(ellipse at 12% 8%, rgba(135, 80, 255, .28), transparent 43%),
radial-gradient(ellipse at 88% 85%, rgba(255, 75, 120, .22), transparent 42%),
linear-gradient(145deg, #110d22, #1b1230 52%, #100c1e);
}
body::before {
content: "";
position: fixed;
inset: 0;
z-index: 0;
pointer-events: none;
opacity: .22;
background-image:
radial-gradient(rgba(255, 255, 255, .18) .7px, transparent .7px);
background-size: 25px 25px;
mask-image: linear-gradient(to bottom, black, transparent 85%);
}
button,
input,
label {
-webkit-tap-highlight-color: transparent;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.background-symbols {
position: fixed;
inset: 0;
z-index: 0;
overflow: hidden;
pointer-events: none;
}
.background-symbols span {
position: absolute;
display: block;
line-height: 1;
animation: background-float 7s ease-in-out infinite alternate;
}
.background-symbols span:nth-child(1) {
left: 6vw;
top: 17%;
color: rgba(255, 111, 156, .075);
font-size: 145px;
transform: rotate(-18deg);
}
.background-symbols span:nth-child(2) {
right: 9vw;
top: 24%;
color: rgba(203, 151, 255, .14);
font-size: 55px;
animation-delay: -2s;
}
.background-symbols span:nth-child(3) {
left: 13vw;
bottom: 8%;
color: rgba(255, 164, 107, .065);
font-size: 88px;
transform: rotate(21deg);
animation-delay: -4s;
}
.app {
position: relative;
z-index: 1;
min-height: 100vh;
min-height: 100svh;
padding: 24px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
}
.eyebrow {
margin: 0 0 12px;
display: inline-flex;
align-items: center;
gap: 9px;
color: #e8c8e4;
font-size: 10px;
font-weight: 800;
letter-spacing: .22em;
text-transform: uppercase;
}
.eyebrow-star {
color: #ffd18a;
font-size: 16px;
line-height: 1;
animation: twinkle 2s ease-in-out infinite alternate;
}
h1 {
margin: 0;
font-size: clamp(2.6rem, 5.4vw, 3.7rem);
line-height: 1.03;
font-weight: 850;
letter-spacing: -.065em;
}
.gradient-text {
display: inline-block;
color: transparent;
background: linear-gradient(95deg, #ff86ad, #ffae79 48%, #c69bff);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
filter: drop-shadow(0 8px 30px rgba(255, 102, 158, .16));
}
.lede {
margin: 12px 0 0;
color: var(--muted);
font-size: 15px;
line-height: 1.5;
}
.post {
position: relative;
width: min(100%, 570px);
margin-top: 25px;
padding: 25px 26px 23px;
overflow: visible;
text-align: left;
border: 1px solid rgba(255, 255, 255, .13);
border-radius: 32px;
background:
linear-gradient(145deg, rgba(49, 37, 77, .92), rgba(29, 22, 52, .94));
box-shadow:
0 30px 85px rgba(0, 0, 0, .42),
inset 0 1px 0 rgba(255, 255, 255, .09);
transition: border-color .4s ease, box-shadow .4s ease;
}
.post::before {
content: "";
position: absolute;
top: -1px;
left: 19%;
right: 19%;
height: 2px;
border-radius: 99px;
opacity: .3;
background: linear-gradient(90deg, transparent, #ff8bb6, #c393ff, transparent);
transform: scaleX(.35);
}
.post-header {
position: relative;
z-index: 3;
display: flex;
align-items: center;
gap: 12px;
}
.avatar {
width: 43px;
height: 43px;
flex: 0 0 auto;
display: grid;
place-items: center;
border: 1px solid rgba(255, 255, 255, .24);
border-radius: 15px;
color: #fff;
font-size: 20px;
background: linear-gradient(135deg, #ff6c9d, #b777ff);
box-shadow: 0 8px 20px rgba(208, 81, 162, .22);
}
.post-by {
min-width: 0;
display: flex;
flex: 1;
flex-direction: column;
gap: 3px;
}
.post-by strong {
font-size: 13px;
font-weight: 750;
letter-spacing: -.01em;
}
.post-by span {
overflow: hidden;
color: #a79eb8;
font-size: 10.5px;
text-overflow: ellipsis;
white-space: nowrap;
}
.live-pill {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 7px 9px;
border: 1px solid rgba(255, 255, 255, .1);
border-radius: 99px;
color: #c9c1d7;
font-size: 8px;
font-weight: 800;
letter-spacing: .15em;
background: rgba(255, 255, 255, .045);
}
.live-pill i {
width: 5px;
height: 5px;
border-radius: 50%;
background: #87e5c9;
box-shadow: 0 0 9px #87e5c9;
animation: pulse-dot 1.8s ease-in-out infinite;
}
.reaction-area {
position: relative;
z-index: 4;
height: 220px;
display: grid;
place-items: center;
isolation: isolate;
}
.aura {
position: absolute;
left: 50%;
top: 50%;
z-index: -1;
width: 190px;
height: 190px;
border: 1px dashed rgba(255, 162, 194, .17);
border-radius: 50%;
background: radial-gradient(circle, rgba(255, 87, 145, .09), transparent 67%);
animation: aura-turn 28s linear infinite;
}
.aura::after {
content: "";
position: absolute;
inset: 15px;
border: 1px solid rgba(194, 151, 255, .09);
border-radius: 50%;
}
.twinkle {
position: absolute;
z-index: 2;
color: #ffb0ca;
font-size: 17px;
line-height: 1;
animation: twinkle 2.3s ease-in-out infinite alternate;
pointer-events: none;
}
.twinkle:nth-of-type(1) {
left: 16%;
top: 25%;
color: #ffcb8a;
}
.twinkle:nth-of-type(2) {
right: 15%;
top: 16%;
animation-delay: -.9s;
}
.twinkle:nth-of-type(3) {
left: 22%;
bottom: 17%;
color: #c8a0ff;
animation-delay: -1.5s;
}
.twinkle:nth-of-type(4) {
right: 9%;
bottom: 28%;
color: #89ead3;
animation-delay: -.4s;
}
.like-button {
position: relative;
z-index: 5;
width: 300px;
max-width: 100%;
height: 88px;
padding: 11px 16px 11px 12px;
display: grid;
grid-template-columns: 58px 1fr 44px;
align-items: center;
gap: 13px;
overflow: visible;
border: 1px solid rgba(255, 255, 255, .85);
border-radius: 999px;
color: #2a1932;
cursor: pointer;
user-select: none;
background: linear-gradient(135deg, #fffaf7, #ffe3ec);
box-shadow:
0 13px 30px rgba(0, 0, 0, .25),
0 3px 0 rgba(0, 0, 0, .09),
inset 0 1px 0 #fff;
transition:
transform .3s cubic-bezier(.2, .9, .3, 1.2),
background .4s ease,
color .4s ease,
border-color .4s ease,
box-shadow .4s ease;
}
.like-button::before {
content: "";
position: absolute;
z-index: 4;
inset: 2px;
overflow: hidden;
border-radius: inherit;
opacity: 0;
pointer-events: none;
background: linear-gradient(105deg, transparent 30%, rgba(255, 255, 255, .5) 48%, transparent 66%);
transform: translateX(-160%) skewX(-18deg);
mix-blend-mode: overlay;
}
@media (hover: hover) {
.like-button:hover {
transform: translateY(-4px) scale(1.02);
box-shadow:
0 18px 36px rgba(0, 0, 0, .3),
0 4px 0 rgba(0, 0, 0, .07),
0 0 35px rgba(255, 103, 158, .18);
}
.like-button:hover .heart {
transform: scale(1.1) rotate(-5deg);
}
}
.like-button:active {
transform: translateY(1px) scale(.985);
}
.heart-wrap {
width: 58px;
height: 58px;
display: grid;
place-items: center;
border: 1px solid rgba(255, 79, 132, .22);
border-radius: 50%;
background: radial-gradient(circle at 35% 25%, rgba(255, 145, 177, .32), rgba(255, 87, 140, .08));
box-shadow: inset 0 1px 2px rgba(255, 255, 255, .6);
transition: background .35s ease, border-color .35s ease;
}
.heart {
display: block;
color: #ff4d86;
font-family: Arial, sans-serif;
font-size: 34px;
font-weight: 900;
line-height: 1;
transform-origin: center;
transition: transform .25s ease, color .35s ease;
}
.button-copy {
position: relative;
z-index: 2;
min-width: 0;
display: flex;
flex-direction: column;
align-items: flex-start;
}
.label-stack,
.sub-stack {
position: relative;
display: block;
}
.label-stack {
width: 90px;
height: 29px;
}
.sub-stack {
width: 120px;
height: 14px;
}
.label-default,
.label-liked,
.sub-default,
.sub-liked {
position: absolute;
left: 0;
top: 0;
white-space: nowrap;
transition: opacity .3s ease, transform .4s cubic-bezier(.2, .9, .3, 1.2);
}
.label-default,
.label-liked {
font-size: 21px;
font-weight: 820;
letter-spacing: -.035em;
}
.sub-default,
.sub-liked {
font-size: 8.5px;
font-weight: 800;
letter-spacing: .14em;
opacity: .57;
}
.label-liked,
.sub-liked {
opacity: 0;
transform: translateY(10px);
}
.count {
position: relative;
z-index: 2;
display: flex;
flex-direction: column;
align-items: flex-end;
}
.count-value {
position: relative;
width: 44px;
height: 19px;
}
.count-old,
.count-new {
position: absolute;
right: 0;
top: 0;
font-size: 14px;
font-weight: 800;
letter-spacing: -.02em;
transition: opacity .3s ease, transform .45s cubic-bezier(.2, .9, .3, 1.2);
}
.count-new {
opacity: 0;
transform: translateY(100%);
}
.count-label {
margin-top: 2px;
font-size: 8px;
font-weight: 800;
letter-spacing: .14em;
opacity: .52;
}
.caption {
position: absolute;
left: 10px;
right: 10px;
bottom: 0;
z-index: 6;
height: 22px;
color: #bcb2c9;
font-size: 11.5px;
font-weight: 550;
}
.caption-before,
.caption-after {
position: absolute;
left: 0;
right: 0;
transition: opacity .35s ease, transform .4s ease;
}
.caption-after {
opacity: 0;
color: #ffb3cc;
font-weight: 750;
transform: translateY(8px);
}
.love-word {
position: absolute;
left: 50%;
top: 29px;
z-index: 12;
opacity: 0;
color: transparent;
background: linear-gradient(100deg, #fff, #ff9ac1 42%, #ffd08e);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-size: clamp(3.2rem, 9vw, 5.5rem);
font-weight: 950;
line-height: 1;
letter-spacing: -.07em;
white-space: nowrap;
pointer-events: none;
filter:
drop-shadow(0 5px 0 rgba(82, 29, 69, .2))
drop-shadow(0 0 25px rgba(255, 108, 157, .45));
}
.love-word::before,
.love-word::after {
position: absolute;
color: #ffcf82;
font-size: 30px;
-webkit-text-fill-color: currentColor;
}
.love-word::before {
content: "♥";
left: -30px;
bottom: -2px;
color: #ff6f9f;
transform: rotate(-18deg);
}
.love-word::after {
content: "✦";
right: -25px;
top: -14px;
transform: rotate(15deg);
}
.ripple {
position: absolute;
left: 50%;
top: 50%;
z-index: 1;
width: 120px;
height: 120px;
opacity: 0;
border: 2px solid rgba(255, 121, 168, .45);
border-radius: 50%;
pointer-events: none;
transform: translate(-50%, -50%) scale(.2);
}
.ripple.r2 {
--delay: 140ms;
width: 104px;
height: 104px;
border-style: dashed;
border-color: rgba(197, 151, 255, .45);
}
.ripple.r3 {
--delay: 280ms;
width: 90px;
height: 90px;
border-color: rgba(255, 209, 132, .5);
}
.burst {
position: absolute;
inset: 0;
z-index: 8;
pointer-events: none;
}
.particle {
--spread: 1;
position: absolute;
left: 50%;
top: 50%;
z-index: 8;
width: 0;
height: 0;
opacity: 0;
pointer-events: none;
}
.particle::before {
content: "";
position: absolute;
left: 0;
top: 0;
width: 7px;
height: 17px;
border-radius: 3px;
background: var(--color);
box-shadow: 0 0 13px var(--color);
transform: translate(-50%, -50%) rotate(18deg);
}
.particle:nth-child(3n)::before {
content: "♥";
width: auto;
height: auto;
color: var(--color);
background: none;
box-shadow: none;
font-family: Arial, sans-serif;
font-size: 24px;
font-weight: 900;
line-height: 1;
transform: translate(-50%, -50%);
}
.particle:nth-child(5n)::before {
width: 9px;
height: 9px;
border-radius: 50%;
}
.particle:nth-child(4n + 1)::before {
transform: translate(-50%, -50%) rotate(-35deg);
}
.post-footer {
position: relative;
z-index: 3;
min-height: 43px;
padding-top: 17px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 14px;
border-top: 1px solid rgba(255, 255, 255, .09);
}
.comment {
min-width: 0;
display: flex;
align-items: center;
gap: 10px;
}
.comment-bubble {
width: 29px;
height: 29px;
flex: 0 0 auto;
display: grid;
place-items: center;
border: 1px solid rgba(255, 255, 255, .13);
border-radius: 10px;
color: #ff91b2;
font-size: 13px;
background: rgba(255, 255, 255, .045);
transition: background .35s ease, color .35s ease, transform .35s ease;
}
.comment-text {
position: relative;
display: block;
min-height: 17px;
color: #a9a0b9;
font-size: 11px;
line-height: 1.5;
}
.comment-default,
.comment-liked {
position: absolute;
left: 0;
top: 0;
white-space: nowrap;
transition: opacity .3s ease, transform .4s ease;
}
.comment-liked {
opacity: 0;
color: #ffbad3;
font-weight: 700;
transform: translateY(7px);
}
.zero-js {
flex: 0 0 auto;
display: inline-flex;
align-items: center;
gap: 6px;
padding: 7px 9px;
border: 1px solid rgba(135, 229, 201, .14);
border-radius: 99px;
color: #9bddca;
font-size: 8px;
font-weight: 800;
letter-spacing: .12em;
background: rgba(135, 229, 201, .045);
}
.zero-js i {
color: #8be4ca;
font-family: ui-monospace, monospace;
font-size: 10px;
font-style: normal;
}
.start-hint {
margin: 15px 0 0;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: 8px;
color: #a79eb7;
font-size: 11px;
}
.mouse-icon {
position: relative;
width: 15px;
height: 21px;
display: inline-block;
border: 1.5px solid #b2a6c0;
border-radius: 8px;
}
.mouse-icon i {
position: absolute;
left: 50%;
top: 4px;
width: 2px;
height: 4px;
border-radius: 2px;
background: #ff82aa;
transform: translateX(-50%);
animation: mouse-scroll 1.8s ease-in-out infinite;
}
kbd {
padding: 3px 7px;
border: 1px solid rgba(255, 255, 255, .14);
border-bottom-color: rgba(255, 255, 255, .24);
border-radius: 6px;
color: #d2c9dd;
font-family: inherit;
font-size: 9px;
background: rgba(255, 255, 255, .05);
box-shadow: 0 2px 0 rgba(0, 0, 0, .18);
}
.flash {
position: fixed;
inset: 0;
z-index: 100;
opacity: 0;
pointer-events: none;
background: radial-gradient(circle at 50% 54%, rgba(255, 160, 194, .24), rgba(255, 128, 177, .07) 35%, transparent 65%);
mix-blend-mode: screen;
}
/* All of the celebration is triggered by the checkbox. */
#like-toggle:checked ~ .app .post {
border-color: rgba(255, 145, 187, .4);
box-shadow:
0 30px 85px rgba(0, 0, 0, .42),
0 0 65px rgba(255, 91, 146, .16),
inset 0 1px 0 rgba(255, 255, 255, .12);
animation: card-celebrate .9s cubic-bezier(.2, .8, .25, 1) both;
}
#like-toggle:checked ~ .app .post::before {
animation: line-reveal .9s ease-out both;
}
#like-toggle:checked ~ .app .like-button {
color: #fff;
border-color: rgba(255, 255, 255, .6);
background: linear-gradient(115deg, #ff477e, #ff7175 47%, #ff9e5e);
box-shadow:
0 17px 38px rgba(255, 67, 120, .33),
0 0 0 7px rgba(255, 102, 151, .075),
0 0 65px rgba(255, 92, 145, .3),
inset 0 1px 0 rgba(255, 255, 255, .4);
animation: button-pop .85s cubic-bezier(.18, .9, .3, 1.15) both;
}
#like-toggle:checked ~ .app .like-button::before {
animation: shine-sweep .95s .12s ease-out both;
}
#like-toggle:checked ~ .app .heart-wrap {
border-color: rgba(255, 255, 255, .4);
background: rgba(255, 255, 255, .22);
}
#like-toggle:checked ~ .app .heart {
color: #fff;
animation: heart-beat .62s ease-in-out infinite;
}
#like-toggle:checked ~ .app .label-default,
#like-toggle:checked ~ .app .sub-default {
opacity: 0;
transform: translateY(-10px);
}
#like-toggle:checked ~ .app .label-liked,
#like-toggle:checked ~ .app .sub-liked {
opacity: 1;
transform: translateY(0);
}
#like-toggle:checked ~ .app .count-old {
opacity: 0;
transform: translateY(-110%);
}
#like-toggle:checked ~ .app .count-new {
opacity: 1;
transform: translateY(0);
}
#like-toggle:checked ~ .app .caption-before {
opacity: 0;
transform: translateY(-6px);
}
#like-toggle:checked ~ .app .caption-after {
opacity: 1;
transform: translateY(0);
}
#like-toggle:checked ~ .app .comment-bubble {
color: #fff;
border-color: rgba(255, 255, 255, .25);
background: linear-gradient(135deg, #ff5e96, #c374ff);
transform: rotate(-8deg) scale(1.08);
}
#like-toggle:checked ~ .app .comment-default {
opacity: 0;
transform: translateY(-7px);
}
#like-toggle:checked ~ .app .comment-liked {
opacity: 1;
transform: translateY(0);
}
#like-toggle:checked ~ .app .love-word {
animation: word-burst 1.35s cubic-bezier(.17, .75, .2, 1) .08s both;
}
#like-toggle:checked ~ .app .ripple {
animation: ripple-out 1s cubic-bezier(.15, .7, .25, 1) var(--delay) both;
}
#like-toggle:checked ~ .app .particle {
animation: particle-flight 1.2s cubic-bezier(.12, .7, .2, 1) var(--delay) both;
}
#like-toggle:checked ~ .app .twinkle {
animation-duration: .8s;
}
#like-toggle:checked ~ .app .flash {
animation: flash-out .75s ease-out both;
}
#like-toggle:focus-visible ~ .app .like-button {
outline: 3px solid #ffe49a;
outline-offset: 6px;
}
@keyframes background-float {
from { translate: 0 -12px; rotate: -5deg; }
to { translate: 0 24px; rotate: 9deg; }
}
@keyframes aura-turn {
from { transform: translate(-50%, -50%) rotate(0deg); }
to { transform: translate(-50%, -50%) rotate(360deg); }
}
@keyframes twinkle {
from { opacity: .35; transform: scale(.7) rotate(-12deg); }
to { opacity: 1; transform: scale(1.15) rotate(12deg); }
}
@keyframes pulse-dot {
0%, 100% { opacity: .45; transform: scale(.8); }
50% { opacity: 1; transform: scale(1.25); }
}
@keyframes mouse-scroll {
0%, 100% { opacity: .35; transform: translate(-50%, 0); }
50% { opacity: 1; transform: translate(-50%, 5px); }
}
@keyframes card-celebrate {
0% { transform: translateY(0) rotate(0); }
18% { transform: translateY(-8px) rotate(-1.1deg) scale(1.012); }
36% { transform: translateY(-3px) rotate(.8deg); }
56% { transform: translateY(-6px) rotate(-.4deg); }
78% { transform: translateY(-2px) rotate(.2deg); }
100% { transform: translateY(0) rotate(0); }
}
@keyframes line-reveal {
0% { opacity: .3; transform: scaleX(.35); }
45% { opacity: 1; transform: scaleX(1); }
100% { opacity: .45; transform: scaleX(.8); }
}
@keyframes button-pop {
0% { transform: translateY(0) scale(1); }
22% { transform: translateY(-7px) scale(1.075) rotate(-1.5deg); }
43% { transform: translateY(-1px) scale(.97) rotate(.8deg); }
65% { transform: translateY(-5px) scale(1.035) rotate(-.5deg); }
100% { transform: translateY(-2px) scale(1.025); }
}
@keyframes heart-beat {
0%, 100% { transform: scale(1) rotate(-2deg); }
22% { transform: scale(1.28) rotate(6deg); }
48% { transform: scale(.9) rotate(-7deg); }
72% { transform: scale(1.16) rotate(4deg); }
}
@keyframes shine-sweep {
0% { opacity: 0; transform: translateX(-160%) skewX(-18deg); }
25% { opacity: 1; }
100% { opacity: 0; transform: translateX(160%) skewX(-18deg); }
}
@keyframes word-burst {
0% { opacity: 0; transform: translate(-50%, 35px) scale(.45) rotate(-12deg); }
23% { opacity: 1; transform: translate(-50%, -12px) scale(1.16) rotate(4deg); }
42% { transform: translate(-50%, -18px) scale(1) rotate(-2deg); }
100% { opacity: 0; transform: translate(-50%, -93px) scale(.91) rotate(-4deg); }
}
@keyframes ripple-out {
0% { opacity: 0; transform: translate(-50%, -50%) scale(.15); }
17% { opacity: .85; }
100% { opacity: 0; transform: translate(-50%, -50%) scale(3.8); }
}
@keyframes particle-flight {
0% {
opacity: 0;
transform: translate(-50%, -50%) scale(.15) rotate(0deg);
}
12% { opacity: 1; }
38% {
opacity: 1;
transform:
translate(calc(-50% + var(--x) * .22), calc(-50% + var(--y) * .72))
scale(1.18)
rotate(calc(var(--turn) * .35));
}
72% {
opacity: 1;
transform:
translate(calc(-50% + var(--x) * .76), calc(-50% + var(--y) * .86))
scale(.95)
rotate(calc(var(--turn) * .72));
}
100% {
opacity: 0;
transform:
translate(calc(-50% + var(--x) * var(--spread)), calc(-50% + var(--y) * var(--spread)))
rotate(var(--turn))
scale(.55);
}
}
@keyframes flash-out {
0% { opacity: 0; }
18% { opacity: 1; }
100% { opacity: 0; }
}
@media (max-width: 520px) {
.app {
padding: 22px 16px;
}
.eyebrow {
font-size: 8px;
letter-spacing: .17em;
}
h1 {
font-size: clamp(2.35rem, 12vw, 3rem);
}
.lede {
max-width: 290px;
margin-top: 11px;
font-size: 13px;
}
.post {
margin-top: 22px;
padding: 20px 18px;
border-radius: 26px;
}
.post-header {
gap: 9px;
}
.avatar {
width: 39px;
height: 39px;
border-radius: 13px;
}
.post-by strong {
font-size: 11.5px;
}
.post-by span {
font-size: 9px;
}
.live-pill {
padding: 6px 7px;
font-size: 7px;
}
.reaction-area {
height: 210px;
}
.like-button {
width: 280px;
grid-template-columns: 54px 1fr 40px;
gap: 10px;
padding-right: 14px;
}
.heart-wrap {
width: 54px;
height: 54px;
}
.heart {
font-size: 31px;
}
.label-stack {
width: 78px;
}
.sub-stack {
width: 112px;
}
.count-value {
width: 40px;
}
.particle {
--spread: .7;
}
#like-toggle:checked ~ .app .ripple {
animation-name: ripple-out-small;
}
.post-footer {
align-items: flex-start;
flex-direction: column;
gap: 11px;
}
.comment-text {
font-size: 10px;
}
.start-hint {
font-size: 10px;
}
.background-symbols span:nth-child(1) {
left: -5vw;
font-size: 100px;
}
}
@keyframes ripple-out-small {
0% { opacity: 0; transform: translate(-50%, -50%) scale(.15); }
17% { opacity: .85; }
100% { opacity: 0; transform: translate(-50%, -50%) scale(2.65); }
}
@media (prefers-reduced-motion: reduce) {
.background-symbols span,
.eyebrow-star,
.aura,
.twinkle,
.live-pill i,
.mouse-icon i {
animation: none !important;
}
}
</style>
</head>
<body>
<input
class="sr-only"
type="checkbox"
id="like-toggle"
aria-label="Like this moment"
aria-describedby="start-hint"
>
<div class="background-symbols" aria-hidden="true">
<span>♥</span>
<span>✦</span>
<span>♥</span>
</div>
<main class="app">
<p class="eyebrow">
<span class="eyebrow-star" aria-hidden="true">✦</span>
Pure CSS · Zero JavaScript
</p>
<h1>
Like it.<br>
<span class="gradient-text">Love what happens.</span>
</h1>
<p class="lede">
One click is all it takes to make the internet<br class="desktop-break">
a little brighter.
</p>
<section class="post" aria-label="Pure CSS like button demo">
<header class="post-header">
<div class="avatar" aria-hidden="true">♥</div>
<div class="post-by">
<strong>little things club</strong>
<span>A tiny reminder to be kind today · now</span>
</div>
<span class="live-pill"><i></i> DEMO</span>
</header>
<div class="reaction-area">
<div class="aura" aria-hidden="true"></div>
<span class="twinkle" aria-hidden="true">✦</span>
<span class="twinkle" aria-hidden="true">✧</span>
<span class="twinkle" aria-hidden="true">✦</span>
<span class="twinkle" aria-hidden="true">✧</span>
<div class="ripple r1" aria-hidden="true"></div>
<div class="ripple r2" aria-hidden="true"></div>
<div class="ripple r3" aria-hidden="true"></div>
<div class="burst" aria-hidden="true">
<i class="particle" style="--x:-200px;--y:-170px;--turn:-260deg;--delay:0ms;--color:#ff6f9d"></i>
<i class="particle" style="--x:-145px;--y:-225px;--turn:180deg;--delay:45ms;--color:#ffb46e"></i>
<i class="particle" style="--x:-75px;--y:-205px;--turn:-320deg;--delay:90ms;--color:#c293ff"></i>
<i class="particle" style="--x:25px;--y:-235px;--turn:420deg;--delay:15ms;--color:#ff76a7"></i>
<i class="particle" style="--x:125px;--y:-210px;--turn:-180deg;--delay:70ms;--color:#ffb86c"></i>
<i class="particle" style="--x:200px;--y:-150px;--turn:300deg;--delay:110ms;--color:#c49aff"></i>
<i class="particle" style="--x:235px;--y:-55px;--turn:-400deg;--delay:35ms;--color:#ff6b98"></i>
<i class="particle" style="--x:220px;--y:45px;--turn:250deg;--delay:135ms;--color:#ffb56d"></i>
<i class="particle" style="--x:160px;--y:135px;--turn:-220deg;--delay:20ms;--color:#ff77ae"></i>
<i class="particle" style="--x:85px;--y:190px;--turn:330deg;--delay:80ms;--color:#ffd077"></i>
<i class="particle" style="--x:-15px;--y:220px;--turn:-300deg;--delay:125ms;--color:#c5a0ff"></i>
<i class="particle" style="--x:-120px;--y:180px;--turn:210deg;--delay:55ms;--color:#ff729f"></i>
<i class="particle" style="--x:-225px;--y:75px;--turn:-190deg;--delay:100ms;--color:#ffb970"></i>
<i class="particle" style="--x:-175px;--y:-40px;--turn:370deg;--delay:10ms;--color:#ffd17b"></i>
<i class="particle" style="--x:160px;--y:-80px;--turn:-360deg;--delay:145ms;--color:#8be5ce"></i>
<i class="particle" style="--x:-15px;--y:-175px;--turn:280deg;--delay:60ms;--color:#8be5ce"></i>
<i class="particle" style="--x:-255px;--y:-5px;--turn:-440deg;--delay:155ms;--color:#c299ff"></i>
<i class="particle" style="--x:250px;--y:115px;--turn:190deg;--delay:25ms;--color:#ff6e9c"></i>
<i class="particle" style="--x:45px;--y:245px;--turn:-270deg;--delay:165ms;--color:#ffb66f"></i>
<i class="particle" style="--x:-185px;--y:125px;--turn:340deg;--delay:115ms;--color:#c9a2ff"></i>
<i class="particle" style="--x:205px;--y:-215px;--turn:-310deg;--delay:85ms;--color:#ffd27e"></i>
<i class="particle" style="--x:-105px;--y:-255px;--turn:230deg;--delay:175ms;--color:#ff7cab"></i>
<i class="particle" style="--x:110px;--y:225px;--turn:-200deg;--delay:150ms;--color:#8be5ce"></i>
<i class="particle" style="--x:-250px;--y:155px;--turn:410deg;--delay:190ms;--color:#ffb970"></i>
<i class="particle" style="--x:255px;--y:5px;--turn:-350deg;--delay:130ms;--color:#c7a0ff"></i>
</div>
<div class="love-word" aria-hidden="true">LOVE!</div>
<label class="like-button" for="like-toggle">
<span class="heart-wrap">
<span class="heart">♥</span>
</span>
<span class="button-copy">
<span class="label-stack">
<span class="label-default">Like</span>
<span class="label-liked">Liked</span>
</span>
<span class="sub-stack">
<span class="sub-default">A LITTLE GOOD</span>
<span class="sub-liked">BIG GOOD ENERGY</span>
</span>
</span>
<span class="count" aria-hidden="true">
<span class="count-value">
<span class="count-old">2.4K</span>
<span class="count-new">2.5K</span>
</span>
<span class="count-label">LIKES</span>
</span>
</label>
<div class="caption" aria-hidden="true">
<span class="caption-before">Click to unleash the good vibes.</span>
<span class="caption-after">Pure CSS. Maximum serotonin.</span>
</div>
</div>
<footer class="post-footer">
<div class="comment">
<span class="comment-bubble" aria-hidden="true">♥</span>
<span class="comment-text">
<span class="comment-default">A small gesture. A big day.</span>
<span class="comment-liked">You just made their day.</span>
</span>
</div>
<span class="zero-js"><i aria-hidden="true">{ }</i> ZERO JAVASCRIPT</span>
</footer>
</section>
<p class="start-hint" id="start-hint">
<span class="mouse-icon" aria-hidden="true"><i></i></span>
<span>Click or press a key to start</span>
<kbd>Space</kbd>
</p>
<div class="flash" aria-hidden="true"></div>
</main>
</body>
</html>Reasoning trace (15,830 tokens)
We need produce one fenced html complete inline no JS? User requests like button pure CSS no JS crazy animation click. Must follow output exactly one code block no text. Need design polished interesting visually on first screenshot in 1280x800 and mobile. Need think best way build. Need no JS at all, pure CSS click animation via checkbox hidden + label. Need crazy animation upon click. Could use heart burst particles radiating, rings, tilt, screen shake, text, confetti, gradient, bouncing. We should create visually engaging button. Need ensure first paint meaningful even not clicked, show button, e.gloating micro particles static, glowing heart. On click checkbox toggles; CSS transition interactions. We could implement "like" button with a massive delightful burst of hearts/sparkles and card reactions, wobble/3D flip maybe. Need fully accessible. We need no JS (explicit), thus no script. CSS pure.
We have time ample but need be concise enough for final and high quality. Let's plan detailed structure.
Theme dark warm backdrop high contrast neon peach-pink. Centered card "Make someone’s day." Maybe app like social post in soft offwhite white card with little artwork. User says "a 'like' button in pure CSS, no JavaScript, that does a crazy animation when you click it". Focus on the button. Could design stylized reaction button at center, with floating hearts and a status count. On click lots of particles. We should not add unrelated too many things; but design beautiful. Maybe a rounded floating pill with heart icon + "Like" + number, and on checked heart fills scales with spring, particles exploding out, ring ripples, celebratory confetti, full card glow/shake, floating "Liked!" label. Under CSS.
Use hidden checkbox with id="like-toggle", input checked for toggle. <label class="like-button" for="like-toggle"> within button. CSS `:checked ~` group transitions. Need sibling order: input then stage with button and particles. Input as sibling before .scene. CSS #like-toggle:checked ~ .scene .like-button { ... }. `#like-toggle:focus-visible ~ .scene .like-button` outline. The button is a label with keyboard accessibility? input visually hidden but focus label styling. Clicking label works, can use aria-hidden spans. label role=button aria-pressed maybe cannot dynamic aria pressed, use label. Input checkbox form? Accessible input inside label? Could simply label with role="button" tabindex="0" but keyboard doesn't toggle without JS. Better real checkbox visually hidden with id and label for. It will respond to Space/Enter when focused? Checkbox receives keyboard, click toggles, label. Use input position absolute opacity 0 width 1px, label for. Focus styles on input sibling. Semantics label for and aria-label "Like this post". A hidden input not need aria-pressed.
First paint should show 1280x800 screenshot vibrant. We can use .backdrop gradient and big typography "Send a little love." with intro. Card post at center with like button. Could simply use main stage 560 wide, big heading "Tap the heart" small caption "A tiny gesture. A ridiculous reaction." Then hero button pill 280w ~100h with big heart and label. On click hearts radiate 18 particles using CSS custom properties. Each particle different --x, --y, --r, --size, --delay, --color; position absolute left 50% top 48%. CSS animation for unchecked? They are hidden opacity 0, transform; checked animation launch .95s cubic-bezier forwards. When uncheck hide after? :checked animation triggers. Unchecking resets all. Need keep button in pressed state after, heart filled, label changes from "Like" to "Liked". A burst lasting 1.2s. Crazy animation can loop? Could have continuous small floating particles to show interest. On click .scene animation "scene-pop" 700ms (scale etc); ripple rings; shockwave. Button fill color gradient, heart jiggle. Huge multi-color radial confetti pieces around heart, plus several hearts flying. "Liked!" pill shoots up, fades, while live dot maybe persists. Card happy with halo.
We can construct .like-button with button shape 260x84 dark navy initial? Design perhaps creamy pink card on gradient lilac background with warm coral heart. Need differentiate by nice typographic system sans no external fonts. Use system-ui / 'Arial Black'. We can use inline SVG? User wants pure CSS like no JavaScript. "pure CSS" can still inline SVG? Better all icon drawn CSS. Heart shape via CSS pseudo elements or use text heart ♥. Text heart is fine but crisp shapes prefer heart using CSS clip-path polygon? CSS heart icon classic using before/after rotated squares. But pure CSS heart can use inline svg no JS but might be considered less pure CSS. Use actual unicode ♥ in span with font-family Arial; shape nice. Another option CSS mask using path data external data URI counts image? Avoid. Use text "♥" with bold font smooth. Heart glyph vector built into browser.
Hero area maybe <main class="app">
<p class="eyebrow"><span class="live-dot"></span> CSS-ONLY INTERACTIONS</p>
<h1>One tiny click.<br><em>Infinite good vibes.</em></h1>
<p class="intro">No JavaScript. No compromises. Just pure CSS ridiculousness.</p>
<section class="post" aria-label="Demo like button">
<div class="post-top">
<div class="avatar">♥</div>
<div><h2>Good things happen...</h2><p>when you share a little love.</p></div>
<span class="tag">POST</span>
</div>
<div class="art"> maybe stylized heart on gradient? Could distract. Have art area small 170px with CSS heart shape behind heart. Or no art; central button.
<div class="reaction-area">
<div class="ambient">...</div>
<button-like>
...
</div>
<footer class="post-footer"><div class="comment-preview"><span>💬</span> ...</div><div class="status"><span></span> Ready to feel the love</div></footer>
</section>
<p class="hint">Click the heart · Watch the chaos unfold</p>
</main>
But user specifically button. Could focus large hero button in card, not add huge redundant copy. A centered card 650 width? 1280x800 with heading and card fits. Mobile adapt down 375 no scrollbar. Layout vertical .app max-width 800. Main h1 64 desktop, 36 mobile. Card max-width 560, padding 28. Button 250x78. Entire ~700 height fits. We need avoid oversize on small.
Crazy animation:
1. .reaction-area has on checked animation arena-jump 800ms with keyframes slight translateY(-16px) rotate(-1deg) etc.
2. button: on checked transform translateY(-8px) scale(1.04), box-shadow bright.
3. .heart: animation heart-thump 800ms infinite 2? Define @keyframes heart-thump {0%,100% transform scale(1) rotate(0); 12% transform scale(1.3) rotate(-9deg); 26% scale(.86) rotate(8deg); 40% scale(1.35)...}. Could infinite on checked to keep beat (animation heart-thump .72s ease-in-out infinite). Then after unchecked animation removed. User asks crazy animation on click; continuous heartbeat after is nice. Confetti one shot.
4. .like-button::before gradient animated shimmer when checked. .like-button::after radial glow.
5. .burst: 28 <i> particles absolute at left 50% top 50%, each translate from center to custom --x --y. Need transform uses variables; `transform: translate(-50%,-50%) rotate(var(--r)) translateY(calc(var(--y) * 1px)) rotate(var(--spin)) scale(...)`; custom x/y values set inline. We can set `--x: 0px` etc inline style. CSS keyframes particle-flight:
0% { opacity:0; transform:translate(-50%,-50%) rotate(0) scale(.3);}
12% {opacity:1;}
100% {opacity:0; transform:translate(calc(-50% + var(--x)),calc(-50% + var(--y))) rotate(var(--spin)) scale(.7);}
But transform order: `translate(-50%, -50%) translate(var(--x),var(--y)) rotate(var(--spin)) scale(.65)` correct. Each particle <i class="particle p1"><span>♥</span></i>. Some are colored tiny rectangles via background and border-radius; shape class .spark. Use 24 particle elements with variables in style. Need number huge enough 24. Could use CSS nth-child to assign variables so no inline style? Inline style is still HTML and CSS. Fine. All have width 12 height 18 background var color border-radius 80% 15% 75% 20%; shape leaf. Alternate .round for circles, .ring for rings. For confetti more fun, little hearts in different colors. `<i style="--x:-220px;--y:-150px;--r:80deg;--delay:0ms;--c:#ff5c8a"><span>♥</span></i>`. Span font-size 24. Others confetti bars `<i class="ribbon" style=...></i>`. Could reuse same i with pseudo content? .particle uses background and border-radius, each has `::before` content "♥"; font-size. For ribbons pseudo none, width 6 height 20. Need maybe 3 types .heart-particle vs .confetti. 28 total. CSS nth-child(3n) width 8 h 16 etc. Create 18 particles plus 8 confetti, circles.
Burst origin from button at 50%, top 52%. Since reaction area 220h with button center, particles travel 280px and may overlap text, should be behind or front. `overflow: visible` app; reaction area .burst overflow visible. z-index 10 and pointer-events none. On small screens x max 140 y max 150 so doesn't exceed viewport. Could scale particles via media query `transform`? Variables in calc multiplied by scale? Custom properties `--distance:1`; @media max-width 500 set `--distance:.65`, but x already px multiplication `calc(var(--x) * var(--distance))` accepted length * number yes CSS calc. Set --distance 1 desktop, .65 mobile. Then particle coordinates fit.
6. rings: .ripple absolute left 50% top 50% border 2px solid rgba pink; width 100 h 100 border-radius 50% opacity 0; checked animation ripple 1000ms forwards delay 80. second ring delay 180. third delay 280. keyframes scale .3 to 4 opacity 0. Could have giant halo ring flash. z-index 0.
7. .love-word absolute left 50% top 0 transform; checked animation word-rise 1200ms forwards. Text "LOVE!" large white/pink letters spaced .04em with text-shadow. starts opacity 0 translate(-50%,30px) scale(.5) rotate(-12deg); 25% opacity 1 translate(-50%,-15px) scale(1.1) rotate(4deg); 100% opacity 0 translate(-50%,-95px) scale(.9) rotate(-3deg). Position top 18? Button in center so goes up.
8. .micro-label beneath "FEELING THE LOVE" maybe show on checked opacity transition. Below button .reaction-caption "One click. Zero JavaScript." initial; checked content can't change easily with two spans .before .after. Use `.status-text` and sibling .before/.after positioned absolute. checked .before opacity 0 translateY(-6), .after opacity 1 translateY(0); .after "That’s a lot of love.".
9. count initial 128 maybe "128" and on checked changes to "129" with layered numbers. .likes-count has two spans stacked, .old and .new, transition transform and opacity. checked old moves up -20 opacity 0 new comes from 20. Could do <span class="count-prev">2,418</span><span class="count-next">2,419</span> but initial new hidden. CSS for .count-next display. Add tiny "LIKES" on bottom. This is nice but could distract.
10. card border glow and slight rotation on checked .post animation card-celebrate 850ms ease; @keyframes 0% rotate 0 translate 0; 15% rotate(-1.2deg) translateY(-6px); 30% rotate(1.2deg) translateY(-3); etc ends 0. Use transform-origin center.
11. Confetti overhead at top of card maybe screen wide? Could have .confetti-rain in .app absolute? Additional particles enough.
12. little floating background hearts in margins always visible with slow float, pure CSS animations. 6 .float-heart at positions around app, opacity .12, font size 28 etc. They animate translateY -24 rotate 8 infinite alternate. Will be visible first paint and add atmosphere.
13. "Click or press a key to start" instruction? Developer says if demo uses keyboard display clear "Click or press a key to start" message. It is checkbox, keyboard used. Need display exact phrase perhaps bottom hint "Click the heart or press Space to start". But since first paint screenshot after 3 seconds, something active. We can put button hint "Click the heart · or press Space". Input is focusable, space toggles. Include .keyboard-tip below or within footer. This satisfies. But user didn't request start game, not game, nonetheless clear instruction "Click the heart or press Space to start". Good.
Need ensure focus ring clear. The hidden input is position fixed? .like-input { position:absolute; opacity:0; width:1px; height:1px; } to avoid overflow. Focus-visible ~ .post .like-button outline 3px solid #7656ff; outline-offset 6px. Native checkbox via label toggles. On pressing space browser will toggle focused checkbox and fire click. Yes.
Pure CSS no JS at all. We should avoid <script>. Include no external fonts/images. Use inline styles only CSS. The full HTML includes meta, title, style.
Visual aesthetics more deliberate:
Background #0d0b1b with radial gradients violet top left and coral bottom right. Main centered over backdrop with glowing orb blurred CSS. App maxwidth 720 and padding 48 24. .eyebrow small uppercase letter spacing .22em with pink dot. h1 using clamp(2.6rem,6vw,4.4rem), line-height 1.04, letterspacing -.06em, color #fff7f5; em gradient text "big feelings." Need h1 actual "Small click.<br><span>Big feelings.</span>" font-weight 850. Background soft grain via CSS repeating radial gradient? Avoid data URI. .backdrop::before background-image radial-gradient(rgba(255,255,255,.06) 1px, transparent 1px); background-size 24px 24px; opacity .24; pointer-events none; mask-image linear-gradient(to bottom,black,transparent 80%). This adds texture.
Header .eyebrow. Main h1 64. Card .post width min(100%, 580px) background rgba(31,25,54,.72) backdrop-filter blur(24px) but if browser supports yes; border 1px solid rgba(255,255,255,.14); border-radius 32; padding 32 32 26; box-shadow 0 30px 90px rgba(0,0,0,.4), inset 0 1px rgba(255,255,255,.1). .post-top includes avatar gradient heart, copy, tag "LIVE". Post top margins 24. Reaction area height 240 display grid place-items center; relative isolation? If isolation isolate particles behind? We want .post-top z1, .reaction-area z2. button z5; particles z8. Set .post-top position relative z-index 3. .reaction-area position relative height 240. button z5.
Button .like-button width 244 height 84 border radius 999; background rgba(255,255,255,.08); border 1px solid rgba(255,255,255,.19); color #fff; display flex center gap 14; font-size 18 weight 700; cursor pointer; user-select none; box-shadow 0 10px 28px rgba(0,0,0,.22), inset 0 1px rgba(255,255,255,.12); transition .3s cubic-bezier etc; -webkit-tap-highlight-color transparent; position relative; overflow visible. Icon .heart-wrap width 54 h 54 display grid center border-radius 50 background rgba white .07; font-size 29 color #ff638d; transition .35. .heart-wrap has pseudo glow. button text flex column? "Like" text 19, "a little good" small 10 uppercase letterspacing. Maybe button contains <span class="heart-wrap"><span class="heart">♥</span></span><span class="button-copy"><span class="label-default">Like</span><span class="label-liked">Liked</span><span class="button-sub">Send a little love</span></span><span class="count"><span class="old">12.8k</span><span class="new">12.9k</span></span>. 244 width maybe cramped. Better width 300 height 90. .heart-wrap 58; copy width 90; count margin-left auto margin-right 22; count font 15 .sub likes font 9. On mobile button width min(280,100%), count display none? Could maintain 280 fits card inner width ~280 for 375 with app padding 16 and card padding 20 -> width 303; button 280. fine. At 375 .post padding 22 -> inner 307, button width 280. Good. h1 clamp etc.
Button after initial heart should bright and inviting. .heart-wrap background radial-gradient(circle at 30% 20%,rgba(255,146,169,.4),rgba(255,84,132,.1)); box-shadow inset 0 0 0 1px rgba(255,137,171,.28),0 0 24 rgba(255,77,129,.18). Heart itself inline text. On checked gradient button background linear-gradient(115deg,#ff527f,#ff7a59,#bd65f4); border-color rgba 255 etc; box shadow 0 14px 40 rgba(255,79,123,.4),0 0 0 7px rgba(255,105,151,.08),0 0 80 rgba(255,105,151,.25). Then transform. .heart-wrap background rgba(255,255,255,.24), color white; .heart animation heart-pop.
`.like-button:active` transform translateY(1px) scale(.98); checked transform overrides? :checked ~ .post .like-button specificity can include active via separate rules. Active during checked animation maybe ignored. fine.
Gradient animated shine using .like-button::before {content:"";position:absolute; inset:1px; border-radius:inherit; background:linear-gradient(105deg,transparent 25%,rgba255 .5 45%,transparent 65%); transform:translateX(-120%); pointer-events none; z-index 3} checked animation shine 900ms 120ms. But the text z-index? set children position relative z-index 2.
Could have gradient button background via .like-button itself checked. Animated shine .like-button::before as transparent. Nice.
.love-word z-index 20. Need allow width no wrap. font-size clamp(2.3rem,7vw,4.8rem) font-weight 1000; letter-spacing -.04em; background linear gradient; background-clip text; color transparent; text-shadow no if transparent; filter drop-shadow. animation.
Caption initial "Click to unleash the good vibes." after "Pure CSS. Maximum serotonin." .caption height 24 and relative. .caption span position absolute. .after gradient. We could just keep both.
Post footer border-top rgba white .1; padding-top 18; display flex space-between. left has .tiny-heart within bubble "No JavaScript was harmed." right keycap with "SPACE" and "or click the heart". Or .tip with icon pointer "Click or press a key to start". Developer wants phrase. Use <p class="hint"><span class="mouse-icon"></span>Click or press a key to start</p> and right .code-chip>CSS ONLY</code-chip. Maybe phrase appears near button. Better below reaction area, centered .hint "Click or press a key to start" with small mouse icon and <kbd>Space</kbd> optional. That is clear. "Click or press a key to start" exact, underlined? Include small `.start-hint`. First screenshot shows.
Need not require user click to reveal content. All visible.
Potential issue checked state counters .new initially display block but hidden via transform; count container height 22 position relative width 42; .old,.new position absolute right 0. .old transition transform .4, opacity .4; .new opacity 0 transform translateY(100%). checked old translateY(-100%) opacity 0; new translateY(0) opacity 1. Count no jumping. "12.8K" initial. The .like-button copy label `.label-liked` absolute? easiest .button-copy position relative display flex flex-direction column; .label-stack position relative height 28; .label-default and .label-liked absolute top 0 left 0 transition; checked .default opacity 0 transform translateY(-12), .liked opacity 1 transform 0. .button-sub margin-top 2. .button-copy align-items flex-start.
Text overlay maybe count only initial 2,418 then 2,419 more credible; count width 44.
Particles:
HTML in .reaction-area:
<div class="ripple r1"></div> x3
<div class="burst" aria-hidden="true">
<i class="particle heart-particle" style="--x:-200px; --y:-180px; --turn:-320deg; --delay:20ms; --color:#ff6b9e"><span>♥</span></i>
... 12
<i class="particle confetti" style="--x:-..."></i> etc
</div>
<div class="love-word" aria-hidden="true">WOW!</div> maybe "LOVE!" uppercase. .love-word animation checked only.
<label ...>...</label>
<div class=caption> ...</div>
<div class=mini-stars>... ambient</div>
Could reduce markup by using .particle i nth-child styles instead of inline values? 20 lines each style is acceptable ~3k tokens. We can assign via CSS nth-child to custom props, ~100 lines. Inline easier readable but full final maybe 8-10k tokens. We have budget plenty but response should fit. We want excellent visual. We can do 18 particles using `<i style="--x:-190px;--y:-160px;--d:0ms;--r:-240deg;--c:#ff668d"></i>` with pseudo content based on .particle:nth-child(3n) hearts, 3n+2 confetti etc. All are spans. CSS `.particle::before {content:"♥";... color var(--c)}` .particle:nth-child(3n+2)::before {content:"";width:7px;height:17px;background:var(--c);border-radius:2px;} .particle:nth-child(4n)::before {content:"";width:9px;height:9px;border-radius:50%;background:var(--c);box-shadow...}. This reduces nested spans. 24 particles; custom --x --y --d --r --c.
Need variety: set --scale .7 to 1.3 as well. .particle width 0 height 0 position absolute left 50% top 50%; transform origin center; z-index 12; opacity 0; pointer events none. ::before position absolute transform translate(-50%,-50%); font-size calc(22px*var(--s)); line-height 1; etc. On checked animation particleFly 1.15s cubic-bezier(.12,.75,.25,1) var(--d) forwards. But `animation` shorthand delay with variable works `animation: particle-fly 1.15s cubic-bezier(...) var(--d) both;` Setting both retains backwards 0 before delay, good. At end opacity0. Keyframes:
0% {opacity:0; transform:translate(-50%,-50%) scale(.2) rotate(0deg)}
15% {opacity:1}
65% {opacity:1}
100% {opacity:0;transform:translate(calc(-50% + var(--x) * var(--distance)),calc(-50% + var(--y)*var(--distance))) rotate(var(--r)) scale(.65)}
CSS calc var(--x) * var(--distance) = dimension multiplication length*number supported modern CSS calc yes. `calc(-50% + var(--x) * var(--distance))` valid. --distance global .particle {--distance:1}. media set .particle {--distance:.65}. But x coordinates origin x values ±200 while actual button center in reaction-area; mobile reaction-area width 307, so max 200*.65=130 good. y -160*.65=-104 plus starts at 50% height 240=120 gives 16px; top of reaction area (post-top below) so love word overlaps header maybe z but fine. Some y -220*.65=-143 => -23 above area, into post header slight okay. Desktop y -220 => -100 above area, into header. Could increase reaction-area height 260, top=130, max -230 -> -100. Heading post-top y30; still particle reaches header but dramatic. Fine. No overflow hidden.
Global background floating confetti hearts always? .ambient-heart positions absolute within .app? If within app main, might interfere. Use body::before/after content "♥" huge blurred? CSS fixed .bg-heart left 8vw top 22vh font-size 150 color rgba pink .08 animation float; another right 11vw bottom 18vh rotate. Could use .bg-symbol one div and ::after. `.background-symbols {position:fixed;inset:0;pointer-events:none;overflow:hidden;z-index:0}` with .bheart absolute. Visual but no need.
We can add `.sparkles` around reaction area static tiny glowing dots at positions that pulse. Use 4 span. CSS animation twinkle 2.4s infinite alternate. Already background looks.
When checked card glow: `.post` transition border-color .4 box-shadow .4; checked border rgba(255,143,179,.4); box-shadow 0 30px 90px rgba..., 0 0 70px rgba(255,93,147,.16). Post animation celebrate. But transition box-shadow plus animation transform only no conflict. .post::before top gradient line animated? Could add .post::before position absolute top 0 left 20%; width 60 height 2 gradient. When checked animation shine-line 1s. But .post overflow hidden? It must not hide particles outside. Keep visible overflow. .post::before z10 pointer none. Fine.
Count status below .caption can be one. Main card top:
<div class="post-header">
<div class="avatar"><span>✦</span></div>
<div class="post-by"><strong>little things club</strong><span>posted a tiny moment of joy · now</span></div>
<span class="live-pill"><i></i> LIVE</span>
</div>
<div class="reaction-area">...</div>
<div class="post-bottom">
<div class="comment"><span class="comment-bubble">♥</span><span><b>You</b> made this feel a little better.</span></div>
<span class="no-js"><i></i> 0 lines of JS</span>
</div>
</section>
Maybe extra header is superfluous but polished. Do not display emoji comment? Use CSS bubble outline heart small. Unicode hearts all okay. .comment-bubble border 1 color etc. "You made this feel a little better." appears initial before clicked, odd. Use "Good vibes are free to share." then checked change text? Could two spans .before "A small gesture for a big day." .after "You just made their day." Show switching. Adds satisfying click result. CSS same stack technique. .post-bottom on checked border pink. Use comment bubble filled pink when checked.
We can reduce complexity to ensure high fidelity. Button screenshot central, card large dark gradient, headline warm. I'd like light background to be visually fresh and not generic dark. Maybe reference modern tactile design, creamy white page with coral gradient and lavender purple accents. In dark, bright saturated button works. User asked "crazy" can neon. A playful polished palette: deep plum #130d24, fuchsia #ff4d8d, tangerine #ff9160, lilac #bb85ff, cream #fff4ee. Main headline "Like it.<br><em>Love what happens.</em>". button gradient fuchsia tangerine. Good.
Use CSS `font-family: ui-rounded, "SF Pro Rounded", "Segoe UI", system-ui, -apple-system, sans-serif`. Font weight 850 might fallback but okay. h1 letter spacing -.06em.
Background body:
background:
radial-gradient(ellipse at 16% 10%,rgba(128,77,255,.26),transparent 42%),
radial-gradient(ellipse at 86% 78%,rgba(255,92,125,.21),transparent 40%),
linear-gradient(145deg,#120e23 0%,#19122e 50%,#100c1e 100%);
min-height:100svh;
overflow-x:hidden.
body::before grid pattern opacity .3. body::after big blurred orange orb maybe but background already.
Top eyebrow align center. .app padding 38px 24px 32px; min-height 100vh display flex column align center justify center gap 24. To fit screenshot 800: eyebrow 14+ margin 20; h1 2 lines font 64 line 1.04 =133; intro 24+margin 16; card height 360; hint 22; gaps ~80 total ~720 fits. h1 maybe one line? "Like it. Love what happens." could one line at desktop 72 ~850 wide; max 760 wraps intentionally. Two lines nice. Card header 60 + reaction 210 + footer 50 + padding 60 =380. Total 14+16+130+14+24+16+380+18+24=736. fits 800. .app justify-content:center; if content >800 mobile vertical scroll acceptable no horizontal scrollbar. Mobile h1 42 two lines 88; card maybe 350, total 600 fits 800. Good.
Heading:
<p class="eyebrow"><span class="eyebrow-star">✦</span> NO JAVASCRIPT. JUST FEELINGS.</p>
<h1>Like it.<br><span class="gradient-text">Love what happens.</span></h1>
<p class="lede">One click is all it takes to make the internet<br class="desktop-break"> a little brighter.</p>
At mobile br maybe display none? Fine.
.card width:min(100%,580px). .card padding 26px 28px 24. Card top 58 high. reaction area 236. card footer 54. total 26+58+20gap? reaction 236+24footer+24 =368 plus border. Good.
Reaction-area margin 18px 0 10. Button centered. caption margin-top 16. Actual button 88. ambient ring absolute 160x160 center; border dashed? .aura {position:absolute;width 178;height 178;border-radius 50%;background:radial-gradient(circle,rgba(255,93,148,.09),transparent 68%); border 1px dashed rgba(255,159,187,.16); animation spin 28s linear infinite;} spin ring slowly, nice first paint. .aura::before maybe second dotted ring. Add `transform` on checked? animation spin sets transform; aura remains. .aura z0.
Button z4.
Particles z10.
Love-word z15 top maybe -2 centered; animation translateY -96 -> top -90 maybe into header. Could set top 40%? Reaction top? Button center y118. .love-word top:44px (button center), initially translateY(35) then up -100 => y -56 from reaction area -> header. Visual dramatic. Better text starts at button top y70? "LOVE!" above button, on click flies up and fades. Use top:42px; 0 opacity, transform translate(-50%,35px) scale(.5); 25% opacity 1 translate(-50%,-14px) scale(1.1); 100% opacity 0 translate(-50%,-90px) scale(.9). At 25 top 28px, within reaction area, good.
caption bottom maybe absolute bottom 0, label etc. Reaction area height 242, button center around118. caption at bottom 8.
Ambient floating mini confetti static? .twinkle positioned around card, tiny star elements. Use `<span class="twinkle t1">✦</span>` etc. Colors. animation twinkle 2s infinite ease-in-out alternate. On checked animation faster? `checked ~ .post .twinkle {animation-duration:.8s}`. Fine.
After unchecked, word resets and particles disappear, button resets. Label changed. Good.
Input is inside main before article; CSS selectors:
#like-toggle:checked ~ .app .post { ... } input and .app siblings yes if input direct body child then .app sibling. If input inside .app, `#like-toggle:checked ~ .post` works if post sibling. Best body `<input class="like-toggle" type="checkbox" id="like-toggle"><main class="app">...</main>`. Selector body `#like-toggle:checked ~ .app .post`. Fine. All input sibling to .app.
Focus-visible: `#like-toggle:focus-visible ~ .app .like-button { outline: 3px solid #ffe27a; outline-offset: 6px; }`. Input opacity 0 position absolute left 50% top 50% maybe screen reader focus fine. use `clip-path:inset(50%)` but focus still. .like-toggle {position:fixed; width:1px;height:1px;opacity:0;pointer-events:none;} pointer events none doesn't prevent keyboard focus by tab still yes. Native hidden via position absolute left:-10000; focus style then no visible input. use `.sr-only` standard clip path, width 1 height 1 overflow hidden; white-space nowrap. Focus label ring.
Need clicking label text doesn't select: user-select none. Input id label htmlFor. <label class="like-button" for="like-toggle">.
Pressed state semantics accessible screen reader input automatically checked. Could add <span class="sr-only">Like this moment</span> inside label? label's accessible name includes text Like, Send a little love, 12.8K likes etc, input aria-label "Like this moment". Set input aria-label. `aria-describedby="start-hint"`. Great.
Count changes "12.8k" vs "12.9k" but since count static 2,418 then 2,419 maybe best social proof. Use .old 2.4K, .new 2.5K. Button width 300; copy label about 80; count width 46. Good.
Button initial text "Like" and sub "A LITTLE GOOD". On checked "Liked" and "BIG GOOD ENERGY". .button-sub two spans? Could change via opacity. .sub-default, .sub-liked stack. height 12.
Maybe label position transitions. The "Like" label initially white; checked white. The heart wrap pink outline. Button initial background #fff? On dark card use white-ish button, like a physical floating button. Initial .like-button background linear-gradient(135deg,#fff8f3,#ffe4ec) color #27162d; heart circle gradient. On checked gradient fuchsia-orange color white. This contrast shift dramatic. Does like initial dark text easier. Button initial design tactile with white light. Sub dark muted. Count dark. On checked text white. Need style .button-copy color inherit; .sub opacity .56. Count inherits. Heart background pink-tint. Like text font 20. Great.
Initial button shape pill 292x84 box-shadow 0 12px 30 rgba(0,0,0,.28), 0 2px 0 rgba(0,0,0,.1). Checked box shadow colored. .like-button::before shine over. Border initial rgba white .8. .heart-wrap background rgba(255,84,128,.11), border1 rgba255 .25; checked bg white .22.
Particle colors. We can make many:
1 (-200,-170) fuchsia
2 (-150,-240) orange
3 (-80,-215) lavender
4 (40,-245) pink
5 (130,-215) orange
6 (205,-155) lavender
7 (238,-55) pink
8 (225,45) orange
9 (155,135) fuchsia
10 (85,185) yellow
11 (-25,220) lavender
12 (-125,180) pink
13 (-225,80) orange
14 (-175,-35) yellow
15 (155,-80) yellow
16 (0,-175) cyan? add mint #75e6d0 for variety
17 (-260,0) lavender
18 (255,110) pink
Then confetti lower similar with delay. Need use top origin at center. Purple and mint palette.
i .particle::before heart shape if nth-child(4n+1) or 4n+2; for others rectangles/circles. Could define class .heart-p explicitly but nth rules fine. Use 24.
CSS:
.particle::before {content:""; display:block; width:8px;height:18px;background:var(--c);border-radius:3px;box-shadow:0 0 12px var(--c);}
.particle:nth-child(3n)::before {content:"♥"; width:auto;height:auto;background:none;box-shadow:none;font:900 24px/1 Arial,sans-serif;color:var(--c);}
.particle:nth-child(4n)::before {width:10px;height:10px;border-radius:50%;}
Maybe nth-child 3n and 4n overlaps at 12 gives circle but hearts rule specificity same and order circle after wins. fine.
Each .particle --s set maybe default 1, some .particle:nth-child(3n) font-size calc(22px*var(--s)). Style inline --s:.8. Could omit.
.particle {animation-play-state?} default opacity 0.
Checked animation launches. After uncheck none.
Ripples .ripple border-color; .r2 border dashed maybe; .r3 solid white. animation ring 950ms ease-out delay. Checked .ripple.r1 etc. Need check selector.
`#like-toggle:checked ~ .app .ripple { animation: ripple 1000ms cubic-bezier(.16,.75,.3,1) var(--delay) both; }`
At 0 opacity 0 transform translate(-50%,-50%) scale(.2); 20% opacity .8; 100% opacity 0 scale(3.7). r3 delay 200. ring max 370px in reaction area width 524, fits. Mobile width 307 ring 370 overflows post but not viewport (center x153 +/-185 = -32 to 338, slight offscreen 32; page overflow x hidden, no horizontal scrollbar. fine). Could media reduce scale to 2.8 via different keyframe ripple-small or scale factor var(--ring-scale) set 1 desktop .65 mobile. `transform:translate(-50%,-50%) scale(calc(.2 + 3.5 * var(--ring-scale)))` keyframe calc maybe okay; simpler use custom --ring-scale: .68 mobile and keyframes scale(calc(3.5 * var(--ring-scale))) but interpolation at 20% not smooth? define transform scale(calc(.2 + var(--ring-scale)*3.5)) at 100%; calc multiplication numbers supported. fine. Or fixed 3.1 ring size 310 fits width 307 almost exactly, okay. Use 3.4 and overflow hidden body. particle left etc.
Post animation card bounce might conflict with .post transform none initial. `animation: card-celebrate .9s ease-out both;` final transform translateY(0) rotate(0). It may override transition none. After animation ends fill both keeps final. Checked remains transform none. When unchecked reset.
@keyframes card-celebrate {0%{transform:translateY(0) rotate(0)}18%{transform:translateY(-8px) rotate(-1.1deg) scale(1.012)}35%{transform:translateY(-3px) rotate(.8deg)}55%{transform:translateY(-6px) rotate(-.4deg)}75%{transform:translateY(-2px) rotate(.2deg)}100%{transform:translateY(0) rotate(0)}}
Maybe animation applies to card while particles positions relative unaffected? It transforms parent, all follows, nice.
Button checked animation: use `animation: button-celebrate .85s cubic-bezier(.2,.9,.3,1.2) both;` keyframes 0 scale 1; 20% translateY(-6) scale(1.07) rotate(-1.5deg); 40% translateY(-2) scale(.98) rotate(.8); 60% translateY(-5) scale(1.03) rotate(-.5); 100% translateY(0) scale(1.02). Then .like-button transition? Transform defined checked rules and animation both, animation wins until end, fill both maintains scale1.02. Good. Heart animation on checked infinite `.72s ease-in-out infinite` but as soon checked .heart pop first and beat. Use heart-beat keyframes 0,100 transform scale 1 rotate(-2deg); 25% scale 1.25 rotate(6deg);50% scale .92 rotate(-7deg);75% scale 1.14 rotate(4deg). .heart-wrap pulse? .heart-wrap checked animation ring? Use .heart-wrap background etc transition. .heart always animation.
Maybe "crazy" include screen-wide ray flash .flash position fixed inset 0 background radial-gradient(circle at 50% 50%,rgba(255,125,170,.24),transparent 35%); opacity 0 pointer events none z-index 50. On checked animation flash .65s forwards. It overlays briefly and softens, not obnoxious. At 3s screenshot clicked? Screenshot won't click so no. User interaction tests likely click. Need ensure animation visually shows on click. Add .flash with mix-blend-mode screen maybe. CSS `:checked ~ .app .flash` but flash inside app. position:fixed. z-index 100. Keyframes 0 opacity 0,20% opacity 1,100% 0. User will see burst.
No JS code. Do we need a toggle to reset? Clicking again unlikes resets, but if user wants replay must click twice. Typical like toggles. Crazy animation only on check; fine. Could maybe animate on unchecked too small collapse. CSS `not(:checked)` can't detect transition from checked to unchecked to re-run aside? You can add .heart-wrap animation only checked. Uncheck will reset. Fine.
Maybe initial ambient animations make first screenshot feel alive. Good.
We should maybe show a tiny CSS-only "code" tag with braces. Footer `span class=zero-js><span class=code-braces>{ }</span> zero JavaScript</span>`.
Footer comment on checked "You just made their day." text. Use two spans with display:block; height. Before and after absolute? .comment-text position relative height 20; .comment-default .comment-liked absolute inset; checked toggles. Like button count. .comment-bubble transition fill.
Detailed CSS structure:
:root variables
* box-sizing
html,body margin; min-height; font
body ...
body::before for grid
.background-heart fixed...
.app ...
.eyebrow...
h1...
.gradient-text
.lede
.post ...
.post::before top rainbow line
.post-header
.avatar
.post-id
.live-pill
.reaction-area
.aura
.aura::after
.twinkle
.like-button
.like-button::before
.button-copy
.label-stack
.label-default/label-liked
.sub-stack
.sub
.count
.count-value
.old/new
.heart-wrap
.heart
.caption
.caption-stack
.caption-before/after
.love-word
.ripple
.burst
.particle
.post-footer
.comment
.comment-bubble
.comment-text
.comment-liked
.zero-js
.start-hint
.mouse-icon / kbd
@keyframes.
Need prevent .post::before conflict with .like-button::before no.
Gradient text for headline:
background:linear-gradient(90deg,#ff87ad 0%,#ffad7a 45%,#c298ff 95%);
background-clip:text; -webkit-text-fill-color:transparent; filter:drop-shadow(0 0 30 rgba...). h1 span display inline-block.
Heading may fit .app max-width 860? h1 .gradient text length "Love what happens." at 64 about 600. max-width 820. card 580. Good.
.card header display flex gap 12 align center. avatar 44 circle background gradient purple pink; `box-shadow:0 0 0 5px rgba(255,255,255,.04)` .avatar icon maybe "✦" 20. live-pill font 9 uppercase letter spacing .16 background rgba white .08 border etc. dot pulse.
Reaction area height 236; button at center. With flex center vertical button and caption absolute bottom. .like-button position absolute? Use grid place-items center. `.reaction-area{display:grid;place-items:center}` then .like-button. caption absolute bottom 0. .aura absolute left 50% top 47% transform translate(-50%,-50%) but keyframe spin would override transform. Define aura animation aura-turn 30s linear infinite; keyframes from transform translate(-50%,-50%) rotate(0) to translate...rotate360. good. .aura::after border etc maybe animation reverse? okay.
.twinkle absolute; top etc; font-size 18; color pink; animation twinkle 2.4s ease-in-out infinite alternate; uses transform rotate.
.love-word absolute top 32? center x. initial hidden via opacity 0 and not animation. when checked animation word-burst 1.35s cubic-bezier(.2,.7,.2,1) .1s both. The animation fill both before delay initial opacity 0. End opacity 0. z-index 12.
.ripple absolute left 50% top 45% width 116 height 116 border 2 solid; border radius 50%; transform translate(-50%,-50%) scale(.2); opacity 0; z1; pointer. On checked animation. r2 width 96 border dashed etc.
.burst z-index 7. .particle positions left 50% top 45%. If top45% of 236=106 vs button center 118 (grid center). Use top 50% 118. good. Reaction area center button at 118, caption bottom 0 y214. Good.
Button z5. Aura z0. Particles z8.
.love-word z10.
At click particles can cover button text; they start center opacity 0 then scale out, no issue. Heart glyph particles move. z8 over text but transient.
Button .heart-wrap font-size 34; heart glyph has possible baseline but display grid center. Use `.heart {display:block; line-height:1; transform-origin:center;}` unicode ♥.
Heart glyph in initial button colored #ff4f89. With Arial Black shape narrower; font-family Arial,sans-serif; font-weight:900. Could use `font-size:35px; line-height:1;`. Good.
Button .count "2.4k" width 44 font 14 weight 750. .count label "LIKES" 9. In stack transition. .count-value height 18. .count-old .count-new absolute. Need preserve label. .count {display:flex;flex-direction:column;align-items:flex-end; padding-right:3px}. .count-value {position:relative;width:44px;height:18px}. .count-old,.count-new {position:absolute;right:0;top:0;transition:transform .45s cubic-bezier(.2,.9,.3,1.2),opacity .3s}. checked new etc. LIKES text initial opacity .56.
.label-stack width 80 height 28; .label absolute top 0; font-size 21 font-weight 800. Liked text might overflow width 80 okay. .sub-stack height 14; .sub absolute top 0; white-space nowrap; font-size 9; letter spacing .13em; font-weight 750. initial "A LITTLE GOOD"; checked "BIG GOOD ENERGY". .sub font 8.8.
Button width 300 display grid grid-template-columns 58px 1fr 44px; gap 13; padding 12px 17px 12px 13px; height 88. 58+13+1fr~136? 300 -34 padding -58 -26 -44=138. Good. Text copy aligned left. On 375 inner card maybe 295, button width 280 => copy 118. good.
.card border radius 32, padding 24 26. @media max-width 520 card padding 22 18, radius 26. button width 100%, max-width 300. Heading 44. Post-footer gap etc. mobile hide .live-pill? keep. .post-by small line text length maybe 200 fits with live; card inner 303: avatar 40 +gap 10+copy~190+live 45 =285 fits. Fine. .post-header gap 10; post-by strong font 13; small 10.5. .live-pill 40.
Initial background float hearts:
<div class="background-symbols" aria-hidden><span>♥</span><span>✦</span><span>♥</span></div>
CSS first left 7vw top 16%; font 140 color rgba255 .055; second right 9vw top 25% size 52 purple .13; third left 13vw bottom 10% size 80 orange .06. anim float. On mobile reduce opacity and positions might cause horizontal overflow hidden. Good.
First screenshot dark background, heading, card. Nice.
Maybe include a small arrow pointing to heart? Not needed.
We should ensure all CSS animations have initial values so static first screenshot polished. Button hover:
@media (hover:hover) .like-button:hover { transform:translateY(-4px); box-shadow..., } checked animation/transform conflict with hover if checked: checked rule appears later with same specificity? Selector ID checked more specificity overrides hover; animation controls anyway. Initial hover nice.
`.like-button:hover .heart {transform:scale(1.08) rotate(-5deg)}` but heart animation when checked more specificity? ID checked selector .heart wins.
Input focus outline works.
"Click or press a key to start" message exact can be under card with mouse SVG? Use CSS mouse:
<span class="mouse-icon" aria-hidden="true"><i></i></span> CSS 15x21 border 1.5 solid, border-radius 8; ::after? .mouse-icon i width 2 h4 top 3 left 50% background pink animation scroll 1.8s infinite.
Text `Click or press a key to start` and `<kbd>Space</kbd>` maybe says press a key; space hint. Layout flex.
But screenshot shows this message clearly. Good. Maybe not put "start" because button is not game but fine. It helps user.
Hint opacity .72.
Header eyebrow text includes "PURE CSS · ZERO JAVASCRIPT" and star. That reinforces.
No `<script>` whatsoever.
Need output exactly one fenced code block with html. Final answer no text. We can produce complete file around 650 lines? Desired enough. We can compact CSS but maintain readability. Since user asks pure CSS, ensure no JS. The actual file only HTML/CSS.
Potential hidden issue CSS `font-weight:850` supported variable fallback maps maybe fine.
`backdrop-filter` no issue. `background-clip:text` -webkit support.
`overflow-x:hidden` on body and html.
`min-height:100vh` plus `100svh` maybe set min-height:100svh supported Chrome. body min-height:100vh. .app min-height:100svh; fallback min-height:100vh first.
Focus input `.sr-only` clip; label focus via sibling.
Space key toggles checkbox: browser default Space toggles checkbox yes, Enter not usually toggles? Space enough. Instruction generic.
Clicking on label toggles input and fires CSS checked.
Would a CSS-only check state count as JavaScript? no.
Let's think if need pure CSS "crazy animation" perhaps we could animate continuously upon clicking using checkbox. User expects when click, one crazy animation. We have big burst + heart beat + bounce + rings + word + shine. Excellent.
We could add an enormous "POP!" word rather than LOVE! because LOve may be too subtle. "LOVE!" with gradient and outlines stands out. Keyframes rotate and scale. Maybe "YESS!" or "LOVE!" chosen.
We can add one "sparkle" .love-word::after content "✦"; animate? static near. .love-word text-shadow multiple offset colored. Use gradient clip. .love-word::after position absolute right -28 top -20 font-size 40 color #ffd166; content:"✦"; transform rotate(18deg). Since opacity of parent animates. Looks fun. ::before content "♥" left -32 bottom -8 font-size 28 pink. That adds extras.
Need ensure animation text not hidden behind .post-header; z-index 20 but parent reaction area no z-index? .post-header z3, .reaction-area z4 creates stacking above header, so word above. .reaction-area position relative z-index 4. Good. Particle z8 within reaction z4 still above header z3. .post::before top line z? 10 might overlay only line. .flash inside app fixed z100 but .app might have transform? no, no transform. position fixed viewport. .flash background radial at center button approximated 50% 56%; opacity 0. `pointer-events:none`.
Input z irrelevant.
Animation card transform creates stacking context; .flash within app but outside post? .app no transform. post animation transform makes particles follow card. fine.
Potential .post::before shine animation on checked but if overflow visible it may show top line 65% width. `left:18%;right:18%;top:-1px;height:2px;background:linear-gradient(...);opacity:.4;transform:scaleX(.3);` checked animation line-shine .9s. It stays opacity? keyframes 0 opacity .3 transform scaleX .2,50 opacity 1 scaleX1,100 opacity .4. Good.
We can add top line glow.
CSS order checked selectors grouped:
#like-toggle:checked ~ .app .post {...}
#like-toggle:checked ~ .app .like-button {...}
#like-toggle:checked ~ .app .heart {...}
#like-toggle:checked ~ .app .label-default {...}
...
Particles etc.
No need add class `.is-liked` because no JS.
Use inline CSS vars in styles: `--x:-210px; --y:-165px; --delay:0ms; --turn:-260deg; --color:#ff6f9d;` values valid.
Particle keyframes final transform:
`transform: translate(calc(-50% + var(--x)), calc(-50% + var(--y))) rotate(var(--turn)) scale(.55);`
At start transform translate(-50%,-50%) scale(.15). This means particle origin at parent's 50% top 50%, and ::before centered. After translate calc(-50% + x) uses own width zero (i width 0), so -50% zero; pseudo own centering handles. Position is exactly center plus x. good.
We don't need distance scaling if custom x within ±210; mobile with max ±210 on card 303, extends 58 beyond each side but body overflow hidden (so clipped at viewport x~375? card center 187, x -210 = -23, so clipped left, not ideal but looks burst clipped. We can reduce via CSS --spread .64 mobile and final calc var(--x)*var(--spread). Calc `var(--x) * var(--spread)` valid multiplication in CSS Values Level 4? Wait CSS calc multiplication `*` is not widely supported! Traditional CSS calc supports + - * /? CSS calc() historically supports + - * /? Let's recall CSS calc Level 3 grammar: calc-sum -> calc-product [ [ '+' | '-' ] calc-product ]*, calc-product -> calc-value [ '*' | '/' ] calc-value ]*. Yes calc supports multiplication by number? Actually CSS calc() supports +, -, *, / with at least one operand number. Widely yes modern Chrome supports calc(100px * .5)? I think CSS calc supports *? Historically calc supports + - * / yes e.g width: calc(100% / 3). Multiplication e.g calc(10px * 2) is supported? MDN says operators + - * / are supported, but at least one side number. Yes fine. Use `calc(var(--x) * var(--spread))`. Alternatively set --x via `--dx` values already responsive by media override all not needed. Could use transform `translate(calc(-50% + var(--x)),calc(-50% + var(--y))) scale(calc(.55 * var(--spread)))` but x scaling use multiplication. Fine.
Set .particle {--spread:1} @media max-width 520 {--spread:.72}. y too .72 makes less vertical dramatic but card size. Could use --spread-x .7 --spread-y .9 but unnecessary.
Particle keyframes at 65% transform? Animation interpolation between start and final will follow linear-ish with cubic-bezier resulting curved path. Could add 35% transform translate(calc(-50% + var(--x)*.22), calc(-50% + var(--y)*.58)) scale(1) to create upward arc; final outward downward. This adds drama. Keyframes:
0% opacity0 transform translate(-50%,-50%) scale(.1) rotate(0)
12% opacity1
38% opacity1 transform translate(calc(-50% + var(--x)*.22), calc(-50% + var(--y)*.72)) scale(1.15) rotate(calc(var(--turn)*.35))
72% opacity1 transform translate(calc(-50% + var(--x)*.76), calc(-50% + var(--y)*.86)) scale(.95) rotate(calc(var(--turn)*.72))
100% opacity0 transform translate(calc(-50% + var(--x)*var(--spread)), calc(-50% + var(--y)*var(--spread))) rotate(var(--turn)) scale(.55)
Need calc(var(--turn) * .35) rotation of deg number works. Works. But keyframes interpolation transform lists consistent. yes.
Animation duration 1.15s plus delay up to 160ms. Full crazy lasts 1.5 sec. Heart beat continuous. Word 1.3 sec.
Sparkles .twinkle static in reaction positions e.g left 12% top 24%; right 15% top 14%; left 21% bottom 18%; right 7% bottom 30%. .twinkle nth color.
Footer comment and zero-js on mobile column? `.post-footer {display:flex;align-items:center;justify-content:space-between;gap:12px}` .comment display flex min-width 0; .comment-text font 11.5; .zero-js font 10; white-space nowrap. On 375 inner 303, comment ~205, zero-js 85 +gap =302 fits. Good. On tiny 320 inner maybe 260; comment wraps. media max 420 .post-footer flex-direction column align-items flex-start; .comment text. fine. min height 375 requirement only down 375; can keep column at 480 for nicer.
At 1280 app top content centered. .app justify-content:center; padding 38. If total content maybe 742, centered 29 top. Nice.
Let's compute card vertical: padding 26 top+24 bottom=50. header 46. reaction margin top 14 + height 236 + margin bottom? reaction margin:14px 0 6px =20. footer border + padding 18 + height 40=59. total 50+46+20+236+59=411. Heading area eyebrow 14 + margin 0? h1 margin 16 0 12 (64*1.04*2=133) + lede 22 +margin 0. Card margin-top 28. total 14+16+133+12+22+28+411+ hint margin 18+20=774. This may exceed 800 with padding 38*2=76 =>850! Need adjust. .app padding maybe 32 and total actual content 722. Let's recalc CSS likely:
.eyebrow margin 0 0 14; height 14
h1 font 64 line 1.04 2 lines=133; margin 0
.lede margin 14px 0 0; font 16 line 1.5=24
.post margin-top 26; height? 26+24 padding=50 +header 44 +reaction 236 + margins 12+6 +footer 19+42=61 =>403.
.hint margin-top 16; height 20.
Total 14+14+133+14+24+26+403+16+20=766. App padding 28 vertical =>822. At 800 overflow slight scroll, but screenshot viewport top maybe bottom clipped. Need lower: heading font 60 two=125, card reaction 210, header 44, margins 8+4, padding 22+20=42, footer 18+38=56 total 42+44+12+210+56=364. total 14+12+125+10+22+22+364+14+20=703 +padding 40=743 fits. Good. Desktop heading maybe clamp max 3.6rem=57.6, line 1.05=121. card width 580. Reaction height 224. Card 378. total ~710. Good.
We can set .app padding:32px 24px; .post margin-top:26. h1 clamp(2.5rem,5.5vw,3.75rem) ->60. .lede margin 10. Card reaction 226. Footer etc. Total 14+12+126+12+24+24+382+14+20=728 +64=792. borderline. Actual h1 line height 1.03 =>124. total 790. Fine. Could padding 24 gives 784. Use min-height 100svh and align center. If content > available browser overflows but no horizontal. Need first screenshot whole card likely. Could choose h1 max 3.4rem=54.4 ->112. card 365. total 14+12+112+12+24+24+365+14+20=697 +48=745. Nice. Heading still strong. At 1280 .app h1 54 might feel slightly small but card is focus. Use 3.7rem 59 and card 350. Reaction 205; card 42+44+10+205+54=355. total 14+12+124+12+24+24+355+14+20=699+48=747. Great. So .reaction-area height 216 maybe card 366 total 758. Good.
Set .app max-width 900. h1 clamp(2.6rem,5.4vw,3.7rem). card width 560? 580. reaction 220. card 26 top 24 bottom+44 header+12 margin+220+54 footer=380. total 14+12+124+12+24+26+380+16+20=728+48=776. fits exactly. Great. .app justify-content:center.
At mobile h1 2.4rem=38.4 line 1.07 ~82; card maybe 350; total 14+12+82+12+48+20+350+16+20+40=714, fits. good.
Maybe card title row live "PURE CSS" rather than "LIVE" because not live. Use tag "DEMO". Avatar "♥". Post text "little things club" / "A tiny reminder to be kind today". No emoji for avatar? Use white "♥" 19. okay.
Footer zero JS chip uses code icon { } not actual code content. CSS `.code-icon {font-family: ui-monospace;...}`. text "0 JS". maybe "ZERO JS" more clear. Header eyebrow already.
Post-footer comment default "A small gesture. A big day." after "You just made their day." Both fit.
Start hint after card. Use kbd "Space" creates extra width but phrase. <span>Click or press a key to start</span><kbd>Space</kbd>. On mobile can wrap. Good.
Potential strict user no JavaScript means even CSS checkbox toggles okay. File no script.
We should deliver final with code fence html. Need ensure code is complete and no extra. We can now draft final file.
Let's write CSS carefully. Start:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset UTF8>
<meta viewport>
<title>Pure CSS Like Button</title>
<style>
:root { color-scheme:dark; ...}
...
</style>
</head>
<body>
<input class="sr-only" ...>
<div class=background-symbols aria-hidden=true>...
<main class=app>
<section class=post aria-label="Like button demo">
<header ...>...
<div class=reaction-area>
<div class=aura aria-hidden=true></div>
<span class=twinkle...>✦</span>
...
<div class=ripples aria-hidden=true><span class=ripple r1>...
<div class=burst aria-hidden=true> 24 i
<div class=love-word aria-hidden=true>LOVE!</div>
<label class=like-button for=like-toggle>
<span class=heart-wrap><span class=heart>♥</span></span>
<span class=button-copy>...
<span class=count><span class=count-value>...
</label>
<div class=caption>...
</div>
</div>
<footer...
</section>
<p class=start-hint id=start-hint>...
<div class=flash aria-hidden=true></div>
</main>
</body>
</html>
Order caption should be after button but absolute bottom. The grid place center button. .caption absolute bottom:0; button center perhaps at110, caption at bottom. The reaction area 220, button 88 centered y66-154; caption bottom 0 y192-214. space 38. Good. Aura centered y110 190x190 extends15-205. Button covers. Twinkles around.
Love word top:32; when word at top 28 within reaction. okay.
Ripples top 50% y110.
Post header z3, reaction z4. caption z6.
Color count etc.
Checked selectors:
#like-toggle:checked ~ .app .like-button {
background: linear-gradient(115deg,#ff477e 0%,#ff6f75 44%,#ff9a5d 100%);
border-color:rgba...
color:#fff;
box-shadow...
animation: button-pop .85s cubic-bezier(...) both;
}
#like-toggle:checked ~ .app .like-button::before {animation: shine-sweep .95s .16s ease-out both;}
#like-toggle:checked ~ .app .heart {color:#fff; animation:heart-beat .62s ease-in-out infinite;}
#like-toggle:checked ~ .app .heart-wrap {background:rgba(255,255,255,.23);border-color:rgba(...);}
default heart color pink. Default .heart transition transform .25s.
.label...
.count...
.post animation
.comment bubble...
.caption...
.love-word...
.ripple...
.particle...
.twinkle animation-duration...
.flash animation...
.post::before animation.
Potential checked .like-button animation transform scale final and hover? no.
Default .like-button transform translateY(0); transition transform .3s. On hover translateY(-4px) scale(1.02). Focus ring.
When checked button-pop keyframes final scale1.035 translateY(-2). checked animation fill both. Good.
Flash animation .7s ease-out forwards opacity. radial at 50% 52%. It adds screenshot if click during animation.
Aura animation spin, .aura::before? maybe no.
Background-symbols span animations no JS.
Keyframes:
background-float
aura-turn
twinkle
button-pop
heart-beat
shine-sweep
word-burst
ripple-out
particle-flight
card-celebrate
flash-out
line-reveal.
Keyframe `shine-sweep`: from transform translateX(-160%) skewX(-20deg); 60% opacity 1; to translateX(160%) opacity 0. .like-button::before inset 1; background linear transparent white; `mix-blend-mode:overlay` maybe.
On default ::before opacity 0.
.love-word::after star.
Font big with drop-shadow.
Could maybe add shadow text around .love-word; background-clip transparent. `filter:drop-shadow(0 6px 0 rgba(95,28,80,.25)) drop-shadow(0 0 25px rgba(255,111,157,.45))`.
Word keyframes final opacity 0, filter remains but parent opacity.
.love-word color via background-clip. Good.
Particle color --color use. CSS nth:
.particle::before content:""; position:absolute; left:0;top:0; width:7px;height:16px; background:var(--color); border-radius:3px; transform:translate(-50%,-50%) rotate(18deg); box-shadow:0 0 12px var(--color);
.particle:nth-child(3n)::before {content:"♥"; width:auto;height:auto;background:none;box-shadow:none;font-family:Arial,sans-serif;font-size:24px;font-weight:900;line-height:1;transform:translate(-50%,-50%);}
.particle:nth-child(5n)::before {width:9px;height:9px;border-radius:50%;}
.particle:nth-child(4n+1)::before {transform:translate(-50%,-50%) rotate(-35deg);}
No span needed.
Particle animation final opacity 0. Delay inline.
Could add .particle:nth-child(odd) --scale .8 but custom not needed.
Ripple style width 120 height 120 border 2px solid rgba...; r2 width 100 border-style:dashed; r3 width 84 border white .5. Animations delay via classes? use style="--delay:0ms" etc. CSS each `.r2 {--delay:140ms;width:104px;}` `.r3{--delay:280ms;width:90px;}`. Keyframes scale 0.2->3.8. Border fades. Mobile ripple max 456 width, okay clipped body. Could use @media keyframe ripple-out-small same selector in media to scale 2.5; easier:
@media(max-width:520px){.ripple{...} .ripple animation name?}
`#like-toggle:checked ~ .app .ripple { animation: ripple-out .95s ...}` within media override animation-name: ripple-out-small; keyframes .95 0 transform scale(.15),100 scale(2.65). width 110*2.65=291 fits 307. Great.
Desktop 120*3.8=456 fits card 580. Nice.
Footer noJS pill includes .js-dot green? "ZERO JAVASCRIPT" chip with mint dot. The green dot could suggest JS? No, 0. Use tiny diamond. .zero-js color #9be5d0. border.
Start hint text and kbd; kbd background white .07 border .12 shadow inset. font 10.
Body::before grid uses position fixed inset 0 z-index 0 pointer none. .app z1. background symbols z0. main background? transparent. Good.
Make first paint meaningful: eyebrow, headline, card all shown, ambient motion. fine.
Need no external network. done.
One concern "Games must start..." irrelevant not game. Clear instruction exists.
We should now final code. Need exactly one fenced code block no text. Let's produce polished code about 500 lines. Ensure no accidental triple backticks inside. Let's generate.