Kimi K3.1 Pro
by MoonshotAIreasoning defaultClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 1 min 42 s
- Cost
- $0.202
- Output tokens
- 20,133
- Spent thinking
- 12,053 tokens
- Speed
- 199.5 tok/s
- Console errors
- 0
- First token after
- 1.0 s
- First visible text after
- 1 min 19 s
- Prompt tokens
- 583
- Code size
- 25.7 KB
- Finish reason
- stop
- Served by
- AkashML
- Model id
moonshotai/kimi-k3.1-pro- Reasoning sent
model default- Max output
- 943,718 tokens
- Generated
- Nov 12, 2026
What it was asked
The prompt
Create a set of four animated weather cards (sunny, rainy, snowy, stormy), made with HTML and CSS only. Requirements: - Absolutely no JavaScript: the file must not contain any <script> tag or inline event handler. - No images, no SVG, no icon fonts: every weather icon is built from HTML elements and pseudo-elements styled with CSS. - Each card shows an animated icon (rotating sun rays, falling rain drops, drifting snowflakes, flashing lightning), a city name, a temperature and a short description. - Each card has its own background gradient matching the weather. - The cards are displayed in a responsive grid (4 per row on desktop, stacked on mobile) and lift up on hover. - Smooth infinite animations using @keyframes, and respect prefers-reduced-motion.
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 · 1063 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Weather in Motion</title>
<style>
:root {
color-scheme: dark;
font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
min-height: 100svh;
overflow-x: hidden;
background: #08111c;
color: #edf4f8;
-webkit-font-smoothing: antialiased;
}
body::before {
content: "";
position: fixed;
inset: 0;
pointer-events: none;
background:
radial-gradient(circle at 8% 0%, rgba(62, 131, 170, 0.17), transparent 34%),
radial-gradient(circle at 94% 18%, rgba(91, 76, 147, 0.13), transparent 30%),
radial-gradient(circle at 50% 110%, rgba(30, 76, 105, 0.16), transparent 42%);
}
.page {
position: relative;
max-width: 1280px;
margin: 0 auto;
padding: 36px 30px 28px;
}
.header {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 28px;
margin-bottom: 26px;
}
.kicker {
display: flex;
align-items: center;
gap: 10px;
margin: 0;
color: #8099ab;
font-size: 10px;
font-weight: 700;
letter-spacing: 0.2em;
text-transform: uppercase;
}
.kicker::before {
content: "";
width: 24px;
height: 1px;
background: #65b8d6;
}
h1 {
margin: 11px 0 0;
color: #f2f6f8;
font-size: clamp(38px, 4vw, 52px);
font-weight: 650;
letter-spacing: -0.055em;
line-height: 1.02;
text-wrap: balance;
}
h1 span {
color: #8298a9;
font-weight: 450;
}
.subtitle {
margin: 12px 0 0;
color: #8ba0b0;
font-size: 13px;
line-height: 1.6;
}
.header-side {
display: flex;
flex: none;
flex-direction: column;
align-items: flex-end;
gap: 10px;
padding-bottom: 3px;
}
.motion-badge {
display: inline-flex;
align-items: center;
gap: 9px;
padding: 10px 14px;
border: 1px solid rgba(172, 205, 224, 0.13);
border-radius: 999px;
background: rgba(255, 255, 255, 0.035);
color: #b8c9d4;
font-size: 9px;
font-weight: 750;
letter-spacing: 0.14em;
white-space: nowrap;
}
.live-dot {
width: 7px;
height: 7px;
border-radius: 50%;
background: #78deb0;
box-shadow: 0 0 0 0 rgba(120, 222, 176, 0.35);
animation: livePulse 2.2s ease-out infinite;
}
.header-note {
margin: 0;
color: #61788a;
font-size: 11px;
}
.weather-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 18px;
}
.weather-card {
--ink: #ffffff;
--muted: rgba(255, 255, 255, 0.68);
--line: rgba(255, 255, 255, 0.17);
--shadow: rgba(0, 0, 0, 0.22);
position: relative;
isolation: isolate;
display: flex;
min-width: 0;
min-height: 458px;
flex-direction: column;
overflow: hidden;
padding: 24px;
border: 1px solid rgba(255, 255, 255, 0.24);
border-radius: 27px;
color: var(--ink);
box-shadow:
0 18px 40px var(--shadow),
inset 0 1px 0 rgba(255, 255, 255, 0.18);
transition:
transform 350ms cubic-bezier(0.2, 0.75, 0.25, 1),
box-shadow 350ms cubic-bezier(0.2, 0.75, 0.25, 1);
}
.weather-card::before {
content: "";
position: absolute;
z-index: 0;
inset: 0;
pointer-events: none;
background: radial-gradient(circle at 90% 4%, rgba(255, 255, 255, 0.26), transparent 36%);
}
.weather-card > * {
position: relative;
z-index: 1;
}
.weather-card:hover {
transform: translateY(-10px);
box-shadow:
0 30px 58px var(--shadow),
inset 0 1px 0 rgba(255, 255, 255, 0.22);
}
.sunny-card {
--ink: #49320b;
--muted: rgba(73, 50, 11, 0.64);
--line: rgba(91, 57, 5, 0.16);
--shadow: rgba(115, 71, 10, 0.19);
background: linear-gradient(155deg, #ffeda9 0%, #ffcc65 45%, #f2a73b 100%);
}
.rainy-card {
--ink: #f4faff;
--muted: rgba(231, 244, 253, 0.68);
--line: rgba(222, 241, 253, 0.17);
--shadow: rgba(4, 23, 43, 0.29);
background: linear-gradient(155deg, #568faf 0%, #326589 47%, #1c3c60 100%);
}
.snowy-card {
--ink: #19394f;
--muted: rgba(25, 57, 79, 0.61);
--line: rgba(33, 75, 99, 0.14);
--shadow: rgba(31, 67, 89, 0.18);
background: linear-gradient(155deg, #f5fcff 0%, #d9edf6 48%, #b3d1e2 100%);
}
.stormy-card {
--ink: #f6f3ff;
--muted: rgba(235, 230, 251, 0.66);
--line: rgba(227, 220, 250, 0.15);
--shadow: rgba(4, 5, 20, 0.34);
background: linear-gradient(155deg, #606183 0%, #393a58 46%, #1a2037 100%);
}
.card-top {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
}
.region {
margin: 0 0 5px;
color: var(--muted);
font-size: 9px;
font-weight: 750;
letter-spacing: 0.15em;
text-transform: uppercase;
}
.city {
margin: 0;
font-size: 22px;
font-weight: 650;
letter-spacing: -0.035em;
line-height: 1.2;
}
.card-number {
display: grid;
width: 31px;
height: 31px;
flex: none;
place-items: center;
border: 1px solid var(--line);
border-radius: 9px;
color: var(--muted);
font-size: 10px;
font-weight: 700;
}
.icon-stage {
height: 190px;
flex: 0 0 190px;
margin: 7px -6px 2px;
}
.card-bottom {
margin-top: auto;
}
.temp-line {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 10px;
}
.temperature {
margin: 0;
font-size: 66px;
font-weight: 520;
letter-spacing: -0.075em;
line-height: 0.92;
}
.degree {
display: inline-block;
margin-top: 0.08em;
margin-left: 0.04em;
font-size: 0.56em;
letter-spacing: 0;
vertical-align: top;
}
.range {
display: flex;
flex-direction: column;
gap: 4px;
margin-bottom: 3px;
color: var(--muted);
font-size: 10px;
font-weight: 650;
line-height: 1.2;
text-align: right;
}
.description {
margin: 13px 0 18px;
font-size: 13px;
font-weight: 550;
line-height: 1.45;
}
.details {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 12px;
padding-top: 15px;
border-top: 1px solid var(--line);
}
.detail {
display: flex;
flex-direction: column;
gap: 4px;
}
.detail:last-child {
text-align: right;
}
.detail-label {
color: var(--muted);
font-size: 8px;
font-weight: 750;
letter-spacing: 0.14em;
line-height: 1.2;
text-transform: uppercase;
}
.detail-value {
font-size: 11px;
font-weight: 650;
line-height: 1.3;
}
/* Sun */
.sun-icon {
position: absolute;
top: 50%;
left: 50%;
width: 170px;
height: 170px;
transform: translate(-50%, -50%);
}
.sun-halo {
position: absolute;
inset: 26px;
border-radius: 50%;
background: rgba(255, 248, 199, 0.2);
box-shadow: 0 0 0 14px rgba(255, 248, 199, 0.1);
animation: haloPulse 4s ease-in-out infinite;
}
.sun-rays {
position: absolute;
inset: 0;
animation: spin 18s linear infinite;
}
.sun-rays span {
position: absolute;
top: 3px;
left: calc(50% - 2px);
width: 4px;
height: 20px;
border-radius: 999px;
background: #fff7c5;
box-shadow: 0 0 8px rgba(255, 251, 213, 0.6);
transform-origin: 2px 82px;
}
.sun-rays span:nth-child(1) { transform: rotate(0deg); }
.sun-rays span:nth-child(2) { transform: rotate(30deg); }
.sun-rays span:nth-child(3) { transform: rotate(60deg); }
.sun-rays span:nth-child(4) { transform: rotate(90deg); }
.sun-rays span:nth-child(5) { transform: rotate(120deg); }
.sun-rays span:nth-child(6) { transform: rotate(150deg); }
.sun-rays span:nth-child(7) { transform: rotate(180deg); }
.sun-rays span:nth-child(8) { transform: rotate(210deg); }
.sun-rays span:nth-child(9) { transform: rotate(240deg); }
.sun-rays span:nth-child(10) { transform: rotate(270deg); }
.sun-rays span:nth-child(11) { transform: rotate(300deg); }
.sun-rays span:nth-child(12) { transform: rotate(330deg); }
.sun-core {
position: absolute;
top: 40px;
left: 40px;
width: 90px;
height: 90px;
border-radius: 50%;
background: radial-gradient(circle at 34% 28%, #fffde4 0%, #fff29e 31%, #ffd45d 70%, #f7b633 100%);
box-shadow:
0 10px 22px rgba(158, 94, 9, 0.18),
0 0 32px rgba(255, 246, 172, 0.55);
animation: sunPulse 4s ease-in-out infinite;
}
.sun-core::after {
content: "";
position: absolute;
top: 17px;
left: 22px;
width: 27px;
height: 14px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.32);
transform: rotate(-28deg);
}
/* Shared cloud construction */
.cloud-icon {
--cloud-light: #edf7fb;
--cloud-dark: #bdd5e1;
--cloud-shadow: rgba(6, 28, 49, 0.24);
position: absolute;
inset: 0;
}
.cloud-icon::after {
content: "";
position: absolute;
z-index: 0;
bottom: 4px;
left: 50%;
width: 118px;
height: 12px;
border-radius: 50%;
background: var(--cloud-shadow);
filter: blur(8px);
opacity: 0.36;
transform: translateX(-50%);
}
.cloud {
position: absolute;
z-index: 2;
top: 48px;
left: 50%;
width: 154px;
height: 50px;
margin-left: -77px;
border-radius: 999px;
background: linear-gradient(180deg, var(--cloud-light), var(--cloud-dark));
filter: drop-shadow(0 10px 10px var(--cloud-shadow));
animation: cloudFloat 4.5s ease-in-out infinite;
}
.cloud::before,
.cloud::after {
content: "";
position: absolute;
border-radius: 50%;
background: linear-gradient(180deg, var(--cloud-light), var(--cloud-dark));
}
.cloud::before {
bottom: 16px;
left: 22px;
width: 78px;
height: 78px;
}
.cloud::after {
right: 20px;
bottom: 18px;
width: 64px;
height: 64px;
}
.snow-icon {
--cloud-light: #ffffff;
--cloud-dark: #d5e7ef;
--cloud-shadow: rgba(48, 88, 110, 0.2);
}
.snow-icon .cloud {
animation-delay: -1.8s;
}
.storm-icon {
--cloud-light: #70788f;
--cloud-dark: #343d57;
--cloud-shadow: rgba(4, 7, 22, 0.42);
}
.storm-icon .cloud {
animation-delay: -3s;
}
/* Rain */
.rain-drops,
.snowflakes,
.storm-rain {
position: absolute;
z-index: 1;
inset: 0;
}
.rain-drops span,
.storm-rain span {
position: absolute;
top: 106px;
width: 4px;
height: 18px;
border-radius: 999px;
background: linear-gradient(180deg, #d5f5ff, #68caff);
box-shadow: 0 0 8px rgba(105, 204, 255, 0.3);
opacity: 0;
animation: rainFall 1.35s linear infinite;
}
.rain-drops span:nth-child(1) {
left: calc(50% - 54px);
animation-delay: -0.2s;
}
.rain-drops span:nth-child(2) {
left: calc(50% - 28px);
animation-duration: 1.5s;
animation-delay: -0.85s;
}
.rain-drops span:nth-child(3) {
left: calc(50% - 1px);
animation-delay: -0.45s;
}
.rain-drops span:nth-child(4) {
left: calc(50% + 27px);
animation-duration: 1.45s;
animation-delay: -1.1s;
}
.rain-drops span:nth-child(5) {
left: calc(50% + 50px);
animation-delay: -0.65s;
}
/* Snowflakes are three crossed CSS bars */
.snowflakes span {
--drift: 10px;
--size: 1;
position: absolute;
top: 108px;
width: 17px;
height: 2px;
border-radius: 999px;
background: #ffffff;
filter: drop-shadow(0 1px 2px rgba(57, 105, 129, 0.38));
opacity: 0;
animation: snowFall 3.4s linear infinite;
}
.snowflakes span::before,
.snowflakes span::after {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
background: inherit;
}
.snowflakes span::before {
transform: rotate(60deg);
}
.snowflakes span::after {
transform: rotate(120deg);
}
.snowflakes span:nth-child(1) {
--drift: 14px;
--size: 0.85;
left: calc(50% - 56px);
animation-duration: 3.2s;
animation-delay: -0.4s;
}
.snowflakes span:nth-child(2) {
--drift: -12px;
--size: 1.1;
left: calc(50% - 30px);
animation-duration: 3.8s;
animation-delay: -2.1s;
}
.snowflakes span:nth-child(3) {
--drift: 8px;
--size: 0.75;
left: calc(50% - 2px);
animation-duration: 3.4s;
animation-delay: -1.2s;
}
.snowflakes span:nth-child(4) {
--drift: -15px;
--size: 1;
left: calc(50% + 27px);
animation-duration: 4s;
animation-delay: -2.8s;
}
.snowflakes span:nth-child(5) {
--drift: 10px;
--size: 0.7;
left: calc(50% + 50px);
animation-duration: 3.6s;
animation-delay: -0.9s;
}
/* Storm */
.storm-scene::before {
content: "";
position: absolute;
z-index: 0;
inset: 8px 12px 0;
border-radius: 50%;
background: radial-gradient(circle, rgba(255, 229, 117, 0.38), transparent 65%);
opacity: 0;
animation: skyFlash 3.4s linear infinite;
}
.lightning-bolt {
position: absolute;
z-index: 3;
top: 99px;
left: 50%;
width: 46px;
height: 82px;
margin-left: -16px;
clip-path: polygon(52% 0, 100% 0, 66% 39%, 93% 39%, 17% 100%, 39% 55%, 8% 55%);
background: linear-gradient(180deg, #fffde3 0%, #ffe36c 45%, #ffb829 100%);
filter: drop-shadow(0 0 9px rgba(255, 220, 75, 0.9));
opacity: 0.62;
transform-origin: 50% 20%;
animation: boltFlash 3.4s linear infinite;
}
.storm-rain span {
top: 110px;
height: 14px;
background: linear-gradient(180deg, #c2d7ff, #799cf3);
animation-duration: 1.5s;
}
.storm-rain span:nth-child(1) {
left: calc(50% - 53px);
animation-delay: -0.5s;
}
.storm-rain span:nth-child(2) {
left: calc(50% + 48px);
animation-delay: -1.15s;
}
.footer {
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
margin-top: 23px;
padding-top: 17px;
border-top: 1px solid rgba(158, 190, 209, 0.1);
color: #61788a;
font-size: 10px;
letter-spacing: 0.04em;
line-height: 1.5;
}
.footer p {
margin: 0;
}
.footer strong {
color: #8da3b3;
font-weight: 650;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
padding: 0;
border: 0;
margin: -1px;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
@keyframes sunPulse {
0%, 100% { transform: scale(1); }
50% {
transform: scale(1.045);
box-shadow:
0 10px 22px rgba(158, 94, 9, 0.18),
0 0 42px rgba(255, 246, 172, 0.7);
}
}
@keyframes haloPulse {
0%, 100% { opacity: 0.7; transform: scale(0.97); }
50% { opacity: 1; transform: scale(1.07); }
}
@keyframes cloudFloat {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-5px); }
}
@keyframes rainFall {
0% {
opacity: 0;
transform: translate3d(4px, -10px, 0) rotate(12deg);
}
20% { opacity: 1; }
82% { opacity: 0.9; }
100% {
opacity: 0;
transform: translate3d(-7px, 50px, 0) rotate(12deg);
}
}
@keyframes snowFall {
0% {
opacity: 0;
transform: translate3d(0, -12px, 0) rotate(0deg) scale(var(--size));
}
15% { opacity: 0.95; }
80% { opacity: 0.9; }
100% {
opacity: 0;
transform: translate3d(var(--drift), 56px, 0) rotate(180deg) scale(var(--size));
}
}
@keyframes boltFlash {
0%, 4%, 10%, 16%, 48%, 55%, 100% {
opacity: 0.62;
transform: scale(1);
}
6%, 12%, 51% {
opacity: 1;
transform: scale(1.09);
}
8%, 14%, 53% {
opacity: 0.28;
transform: scale(0.97);
}
}
@keyframes skyFlash {
0%, 4%, 10%, 16%, 48%, 55%, 100% { opacity: 0; }
6%, 12%, 51% { opacity: 0.55; }
8%, 14%, 53% { opacity: 0.08; }
}
@keyframes livePulse {
0% { box-shadow: 0 0 0 0 rgba(120, 222, 176, 0.38); }
65%, 100% { box-shadow: 0 0 0 7px rgba(120, 222, 176, 0); }
}
@media (max-width: 1023px) {
.page {
max-width: 920px;
}
.weather-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.weather-card {
min-height: 448px;
}
}
@media (max-width: 700px) {
.header {
flex-direction: column;
align-items: flex-start;
gap: 18px;
}
.header-side {
width: 100%;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding-bottom: 0;
}
}
@media (max-width: 640px) {
.page {
max-width: 480px;
padding: 27px 16px 24px;
}
.header {
margin-bottom: 22px;
}
.weather-grid {
grid-template-columns: 1fr;
gap: 16px;
}
.weather-card {
min-height: 442px;
padding: 24px;
border-radius: 24px;
}
.footer {
flex-direction: column;
align-items: flex-start;
gap: 7px;
}
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
scroll-behavior: auto !important;
animation: none !important;
transition: none !important;
}
.weather-card:hover {
transform: none;
}
.rain-drops span,
.storm-rain span {
opacity: 0.85;
transform: translateY(15px) rotate(12deg);
}
.snowflakes span {
opacity: 0.9;
transform: translateY(16px) rotate(20deg) scale(var(--size));
}
.lightning-bolt {
opacity: 1;
transform: none;
}
.storm-scene::before {
opacity: 0.12;
}
.live-dot {
box-shadow: 0 0 0 4px rgba(120, 222, 176, 0.12);
}
}
</style>
</head>
<body>
<main class="page">
<header class="header">
<div>
<p class="kicker">The atmosphere collection</p>
<h1>Weather, <span>in motion.</span></h1>
<p class="subtitle">Four cities. Four atmospheres. One pure-CSS sky.</p>
</div>
<div class="header-side">
<div class="motion-badge">
<span class="live-dot" aria-hidden="true"></span>
4 ANIMATED SCENES
</div>
<p class="header-note">Hover to lift a card</p>
</div>
</header>
<section class="weather-grid" aria-label="Animated weather conditions">
<article class="weather-card sunny-card">
<div class="card-top">
<div>
<p class="region">Portugal · Now</p>
<h2 class="city">Lisbon</h2>
</div>
<span class="card-number" aria-hidden="true">01</span>
</div>
<div class="icon-stage" aria-hidden="true">
<div class="sun-icon">
<div class="sun-halo"></div>
<div class="sun-rays">
<span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span>
<span></span><span></span><span></span><span></span>
</div>
<div class="sun-core"></div>
</div>
</div>
<div class="card-bottom">
<div class="temp-line">
<p class="temperature">
<span aria-hidden="true">24<span class="degree">°</span></span>
<span class="sr-only">24 degrees Celsius</span>
</p>
<div class="range" aria-label="High 27 degrees, low 18 degrees">
<span>H 27°</span>
<span>L 18°</span>
</div>
</div>
<p class="description">Golden light & clear skies</p>
<div class="details">
<div class="detail">
<span class="detail-label">Wind</span>
<span class="detail-value">9 km/h</span>
</div>
<div class="detail">
<span class="detail-label">Humidity</span>
<span class="detail-value">42%</span>
</div>
</div>
</div>
</article>
<article class="weather-card rainy-card">
<div class="card-top">
<div>
<p class="region">Washington · Now</p>
<h2 class="city">Seattle</h2>
</div>
<span class="card-number" aria-hidden="true">02</span>
</div>
<div class="icon-stage cloud-icon" aria-hidden="true">
<div class="cloud"></div>
<div class="rain-drops">
<span></span><span></span><span></span><span></span><span></span>
</div>
</div>
<div class="card-bottom">
<div class="temp-line">
<p class="temperature">
<span aria-hidden="true">14<span class="degree">°</span></span>
<span class="sr-only">14 degrees Celsius</span>
</p>
<div class="range" aria-label="High 16 degrees, low 11 degrees">
<span>H 16°</span>
<span>L 11°</span>
</div>
</div>
<p class="description">Steady rain & soft skies</p>
<div class="details">
<div class="detail">
<span class="detail-label">Wind</span>
<span class="detail-value">12 km/h</span>
</div>
<div class="detail">
<span class="detail-label">Rainfall</span>
<span class="detail-value">80%</span>
</div>
</div>
</div>
</article>
<article class="weather-card snowy-card">
<div class="card-top">
<div>
<p class="region">Japan · Now</p>
<h2 class="city">Sapporo</h2>
</div>
<span class="card-number" aria-hidden="true">03</span>
</div>
<div class="icon-stage cloud-icon snow-icon" aria-hidden="true">
<div class="cloud"></div>
<div class="snowflakes">
<span></span><span></span><span></span><span></span><span></span>
</div>
</div>
<div class="card-bottom">
<div class="temp-line">
<p class="temperature">
<span aria-hidden="true">−3<span class="degree">°</span></span>
<span class="sr-only">Minus 3 degrees Celsius</span>
</p>
<div class="range" aria-label="High 0 degrees, low minus 7 degrees">
<span>H 0°</span>
<span>L −7°</span>
</div>
</div>
<p class="description">Quiet snow & frozen air</p>
<div class="details">
<div class="detail">
<span class="detail-label">Wind</span>
<span class="detail-value">8 km/h</span>
</div>
<div class="detail">
<span class="detail-label">Snowfall</span>
<span class="detail-value">90%</span>
</div>
</div>
</div>
</article>
<article class="weather-card stormy-card">
<div class="card-top">
<div>
<p class="region">Singapore · Now</p>
<h2 class="city">Singapore</h2>
</div>
<span class="card-number" aria-hidden="true">04</span>
</div>
<div class="icon-stage cloud-icon storm-icon storm-scene" aria-hidden="true">
<div class="cloud"></div>
<div class="storm-rain"><span></span><span></span></div>
<div class="lightning-bolt"></div>
</div>
<div class="card-bottom">
<div class="temp-line">
<p class="temperature">
<span aria-hidden="true">27<span class="degree">°</span></span>
<span class="sr-only">27 degrees Celsius</span>
</p>
<div class="range" aria-label="High 29 degrees, low 25 degrees">
<span>H 29°</span>
<span>L 25°</span>
</div>
</div>
<p class="description">Thunderstorms rolling in</p>
<div class="details">
<div class="detail">
<span class="detail-label">Wind</span>
<span class="detail-value">24 km/h</span>
</div>
<div class="detail">
<span class="detail-label">Storm risk</span>
<span class="detail-value">75%</span>
</div>
</div>
</div>
</article>
</section>
<footer class="footer">
<p><strong>Pure HTML + CSS</strong> · Every shape drawn with elements</p>
<p>Motion respects your system preference</p>
</footer>
</main>
</body>
</html>Reasoning trace (12,053 tokens)
Kimi needs to create a complete self-contained HTML file with exactly one fenced code block, no JS, no SVG, no images, no icon fonts, no inline handlers. Four animated weather cards sunny rainy snowy stormy built with HTML elements pseudo CSS. Should impressive visual quality, responsive grid 4 desktop stack mobile, hover lift, gradients, infinite keyframes, reduced motion. Something visible first paint. Make sure no script. I can use CSS shapes elements pseudo. Perhaps accessible semantic. Should design polished.
I should think through visual. I can create a page dark/navy elegant background, title "Atmosphere / live weather" maybe aesthetic editorial dashboard. Four cards with colorful gradients: sunny golden/sky, rainy cool blue, snowy pale, stormy dark purple. Each card city temp description, animated icon distinct. All no JS. CSS-only icons composed divs/spans/pseudos. Rotating sun rays (ring of rays using spans rotated), sun core. Rainy cloud with raindrops. Snow cloud with snowflakes drifting. Storm cloud + bolt flashing.
Should have no SVG. Use HTML elements and pseudo. Could use unicode symbols? No icon fonts; text symbols maybe but better all shapes CSS. For snowflake CSS perhaps create spans with 3 crossing bars via ::before/after; actual flake shape. Should multiple flakes, animate. Rain drops elements. Lightning CSS bolt using clip-path polygon on div, animation flash. Cloud CSS using multiple rounded elements or a cloud base with pseudo circles. No SVG. Use CSS pseudo.
Grid: 4 cards desktop at >= 1100 maybe minmax 0,1fr repeat(4). Cards max width. Main max-width 1240, viewport 1280 margins 24. Cards around 280 width, height 440 maybe all fit in 800 including header 140 + card 450 = 650. Good. Mobile stacked via media. Requirement stacked on mobile maybe at 700 1 column; tablet 2. Desktop 4. Use grid-template-columns: repeat(4,minmax(0,1fr)); @max 1100 repeat 2; @max 640 1. Responsive gracefully 375 no horizontal. Cards min-height maybe 440 desktop, mobile ~400. At 1280 main width calc - 48 max 1200 gap 18 gives card ~286. Main padding. Design polished.
I should avoid external fonts per instruction. Use system fonts. Could use typography with letter spacing. Body background #080e1a with radial gradients(no images? CSS gradients allowed). Add decorative grid/noise? No images. Use pseudo blurred blobs via CSS. body ::before etc fixed radial gradient. Keep no horizontal scrollbar overflow-x clip.
Page header with eyebrow "WEATHER / WORLDWIDE" and "Conditions in motion" title, subtitle. Top right status badge with pulse dot "LIVE CONDITIONS" (animation). Maybe date static "FOUR CITIES · ONE SKY". Cards labelled indexes 01 etc. Each card article.weather-card sunny etc. Background gradients unique. Inner top row city and maybe country code. Icon stage center ~180. Temp bottom. description and small meta row maybe humidity/wind to polish though requirement short desc. Keep visible. Could include "24°" and "Clear skies" etc.
Should have each card own gradient matching weather. Card sunny linear gradient(160deg,#ffd97a,#f3a531?) text dark maybe. Rainy linear gradient blue #3a78a8 #193c63 text white. Snowy linear gradient #e9f6ff #adca e0 with dark text. Stormy #443c73 #151a33 white. Add border, shadows.
Weather icons:
Sunny:
<div class="icon-scene sun-scene" aria-hidden="true">
<div class="sun">
<div class="sun-rays">
<i style="--i:0"></i>... 12 maybe inline style custom property allowed (not event handler). Requirement no inline event handler only style okay. Could use nth-child selectors avoid inline style maybe cleaner. <span></span>*12, CSS .sun-rays span {position:absolute; left:50%; top:50%; width:4px;height:20px; margin-left:-2px; margin-top:-70px? transform-origin:2px 70px; transform:rotate(calc(var(--i)*30deg));} Should reliable. Easier .sun-rays { width:150;height:150; animation:spin 18s linear infinite;} .sun-rays span { position:absolute; top:0; left:calc(50% - 2px); width:4px; height:18px; border-radius:4px; background:#fff4ad; transform-origin:2px 75px; transform:rotate(...)} nth-child transforms. .sun-core centered 88 circle at center; box shadow. .sun maybe width 160 height160 position relative. Rays 150 and core absolute 50%. Additional glow. Sun floating animation separate .sun-scene maybe transform. Rotating sun rays requirement. Core pulse. Perhaps subtle small cloud? No, sunny pure sun. Add small orbit dots? no.
Sun core ::after highlight radial gradient. CSS gradients okay. Outer .sun-halo absolute.
Rain:
<div class="cloud-icon rain-icon">
<div class="cloud">
<span class="cloud-puff puff-a"></span>...
maybe a single div .cloud-shape with width 150 height 50 background border-radius:50px; top 70 left; ::before circle 80 at left 25 bottom 15; ::after circle 100 at right 15 bottom 5. All one element with pseudo. Should cloud gradients differ via CSS variables:
.cloud { --cloud...; position:absolute; width:154px;height:52px; top:72px;left:50%; transform:translateX(-50%); background:linear-gradient; border-radius:999px; box-shadow...; animation:cloud-drift 4s ease-in-out infinite; }
.cloud::before {content:""; position:absolute;width:82px;height:82px;left:24px;bottom:16px;border-radius:50%; background:inherit; } background:inherit means gradient sizing maybe okay. ::after 66 right 20 bottom 22. Better base and pseudo same solid/gradient. Could use spans with explicit backgrounds to avoid issues, but pseudo exactly requested. Cloud base z-index? Pseudo behind base okay. .cloud::before,after z-index:-1 requires stacking context weird. Instead no z-index, pseudos position and base background, same color so seamless. Put box shadow on base only. Background linear gradient inherit with border radius. Use .cloud > .cloud-shine optional small top sheen.
Cloud animation .cloud-wrap? If .cloud itself animation transform translateX + translateY, base centered uses left calc(50%-77px) so animation transform translateY only. Set left:50%; margin-left:-77px; @keyframes cloudFloat {0,100 transform:translateY(0);50 transform:translateY(-5px)}. pseudos follow.
Drops: <div class="rain-drops"><span></span>*5 maybe positions via nth-child. .rain-drops absolute inset? stage 210. .rain-drops span { top:135px; width:4px;height:17px; background:linear-gradient(#bfedff,#55b9ff); border-radius: 60% 60% 70% 70%; transform:rotate(12deg); animation:rainfall 1.25s linear infinite; } each left percentages; delay. @keyframes rainfall {0% {transform:translate3d(0,-12px,0) rotate(12deg);opacity:0;}20% opacity1; 100% {transform:translate3d(-8px,54px,0) rotate(12deg);opacity:0;}} Should drop starts below cloud and ends bottom. Stage height 190. Cloud top 42 maybe. rain drops top 110 then 45 downward. icon stage 190. Good.
Could use drops shaped with pseudo? Each drop span, border radius. Enough.
Snow:
Cloud pale white. snowflakes drifting. Each <span class=flake> with inner? To make snowflake via CSS, span width 20 height 2 background white; ::before and ::after same absolute full, transform rotate(60deg) and 120deg. This yields six spoke asterisk. Add center maybe circle via box-shadow? span itself is horizontal line, rounded. Should animate whole flake translate fall + rotate but pseudos are rotated. @keyframes snowfall from transform:translate3d(0,-10px,0) rotate(0); to transform translate3d(var drift,50px) rotate(180deg); opacity. Each nth child left, animation durations delays, --drift. Flakes visible. Could set width 16 height2. .flake:nth-child(2) transform scale? Animation overrides scale. Use --scale variable included in keyframe transforms. Keyframes can use var --s. .flake {--s:1; --drift:10px;} @keyframes snowFall {0% {transform:translate3d(0,-15px,0) rotate(0deg) scale(var(--s));opacity:0;}15% opacity .95;100% {transform:translate3d(var(--drift),55px,0) rotate(180deg) scale(var(--s));opacity:0;}} all good.
Perhaps cloud light blue with text dark.
Storm:
Dark cloud with flash bolt. .storm-icon .cloud top 50 background dark gradient #48536d #202a43 border. Lightning bolt .bolt {position:absolute; top:112px; left:50%; width:42px;height:74px; margin-left:-12px; background:linear-gradient(#fff9a8,#ffc633); clip-path:polygon(54% 0,100% 0,68% 38%,96% 38%,20% 100%,40% 54%,10% 54%); filter:drop-shadow(0 0 10px rgba(...)); animation:lightning 3s infinite;} Keyframes opacity and transform scale. Flashing lightning, perhaps scene ::after flash overlay radial gradient anim. Multiple bolt small second? Main enough. Add rain lines to storm maybe two drops to convey storm, but lightning strong. .storm-flash background radial-gradient etc animation. I can use .storm-scene::before positioned inset 0 background radial gradient opacity animation. Should cloud and bolt z-index.
Animations reduced motion:
@media (prefers-reduced-motion: reduce) {
*,*::before,*::after {animation-duration:0.01ms !important; animation-iteration-count:1 !important; transition-duration:0.01ms !important; scroll-behavior:auto !important;}
.sun-rays { transform:rotate(0); } etc.
}
Requirement smooth infinite and respect reduced. Could use animation:none !important rather than tiny duration. Standard:
@media (prefers-reduced-motion: reduce) {
*,*::before,*::after { animation-duration:0.01ms !important; animation-iteration-count:1 !important; transition-duration:0.01ms !important; }
}
This stops after one. But if delay negative and tiny duration ending opacity 0 may hide drops/flakes/bolt. Better explicitly animation:none !important; transition:none !important; .rain-drops span,.snowflakes span {opacity:.85; transform:none;} .bolt {opacity:1;} .status-dot etc. Universal animation:none !important; transition-duration:.01ms. Then set final visible states. This respects fully. Hover lift with no transition instantaneous okay. Could keep hover transform but reduced-motion no animation. Good.
Hover: .weather-card {transition:transform .35s cubic-bezier,box-shadow...;} .weather-card:hover {transform:translateY(-10px); box-shadow...} maybe icon accent changes .weather-card:hover .sun-core etc but not necessary. Focus-within? Cards article not interactive. Could add tabindex=0 to card to allow keyboard focus and focus-visible lift, semantic not necessary. I can add tabindex="0" and CSS :focus-visible outline; no event handlers. Is it okay? yes. Gives interaction. But cards non-interactive maybe tab focus not necessary. I can use article and hover only.
No JS exactly. Make sure no <script> text in comments? User says file must not contain any <script> tag. Fine none. Could include comments? no need.
Should output only one fenced code block html complete. I should create robust 1280x800. Let's design CSS carefully.
Structure:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name=viewport content...>
<title>Weather in Motion</title>
<style>
:root { color-scheme:dark; font-family: Inter, ui-sans-serif, system...; }
* {box-sizing:border-box}
body {margin:0; min-height:100vh; background:#08111d; color...; overflow-x:hidden;}
body::before {content:""; position:fixed; inset:0; pointer-events:none; background: radial-gradient(circle at 10% 0%,rgba(54,117,164,.15),transparent 32%), radial...;}
body::after maybe grid lines using linear gradients considered background no images okay. But subtle and no external.
.page {position:relative; max-width:1280px; margin:0 auto; padding:42px 30px 36px;}
.header {display:flex; justify-content:space-between; align-items:flex-end; gap:24px; margin-bottom:28px;}
.kicker {display:flex; align-items:center; gap:10; font-size:11; letter-spacing:.18em; text-transform uppercase;color:#8fa6b8;}
.kicker::before small line.
h1 margin etc font-size clamp(2rem,4vw,3.4rem); font-weight:600; letter spacing -0.05em; line-height:1.04; maybe "Weather, in motion." With gradient text word? h1 span color #9fb3c4 font weight 400? E.g. <h1>Weather, <span>in motion.</span></h1> span color #7e91a4. Could look polished. subtitle.
.header-meta align right maybe status.
.status {display:flex...; border:1px solid; background; border radius:100px; padding...}
.status-dot animation pulse.
.grid display:grid repeat 4 gap 18.
.weather-card { --text...; position:relative; isolation:isolate; overflow:hidden; min-width:0; height:460px; border-radius:28px; padding:24px; display:flex; flex-direction:column; color:var(--ink); border:1px solid rgba(255...); box-shadow:0 18px 40px ...; transition...}
Gradient classes:
.sunny-card {--ink:#3c2c10; --muted:rgba(60,44,16,.68); --line:rgba(80,54,5,.13); background:linear-gradient(155deg,#ffe89b 0%,#ffc85c 43%,#f3a638 100%); box-shadow...}
.rainy-card {--ink:#f4faff; --muted:rgba(235,246,255,.7); --line:rgba(...); background:linear-gradient(155deg,#508eb5,#2e5f87 48%,#1d3e63);}
.snowy-card {--ink:#19374c; --muted:rgba(25,55,76,.65); --line:...; background:linear-gradient(155deg,#f4fbff,#d5eaf5 50%,#b3d0e2);}
.stormy-card {--ink:#f5f2ff; --muted:rgba(238,233,255,.68); --line...; background:linear-gradient(155deg,#5b5d86,#343653 48%,#1b2038);}
Card ::before decorative top radial shine:
.weather-card::before {content:"";position:absolute;inset:0;z-index:-1;background:radial-gradient(circle at 85% 10%,rgba(255,255,255,.24),transparent 35%);pointer-events:none;}
Card ::after maybe large circle bottom? Not necessary.
.card-top {display:flex; justify-content:space-between; align-items:flex-start; position:relative; z-index:2;}
.place-label text uppercase font-size10 letter spacing.
.city margin 4px 0 0;font-size 22; line-height; font-weight650; letter-spacing:-.03em.
.card-number {font-size:11; font-weight 600; padding:6px 8px; border 1px solid var line; border-radius:8px;}
.icon-stage {position:relative;height:196px; flex:0 0 196px; margin:8px -6px 2px;}
.bottom margin-top:auto.
.temp-row display flex align-start maybe temp 72.
.temperature {font-size:68px; line-height:.9; font-weight:500; letter-spacing:-.075em;} degree built as <span class=temp>24<span class=degree>°</span></span>. Or 24° all with font. unit C in small? "24°" and <span class="unit">C</span>. Requirement temperature. Better <div class=temp>24<span>°</span></div>, description separate "Sunlit & clear". small high low right maybe "H 27° / L 18°". Add meta data humidity/wind at bottom.
.description {margin:12px 0 18px; font-size:14px;font-weight:550;}
.details {border-top:1px solid var line; padding-top:15px; display:flex; justify-content:space-between; gap:12px;}
.detail {display:flex flex-direction column gap4}
.detail-label uppercase 9 letter spacing .12 color muted; .detail-value font-size 12 weight600.
Maybe bottom details make height. Card 460: padding 24*2=48, header 50, stage196+10, temp64, desc34, details44 totals446? Let's calc: content height412. header 49, stage 206, temp61, desc line17+ margins 12+18=47, details 47 =>410. Good fits 460. Main header maybe 150 plus card 460 + padding 78 =688 fits 800. Good.
Header heights: page top 38, header kicker 15 + h1 50 + subtitle20 + gaps =105, margin bottom26, card460, bottom maybe footer 28+ => total38+105+26+460+24+20+36=709. Fine.
Footer simple "* Live visual study · Conditions updated just now" and "HTML + CSS" maybe a footer visible. Keep no JS. "A pure CSS forecast" badge. User wants set of cards only, header/footer okay. Could add "Pure CSS • No scripts" but no need maybe nice. Footer small. Should have title perhaps not too much. I should prioritize cards.
Icon CSS exact geometry:
.icon-stage > div absolute. .sun-icon {position:absolute;width:170px;height:170px;left:50%;top:50%;transform:translate(-50%,-50%);}
.sun-halo {position:absolute;inset:20px;border-radius:50%;background:rgba(255,244,181,.24);box-shadow:0 0 0 14px rgba(255,248,199,.12);animation:halo 4s ease-in-out infinite;}
.sun-rays {position:absolute;inset:0;animation:spin 20s linear infinite;}
.sun-rays span {position:absolute;top:4px;left:calc(50% - 2px);width:4px;height:19px;border-radius:999px;background:#fff4b0;box-shadow:0 0 8px rgba(255,250,202,.55);transform-origin:2px 81px;} Since inset height 170, center y85. Top4 and transform origin y81 -> rotation origin at top 4+81=85. yes x left center-2 +2 =center. Each rotate nth 30deg. Ends radial from center 85 - top? ray top at y4, length19, radial distance center to top =81, center to bottom62. Core radius45 => gap17. Good.
Sun-core position absolute width90 height90 left40 top40 border-radius50 background radial gradient(circle at 35% 30%,#fffde0 0,#fff19a 30%,#ffd358 72%,#f9b831 100%); box-shadow:0 8px 20px rgba(164,101,13,.18),0 0 30px rgba(255,247,181,.5); animation sunPulse 4s.
.core::after small glint maybe no.
@keyframes spin to rotate360.
@keyframes sunPulse {50% transform:scale(1.04); box-shadow...}
@keyframes haloPulse 50 transform scale(1.08) opacity .65.
Cloud:
.cloud-icon {position:absolute;inset:0;} scene relative.
.cloud {position:absolute;left:50%;top:54px;width:154px;height:50px;margin-left:-77px;border-radius:999px;background:linear-gradient(180deg,var(--cloud-light),var(--cloud-dark));box-shadow:0 12px 20px var(--cloud-shadow);animation:cloudFloat 4.5s ease-in-out infinite; z-index:2;}
.cloud::before {content:"";position:absolute;width:78px;height:78px;left:22px;bottom:16px;border-radius:50%;background:var(--cloud-light);} .cloud::after {width:64px;height:64px;right:20px;bottom:18px;background:var(--cloud-light)} But background circles solid cloud-light and base gradient cloud-dark at bottom; okay seams might show. Set background:linear-gradient(180deg,var(--cloud-light),var(--cloud-dark)); for pseudo too; dimensions different but seam minor. Could cloud use solid? Modern subtle. Use same linear gradient. Pseudo maybe box-shadow inset -8 -8 15 rgba? no.
Should shape order: base with pseudo, pseudo could overlay base but same gradient, fine.
.cloud .cloud-highlight {position:absolute;width:44px;height:12px;left:48px;top:8px;border-radius:50%;background:rgba(255,255,255,.18);transform:rotate(-8deg);} span okay but not needed. Pseudo before/after used circles, cannot extra sheen.
Rain icon variables --cloud-light:#e9f4fa; --cloud-dark:#b8d2e0; --cloud-shadow:rgba(7,32,59,.25).
Snow cloud white with darker #d3e4ed shadow.
Storm #69728c and #343d58.
Cloud floating transform doesn't affect drop start (fine).
Drops:
.rain-drops {position:absolute;inset:0;z-index:1;}
.rain-drops span {position:absolute;top:112px;width:5px;height:18px;border-radius:70% 40% 65% 65%;background:linear-gradient(180deg,#c7f1ff,#63c6ff);box-shadow:0 0 8px rgba(105,201,255,.3);opacity:0;animation:rainFall 1.35s linear infinite;}
Maybe rain drop teardrop with transform rotate(15deg). border-radius: 70% 30% 60% 40% /70% 40% 60% 30%; standard raindrops maybe capsule adequate. Weather icon uses falling rain drops often slanted capsules. Use width4 height18 border-radius:999px; transform rotate(14deg). Fine.
nth left calc(50%-55) etc:
1 left:calc(50% - 54px); delay:-.2
2 left:calc(50% - 28px); delay:-.85; duration1.5
3 left:calc(50% - 1px); delay:-.45
4 left:calc(50% + 27px); delay:-1.1
5 left:calc(50% + 50px); delay:-.65
@keyframes rainFall {0% {opacity:0;transform:translate3d(4px,-10px,0) rotate(12deg);}20% {opacity:1;}85% {opacity:.9;}100% {opacity:0;transform:translate3d(-7px,48px,0) rotate(12deg);}}
Total stage 196; top112+48+18=178 good.
Snowflakes similar top112; animation 3s. .snowflakes span {position:absolute;top:111px;width:17px;height:2px;background:#fff;border-radius:99px;box-shadow:0 0 6px rgba(...);opacity:0;animation:snowFall 3.2s linear infinite;} .snowflakes span::before,.after {content:"";position:absolute;inset:0;background:inherit;border-radius:inherit;} before rotate60 after rotate120. But animation transforms span rotate and scale, pseudo rotate works. span box-shadow maybe weird asterisk lines but okay. Position left same. --drift values negative positive. nth durations etc. .snowflakes span:nth-child(2){--size:.75; ...} custom props. In @keyframes 0 transform translate3d(0,-12px,0) rotate(0deg) scale(var(--size));100 transform translate3d(var(--drift),56px,0) rotate(180deg) scale(var). Opacity mid. .snowflakes span background white; snow card background light still white visible against blue cloud and light card maybe flake falls below cloud onto pale background low contrast. Use #ffffff with text-shadow? Filter drop-shadow(0 1px 3px #6b9eb6) on each; background #fff; box-shadow:0 0 0 1px rgba(80,130,155,.08),0 0 7px rgba(255,255,255,.9). White against #c3dce9 enough subtle. Could flakes colored #fff with darker outline impossible but drop shadow helps.
Cloud top 50, bottom cloud puffs up; flakes below at110.
Storm cloud and bolt:
.storm-scene::before {content:"";position:absolute;inset:15px 20px 0;border-radius:50%;background:radial-gradient(circle,rgba(255,229,117,.32),transparent 65%);opacity:0;animation:skyFlash 3.4s linear infinite;}
.bolt {position:absolute;z-index:3;left:50%;top:105px;width:46px;height:80px;margin-left:-16px;background:linear-gradient(180deg,#fffde2 0%,#ffe269 45%,#ffb928 100%);clip-path:polygon(52% 0,100% 0,66% 39%,93% 39%,17% 100%,39% 55%,8% 55%);filter:drop-shadow(0 0 8px rgba(255,221,80,.9));transform-origin:50% 20%;animation:boltFlash 3.4s linear infinite;}
Keyframes lightning: typical flashes around 0,8,12 then rest low opacity? Requirement flashing lightning. Should always visible enough first screenshot 3 sec. If at 3 sec opacity .35 may still visible. Make baseline .55 and flash 1.
0%,100% opacity:.45 transform scale(.96); 5% .45; 7%1 scale1.08;9%.25;11%1;15%.55;50%.4;52%1;55%.45. Infinite 3.2. At screenshot any visible. But bolt baseline .65 maybe better. Scene flash matching.
Maybe two mini rain streaks left/right at top120 with animations for storm extra. Could include .storm-rain span 3 similar but dark background blue rain visible. Not required but good. Yet avoid clutter.
Storm icon cloud top50. Bolt at110 to185 stage196. Good. Perhaps cloud float transform means bolt doesn't follow exactly but subtle.
Rain icon cloud high, snow. All share cloudFloat same phase unless animation-delay per card negative to organic.
Card hover:
.weather-card:hover {transform:translateY(-10px);}
.weather-card:hover .icon-stage maybe no.
At mobile, hover no issue.
@media (hover:hover) maybe only apply on hover capable.
Grid at 1280: page max 1240? .page max-width:1280 padding 32 => content1216; 4 cards with gaps18 gives (1216-54)/4=290.5. good. Height460.
At 1024 media <=1100 2 columns, page padding 24, cards maybe 460 wide huge but can set max? grid 2. Height maybe 440. Requirement desktop 4 per row maybe desktop 1024 typically 4? User might test 1280. "4 per row on desktop" often media min 1024. I can set breakpoint 1050 or 980. At 1024 content 976, four cards (976-54)/4=230.5; city fine, icon 170, padding22 -> content186, okay details. Could still 4 at 1024 if breakpoint900. But at 900 cards 195 too small. Use @media(max-width:1023px) 2. 1024 4. Good. At 1100 card 252. fine. Set media max-width:1000 maybe. Standard desktop >=1024. @media(max-width:1023px){grid 2;} @media(max-width:640px){grid 1;}. At 768 2 cards each ~342. Good. At 375 page padding16 =>343 card. card height maybe430. Header stacked. No horizontal.
Page mobile:
.page padding:28px 16px.
.header align-items:flex-start; flex-direction:column; gap:18px; .header-side align-self:stretch? Status etc.
h1 font-size clamp maybe 38 at375. subtitle max.
.weather-card height:440 maybe; padding24; border-radius24.
.grid gap16.
.footer flex-direction column.
No horizontal.
At 640 maybe card one and height440. At 375 header status two badges? Keep only live badge and small text "4 cities". Header-side display flex align center gap. At desktop align right column? Could make <div class=header-side><div class=live><i> ...</div><p>4 cities · CSS forecast</p></div> . At mobile flex row justify space-between width100. Good.
Footer <p><span class footer-dot></span> Conditions rendered entirely with CSS</p><span>Animations adapt to your motion preferences</span>. This explicitly conveys.
Accessibility: each article aria-label="Sunny weather in Lisbon, 24 degrees Celsius" or headings. Icons aria-hidden true. Temp include visually hidden unit maybe <span class=sr-only>degrees Celsius</span><span aria-hidden>24°</span>? I can simple <div class=temperature aria-label="24 degrees Celsius">24°</div>. aria-label on div works maybe role=text not universal; acceptable. Use <p class=temperature><span aria-hidden=true>24°</span><span class=sr-only>24 degrees Celsius</span></p>. But duplication if aria label not considered. Better <div class="temperature">24<span class="degree">°</span><span class="sr-only">Celsius</span></div> reads 24 degrees Celsius. Visual only 24°. Good. City heading h2. Description <p>. Details with labels.
No inline style needed. Use nth-child selectors. Should count ray spans 12. No JS. No external assets. No images or svg.
Could use CSS @property? no. Ensure latest Chrome yes. backdrop-filter okay but no need.
Color-scheme dark makes default but cards dark text forms no forms.
Body maybe min-height 100svh. background.
At 1280 screenshot 3 sec animations in progress, all visible due negative delays. Sun rotating. Rain negative delays ensures drops mid-fall. Snow negative delays. Bolt keyframes at ~3 sec if duration3.6 baseline .6 still visible. Good.
Infinite animations. Header status pulse. Respect reduced.
Could add demo start message? Not a game, no need.
Should have exactly one code block. Let's construct full HTML. Let's refine sizes. Cards min-height or fixed height? Requirement adapt gracefully. Use min-height:458px; rather than height so content can expand. But grid align stretch. On desktop all min-height same. .weather-card padding24. .icon-stage height190 flex-shrink:0. bottom margin-top:auto. If min-height, bottom naturally? article flex column min-height. Works. All card same min height. On mobile min-height:438. I can use height:458px and at small font. Content fit. Let's calculate actual:
card top header label 11 line-height maybe 13 + city margin5 line28 =46. icon stage margin 6 top +190 +0 =196. temperature line-height .92 font66 =61; desc margin 12 0 18, line20 =50; details padding15+ border + labels line11+ gap4+ value line16 =46. Total 46+196+61+50+46=399. Padding 48 =>447. min-height458 leaves11 margin auto. Good.
Header page total maybe:
page padding top36 bottom28
header .kicker 13, h1 margin12 top 8 bottom? h1 49, subtitle margin12 20 =>102. header bottom margin24 =>126.
cards458.
footer margin20, line18 =38.
total 36+126+458+38+28=686. Great. Could vertical center? body no. top at36. Balanced.
Card top location. Icon stage sun170 within190. top 50%. Good.
Cloud .cloud top45? stage190, cloud base top48 height50; puffs bottom16 -> circle from top48+50-16-78 =4 to82, good. So cloud occupies y4..98. Drops top105 to171. Nice. .cloud top48. Before top base+50-16-78=4, after top48+50-18-64=16. nice. Base y48..98. Cloud overall height94. Perfect.
Cloud left center width154. Cloud before left22 and after right20. Overall puff x22..100 and right base x70..134, inside base horizontally. Good. cloud outline shape.
Cloud base z-index? .cloud::before and after have background, base children pseudos painted before content? Pseudo before is first child; both could cover base but same. No issue. box shadow only base rectangle pill not puffs, maybe add filter drop-shadow on .cloud instead of box-shadow would include pseudos? filter drop-shadow applies entire element including pseudo yes. Use filter:drop-shadow(0 10px 10px var(--cloud-shadow)); animation transform. But storm bolt filter separate. filter custom var rgba okay. Cloud filter may create containing? fine. Use box-shadow simpler. Add .cloud::before box-shadow:inset -10px -10px 20px rgba(37,68,90,.06) for depth but pseudo same. no.
Rain stage maybe .cloud background. Should card unique.
Sun color rays #fff7c4 on golden card contrast moderate but core bright. Good.
Sunny card text #4a330c. temperature shadow subtle.
Rain card perhaps rich blue; snow bright; storm purple.
Add top-right number in translucent small rounded square. Could show country code in city label:
<p class=region>PORTUGAL · 38.72° N</p><h2>Lisbon</h2>
Cities: Lisbon 24° "Golden light, clear skies" high low humidity? Details wind and humidity. Rainy: London 14° "Steady rain, soft skies" wind 12 km/h rain 80%. Snowy: Sapporo −3° "Quiet snow, frozen air" wind 8 km/h snow 90%. Stormy: Singapore 27° "Thunderstorms rolling in" wind 24 km/h storm 75%. Singapore storm at27 and dark gradient. Or "Reykjavík" snow -3. Four distinct regions.
Sunny city "Lisbon"; rainy "Seattle"; snowy "Sapporo"; stormy "Manila" (29). Use static generic no live claim maybe "CSS WEATHER ATLAS" and "A little atmosphere, everywhere." Header status "FORECAST IN MOTION" not real live. Weather "Now" and conditions. Footer "Four cities · one animated sky" and "Crafted with HTML + CSS". Status dot "CSS ONLY" could pulse but live conditions misleading. Use <span class=status-dot></span> ANIMATED FORECAST.
Title "Weather, in motion." subtitle "Four cities. Four atmospheres. One pure-CSS sky." Nice.
Kicker "THE ATMOSPHERE COLLECTION".
Top right badge "4 LIVE SCENES" maybe animation live no real data. "4 ANIMATED SCENES" and subtext "Hover to elevate".
Footer includes "Built without images or JavaScript" but user prohibits script tag, word JavaScript okay. Fine. "Pure HTML + CSS" concise. No need mention code restrictions in demo? Could add small "PURE CSS / 001". Polished.
Perhaps details include arrow up/down icons? Can't use icon fonts, can use plain text H/L. okay. No inline SVG.
I should include visually hidden h? h1. h2 city. Description.
Reduced motion:
@media (prefers-reduced-motion:reduce) {
*,*::before,*::after {animation:none !important; transition:none !important; scroll-behavior:auto !important;}
.rain-drops span {opacity:.85; transform:translateY(15px) rotate(12deg);}
.snowflakes span {opacity:.9; transform:translateY(16px) rotate(20deg) scale(var(--size));}
.bolt {opacity:1;transform:none;}
.storm-scene::before {opacity:.12;}
.status-dot {box-shadow:0 0 0 4px rgba(125,229,183,.12);}
}
No hover animation transition but transform still applied instant; okay. Could in reduced hover transform none to avoid motion entirely: .weather-card:hover {transform:none;} But hover lift is a static state not motion though safe. Set transform:none maybe requirement lift hover under standard, reduced intentionally off. Use @media (prefers-reduced-motion:reduce){.weather-card:hover{transform:none}}.
Universal animation none stops cloud etc. snowflake before after no animations. rays static.
Initial .rain drops opacity0 but override. Good.
Bolt baseline initial animation controls opacity? base .bolt opacity:.7 maybe. Define base opacity .7. Reduced1.
Sun core base transform none; pulse.
Status dot base background.
Potential issue CSS animations transform for .cloud which margin-left ensures center. good.
Cloud pseudo radial gradient? all good.
Rain drop transforms at end, negative animation delay works.
Snowflake --size variable set default1. nth. Keyframes custom var interpolated? transforms with var scale accepted.
Hover transform can conflict with card entrance no entrance. Fine.
Card use isolation:isolate and ::before z-index:-1. Because background on card itself, pseudo z-index -1 with isolation might be behind background and invisible? In stacking context, negative z-index pseudo is painted behind content but above background? CSS stacking: background/border of element forming stacking context painted first, then negative stack levels. So visible. Could instead z-index:0 pseudo and children z-index1, but not needed. .weather-card::before z-index:0 and .card-top etc position relative z1; but icon also. Simpler ::before pointer-events none z-index:0 and .weather-card > * {position:relative;z-index:1}. But icon-stage children absolute still okay. I can set .card-top,.icon-stage,.card-bottom{position:relative;z-index:1;} .icon-stage position already. ::before no negative. Then background glow overlays card background but under contents. Use ::after decorative circle bottom? optional.
Card ::before radial highlight.
Maybe add .sunny-card::after a fine ring decoration top right? No all icons enough.
Box shadow unique colors via --shadow variable: .weather-card box-shadow:0 18px 40px var(--shadow), inset 0 1px 0 rgba...; hover box-shadow 0 28px 56px var. custom --shadow includes rgba. Set default.
Transitions box-shadow .35s.
At hover .weather-card::before opacity? base1. no.
Focus visible maybe article tabindex=0. Could add to support keyboard interactions and hover equivalent .weather-card:focus-visible {transform:translateY(-10px);outline:3px solid rgba(255,...);outline-offset:4px;}. But non-interactive card focus may be weird. Yet visual demo doesn't need. Requirements only hover. Avoid tab indexes.
At touch, hover sticky but okay.
No horizontal scroll: .page max width etc, body overflow-x:hidden. Card filter may overflow clipped due card overflow hidden. Icons centered within. header h1 no long. Details gap. At 230 card content182, .details two details okay. City font 22 "Singapore" 100 px fits. Could use storm city "Singapore" width110; card at1024 content~182 fits. Top number 32 plus city, no issue.
At 375 content295, fine. Grid 1 at640. At 641 grid2, page 24*2 gives593, gaps16 each 288, good. At 1023 grid2 each ~465. At 1024 grid4 each ~229; a bit abrupt but okay. Could breakpoint1100 for better, but desktop at1024 maybe requirement 4. 1024 exactly4. Fine.
Should use clamp for h1. header side at <760 maybe header column? grid at2 but header maybe row; at640 header column. At 768 h1 40, header side width? okay.
@media(max-width:700px) header flex-direction column; grid remains2 until640 maybe at650 header column. Fine.
At mobile stacked exactly max640. Good.
Maybe 4 per row desktop includes width1280 yes.
Let's think if I can make visually richer icons with atmospheric small specks. Add .icon-stage::after subtle horizontal elliptical shadow under icons? For sun shadow not needed. Rain/snow/storm could use .cloud-icon::after {content:"";position:absolute;bottom:8px;left:50%;width:120px;height:12px;transform translateX; background:rgba(...);filter:blur(8px);border-radius:50%;opacity:.2;} Might create ground shadow but weather icons float, nice. Different --ground. Use pseudo already storm scene ::before for flash; ::after for ground could apply all. .cloud-icon::after ... z-index0; .storm-scene::before z-index0. Cloud z2 drops z1 bolt z3. ground ellipse behind.
Sun icon maybe ::after elliptical shadow not needed.
For storm cloud add small rain streaks: reuse .storm-drizzle with 3 spans left positions top112 width4 height14 bg#93b8ff opacity animation. But bolt occupies center. Use left calc50-52 and +50, two streaks. <div class=storm-drops><span></span><span></span><span></span></div>. Animate same rainFall but blue. Could overload. Requirements storm icon flashing lightning only, bolt enough. Could show cloud plus two small raindrops to convey storm. It adds visual complexity. Use <div class="storm-rain" aria-hidden=true><span></span><span></span></div> nested icon but parent already aria hidden. CSS .storm-rain span similar animation rainFall duration1.4; left calc ±50. But @keyframes rainFall translates top48, okay. Bolt center. Good.
Snowflake six-spoke CSS might look like simple star line; acceptable. Add a small center circle using box-shadow? Span line center maybe no circle. Could use .snowflakes span {border-radius...} and after rotates. Looks like snowflake. Could add tip branches impossible without more pseudo because used bars. Good enough.
Sun rays 12. CSS nth-child:
1 rotate0,2 30,3 60,4 90,5 120,6 150,7 180,8 210,9 240,10 270,11 300,12 330. Rotating entire .sun-rays. Initial negative animation delay? animation:spin 18s linear infinite; at 3s 60deg. fine.
Sun halo animation alternate. .sun-core animation pulse 4s ease-in-out infinite.
Cloud animation float 4s negative delay rain -1s snow -2s storm -3s maybe same class with per .rain-icon .cloud. Animation transform y. Negative ensures first frame variation.
Details maybe <div><span class=detail-label>Wind</span><span class=detail-value>9 km/h</span></div><div class=align-right><span...>Humidity</span> ... . Use values.
Snow precipitation maybe "Snowfall" "80%". Storm "Thunder" "70%".
I can include small high/low at temp right to use whitespace: .temp-line display flex justify-between align-end; .temperature; .range font-size11 margin-bottom5. At card width230, temp90 and range80 fits. Adds polish. Structure:
<div class=card-bottom>
<div class=temp-line>
<div class=temp>24<span...></span></div>
<div class=range><span>H 27°</span><span>L 18°</span></div>
</div>
<p class=description>Golden light & clear skies</p>
<div class=details>...
</div>
Range two spans column, color muted. At temperature font64.
Description short. Details top border.
Card top region font9.5 maybe. Browser default p margins reset specific.
Maybe weather card headers top on gradient. Good.
Body footer with divider? .footer border-top 1px rgba; margin-top24;padding-top18; display flex. At 686 total. Nice.
Should consider user asked HTML CSS only. Output HTML with CSS no JavaScript. Fine.
Should not mention code before. One block.
I can now formulate. Ensure not accidentally use inline event handlers. No style attrs maybe none. No external anything.
Let's draft complete code with around 500 lines maybe acceptable. I have huge token budget but no need. Could create concise ~450 lines.
Let's verify animations reduced universal selector affects status-dot ::after? status-dot maybe box-shadow pulse only. .live-dot animation livePulse. Keyframes livePulse with box-shadow. reduced none.
Status badge:
.header-side {display:flex;flex-direction:column;align-items:flex-end;gap:10px;padding-bottom:4px}
.motion-badge {display:inline-flex;align-items:center;gap:9px;padding:10px 14px;border:1px solid rgba(...);border-radius:999px;background:rgba(255,255,255,.04);color:#b6c7d4;font-size:10px;font-weight:700;letter-spacing:.12em;white-space:nowrap;}
.live-dot {width:7px;height:7px;border-radius:50%;background:#79ddb0;box-shadow...;animation:livePulse 2s ...}
.header-note margin0;color#637b8e;font-size11.
Header h1 color#f0f5f8. span color#8ba0b2 maybe font-weight400.
kicker color#7f98aa.
Subtitle color#8ba0b2.
Background body ::before fixed inset 0 gradient. z-index? body::before position fixed, no z-index defaults stack as child; .page position relative z-index1 to ensure. pointer none. Body background #08111c.
Body ::after with grid maybe position fixed inset0 background-image linear gradients? "No images" could interpret no CSS background-image? They say no images meaning no image assets; gradients required. CSS linear gradient okay. But avoid grid. Use only radial gradients. body::before can have multiple background gradients. Good.
Card background gradient explicitly. Additional card radial before.
Cloud pseudo background uses linear gradient inherited variables. CSS filter drop-shadow with var custom property. Syntax filter:drop-shadow(0 10px 10px var(--cloud-shadow)); accepted color var. Cloud animation transform changes filter no.
Rain card cloud puffs light. snow cloud #fff/#dcebf2. storm #69728a/#343b55.
Storm bolt keyframes:
@keyframes boltFlash {
0%,4%,10%,16%,48%,55%,100% {opacity:.62;transform:scale(1);}
6%,12%,51% {opacity:1;transform:scale(1.09);}
8%,14%,53% {opacity:.28;transform:scale(.97);}
}
At t=3s of 3.4 (88%) .62. At t=0 screenshot initial .62. Flash at 6% (~0.2s),12% etc. Great.
Sky flash:
0,4,10,16,48,55,100 opacity0;6,12,51 .55;8,14,53 .08.
Drop shadow always .8 even when low opacity applies opacity whole bolt so good.
Lightning z3 over cloud? Bolt top105 below cloud bottom98 so not overlap much. Maybe top96 for connection. Set top:99, height82 ends181. cloud base ends98. Perfect. Clip path. .bolt width46.
storm-rain top112 ends; left ±52.
Raindrops base top105 (cloud base bottom98) good. snow top107. Keyframe 100 +52 =>159 plus line height17 =176. stage190. Fine.
Ground shadow bottom3 y177 maybe overlaps drops fade but okay.
Snowflake --drift, --size and left. Nth:
1 left calc(50%-55), animation-delay:-.4,duration3.2,--drift:14px,--size:.85
2 left calc50-30, delay:-2.1,duration3.8,drift:-12,size:1.1
3 left calc50-2, delay:-1.2,dur3.4,drift8,size:.75
4 left calc50+27,delay:-2.8,dur4,drift:-15,size:1
5 left calc50+50,delay:-.9,dur3.6,drift:10,size:.7.
At first paint negative ensures visible. Keyframes opacity 0 at0, 15 .95,80 .9,1000. Some at negative could near end invisible but five enough.
Rain delays negative all.
Storm drops reuse rainFall; base opacity0 and animation. z1. At top112 with left ±50, no central.
Maybe storm-rain span CSS same dimensions, background#8fb6ff.
Cloud variables set on .cloud-icon to be inherited into .cloud. .cloud {-- defaults}. cloud-highlight not needed.
Range align right, details align right. Good.
Media:
@media (max-width:1023px) {
.page {max-width:820px;} maybe grid2 at width1023 cards ~475 if max width820 means content~756 each370, nice; at1280 no. Setting max-width:900 at media can center. At 768 content720 cards352. At 1023 max900 padding28 content844 cards413. fine. Header h1.
.weather-card {min-height:448px;} icons same.
}
But page max width change from1280 to900 abrupt at breakpoint but okay. At1024 4 cards229, at1023 2 cards414 big; responsive normal. Could no max to cards 475 huge. Better max-width:920.
@media (max-width:700px) header col.
@media(max-width:640px){.page{padding:26px 16px 24px;max-width:480px;} .grid{grid-template-columns:1fr;gap:16;} .weather-card{min-height:442px;padding:24px;border-radius:24px;} .header{margin-bottom:22px;} .header-side{width:100%;flex-direction:row;justify-content:space-between;align-items:center;} .footer{align-items:flex-start;flex-direction:column;gap:8px;} }
At 375 max480 actual width375. Card content295. Good.
@media(max-width:380px){h1 font-size:36 maybe clamp already; .motion-badge font-size9 padding9 11; .header-note font-size10;} Not needed no overflow: header side badge ~162, note "Hover to lift a card" ~100 + gap maybe >343? 162+100=262 okay.
Footer text long "Animation follows your system preferences" width maybe wrap. flex column.
Temperature letter-spacing negative, degree maybe font-size .55em vertical-align top margin-left2. Standard temp visual "24°" with degree smaller maybe top. .degree {font-size:.55em;vertical-align:top;display:inline-block;margin-top:.08em;margin-left:.04em;letter-spacing:0;} Then minus sign works. Screen reader with hidden Celsius. E.g <div class=temperature>−3<span class=degree aria-hidden=true>°</span><span class=sr-only>degrees Celsius</span></div> screen reader reads minus three then degrees Celsius. For 24 same. Good. `aria-hidden` degree hides degrees symbol but hidden text includes degrees. For screen reader text "24degrees Celsius" no whitespace? Add space in sr-only content? " degrees Celsius" leading collapses maybe. fine. Simpler `<div class="temperature" aria-label="24 degrees Celsius">24<span class="degree">°</span></div>` aria-label on generic div is not reliably named unless role. Use role="text" not standard maybe. Use `<p class=temperature><span aria-hidden=true>24<span class=degree>°</span></span><span class=sr-only>24 degrees Celsius</span></p>` robust. Visual outer p contains span. CSS p temp margin0. Do that each. Card content. .temperature > span aria hidden doesn't matter. Good.
Description heading? p.
One potential prohibition "No images, no SVG" use no <img>, no svg. CSS clip-path polygon okay.
No icon fonts. System font numbers not icons. Good.
No JS. Good.
Should I mention reduced-motion in footer? yes "Motion respects your system preference" static.
Let's assess aesthetic first paint: body dark, header bold, four tall colorful cards with weather icons animated. At screenshot 3 sec sun rays rotated, rain mid, snow mid, bolt maybe at 3 sec baseline. Great.
I should perhaps make lightning flash more frequent at 3 sec to judge animated if screenshots compared static won't show animation but requirement visual. Fine.
Cards hover lift via transform translateY(-10px) scale? requirement lift up; translate only. box shadow.
Transition with `will-change: transform` maybe no need.
No horizontal scrollbar from focus outline? no focus.
Weather-card overflow hidden clips shadow? box shadow outside not clipped by itself. Grid enough bottom. Hover top -10 within header gap. okay.
Cloud `filter:drop-shadow` and card overflow hidden fine.
Sun ray transform origin correct: .sun-rays spans top2? I'll set .sun-rays inset0; span top3 left calc50%-2 height20 transform-origin2px82px, center85. yes. Rotation 90 ray initially vertical above center, rotates to right etc.
Halo inset26 =>118 diameter, core90. Rays inner endpoint center distance62, core radius45 gap17. halo radius59 under ray inner maybe glow ring. fine.
Sun icon170 in stage190, top10.
Sun background radial core.
Card before radial shine on snow maybe bright but okay.
Add `.weather-card > * { position:relative; z-index:1; }` .card-top already flex but position relative okay. .icon-stage position relative already. .card-bottom. This sets all direct children relative. Could affect .card-top no issue. Use .weather-card::before z-index:0. .card-bottom margin-top:auto.
No other pseudo card. fine.
Body `font-synthesis:none` optional.
`-webkit-font-smoothing:antialiased`.
Selection colors maybe no.
Could use `text-wrap:balance` h1 and subtitle latest Chrome but graceful. Add.
No script tag includes `<meta ...>` okay.
Respond with the code.