MiniMax M3
by MiniMaxreasoning defaultClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 2 min 11 s
- Cost
- $0.027
- Output tokens
- 22,147
- Spent thinking
- 12,376 tokens
- Speed
- 170 tok/s
- Console errors
- 0
- First token after
- 558 ms
- First visible text after
- 1 min 40 s
- Prompt tokens
- 679
- Code size
- 29.8 KB
- Finish reason
- stop
- Served by
- Minimax
- Model id
minimax/minimax-m3- Reasoning sent
model default- Max output
- 512,000 tokens
- Generated
- Nov 13, 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 · 1138 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#090e1d">
<title>Atmos — Weather in Motion</title>
<style>
:root {
color-scheme: dark;
--ink: #f7f9ff;
--muted: rgba(226, 234, 255, 0.62);
--glass: rgba(255, 255, 255, 0.09);
--line: rgba(255, 255, 255, 0.15);
--ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}
* {
box-sizing: border-box;
}
html {
min-width: 320px;
background: #080d19;
}
body {
position: relative;
isolation: isolate;
min-width: 320px;
min-height: 100vh;
margin: 0;
overflow-x: hidden;
color: var(--ink);
background:
radial-gradient(circle at 8% 0%, rgba(53, 118, 255, 0.2), transparent 31rem),
radial-gradient(circle at 94% 24%, rgba(145, 79, 255, 0.17), transparent 28rem),
radial-gradient(circle at 55% 100%, rgba(36, 185, 190, 0.08), transparent 32rem),
linear-gradient(145deg, #0b1428 0%, #090e1d 48%, #070a14 100%);
font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
-webkit-font-smoothing: antialiased;
}
body::before {
position: fixed;
z-index: -1;
inset: 0;
content: "";
pointer-events: none;
background-image:
linear-gradient(rgba(255, 255, 255, 0.025) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.025) 1px, transparent 1px);
background-size: 52px 52px;
mask-image: radial-gradient(circle at 50% 35%, black, transparent 78%);
opacity: 0.7;
}
.page {
width: min(100%, 1340px);
min-height: 100vh;
margin: 0 auto;
padding: 25px 28px 18px;
display: flex;
flex-direction: column;
}
.masthead {
display: flex;
align-items: center;
justify-content: space-between;
gap: 24px;
}
.brand {
display: flex;
align-items: center;
gap: 12px;
}
.brand-mark {
position: relative;
width: 40px;
height: 40px;
flex: 0 0 auto;
overflow: hidden;
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 13px;
background: linear-gradient(145deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0.035));
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15);
}
.brand-mark::before {
position: absolute;
top: 9px;
left: 10px;
width: 11px;
height: 11px;
content: "";
border-radius: 50%;
background: #ffd36c;
box-shadow: 0 0 12px rgba(255, 211, 108, 0.75);
}
.brand-mark::after {
position: absolute;
bottom: 8px;
left: 8px;
width: 25px;
height: 13px;
content: "";
border: 2px solid #8edcff;
border-top-color: transparent;
border-radius: 50%;
transform: rotate(-9deg);
}
.brand-type {
display: grid;
gap: 2px;
}
.brand-type strong {
font-size: 14px;
line-height: 1;
letter-spacing: 0.23em;
}
.brand-type span {
color: var(--muted);
font-size: 8px;
font-weight: 700;
letter-spacing: 0.2em;
}
.live-chip {
display: flex;
align-items: center;
gap: 9px;
padding: 9px 13px;
border: 1px solid var(--line);
border-radius: 999px;
color: rgba(255, 255, 255, 0.72);
background: rgba(255, 255, 255, 0.045);
font-size: 9px;
font-weight: 700;
letter-spacing: 0.14em;
backdrop-filter: blur(12px);
}
.live-dot {
width: 7px;
height: 7px;
border-radius: 50%;
background: #74e9b1;
box-shadow: 0 0 0 0 rgba(116, 233, 177, 0.5);
animation: livePulse 2.2s ease-out infinite;
}
.chip-divider {
width: 1px;
height: 13px;
background: rgba(255, 255, 255, 0.16);
}
.live-chip time {
color: #fff;
font-variant-numeric: tabular-nums;
}
.hero {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 36px;
margin: 23px 0 22px;
}
.eyebrow {
display: flex;
align-items: center;
gap: 9px;
margin: 0 0 9px;
color: rgba(255, 255, 255, 0.55);
font-size: 9px;
font-weight: 800;
letter-spacing: 0.21em;
}
.eyebrow::before {
width: 22px;
height: 1px;
content: "";
background: linear-gradient(90deg, #ffd170, rgba(255, 209, 112, 0));
}
.hero h1 {
margin: 0;
font-size: clamp(38px, 4.1vw, 53px);
font-weight: 650;
line-height: 1.02;
letter-spacing: -0.055em;
}
.hero h1 span {
color: transparent;
background: linear-gradient(90deg, #ffe38b 5%, #ffa99e 62%, #c6b5ff 100%);
background-clip: text;
-webkit-background-clip: text;
}
.intro-subtitle {
margin: 8px 0 0;
color: var(--muted);
font-size: 13px;
line-height: 1.5;
letter-spacing: 0.01em;
}
.hero-counter {
display: flex;
align-items: center;
gap: 12px;
min-width: 126px;
padding: 12px 16px;
border: 1px solid rgba(255, 255, 255, 0.11);
border-radius: 18px;
background: linear-gradient(145deg, rgba(255, 255, 255, 0.075), rgba(255, 255, 255, 0.025));
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
backdrop-filter: blur(14px);
}
.counter-number {
color: #fff;
font-size: 31px;
font-weight: 300;
line-height: 1;
letter-spacing: -0.06em;
}
.counter-label {
color: rgba(255, 255, 255, 0.52);
font-size: 8px;
font-weight: 800;
line-height: 1.55;
letter-spacing: 0.17em;
}
.weather-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 16px;
min-width: 0;
}
.weather-card {
position: relative;
isolation: isolate;
min-width: 0;
min-height: 518px;
overflow: hidden;
padding: 20px 19px 17px;
display: flex;
flex-direction: column;
color: #fff;
border: 1px solid rgba(255, 255, 255, 0.22);
border-radius: 27px;
box-shadow:
0 18px 38px rgba(0, 0, 0, 0.22),
inset 0 1px 0 rgba(255, 255, 255, 0.2);
transform: translateY(0);
transition:
transform 0.38s var(--ease-out),
border-color 0.38s ease,
box-shadow 0.38s ease;
}
.weather-card::before {
position: absolute;
z-index: 0;
inset: 0;
content: "";
pointer-events: none;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.12), transparent 38%);
}
.weather-card::after {
position: absolute;
z-index: 0;
bottom: -180px;
left: 50%;
width: 260px;
height: 260px;
content: "";
border-radius: 50%;
background: rgba(255, 255, 255, 0.12);
filter: blur(18px);
opacity: 0.26;
transform: translateX(-50%);
pointer-events: none;
}
.weather-card > * {
position: relative;
z-index: 1;
}
.sunny-card {
background:
radial-gradient(circle at 50% 30%, rgba(255, 250, 190, 0.62), transparent 31%),
linear-gradient(155deg, #ffbd57 0%, #ff845d 48%, #d94e78 100%);
}
.sunny-card::after {
background: #ffca70;
}
.rainy-card {
background:
radial-gradient(circle at 75% 5%, rgba(126, 192, 255, 0.22), transparent 31%),
linear-gradient(155deg, #355e8b 0%, #203e6b 48%, #101d3d 100%);
}
.rainy-card::after {
background: #3fa8e8;
}
.snowy-card {
background:
radial-gradient(circle at 26% 4%, rgba(239, 252, 255, 0.46), transparent 30%),
linear-gradient(155deg, #91bad7 0%, #7188b6 48%, #59659a 100%);
}
.snowy-card::after {
background: #d8efff;
}
.stormy-card {
background:
radial-gradient(circle at 78% 2%, rgba(177, 137, 255, 0.3), transparent 29%),
linear-gradient(155deg, #57416f 0%, #302a50 48%, #151a37 100%);
}
.stormy-card::after {
background: #a978ff;
animation: stormPulse 3.6s ease-in-out infinite;
}
@media (hover: hover) {
.weather-card:hover {
z-index: 3;
border-color: rgba(255, 255, 255, 0.42);
box-shadow:
0 28px 54px rgba(0, 0, 0, 0.32),
inset 0 1px 0 rgba(255, 255, 255, 0.28);
transform: translateY(-9px);
}
}
.card-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
}
.city {
margin: 0;
font-size: 20px;
font-weight: 700;
line-height: 1.1;
letter-spacing: -0.025em;
text-shadow: 0 2px 12px rgba(0, 0, 0, 0.16);
}
.country {
margin: 5px 0 0;
color: rgba(255, 255, 255, 0.62);
font-size: 8px;
font-weight: 800;
letter-spacing: 0.16em;
text-transform: uppercase;
}
.weather-pill {
display: inline-flex;
align-items: center;
gap: 6px;
flex: 0 0 auto;
padding: 7px 9px;
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 999px;
color: rgba(255, 255, 255, 0.86);
background: rgba(255, 255, 255, 0.11);
font-size: 8px;
font-weight: 800;
letter-spacing: 0.12em;
text-transform: uppercase;
backdrop-filter: blur(9px);
}
.weather-pill::before {
width: 5px;
height: 5px;
content: "";
border-radius: 50%;
background: currentColor;
box-shadow: 0 0 8px currentColor;
}
.icon-stage {
position: relative;
z-index: 1;
height: 205px;
margin: 1px 0 3px;
}
.sunny-card .icon-stage::before {
position: absolute;
top: 17px;
left: 50%;
width: 160px;
height: 160px;
content: "";
border-radius: 50%;
background: radial-gradient(circle, rgba(255, 249, 183, 0.36), transparent 68%);
filter: blur(4px);
transform: translateX(-50%);
animation: sunHalo 3.2s ease-in-out infinite;
}
.sun-scene {
position: absolute;
top: 17px;
left: 50%;
width: 170px;
height: 170px;
margin-left: -85px;
animation: sunFloat 4.6s ease-in-out infinite;
}
.sun-rays {
position: absolute;
inset: 0;
border-radius: 50%;
animation: sunSpin 16s linear infinite;
}
.sun-rays::before {
position: absolute;
inset: 23px;
content: "";
border: 1px dashed rgba(255, 255, 255, 0.22);
border-radius: 50%;
animation: sunSpin 24s linear infinite reverse;
}
.sun-rays i {
position: absolute;
top: 50%;
left: 50%;
width: 4px;
height: 19px;
margin-left: -2px;
border-radius: 99px;
background: linear-gradient(180deg, #fff9c9, #ffd45b);
box-shadow: 0 0 9px rgba(255, 230, 114, 0.82);
}
.sun-rays i:nth-child(1) { transform: translate(-50%, -68px) rotate(0deg); }
.sun-rays i:nth-child(2) { transform: translate(-50%, -68px) rotate(45deg); }
.sun-rays i:nth-child(3) { transform: translate(-50%, -68px) rotate(90deg); }
.sun-rays i:nth-child(4) { transform: translate(-50%, -68px) rotate(135deg); }
.sun-rays i:nth-child(5) { transform: translate(-50%, -68px) rotate(180deg); }
.sun-rays i:nth-child(6) { transform: translate(-50%, -68px) rotate(225deg); }
.sun-rays i:nth-child(7) { transform: translate(-50%, -68px) rotate(270deg); }
.sun-rays i:nth-child(8) { transform: translate(-50%, -68px) rotate(315deg); }
.sun-core {
position: absolute;
top: 47px;
left: 47px;
width: 76px;
height: 76px;
border: 1px solid rgba(255, 255, 255, 0.56);
border-radius: 50%;
background:
radial-gradient(circle at 34% 28%, #fffde7 0 8%, transparent 9%),
radial-gradient(circle at 38% 32%, #fff7ad 0%, #ffd43e 45%, #ffad2d 100%);
box-shadow:
0 0 0 8px rgba(255, 225, 100, 0.12),
0 0 35px rgba(255, 216, 73, 0.62),
inset -8px -9px 18px rgba(255, 137, 48, 0.24);
animation: sunPulse 3.2s ease-in-out infinite;
}
.sun-core::after {
position: absolute;
inset: 10px;
content: "";
border: 1px solid rgba(255, 255, 255, 0.25);
border-radius: 50%;
}
.rain-scene,
.snow-scene,
.storm-scene {
position: absolute;
top: 8px;
left: 50%;
width: 190px;
height: 190px;
margin-left: -95px;
}
.cloud {
position: absolute;
z-index: 3;
top: 31px;
left: 18px;
width: 154px;
height: 59px;
border-radius: 52px;
background: linear-gradient(180deg, #e9f4ff 0%, #a9c2df 100%);
box-shadow:
inset 0 -9px 17px rgba(50, 85, 130, 0.16),
0 13px 24px rgba(12, 35, 68, 0.22);
animation: cloudBob 4.2s ease-in-out infinite;
}
.cloud::before,
.cloud::after {
position: absolute;
content: "";
border-radius: 50%;
background: inherit;
}
.cloud::before {
top: -31px;
left: 16px;
width: 65px;
height: 65px;
}
.cloud::after {
top: -43px;
left: 61px;
width: 80px;
height: 80px;
}
.rain-drop {
position: absolute;
z-index: 2;
top: 88px;
width: 6px;
height: 17px;
border-radius: 60% 40% 58% 42%;
background: linear-gradient(180deg, rgba(211, 242, 255, 0.98), rgba(84, 185, 239, 0.88));
box-shadow: 0 0 7px rgba(108, 206, 255, 0.42);
opacity: 0;
animation: rainFall 1.25s linear infinite;
}
.rain-drop::after {
position: absolute;
top: 3px;
left: 1px;
width: 1px;
height: 7px;
content: "";
border-radius: 99px;
background: rgba(255, 255, 255, 0.62);
}
.rain-drop.d1 { left: 21px; animation-delay: -0.12s; }
.rain-drop.d2 { left: 43px; animation-delay: -0.72s; animation-duration: 1.08s; }
.rain-drop.d3 { left: 66px; animation-delay: -0.36s; }
.rain-drop.d4 { left: 88px; animation-delay: -0.93s; animation-duration: 1.15s; }
.rain-drop.d5 { left: 110px; animation-delay: -0.54s; }
.rain-drop.d6 { left: 132px; animation-delay: -0.2s; animation-duration: 1.08s; }
.rain-drop.d7 { left: 151px; animation-delay: -0.82s; }
.rain-drop.d8 { left: 33px; animation-delay: -1.02s; animation-duration: 1.32s; }
.rain-drop.d9 { left: 98px; animation-delay: -0.63s; animation-duration: 1.32s; }
.rain-drop.d10 { left: 143px; animation-delay: -0.42s; animation-duration: 1.35s; }
.snow-scene .cloud {
top: 21px;
background: linear-gradient(180deg, #f6fbff 0%, #c8d9eb 100%);
box-shadow:
inset 0 -8px 15px rgba(86, 117, 153, 0.13),
0 13px 25px rgba(31, 55, 95, 0.18);
animation-duration: 4.8s;
}
.snowflake {
position: absolute;
z-index: 2;
width: 16px;
height: 16px;
opacity: 0;
filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.7));
animation: snowFall 4.6s linear infinite;
}
.snowflake i {
position: absolute;
top: 50%;
left: 50%;
width: 1.5px;
height: 16px;
border-radius: 99px;
background: #fff;
transform-origin: center;
}
.snowflake i:nth-child(1) { transform: translate(-50%, -50%) rotate(0deg); }
.snowflake i:nth-child(2) { transform: translate(-50%, -50%) rotate(60deg); }
.snowflake i:nth-child(3) { transform: translate(-50%, -50%) rotate(120deg); }
.snowflake i::after {
position: absolute;
top: 4px;
left: 0;
width: 5px;
height: 1px;
content: "";
border-radius: 99px;
background: #fff;
box-shadow: 0 7px 0 #fff;
}
.snowflake.f1 { top: 81px; left: 21px; animation-delay: -0.2s; }
.snowflake.f2 { top: 75px; left: 50px; animation-delay: -2.1s; animation-duration: 5.2s; }
.snowflake.f3 { top: 84px; left: 82px; animation-delay: -1.3s; animation-duration: 4.3s; }
.snowflake.f4 { top: 73px; left: 113px; animation-delay: -3.4s; animation-duration: 5.6s; }
.snowflake.f5 { top: 82px; left: 146px; animation-delay: -0.8s; animation-duration: 4.9s; }
.snowflake.f6 { top: 72px; left: 35px; animation-delay: -3.8s; animation-duration: 5.7s; }
.snowflake.f7 { top: 77px; left: 128px; animation-delay: -2.7s; animation-duration: 4.7s; }
.storm-scene .cloud {
top: 16px;
background: linear-gradient(180deg, #afb3ca 0%, #5d6179 100%);
box-shadow:
inset 0 -10px 17px rgba(24, 25, 46, 0.3),
0 13px 26px rgba(8, 9, 25, 0.38);
animation-duration: 3.7s;
}
.bolt {
position: absolute;
z-index: 4;
top: 78px;
left: 71px;
width: 52px;
height: 88px;
background: linear-gradient(135deg, #fffde0 0%, #ffe45e 43%, #ff9f36 100%);
clip-path: polygon(53% 0, 100% 0, 67% 38%, 91% 38%, 24% 100%, 42% 55%, 12% 55%);
filter: drop-shadow(0 0 8px rgba(255, 224, 89, 0.9));
opacity: 0.88;
transform: rotate(-3deg);
animation: lightningFlash 3.4s ease-in-out infinite;
}
.bolt::after {
position: absolute;
inset: 5px 12px 9px 4px;
content: "";
background: linear-gradient(180deg, #fff, rgba(255, 255, 255, 0.18));
clip-path: polygon(53% 0, 100% 0, 67% 38%, 91% 38%, 24% 100%, 42% 55%, 12% 55%);
}
.reading-head {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 12px;
}
.temperature {
display: flex;
align-items: flex-start;
font-size: clamp(58px, 5vw, 70px);
font-weight: 300;
line-height: 0.9;
letter-spacing: -0.075em;
font-variant-numeric: tabular-nums;
text-shadow: 0 7px 22px rgba(0, 0, 0, 0.17);
}
.temperature sup {
margin: 4px 0 0 3px;
font-size: 27px;
font-weight: 300;
line-height: 1;
letter-spacing: 0;
}
.condition {
padding-bottom: 4px;
color: rgba(255, 255, 255, 0.83);
font-size: 11px;
font-weight: 750;
letter-spacing: 0.08em;
text-align: right;
text-transform: uppercase;
}
.description {
min-height: 39px;
margin: 10px 0 16px;
color: rgba(255, 255, 255, 0.68);
font-size: 12px;
line-height: 1.55;
}
.card-footer {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 8px;
margin-top: auto;
padding-top: 14px;
border-top: 1px solid rgba(255, 255, 255, 0.18);
}
.metric {
min-width: 0;
}
.metric span {
display: block;
margin-bottom: 5px;
color: rgba(255, 255, 255, 0.45);
font-size: 7px;
font-weight: 800;
letter-spacing: 0.14em;
}
.metric strong {
display: block;
overflow: hidden;
color: rgba(255, 255, 255, 0.92);
font-size: 12px;
font-weight: 650;
line-height: 1;
letter-spacing: 0.02em;
text-overflow: ellipsis;
white-space: nowrap;
}
.page-footer {
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
margin-top: 13px;
padding: 0 4px;
color: rgba(255, 255, 255, 0.35);
font-size: 8px;
font-weight: 700;
letter-spacing: 0.15em;
text-transform: uppercase;
}
.footer-motion {
display: inline-flex;
align-items: center;
gap: 8px;
}
.footer-motion::before {
width: 17px;
height: 1px;
content: "";
background: linear-gradient(90deg, #ffd170, #ff8ba1);
}
@keyframes livePulse {
0% { box-shadow: 0 0 0 0 rgba(116, 233, 177, 0.5); }
70% { box-shadow: 0 0 0 7px rgba(116, 233, 177, 0); }
100% { box-shadow: 0 0 0 0 rgba(116, 233, 177, 0); }
}
@keyframes sunSpin {
to { transform: rotate(360deg); }
}
@keyframes sunFloat {
0%, 100% { transform: translateY(-3px); }
50% { transform: translateY(5px); }
}
@keyframes sunPulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.045); }
}
@keyframes sunHalo {
0%, 100% { opacity: 0.58; transform: translateX(-50%) scale(0.96); }
50% { opacity: 0.92; transform: translateX(-50%) scale(1.06); }
}
@keyframes cloudBob {
0%, 100% { transform: translateX(-2px); }
50% { transform: translateX(3px); }
}
@keyframes rainFall {
0% { transform: translateY(-19px) rotate(12deg); opacity: 0; }
14% { opacity: 0.95; }
82% { opacity: 0.8; }
100% { transform: translateY(85px) rotate(12deg); opacity: 0; }
}
@keyframes snowFall {
0% { transform: translate3d(-7px, -15px, 0) rotate(0deg); opacity: 0; }
15% { opacity: 0.95; }
82% { opacity: 0.78; }
100% { transform: translate3d(11px, 73px, 0) rotate(230deg); opacity: 0; }
}
@keyframes lightningFlash {
0%, 18%, 22%, 43%, 47%, 70%, 74%, 100% {
opacity: 0.76;
filter: drop-shadow(0 0 7px rgba(255, 217, 71, 0.68));
}
20%, 45%, 72% {
opacity: 1;
filter: drop-shadow(0 0 15px rgba(255, 239, 133, 1));
}
}
@keyframes stormPulse {
0%, 100% { opacity: 0.18; }
45% { opacity: 0.36; }
48% { opacity: 0.22; }
52% { opacity: 0.44; }
58% { opacity: 0.22; }
}
@media (max-width: 1050px) {
.weather-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 640px) {
.page {
padding: 18px 17px 16px;
}
.brand-type span,
.live-chip .chip-divider,
.live-chip time,
.hero-counter {
display: none;
}
.live-chip {
padding: 8px 10px;
font-size: 8px;
}
.hero {
margin: 22px 0 18px;
}
.hero h1 {
max-width: 340px;
font-size: 37px;
}
.intro-subtitle {
max-width: 310px;
font-size: 12px;
}
.weather-grid {
grid-template-columns: 1fr;
gap: 15px;
}
.weather-card {
min-height: 510px;
border-radius: 24px;
}
.icon-stage {
height: 198px;
}
.page-footer {
justify-content: center;
}
.page-footer span:last-child {
display: none;
}
}
@media (max-width: 370px) {
.page {
padding-inline: 13px;
}
.weather-card {
padding-inline: 16px;
}
.city {
font-size: 18px;
}
.weather-pill {
padding-inline: 8px;
font-size: 7px;
}
.temperature {
font-size: 58px;
}
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation: none !important;
transition: none !important;
scroll-behavior: auto !important;
}
.weather-card:hover {
transform: none;
}
.sun-rays {
transform: rotate(18deg);
}
.rain-drop {
opacity: 0.72;
transform: translateY(28px) rotate(12deg);
}
.snowflake {
opacity: 0.8;
transform: translateY(24px);
}
.bolt {
opacity: 0.92;
}
}
</style>
</head>
<body>
<main class="page">
<header class="masthead">
<div class="brand">
<div class="brand-mark" aria-hidden="true"></div>
<div class="brand-type">
<strong>ATMOS</strong>
<span>WEATHER, IN MOTION</span>
</div>
</div>
<div class="live-chip" aria-label="Live global forecast">
<span class="live-dot" aria-hidden="true"></span>
<span>LIVE FORECASTS</span>
<span class="chip-divider" aria-hidden="true"></span>
<time datetime="2025-01-01T08:42:00Z">08:42 UTC</time>
</div>
</header>
<section class="hero">
<div>
<p class="eyebrow">FOUR CITIES / ONE LIVE SKY</p>
<h1>Weather with <span>atmosphere.</span></h1>
<p class="intro-subtitle">A miniature forecast studio, shaped entirely with HTML and CSS.</p>
</div>
<div class="hero-counter" aria-hidden="true">
<span class="counter-number">04</span>
<span class="counter-label">ACTIVE<br>MOODS</span>
</div>
</section>
<section class="weather-grid" aria-label="Animated city forecasts">
<article class="weather-card sunny-card">
<header class="card-header">
<div>
<h2 class="city">Lisbon</h2>
<p class="country">Portugal</p>
</div>
<span class="weather-pill">Sunny</span>
</header>
<div class="icon-stage" role="img" aria-label="Animated sunny icon with rotating rays">
<div class="sun-scene" aria-hidden="true">
<div class="sun-rays">
<i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i>
</div>
<div class="sun-core"></div>
</div>
</div>
<div class="reading">
<div class="reading-head">
<div class="temperature">26<sup>°</sup></div>
<div class="condition">Clear skies</div>
</div>
<p class="description">Golden warmth drifts in from the Atlantic.</p>
</div>
<footer class="card-footer">
<div class="metric"><span>FEELS LIKE</span><strong>27°</strong></div>
<div class="metric"><span>WIND</span><strong>8 km/h</strong></div>
<div class="metric"><span>UV INDEX</span><strong>6</strong></div>
</footer>
</article>
<article class="weather-card rainy-card">
<header class="card-header">
<div>
<h2 class="city">Seattle</h2>
<p class="country">United States</p>
</div>
<span class="weather-pill">Rainy</span>
</header>
<div class="icon-stage" role="img" aria-label="Animated rain cloud with falling drops">
<div class="rain-scene" aria-hidden="true">
<span class="cloud"></span>
<span class="rain-drop d1"></span>
<span class="rain-drop d2"></span>
<span class="rain-drop d3"></span>
<span class="rain-drop d4"></span>
<span class="rain-drop d5"></span>
<span class="rain-drop d6"></span>
<span class="rain-drop d7"></span>
<span class="rain-drop d8"></span>
<span class="rain-drop d9"></span>
<span class="rain-drop d10"></span>
</div>
</div>
<div class="reading">
<div class="reading-head">
<div class="temperature">14<sup>°</sup></div>
<div class="condition">Steady drizzle</div>
</div>
<p class="description">Soft rain taps a quiet rhythm across the city.</p>
</div>
<footer class="card-footer">
<div class="metric"><span>FEELS LIKE</span><strong>12°</strong></div>
<div class="metric"><span>HUMIDITY</span><strong>92%</strong></div>
<div class="metric"><span>WIND</span><strong>11 km/h</strong></div>
</footer>
</article>
<article class="weather-card snowy-card">
<header class="card-header">
<div>
<h2 class="city">Reykjavík</h2>
<p class="country">Iceland</p>
</div>
<span class="weather-pill">Snowy</span>
</header>
<div class="icon-stage" role="img" aria-label="Animated cloud with drifting snowflakes">
<div class="snow-scene" aria-hidden="true">
<span class="cloud"></span>
<span class="snowflake f1"><i></i><i></i><i></i></span>
<span class="snowflake f2"><i></i><i></i><i></i></span>
<span class="snowflake f3"><i></i><i></i><i></i></span>
<span class="snowflake f4"><i></i><i></i><i></i></span>
<span class="snowflake f5"><i></i><i></i><i></i></span>
<span class="snowflake f6"><i></i><i></i><i></i></span>
<span class="snowflake f7"><i></i><i></i><i></i></span>
</div>
</div>
<div class="reading">
<div class="reading-head">
<div class="temperature">−7<sup>°</sup></div>
<div class="condition">Gentle flurries</div>
</div>
<p class="description">Slow snowflakes soften a frosty blue morning.</p>
</div>
<footer class="card-footer">
<div class="metric"><span>FEELS LIKE</span><strong>−11°</strong></div>
<div class="metric"><span>SNOW</span><strong>4 cm</strong></div>
<div class="metric"><span>WIND</span><strong>16 km/h</strong></div>
</footer>
</article>
<article class="weather-card stormy-card">
<header class="card-header">
<div>
<h2 class="city">Osaka</h2>
<p class="country">Japan</p>
</div>
<span class="weather-pill">Stormy</span>
</header>
<div class="icon-stage" role="img" aria-label="Animated storm cloud with flashing lightning">
<div class="storm-scene" aria-hidden="true">
<span class="cloud"></span>
<span class="bolt"></span>
</div>
</div>
<div class="reading">
<div class="reading-head">
<div class="temperature">24<sup>°</sup></div>
<div class="condition">Thunderstorm</div>
</div>
<p class="description">Electric skies roll over the evening skyline.</p>
</div>
<footer class="card-footer">
<div class="metric"><span>FEELS LIKE</span><strong>26°</strong></div>
<div class="metric"><span>RAIN</span><strong>68%</strong></div>
<div class="metric"><span>WIND</span><strong>24 km/h</strong></div>
</footer>
</article>
</section>
<footer class="page-footer">
<span class="footer-motion">HTML + CSS motion study</span>
<span>Sunny · Rainy · Snowy · Stormy</span>
</footer>
</main>
</body>
</html>Reasoning trace (12,376 tokens)
We need answer exactly one fenced html complete. Need construct polished. Need no JS no SVG/images. CSS icon elements/pseudo. Four cards responsive 4 desktop, stacked mobile. Animated rays rotating, rain, snow drifting, lightning flashing. Respect reduced motion. Need self-contained meaningful first paint.
Need reason implementation. Use HTML semantic cards. CSS elaborate. Need ensure icons pure HTML and pseudo. Sun icon could .sun with .sun-core and 8 .ray spans, perhaps group rays rotate. "rotating sun rays" Use span class rays and 8 i. No SVG. Rain cloud with drops. Snow cloud flakes. Storm cloud bolt via CSS clip-path? Is clip-path okay no SVG; built CSS. Need icons.
Need 1280x800. likely page fits. Four cards in row with margins. Elegant weather dashboard. Need cards 4 per row desktop. At viewport 1280 content max maybe 1240, each 285. Height ~600. Background deep navy atmospheric. Header, status pill, cards. Need no JS.
Everything interesting visible first paint. Use animations. Add maybe labels / details. Requirements only city name temp desc. Could add "LIVE FORECAST" etc. We need likely visual quality. Let's design.
Page body gradient midnight blue with decorative radial glows via body::before/after perhaps. Main max width 1280 padding 30. Header top branding "ATMOS / LIVE WEATHER", right "4 cities • updated now" no dynamic. title maybe "Weather, beautifully in motion." Cards row.
At 1280x800: body 100%; header 80, title maybe 85, grid cards height ~540, footer. Need screenshot within full viewport. We can do min-height 100vh and grid.
Could have hero:
header flex align
brand icon CSS maybe cloud/sun? But requirement no external. Could avoid.
left title "Today's atmosphere" h1 44, subtitle.
right maybe clock "GLOBAL CONDITIONS / 08:42 UTC" static awkward. Fine.
Cards each own gradient:
sunny: linear gradient(135deg,#ffb347,#ff6b6b) maybe bright. Need text readability. Gradient specific. rainy blue. snowy lavender. stormy purple.
Cards border radius 26, box shadow, overflow hidden, hover translateY(-10px) scale perhaps. At desktop 4 cards. Each card top location row with chip and time-of-day. Big icon 190. Temp 62px. description. Bottom mini stats perhaps to enrich. Requirement city/temp/desc. We can include conditions and ranges. But keep polished.
Need animated icon:
Sunny:
.scene sun
rays wrapper absolute inset, rotate linear infinite.
8 ray elements positions. Each ray is perhaps line capsule from center. ray nth transform rotate(angle) translateY(-68px). .rays animation spin 12s. Core with radial gradient, box shadow.
Maybe use pseudo-elements on ray? Span widths height.
Floating sun wrapper animation float.
Rain:
cloud made .cloud with .cloud-puff etc. Need all HTML. cloud perhaps div class cloud with ::before and ::after plus span puffs. A single .cloud base. Rain drops 9 span .drop, animation rain-fall. Position under cloud. Drops line/ teardrop CSS border-radius 50% 50% 50% 0 transform rotate(-45deg)? Animation transform includes. Use drop width 7 height 17 background cyan border radius 50% 50% 50% 0. animate opacity and translate from y -10 to 95. Position absolute top maybe 118. Use animation-delay.
Cloud at top 45. icon stage 200.
Puffs can use spans? Use .cloud span:nth. A cloud shape with background and pseudo. HTML can be <span class=puff p1>. Pseudo before after. Easiest .cloud consists of three span .puff + .base. But need aesthetically. .cloud-main width 150 height 60, border-radius 50px background gradient, positioned left25 top70; before circles positions. Could use cloud's ::before and ::after as two circles; main itself elliptical. Eg width 142 height 53; border-radius: 40px; top 55; ::before circle 62 top -27 left 18; ::after 75 top -40 left 57. Good.
Then drops top 102 through 176.
Snow:
similar cloud perhaps reuse .cloud. Snowflakes 7 spans each with text? Need no icon fonts, every icon built elements. Could use span.flake and ::before/::after bars. CSS. Position and drift animation. Better each flake element is central line and pseudo horizontal? We can make 6-spoke via ::before vertical and ::after horizontal only (plus can use box-shadow to mimic diagonal? no). A simple 4-point sparkle using transform rotate(45deg), width 14 height 14, border solid with pseudo. But snowflake recognizable if text "✦" perhaps glyph counts icon font? no, built HTML and pseudo better. Use .flake span? Each .flake with ::before and ::after crossing, plus box-shadow maybe. Make 6 arms via repeating conic-gradient mask? Mask can be CSS with no external; but browser. Or .flake as 4-line shape. We can create 3 spans per flake, but markup 6 flakes each containing 3 i =.flake > i:nth child. CSS each i position, transform rotations. A six-arm snowflake: .flake width 16 height16, i absolute left 50 top50 width2 height16 transform translate(-50%,-50%) rotate(0/60/120). Add little branching not needed. Six-point star looks snowflake. Animate each flake drift with translate / rotate.
Storm:
cloud and bolt. lightning CSS clip-path polygon. .bolt with glow animation 4s infinite, perhaps multiple flashes. Use gradient, clip-path. Need flashing lightning. cloud dark. Maybe rain mini.
Animations @keyframes lightning: 0, 42, etc opacity 0; 44 opacity1; 46 .5; 48 1; 52 0. Could animate filter drop shadow too. CSS clip-path allowed. Maybe bolt shape.
Sun rays rotating: rays wrapper with 8 i. Core pulse. Sun scene float.
Cloud animations slight bob.
Rain drops.
Snow drift.
Lightning.
Reduced motion:
@media (prefers-reduced-motion: reduce) {
*,*::before,*::after { animation-duration:0.001ms !important; animation-iteration-count:1 !important; transition-duration:0.001ms !important; }
}
But if screenshot environment reduced motion maybe static still good. Need maybe specific animation none? Generic accepted. Infinite smooth otherwise.
No JS; ensure no script string. No inline event handlers. Use CSS only.
Potential issue exact one fenced block. Need complete HTML. Let's plan design in detail.
HTML:
<!doctype html>
<html lang=en>
<head>...
<style>
:root etc
* box-sizing
html body margin; min-height; color
body background:
radial-gradient(circle at 10% 0%, rgba(67,137,255,.22), transparent 32rem),
radial-gradient(circle at 95% 25%, rgba(140,74,255,.18), transparent 30rem),
linear-gradient(150deg,#081225 0%,#0a1020 45%,#070b16 100%);
font-family ui-sans-serif system etc.
body::before grid texture with linear-gradients; opacity; pointer; maybe fixed.
.page max-width 1320 padding 28 30 22 margin auto min-height 100vh display flex column.
masthead flex.
.brand display flex, .brand-mark CSS circle and pseudo rays? Could build a mini "weather mark" using CSS. Nice.
.brand-mark width 38 etc border 1; .brand-mark::before sun circle; ::after arc maybe. No icon issue.
.brand-copy.
.eyebrow.
.header-meta maybe condition display; right.
.hero flex align-end justify; margin 28 0 24. h1. Description.
.live pill.
.grid display grid repeat(4,minmax(0,1fr)) gap 18. align-stretch.
.card position relative min-height maybe 515; border-radius 28; padding 22 20 18; display flex column; isolation; overflow hidden; color; background own gradient.
Pseudo atmospheric highlights/noise. .card::before top radial. ::after maybe bottom wavy glow.
card:hover transform translateY(-10px); border color; box-shadow.
Top row .card-head display flex; .location .city font 21; .region uppercase.
.badge "SUNNY" etc perhaps.
.icon-stage height 214 position relative display grid place-items; margin maybe.
.temp-row display flex align-end justify.
.temp font clamp(58 etc)
.temp-degree maybe superscript °
.condition
.description.
.metrics bottom margin-top:auto border top rgba; display grid 3; labels values.
Maybe use bottom decorative bar.
At 1280 x 800:
page padding 26 top 28.
masthead 42.
hero margin 24, h1 44 plus 26 => around 95.
grid card 530? 26+42+24+95+24? Let's calculate: page y 26 header 42 => 68, hero margin top22 and bottom22 with content maybe 72 => 184; grid top maybe 180. Card 515 ends 695; footer maybe 30 ends 725. Good. At 800.
Set .weather-grid flex 1 maybe cards 520. page min-height. Grid. Card min-height 520.
At narrower > maybe 1024 2x2? requirement 4 per row desktop; desktop 1280 yes. Breakpoint 900 2 col, 560 one. "stacked on mobile" likely at 375 one. Could at 980 two then 620 one.
Use card gradients:
sunny: background:
radial-gradient(circle at 78% 8%, rgba(255,255,213,.72), transparent 20%),
radial-gradient(circle at 22% 92%, rgba(255,93,115,.48), transparent 38%),
linear-gradient(150deg,#ffbf5f 0%,#ff8c58 45%,#ec5f78 100%);
color #fff. But white text in bright top maybe okay with shadows.
rainy:
radial-gradient(...), linear #273b73 to #15264d.
snowy #8eb5db to #6675b5 maybe.
stormy #312653 to #141c3c.
Could differentiate. Card top text readable.
Weather icon stages:
Set width 100%, height 205.
Sun:
.sun-scene position absolute width 165 height165 top 21 left 50 transform translateX(-50%) maybe animation float. But if wrapper includes animation transform, initial translate overwritten. Better .sun-wrap position abs inset; .sun-orbit position absolute width etc. Or .sun-scene left:50%; margin-left:-82.5. animation float uses translateY only preserving margin.
.rays absolute inset 0; animation spin 16s linear infinite.
.ray absolute width 5 height 22; left calc(50% - 2.5); top calc(50% - 84px); border-radius; background; transform-origin: 50% 75px? Position top maybe. Let's accurately position rays around center:
.rays width 160 height160 center.
.ray {position:absolute; left:50%; top:50%; width:5px;height:20px; margin-left:-2.5px; border-radius; transform-origin: 2.5px 68px; } Since transform-origin relative to element, y origin at 68px downward from element center? Element top at center, origin at y68, so rotates around point below, wrong. Want each ray located around center at radius 67. Place element center at top 50% then transform translateY(-68px) rotate(angle) with transform-origin center. CSS:
.ray { left:50%; top:50%; transform:translate(-50%,-68px) rotate(var(--a));}
Then ray center radius 68. Eight angles.
.rays animation rotate; but rays children have transforms. rays wrapper rotates.
.core width 76 height76 left42 top42 radial gradient, box-shadow. Pseudo maybe halo.
.rays opacity .9.
.sun scene animation bob 5s ease-in-out infinite alternate. Note transform translate? use translateY.
Rain:
.icon-stage .rain-scene absolute width190 height190 top 8 left50 margin-left -95. cloud. Cloud at top 20 left15 width160 height60. Puffs pseudo. Could main itself ellipse and circles:
.cloud {position:absolute; width:154; height:56; top:40px; left:18px; border-radius:50px; background: linear-gradient(...); box-shadow}
cloud::before {content; width:70;height70; border-radius; top:-34; left:22}
cloud::after width84 height84 top:-46 left64.
Need z-index cloud pieces; pseudo stack; main background. Before and after positions.
rain drops top 94, width6 height17; left varying; animation fall 1.3s linear infinite. Animation transform from translateY(-18) to translateY(78), opacity 0 at 0, . etc. Initial delays. But top at 91 and animation starts perhaps transform -18 => y73. Good.
.drop::after maybe smaller highlight.
@keyframes dropFall {0% transform translateY(-18) scale(.75); opacity0; 15% opacity .9; 85% opacity .8;100% translateY(83); opacity0}
drop rounded.
rain scene animate bob maybe on cloud only. `.rain-scene .cloud { animation: cloudBob 4s ... }`.
Snow:
cloud top perhaps 20. flakes top 88. .flake position absolute width14 height14; animation drift 4-6s ease-in infinite. Children i lines. Position custom using style? Inline style forbidden? "No inline event handler" but inline style perhaps allowed; still better classes. Use classes flake f1 etc CSS each positions and delay. Each flake:
.flake { position:absolute; width:15px;height:15px; opacity:.9; }
.flake i { position:absolute; top:50%; left:50%; width:1.5px;height:14px; background:#fff;border-radius; transform:translate(-50%,-50%); box-shadow}
nth1 rotate(0), nth2 rotate60, nth3 rotate120. We need transform on i includes translate and rotate.
Animation on parent .flake with transform translate. @keyframes snowDrift {0% transform:translate3d(-8px,-10px,0) rotate(0); 50% translate3d(10px,24px,0) rotate(100deg);100% translate3d(-5px,65px,0) rotate(220deg)}. Different classes assign animation-duration, delay, perhaps custom individual horizontal via --drift? CSS variables custom props in rules classes okay. Could use animation with each f but same movement. Position left values.
Potential flake falls from 88 to 153.
Storm:
storm-scene width190. cloud same, dark. Perhaps set `.storm-scene .cloud` background. top 27.
bolt absolute width50 height82 top92 left73; clip path polygon. z-index maybe. CSS background linear white-yellow. animation flash 4s infinite. `filter: drop-shadow`.
Could use .bolt::after glow. But pseudo within clipped.
Lightning visible maybe static at screenshot depending timing. Animation should flash 1 sec around every 4.5. At t3 perhaps could be off. Requirement animated. Fine. But screenshot 3 seconds after load perhaps should catch maybe define flash keyframe such that at 60% etc. Better cycle 3.2 sec with at 55%-70% flash. Screenshot exactly ~3 sec could be near end. We can have animation delays? `animation-delay:-1s` etc to ensure. But no need perhaps visually. To guarantee bolt visible at first paint and still flashing, initial keyframe 0 opacity1, then off at 12%, etc, repeat. Define 0%,7% opacity1; 11% .3; 14% 1; 19%,55% 0; 58%1; 62%0; 65%1; 70%,100%0. At t3 of 4 sec =75 off. Could duration 3 sec: t3 resets exactly visible. screenshot 3 sec likely catches. Use 3.4 sec and 0 visible; 0-8. At t3 88 off. Not guaranteed. Could bolt itself have base opacity .85 and pseudo flash separately. The requirement flashing lightning; animate filter/box shadow while base visible. But animate opacity can make off. We can keep opacity .9 always and animate brightness at moments, also bolt shimmer. e.g. @keyframes lightningFlash {0%,38%,44%,70%,76%,100% {filter drop-shadow...; opacity:.88} 40%,42%,72%,74% {filter bright; opacity:1}}. Always visible, flashes brightness. Great.
Maybe storm background pulses subtly `.storm-card::after animation stormGlow`. Pseudo after atmospheric.
Additional animations in card backgrounds and maybe temperature? Requirements only icons. Use card hover transitions.
Need accessible. Use aria-label for scenes? `<div class="icon-stage sunny-icon" role="img" aria-label="Animated sunny weather icon">`; pure HTML. aria hidden maybe rays. Good.
No external fonts. Use system fonts. Could use font-family "Arial"? system.
Could make typography sleek.
At desktop each card widths around (1220 - 54)/4 =291.5. Nice.
Page max 1320 with padding 28 => inner 1224. grid gap 16 = (1224-48)/4=294.
Card min-height 520.
At 1280 body no scrollbar? Vertical perhaps around 760. Need horizontal no. At 375 cards stacked means page tall okay. no horizontal.
At mobile header meta maybe hide. hero title 34. grid one. card min-height 500. Icon. Good.
At 900 2 cols.
Need "4 per row on desktop" perhaps don't break at 1024? 1280 works. Use @media max-width 900 =>2. Fine.
Footer maybe `Forecasts are illustrative • CSS motion study` maybe tiny. At 800 vertical. But could not include unnecessary. Keep at bottom.
Need CSS only. Ensure no `script`. We need exact one code fence.
Let's refine visual.
HTML structure:
<body>
<div class=ambient-grid></div> maybe body pseudo.
<main class=page>
<header class=masthead>
<a class=brand href="#" aria-label="Atmos home"> - href is okay, but clicking jumps. Use div.
<div class=brand-mark aria-hidden=true><span></span></div>
<div><span class=brand-name>ATMOS</span><span class=brand-tag>WEATHER STUDIO</span></div>
</div>
<div class=header-status><span class=status-dot></span><span>Live conditions</span><span class=divider></span><strong>08:42 UTC</strong></div>
</header>
<section class=intro>
<div><p class=kicker>THE WORLD, RIGHT NOW</p><h1>Every forecast has <em>a feeling.</em></h1><p class=lede>Four cities. Four moods. One beautifully moving sky.</p></div>
<div class=weather-note><span>24°</span> etc maybe global average. Could instead "4 / 4 ACTIVE SCENES". Not necessary.
</section>
<section class=weather-grid aria-label...>
<article class="weather-card sunny-card">
<div class=card-glow...> no need.
<header class=card-header>
<div><p class=city>Santa Monica</p><p class=country>California, US</p></div>
<span class=weather-pill>Sunny</span>
</header>
<div class="icon-stage sunny-scene" role img...>
<div class=sun-scene> ... </div>
</div>
<div class=reading>
<div class=temperature aria-label...>24<span>°</span></div>
<div class=condition>Golden hour</div>
<p class=description>Warm light, clear skies and a soft ocean breeze.</p>
</div>
<div class=card-footer>
<div><span>FEELS LIKE</span><strong>25°</strong></div> ...
</div>
</article>
...
</section>
<footer ...> maybe "ANIMATED WITH PURE CSS" and legend. We can put after grid; at 800 may fit? Need calculate.
Masthead 42. intro: margin-top 24, h1 maybe 48 line 1, lede 22; total ~88, bottom margin22. Grid card 520. page top 26 +42+24+88+22+520+ maybe footer 35 + bottom 20 =777. Great. At 800. Set grid cards maybe 504. Let's calculate: top 26; header 40; margin intro 20; intro h1 49 + kicker 14+10 + lede 21+8 =>102 maybe; bottom margin22 => total 230. Grid 505 =>735; footer 30 + bottom20 =>785. Good.
But CSS grid card intrinsic content might >505:
padding top 22 bottom18; card header 50; icon 205; reading temp maybe76; desc 40; footer 58 =>22+50+205+76+40+58+18=469 plus gaps. 505. Fine.
Use `.weather-grid {flex:1}`? Page flex column. If footer and grid flex 1, cards stretch to available. Set min-height 500. At 800 it might use. But body page minheight and grid flex 1. card height 100%. Footer after 16.
Main .page display flex. Header etc.
Set weather-grid `flex: 1 0 auto` not. Better fixed min-height 512.
Could not include footer to keep.
At 1280×800 screenshot perhaps screenshot page full 800. Need cards almost all. Fine.
Body pseudo ambient grid:
body::before fixed inset 0 background-image linear-gradient(rgba... 1px transparent 1px), etc; mask-image radial-gradient; pointer; opacity .22; z-index - maybe body stacking. body background. body::after radial glows? We can just use body background radial.
Card internal:
`.weather-card::before { content:""; position:absolute; inset:0; background: radial-gradient(circle at 50% 36%, rgba(255,255,255,.18), transparent 36%); pointer-events:none; }`
`.weather-card::after { content:""; position absolute; width:220;height:220; border-radius:50%; bottom:-130; left:20%; background...; filter blur(2px); opacity;}`
Need layer content z-index 1. Set > * position relative z-index 1.
Sun card card pseudo maybe warm. Different background enough.
Borders: rgba white .25, inset shadow.
`.weather-card:hover { transform: translateY(-9px); box-shadow: 0 22px 48px rgba(...), inset...; }`
transition transform .35 cubic, box-shadow. `@media (hover:hover)` perhaps.
Card `.weather-pill` with backdrop blur, white alpha background.
Temperature. `font-size: clamp(58px,5vw,72px)` but with 4 row 5vw=64 at 1280. Great. line-height .85.
Condition maybe uppercase letter spacing.
Description min-height 42.
Footer top border, metrics. Footer values 14.
Color for sunny white. All white. Rain etc.
City names:
Sunny: Lisbon, Portugal, 26°, Clear & warm.
Rainy: Seattle, Washington, 14°, Soft rain.
Snowy: Reykjavík, Iceland, −6°, Quiet flurries.
Stormy: Singapore maybe 24°, Thunderstorms. Different.
Perhaps weather card own descriptions.
Header use uppercase.
Animated card backgrounds:
sunny card pseudo `animation: sunnyGlow 5s ease-in-out infinite alternate`.
rainy `::after` maybe animated rain-light.
snowy.
stormy lightning background.
But pseudo ::before used all; can target.
Icon details.
Let's ensure CSS selector doesn't animate card's ::before transform unexpectedly. We can animate opacity only.
Sun:
.sun-scene {position:absolute; width:170px;height:170px; left:50%; top:18px; margin-left:-85px; animation: sunFloat 5s ease-in-out infinite;}
.sun-rays {position:absolute; inset:0; animation: sunSpin 18s linear infinite;}
.ray { ... }
Could use CSS custom property `--angle` set per nth child in CSS. No inline style. This is okay.
`.sun-rays i:nth-child(1){transform:translate(-50%,-68px) rotate(0deg)}` etc. But when parent spins, good.
ray gradient maybe `background:linear-gradient(#fff8bd,#ffd45c)`, box shadow.
Core position abs 47 47? width76, left47 top47.
`::before` inner highlight.
Core animation sunPulse.
Maybe sun rays are behind core.
Sun scene stage 215. Scene 170, top 20.
Rain:
`.rain-scene` position absolute width190 height190 top10 left 50 margin-left -95.
cloud top 18 maybe.
Cloud pieces:
```
.cloud {
position:absolute; left:18px; top:38px; width:154px; height:58px;
border-radius:52px;
background:linear-gradient(...);
box-shadow: inset 0 -8px 18px rgba... , 0 12px 25px ...
}
.cloud::before { width:64;height:64;left:16;top:-31}
.cloud::after {width:79;height:79;left:57;top:-43}
```
Pseudo backgrounds.
Need cloud pseudo z-index perhaps.
Cloud animation `cloudDrift 4s`.
Drops:
top 92; animation. Each .drop classes n1 etc positions.
We can use nth-child.
`.rain-drop {position:absolute; top:88px; width:6px;height:17px; border-radius:50% 50% 50% 0; transform:rotate(10deg)?` Animation overrides transform, so shape orientation fixed from border radius. Teardrop with border-radius 60% 40% 55% 45%; rotate maybe wrapper. If animation transform includes rotate(12deg) and translate. Fine.
n1 left18 animation-delay -.9s etc.
We want multiple continuous.
Maybe `drop` with ::after highlight.
Snow:
Cloud perhaps top 25. Flakes top 86. Need flake i structure:
```
<div class="snowflake sf1"><i></i><i></i><i></i></div>
```
6 flakes. .snowflake animation.
Set nth positions.
`@keyframes flakeFall {0% {transform:translate3d(-8px,-18px,0) rotate(0); opacity:0} 15% opacity1; 80% ...;100% translate3d(12px,70px)...}`
Since snowflakes width 16 and stage scene 190. top maybe85 -> down to155.
sf1 left25 top80 etc.
Durations 4.2 to 5.8, delays negative to populated.
Cloud animation snowBob.
Storm:
Cloud top 17, width. dark gradient. Add under-cloud rain? Requirement storm icon flashing lightning, no need. But storm icon can have small rain strokes. Add `.storm-rain` 5 spans? Could clutter. Could use cloud::? We already pseudo circles. Add `<div class=storm-drizzle><i...>` but no need.
Bolt top85, width54 height84, left68. clip-path polygon(50% 0,100% 0,68% 38%,92% 38%,26% 100%,40% 56%,12% 56%). Background.
Bolts shadow.
Could animate scale? clip path plus opacity. Use filter brightness animation.
Maybe `.bolt-shadow` pseudo? `.bolt::after` cannot extend due clip? pseudo inherits clip parent, can be inner shine. Add `background:linear-gradient`.
`@keyframes boltFlash { 0%, 24%, 28%, 56%, 60%, 82%,86%,100% {opacity:.72; filter:drop-shadow(...)} 25%,27%,57%,59%,83%,85% {opacity:1; filter...}}`
This always visible.
Storm card background `::after animation stormPulse`.
The user asked HTML and CSS only. Include HTML and style. Great.
No SVG, images, icon fonts. All graphics div/i spans/pseudo. Ensure no unicode weather icon symbols. We can use degree and minus characters, okay not icons. Em dash etc.
Prefer reduced motion:
```
@media (prefers-reduced-motion: reduce) {
*, *::before,*::::after {
animation-duration: 0.001ms !important;
animation-iteration-count:1 !important;
transition-duration:0.001ms !important;
scroll-behavior:auto !important;
}
.sun-rays { transform: rotate(22deg); }
.weather-card:hover {transform:none;}
}
```
Generic causes animations to land at final state? CSS animations with 0.001 one iteration and fill default none, element returns base. Raindrops base opacity maybe currently style no opacity, could show static at top. Snowflakes base position. Bolt base visible. Sun rays static. Fine. But "respect" typically disable:
```
@media (...) {
*, *::before,*::after { animation: none !important; transition:none !important; }
.weather-card:hover {transform:none;}
}
```
Better. But some base animation transforms? `.sun-scene` no transform base; okay. `.cloud` no transform. drops no opacity base? Set opacity .85 maybe but animation keyframe. Snowflakes base. lightning base opacity .9. Fine.
Hover transform persists but motion preference could disable transition; lift on hover technically movement, should disable transform too.
Set `.weather-card:hover {transform: translateY(0)}`.
Responsive:
- `@media (max-width: 1050px)`: grid repeat(2)
- `@media max-width: 620px`: grid 1; page padding; intro etc; card maybe min-height 500.
Need desktop 1280 4.
Maybe at width 1024 considered desktop and 2. Requirement likely okay.
- Mobile card not too tall. 375 width inner 335. Icon stage 200.
- Masthead status hide location or entire.
- intro h1 37.
- weather-grid gap16.
- `card-footer` 3 columns.
No horizontal.
Could maybe make cards horizontally not overflow. `min-width:0`.
Body overflow-x:hidden.
Accessibility contrast. Sunny bright white may low contrast. Add text-shadow and card gradient darker. Set sunny gradient bottom #d84c70, text. Header. Temperature shadows. Could use dark text? White with shadows is fine.
Let's draft HTML.
Potential `href` not needed. Brand div.
Masthead:
```
<div class="brand">
<div class="brand-orbit" aria-hidden=true><span></span></div>
<div class=brand-type><strong>ATMOS</strong><span>WEATHER, IN MOTION</span></div>
</div>
<div class="live-chip"><span class=live-dot></span> LIVE FORECASTS <span class=chip-separator></span><time>08:42 UTC</time></div>
```
`time datetime="...">08:42 UTC</time>` static but okay. Could avoid wrong. "GLOBAL SKY · 08:42 UTC".
Intro:
```
<section class=hero>
<div>
<p class=eyebrow><span></span> FOUR CITIES / ONE LIVE SKY</p>
<h1>Weather with <span>atmosphere.</span></h1>
<p class=subtitle>A miniature forecast studio...</p>
</div>
<div class=hero-stat><strong>04</strong><span>moods<br>in motion</span></div>
</section>
```
Right stat adds interest. On mobile hide.
Grid.
Card content specifics:
Sunny:
city Lisbon, country Portugal
badge Sunny
stage
reading:
temp 26°, condition "Clear skies"
description "Golden warmth drifts in from the Atlantic."
footer: FEELS 27°, WIND 8 km/h, UV 6.
Rain:
Seattle, United States
14°, "Steady drizzle"
"Soft rain taps a rhythm across the city."
footer FEELS 12, HUMIDITY 92%, WIND 11
Snow:
Reykjavík, Iceland
−7°, "Gentle flurries"
"Slow snowflakes soften a frosty blue morning."
footer FEELS −11, SNOW 4 cm, WIND 16
Storm:
Osaka, Japan? 24°, "Thunderstorm"
"Electric skies roll over the evening skyline."
footer FEELS 26, RAIN 68%, WIND 24.
Maybe city card region.
Temperature semantics `span class=temp-value`.
```
<div class=temperature><span>26</span><sup>°</sup></div>
```
No Celsius indicated? Add `°C` maybe requirement temperature. Use 26° and footer.
Maybe condition text.
Footer labels.
CSS structure. Need check dimensions.
Let's calculate stage: `.icon-stage {height:210px; display:block; position:relative; margin:2px 0 4px;}`. Card header 50. Reading temp maybe 77. footer 63. Card padding vertical 20+18 =38. total 50+210+77+40 desc+65+38 =480. min-height 520. Good.
`.reading` maybe temp row.
```
.reading-head {display:flex; align-items:flex-end; justify-content:space-between;}
.condition {padding-bottom:6}
.description margin 10 0 18; font 14 line1.5; min-height42}
.card-footer margin-top:auto; padding-top:15.
```
Total card header 52 + stage210 + temp67 + condition in same row + desc (42+28 margins) + footer (56+15) + padding38 =508. Fine.
Footer bottom.
Pseudo background with z-index. `weather-card > * {position:relative;z-index:1}` but `.icon-stage` needs position and z. good.
Sun card `background`. Need pseudo before radial. `weather-card::before` perhaps pointer. Since card content z.
```
.weather-card::before { content:""; position:absolute; inset:0; background:linear-gradient(...); }
```
Different cards target background radial via background itself no.
`::after` decorative circle. target.
Maybe add a thin top line.
`.weather-card {border:1px solid rgba(...); box-shadow:...; backdrop-filter:blur(12px);}`.
Sun card gradient:
```
background:
radial-gradient(circle at 50% 30%, rgba(255,248,188,.55), transparent 31%),
linear-gradient(155deg,#ffbd59 0%,#ff835d 48%,#d94e78 100%);
```
Radial makes icon blend. Darken lower.
Rain:
`linear-gradient(155deg,#315582,#172f5c 55%,#101d3f)`.
Snow:
`#90b9d7,#6f83b5,#59659b`.
Storm:
`#51416f,#292747,#151a37`.
The hero background body deep.
Brand mark CSS:
```
.brand-mark width38 height38 border 1px solid rgba; border-radius 12; position relative; overflow hidden
::before circle at 14 13 6 yellow gradient
::after width24 height12 border:2px solid #80d8ff; border-top-color transparent; border-radius:50%; left7 bottom7; transform rotate(-12)
```
Pure CSS.
Hero stat glass.
Card badge with icon? just text no icon. pill.
All icons built from HTML. Maybe role img.
Sun rays `<i aria-hidden=true>` repeated 8. This is technically empty i but okay.
Rain drops spans.
Snowflakes each 3 i.
Storm bolt span.
CSS:
```
.sun-rays i {
position:absolute; left:50%; top:50%; width:4px;height:19px; margin-left:-2px; border-radius:99px; background:linear-gradient(...); box-shadow:0 0 8px...
transform:translateY(-68px);
}
```
Need rotation per child. Set `transform: translate(-50%, -68px) rotate(...)`; translate percentages includes element center. Parent rotates.
Pseudo ray perhaps width. Fine.
Ray animation parent spins.
Sun core pseudo:
```
.sun-core::before {inset:8; border-radius; background:radial...}
```
Core itself radial.
Animation pulse scaling. Scaling may conflict position but okay transform.
Core box shadow.
Sun wrapper float. keyframe transform translateY(-5 to5). Parent static left via margin.
Cloud:
The cloud main's pseudo may be behind? `::before,::after` position absolute and background. They render as children stacking before content; main's background is bottom. Pseudo likely painted before child background? CSS pseudo ::before generated as first child; its background may cover main, good. Set z-index -? If z-index - within positioned parent maybe behind main. Better no z; pseudo elements generated before content and main background painted behind child. They show. Cloud base.
```
.cloud::before{...}
.cloud::after{...}
```
Main background might cover lower parts of circles because child backgrounds paint above parent background. yes.
Cloud subtle bottom gradient.
Rain drop animation: Since nth positions and top.
```
.rain-drop {
top:92px;
opacity:0;
animation: rainFall 1.25s linear infinite;
}
```
At reduced motion animation none but opacity remains 0 -> drops invisible. Need set reduced specific `.rain-drop{opacity:.75;transform:translateY(25px)}`. Similar snow base. Add in reduced.
At normal first paint drops might be all distributed due negative delays.
@keyframes:
```
0%{transform:translateY(-20px) rotate(12deg);opacity:0}
15%{opacity:1}
85%{opacity:.85}
100%{transform:translateY(84px) rotate(12deg);opacity:0}
```
Top 88 => bottom172.
nth delays -0.1 -0.4 etc durations.
Drop border-radius: `50% 50% 50% 0` and rotate(12) means point toward bottom-left maybe.
Cloud z-index2, drops z1.
Rain scene may animate cloud only.
Snowflakes top 85:
```
.snowflake { width:16;height16; opacity:0; animation...}
```
At negative delays some visible. reduced set opacity.
The lines:
```
.snowflake i {position:absolute; left:50%; top:50%; width:1.5px;height:15px; background:#fff; border-radius; transform-origin:center;}
i:nth1 transform translate(-50%,-50%) rotate(0)
...
```
Actually all lines overlap; rotated makes 6-spoke. Box shadow 0 0 4.
Could add small branches via pseudo? `i::after` impossible each i pseudo:
```
.snowflake i::after { content:""; position:absolute; top:4px; left:0; width:5px;height:1px;background...; box-shadow:0 7px...}
```
This adds branches to each arm maybe visual. But because i is rotated, pseudo rotates too. Good.
Set i::after at top 3 left0. Might clutter. Add.
Storm drizzle optional: `<span class=storm-rain sr1>` etc. Could add 4 small lines, animate stormRain. But card requirement only flash. Adds dynamic. We can use same `storm-drizzle i`.
Cloud top maybe 18, bolt begins 80. drizzle around. Avoid.
Bolt is a span:
```
.bolt {position:absolute; z-index:3; top:86px; left:70px; width:50;height:82; background:linear-gradient(...); clip-path:...; transform:rotate(-2deg); animation: lightningFlash 3.8s infinite; filter}
.bolt::after { content:""; position:absolute; inset:4px 12px 8px 5px; background:rgba...; clip-path same}
```
Pseudo same clip? inherited clipping parent anyway. Fine.
Storm cloud dark.
Storm card after animate background purple.
Card hover lift. Focus? articles not focusable. Could set tabindex=0? Interactive? Cards aren't interactive, no. Hover requirement only. Maybe hover effects. No need keyboard focus.
No horizontal overflow due large pseudo. `overflow:hidden`.
Desktop row cards. At 1280 inner page maybe 1220. Hero.
At width <=1050 grid 2; at 800 perhaps 2. Mobile <=640 one.
At 375, intro `h1` 36, stat hidden, header brand tag maybe hidden. Cards width 343. Fine.
Page padding 18.
Card padding 20 18.
Footer metrics labels fit.
Reduced motion also disable status dot pulse perhaps generic.
First paint visible animation no hiding. Intro all visible.
Need no JavaScript. Good.
Should we include meta viewport. yes.
Potential issue CSS `backdrop-filter` fine.
Need exact one fenced code block. No prose.
Let's write full code. But given desired quality maybe can enhance more.
Let's deeply think visual layout at 1280x800:
Main max width 1320 width auto. body viewport 1280. .page padding 26 28 18; box sizing border-box max-width 1340 perhaps. inner width1224. Weather grid 4 x (1224 - 3*16)/4=294.
Header height 42. Hero margin top24 bottom24; hero content maybe h1 48. `.hero h1 font-size:48 line-height:1.02`; kicker margin0 0 10 14 high; subtitle margin8 0 0 18. total 14+10+49+8+18=99. header top26 to68; hero top92 to191; bottom to215. Grid card minheight 520 ends735. footer maybe margin top14 line 12 ends761 + page bottom 18=779. Perfect.
Card content:
padding20; header city 22 line26 country11 line13 + margin3 =42. card top 42? header.
icon stage 202 maybe. Header ends 62 relative, stage 202 ends264.
reading temp 68, desc 42 plus margins, footer61 => around450 + padding40=490. card stretches to520.
Set min-height 518.
Footer page:
```
<footer class=page-footer>
<span><i></i> Pure CSS animation study</span>
<span>Sunny · Rainy · Snowy · Stormy</span>
</footer>
```
i dot CSS. height 14 margin14. Total 28. card ends maybe 746. Fine.
Set `.page {min-height:100vh}` but content 779. At exactly800 okay. vertical no scrollbar likely.
Ambient body pseudo with fixed grid can create no scroll.
Brand status.
Hero stat:
```
<div class=hero-counter>
<div class=counter-number>04</div>
<div>ACTIVE<br>SCENES</div>
</div>
```
Height72. Hero overall max of h1 section 99, okay.
Maybe description text "A miniature forecast studio, rendered entirely in HTML and CSS." reinforces constraints. Nice.
Card desc exact short.
Use `aria-live`? no.
No inline styles. Good.
Let's ensure CSS-only icon uses only HTML elements and pseudo. Yes.
Pseudo rays? no.
Maybe `i` semantic italic but aria hidden.
Let's formulate code.
Potential HTML validator `time datetime="08:42Z"` can use.
No script tag in comments either. User says file must not contain any <script> tag. We won't mention literal perhaps footer says no script? If comment contains script maybe avoid. Use "Pure CSS motion". No "script" string maybe okay, but requirement no tag specifically. Footer "HTML + CSS MOTION STUDY".
CSS includes no `url()` external. No font import. No image.
Animations:
- sunSpin, sunFloat, sunPulse
- cloudBob, rainFall
- snowBob, snowFall
- lightningFlash, stormPulse
- livePulse, ambient.
Smooth infinite.
Reduced:
```
@media (prefers-reduced-motion: reduce) {
html {scroll-behavior:auto}
*,*::before,*::after {animation:none!important;transition:none!important}
.weather-card:hover{transform:none}
.rain-drop,.snowflake {opacity:.8; transform:translateY(25px);}
.sun-rays{transform:rotate(18deg)}
}
```
But generic `animation:none` means sun core etc base. `.sun-rays` base no transform, but explicit in reduced.
Rain drops transform rotate? style `transform:translateY(20px) rotate(12deg)`.
Snowflake positions class but transform overridden all same. Fine.
Cloud base top.
Bolt base opacity .9.
Could add focus-within? no.
Card cursor default.
Header live dot pulse.
`@keyframes livePulse {0,100 box-shadow 0 0 0 0; 50 box-shadow...}`.
Weather stage perhaps animated halo pseudo:
sunny stage::before circle, rain etc. But card pseudo layers. Could use `.icon-stage::before` generic? For each.
Sunny stage background radial.
Rain stage maybe.
Snow.
No need.
To make icon sizes consistent.
CSS exact:
```
.icon-stage::after { ... }
```
avoid.
Sun wrapper:
```
.sun-scene { ... animation:sunFloat ...}
.sun-rays { position:absolute; inset:0; border-radius:50%; animation:sunSpin ...}
.sun-rays::before {content:""; position:absolute; inset:28px; border:1px dashed rgba(...); border-radius:50%; animation:sunSpin 22s reverse linear infinite;}
```
This adds rotating halo but requirement rays. Fine. pseudo built.
Core.
Cloud scene:
rain stage top maybe 8. `.rain-scene` width190 height190.
Cloud base.
Rain drops.
Rain cloud white/blue.
Snow cloud white. snowflakes.
Storm cloud:
`.storm-scene .cloud {background:linear-gradient(180deg,#aeb4d2,#626987);}` perhaps dark storm should cloud dark charcoal with purple. `linear-gradient(#a3a7c3,#505772)`. Bolt yellow. Background stormy.
Bolts CSS shape:
```
clip-path: polygon(53% 0, 100% 0, 67% 38%, 91% 38%, 24% 100%, 42% 55%, 12% 55%);
```
Works.
Need animation transform rotate perhaps filter. `transform: rotate(-3deg);` keyframe only filter opacity so transform retained.
Lightning card pseudo glow.
Snowflake animation rotates parent. Its children rotations.
Set negative delays to ensure visual.
No CSS variables? `--angle` not needed.
Let's check animation overwritten: `.sun-rays i:nth-child(1) { transform: translate(-50%, -68px) rotate(0deg); }`; parent animation `transform: rotate(...)`, fine.
`.sun-core` animation sunPulse uses transform scale; no positioning transform because left top. fine.
`.cloud` animation cloudBob transform translateY; positioned top left unaffected.
`.rain-drop` animation transform includes translate and rotate. base no transform.
`.snowflake` animation transform includes translate and rotate; positions left/top.
`.bolt` animation only opacity/filter so base rotate.
`.weather-card:hover` transform; no internal animation on card.
`.weather-card::after` storm animation opacity transform? transform on pseudo okay.
Header status.
Gradient perhaps cards need unique obvious weather:
Sun yellow pink.
Rain blue.
Snow icy periwinkle.
Storm purple charcoal.
Card badge text uppercase. Could pill have dot color via ::before:
`.weather-pill::before {width6;height6;border-radius;background:currentColor;}` all same.
Sunny badge background rgba; text.
Card all white.
Bottom metric footer top line.
Footer labels 9px uppercase, values 14.
Add card top tiny `.city` etc.
No need actual location flags (would be icons perhaps).
We need maybe mention city names clearly.
Let's write code now in final eventually. But before, assess potential policy no issue.
We must output exactly one fenced code block. Fine.
Let's maybe use semantic `<span>` rather than `<i>`? Rays `<span>`, but nested many. `<i aria-hidden>` okay.
One concern: "No SVG" We use CSS `clip-path: polygon` but no SVG; valid. They specifically prohibit SVG elements. CSS clip-path polygon fine. Every icon built elements/pseudo. Good.
No images. No icon fonts. Use no emoji.
"Absolutely no JavaScript: file must not contain any <script> tag or inline event handler." No scripts, no handlers. Fine.
"HTML and CSS only" meta etc.
"rotating sun rays" clear.
"falling rain drops" yes.
"drifting snowflakes" yes.
"flashing lightning" yes.
"city name, temperature, short description" yes.
"own background gradient" yes.
"responsive grid (4 per row on desktop, stacked on mobile)" yes.
"lift up on hover" yes.
"Smooth infinite animations using @keyframes, and respect prefers-reduced-motion." yes.
Could make animation loops seamless. Rain drops linear. Snow. Lightning. Sun. Good.
Maybe status dot also.
Let's ensure all animations base visible and no blank. Snowflakes opacity 0 base but negative delays should show after style calculation immediately; animation starts at current time and negative delay means several visible. Good.
Rain same.
At first screenshot 3s, scene ongoing.
Let's refine footer sizing and mobile.
CSS:
```
.page-footer {display:flex; justify...; margin-top:14px; padding:0 4px; color...; font-size:10px; letter-spacing...}
.footer-tag {display:flex;align}
.footer-tag::before...
```
No icon.
At mobile footer second span hide maybe.
`@media(max-width:640) { .page-footer span:last-child{display:none} .hero-counter{display:none} .card{min-height:500px} .icon-stage{height:196px}.sun-scene transform? wrapper at top 15. Rain etc.
}`
Stack exactly one. Grid gap16.
At 375 h1 34 maybe no overflow. Text "Weather with atmosphere." line perhaps 2 lines. Good.
At desktop, `.weather-grid` cards min-height 520 but grid stretch to max content same.
Maybe body content width 100%.
Let's write exact CSS with all classes.
Detailed CSS:
```
:root { color-scheme: dark; --ease: cubic-bezier...}
html{background:#080d19}
body{margin:0;min-width:320px; min-height:100vh; overflow-x:hidden; ...}
body::before{content:""; position:fixed; inset:0; z-index:-1; pointer-events:none; background-image:linear-gradient(...); background-size:48px 48px; mask-image:radial-gradient(...); opacity:.18;}
```
`z-index:-1` body pseudo might disappear behind body background because body establishes? body::before z -1 might go behind root. Better body `position:relative; isolation:isolate;` and pseudo z-index:-1. Body background covers? Pseudo as child with z -1 inside isolated stacking above background? likely. Or use `.page::before` fixed z-index -1 and page isolate. Set:
```
body {position:relative; isolation:isolate;}
body::before {z-index:-1}
```
Should show.
body background radial.
Page z0.
Header.
```
.brand-mark { ... background:rgba; }
.brand-mark span {position:absolute...}
.brand-mark span::before { ... }
```
Need maybe mini rays built. Simpler:
```
.brand-mark::before { circle sun}
.brand-mark::after { cloud arc}
```
Pseudo.
No actual child needed but HTML can empty div.
`brand-mark::after` border 2 solid #7dd3fc; border-top-color transparent; width24 height13; border-radius 50%; transform rotate(-10deg); bottom7 left7.
Looks.
Hero h1 span color #ffd882 maybe gradient text:
```
background:linear-gradient(90deg,#ffd477,#ff8fa3); -webkit-background-clip:text;color:transparent
```
In screenshot maybe.
Kicker dot.
Hero counter glass.
Weather cards.
Set `color:#fff`.
Sun card might text shadows only icon.
`text-shadow` not all.
Card header.
Country uppercase.
Pill.
Icon stage.
Add scene-specific stage glow:
```
.sunny-card .icon-stage::before {content:""; position:absolute; width:150;height:150; left:50%; top:20; transform translateX; border-radius; background:radial-gradient(...); filter:blur(8px); animation:sunHalo 3s...}
```
But `.icon-stage` children z maybe. Set pseudo z0, scenes z1. Add.
Rain card stage maybe no.
`icon-stage > * {z-index:2}` but `.sun-scene`.
Rain scene.
Cloud animation.
Cloud pseudo border radius.
Drop position nth:
```
.rain-drop:nth-child(1) {left:19px; animation-delay:-.2s}
```
HTML cloud then spans. nth-child counts cloud as first, so rain drops are child 2 onward. Better assign classes d1 d2.
```
.rain-drop.d1 ...
```
Likewise snowfall classes.
Rain cloud plus 10 drops.
HTML:
```
<div class=rain-scene>
<span class=cloud></span>
<span class="rain-drop d1"></span>...
</div>
```
Great.
Cloud uses pseudo. `rain-scene` has no animation.
Snow cloud + 7 snowflake.
Storm cloud + 4 drizzle? `<span class=storm-drop d1>` could collide; separate classes.
Add 5 `.storm-rain`:
```
.storm-rain {position:absolute; top:100; width:2;height:13;background...; transform rotate(12); animation: stormRain 1s infinite}
```
Anim transform. But if behind bolt. Could enrich. Requirement storm. Fine.
Positions left 38,52,120,144. Duration 1.1 delays.
Bolt top83.
Potential visual confusion.
Maybe don't add storm rain to keep clear.
Snow cloud starts top22; flakes.
Card pseudo after:
```
.weather-card::after { content:""; position:absolute; width:240px;height:240px; border-radius:50%; left:50%; bottom:-190px; transform:translateX(-50%); background:rgba(...); filter:blur(10px); opacity:.22; pointer-events:none;}
```
But this same after all; target backgrounds. For storm animate.
Need no `transition` on pseudo.
`weather-card::before` use radial. Could perhaps pseudo takes over gradient? transparent.
Let's write specific:
```
.weather-card::before{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(255,255,255,.12),transparent 36%);pointer-events:none}
.weather-card::after{...}
```
All card content z1. after z0. Before default stack maybe pseudo first child z auto; could sit behind content. Set before z0; after z0; content z1.
`isolation:isolate`.
Sunny after yellow bottom.
Rain after blue.
Snow after white.
Storm after purple.
Use pseudo animation only storm; generic `weather-card::after` transform translateX. If animation stormPulse changes opacity only, preserves transform.
Footer.
Media queries.
Need perhaps at 1050 grid 2 means page much taller; okay.
At 640 one.
At 380 grid one.
At 375 no horizontal. Hero h1 width.
`@media(max-width:640px){ .hero{margin-top:20} .hero h1{font-size:36} .intro-subtitle{max-width:300} .weather-card{min-height:510px} }`
At 375, card 510. long page.
Do we need card `height:100%`? Grid stretch. `.weather-card {min-height:520px;}`.
At desktop all same.
No need script.
Let's think if `mask-image` considered external? no. Chrome supports with -webkit maybe. Zero console errors doesn't concern.
No `url()`.
Can use `font-variant-numeric:tabular-nums`.
Potential icon aria role img and child spans hidden to screen readers? role img label enough; children text none. fine.
One issue `role="img"` on stage with nested elements perhaps okay.
Let's perhaps add visually hidden `<span class=sr-only>`? Not needed.
No HTML comments maybe.
Let's formulate final code with exactly one fence. We should not mention anything outside.
But ensure output only code block. Yes.
Let's mentally inspect CSS specificity:
- `.weather-card > *` sets position relative. For `.icon-stage`, already position relative. For `.sun-scene` absolute. fine.
- `.weather-card::before/after` z0.
- `.weather-card > * { z-index:1; }`; absolute scene z-index2 maybe.
- `.weather-card` isolation isolate.
- `overflow:hidden`.
- Hover transform works. Pseudo not.
- `backdrop-filter` maybe card over body.
Card background gradients exact.
Weather badge has backdrop.
Footer.
Maybe hero stat numbers.
Let's make body min-height and page.
Need `box-sizing`.
Let's now prepare code.