Four weather cards — CSS only, built by GPT-6 Luna
Hostedvia Codex CLIOpenRouter
Show the code the model wroteHide the code
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#f2f3ef" />
<title>Weather, in motion</title>
<style>
:root {
color-scheme: light;
font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-synthesis: none;
text-rendering: optimizeLegibility;
--ink: #182c3e;
--muted-ink: #617487;
--paper: #f2f3ef;
}
* { box-sizing: border-box; }
body {
min-width: 320px;
min-height: 100vh;
margin: 0;
padding: clamp(28px, 6vw, 76px) 24px 34px;
color: var(--ink);
background:
radial-gradient(ellipse at 50% 0%, rgba(255,255,255,.95), transparent 46rem),
var(--paper);
}
.page {
width: min(100%, 1192px);
margin: 0 auto;
}
.intro {
display: flex;
align-items: end;
justify-content: space-between;
gap: 28px;
margin: 0 2px 30px;
}
.kicker, .card-kicker, .condition {
font-size: 10px;
font-weight: 750;
letter-spacing: .16em;
text-transform: uppercase;
}
.kicker {
display: inline-flex;
align-items: center;
gap: 9px;
margin: 0 0 13px;
color: #718391;
}
.kicker::before {
width: 7px;
height: 7px;
border-radius: 50%;
background: #f0a854;
box-shadow: 0 0 0 4px rgba(240,168,84,.15);
content: "";
}
h1 {
margin: 0;
font-size: clamp(31px, 4vw, 48px);
font-weight: 570;
letter-spacing: -.055em;
line-height: 1;
}
.intro-note {
max-width: 220px;
margin: 0 0 2px;
color: #758594;
font-size: 13px;
line-height: 1.6;
text-align: right;
}
.weather-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 16px;
}
.weather-card {
position: relative;
isolation: isolate;
min-width: 0;
height: 392px;
overflow: hidden;
border: 1px solid rgba(255,255,255,.53);
border-radius: 25px;
box-shadow: 0 18px 38px rgba(32,53,71,.095), 0 2px 6px rgba(32,53,71,.04);
color: #173348;
background: #c4e9f4;
}
.weather-card::before {
position: absolute;
z-index: -1;
inset: 0;
background: linear-gradient(180deg, rgba(255,255,255,.18), transparent 44%, rgba(255,255,255,.13));
content: "";
pointer-events: none;
}
.card-sun {
background: linear-gradient(160deg, #65c8e9 0%, #a4e5ec 49%, #f9d49f 100%);
}
.card-rain {
color: #f2f7fa;
background: linear-gradient(155deg, #859cab 0%, #a9c1c9 51%, #d2e0de 100%);
}
.card-snow {
color: #f5fbff;
background: linear-gradient(155deg, #7ea9c2 0%, #a9cfdd 49%, #dce9e8 100%);
}
.card-storm {
color: #eef5ff;
background: linear-gradient(150deg, #202e48 0%, #36465d 52%, #647487 100%);
}
.card-top {
position: absolute;
z-index: 8;
top: 20px;
right: 20px;
left: 20px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.card-kicker {
margin: 0;
color: currentColor;
opacity: .76;
}
.condition {
padding: 7px 9px 6px;
border: 1px solid rgba(255,255,255,.37);
border-radius: 999px;
color: currentColor;
background: rgba(255,255,255,.14);
font-size: 8px;
letter-spacing: .12em;
white-space: nowrap;
backdrop-filter: blur(8px);
}
.scene {
position: absolute;
z-index: 1;
top: 62px;
right: 0;
bottom: 113px;
left: 0;
overflow: hidden;
}
.card-copy {
position: absolute;
z-index: 7;
right: 21px;
bottom: 21px;
left: 21px;
}
.card-copy h2 {
margin: 0 0 6px;
font-size: 12px;
font-weight: 760;
letter-spacing: .17em;
line-height: 1;
}
.temperature {
display: flex;
align-items: start;
gap: 5px;
margin: 0;
font-size: 52px;
font-weight: 520;
letter-spacing: -.075em;
line-height: 1;
}
.temperature sup {
margin-top: 7px;
font-size: 22px;
font-weight: 450;
letter-spacing: -.04em;
}
.summary {
margin: 11px 0 0;
color: currentColor;
font-size: 12px;
font-weight: 520;
opacity: .78;
}
/* Sun */
.sun-rays, .sun-disc, .sun-cloud {
position: absolute;
left: 50%;
border-radius: 50%;
transform: translate(-50%, -50%);
}
.sun-rays {
top: 46%;
width: 190px;
aspect-ratio: 1;
background: repeating-conic-gradient(from 0deg, transparent 0deg 9deg, rgba(255,249,214,.68) 9deg 11deg, transparent 11deg 20deg);
-webkit-mask: radial-gradient(circle, transparent 0 40%, #000 44% 59%, transparent 64%);
mask: radial-gradient(circle, transparent 0 40%, #000 44% 59%, transparent 64%);
animation: rays-turn 32s linear infinite;
animation-delay: -7s;
}
.sun-disc {
top: 46%;
width: 104px;
aspect-ratio: 1;
background: radial-gradient(circle at 35% 30%, #fff6bf 0%, #ffdb7b 47%, #ffb85f 100%);
box-shadow: 0 0 25px 8px rgba(255,222,127,.46), 0 0 70px 24px rgba(255,221,132,.25);
animation: sun-breathe 5.8s ease-in-out infinite;
animation-delay: -2.1s;
}
.sun-cloud {
top: 66%;
left: 0;
width: 87px;
height: 25px;
border-radius: 30px;
background: linear-gradient(180deg, #fff 0%, #e9f5ee 100%);
box-shadow: 0 8px 16px rgba(57,111,128,.13);
opacity: 0;
animation: cloud-drift 22s ease-in-out infinite;
animation-delay: -9s;
}
.sun-cloud::before, .sun-cloud::after {
position: absolute;
bottom: 10px;
border-radius: 50%;
background: inherit;
content: "";
}
.sun-cloud::before { left: 17px; width: 38px; height: 38px; }
.sun-cloud::after { right: 11px; width: 47px; height: 47px; }
/* Shared cloud made from one element and two CSS lobes. */
.cloud {
position: absolute;
top: 29px;
left: 50%;
width: 119px;
height: 31px;
border-radius: 28px;
background: linear-gradient(180deg, #f5f8f7 0%, #dce8e8 100%);
box-shadow: 0 10px 18px rgba(43,65,79,.16);
transform: translateX(-50%);
}
.cloud::before, .cloud::after {
position: absolute;
bottom: 12px;
border-radius: 50%;
background: inherit;
content: "";
}
.cloud::before { left: 19px; width: 48px; height: 48px; }
.cloud::after { right: 15px; width: 60px; height: 60px; }
.card-storm .cloud {
top: 27px;
width: 133px;
height: 34px;
background: linear-gradient(180deg, #8595a7 0%, #526277 100%);
box-shadow: 0 12px 25px rgba(8,17,31,.38);
}
.card-storm .cloud::before { left: 20px; width: 53px; height: 53px; }
.card-storm .cloud::after { right: 13px; width: 67px; height: 67px; }
.rain-drop {
position: absolute;
top: 89px;
left: var(--x);
width: 3px;
height: var(--length, 19px);
border-radius: 50%;
background: linear-gradient(180deg, rgba(245,252,255,.08), rgba(239,251,255,.9));
box-shadow: 0 0 5px rgba(225,247,255,.3);
opacity: 0;
animation: rain-fall var(--duration, 1.24s) linear infinite;
animation-delay: var(--delay, 0s);
}
.card-storm .rain-drop {
top: 87px;
width: 3px;
background: linear-gradient(180deg, rgba(205,227,255,.1), rgba(213,234,255,.96));
animation-duration: var(--duration, .78s);
}
.puddle {
position: absolute;
right: 13%;
bottom: 6px;
left: 13%;
height: 12px;
border-top: 1px solid rgba(243,255,255,.57);
border-radius: 50%;
background: radial-gradient(ellipse at 50% 0%, rgba(238,253,255,.33), rgba(238,253,255,0) 70%);
opacity: .86;
}
.ripple {
position: absolute;
bottom: 5px;
left: var(--x);
width: 19px;
height: 6px;
border: 1px solid rgba(244,255,255,.72);
border-radius: 50%;
opacity: 0;
transform: scale(.3);
animation: ripple-out 1.65s ease-out infinite;
animation-delay: var(--delay, 0s);
}
.ripple:nth-of-type(2) { width: 25px; animation-duration: 1.9s; }
/* Snow */
.snowbank {
position: absolute;
right: -12%;
bottom: -14px;
left: -12%;
height: 32px;
border-radius: 50% 50% 0 0 / 55% 55% 0 0;
background: linear-gradient(180deg, rgba(250,254,255,.88), rgba(236,247,250,.96));
box-shadow: 0 -4px 18px rgba(246,254,255,.32);
}
.card-snow .card-copy { color: #2b566d; }
.flake {
position: absolute;
top: -9px;
left: var(--x);
width: var(--size, 6px);
height: var(--size, 6px);
border-radius: 50%;
background: rgba(255,255,255,.96);
box-shadow: 0 0 8px rgba(255,255,255,.9);
opacity: 0;
animation: snow-drift var(--duration, 8s) ease-in infinite;
animation-delay: var(--delay, 0s);
}
.flake.crystal {
width: 2px;
height: var(--size, 13px);
border-radius: 3px;
background: rgba(250,255,255,.88);
box-shadow: 0 0 7px rgba(255,255,255,.7);
}
.flake.crystal::before, .flake.crystal::after {
position: absolute;
top: 50%;
left: 50%;
width: 2px;
height: var(--size, 13px);
border-radius: inherit;
background: inherit;
content: "";
}
.flake.crystal::before { transform: translate(-50%, -50%) rotate(60deg); }
.flake.crystal::after { transform: translate(-50%, -50%) rotate(-60deg); }
/* Thunderstorm */
.card-storm .scene { bottom: 108px; }
.bolt {
position: absolute;
z-index: 2;
top: 86px;
left: 52%;
width: 28px;
height: 77px;
background: #fff3a6;
clip-path: polygon(54% 0, 100% 0, 69% 41%, 100% 41%, 28% 100%, 43% 55%, 8% 55%);
filter: drop-shadow(0 0 7px rgba(255,238,147,.95)) drop-shadow(0 0 16px rgba(180,215,255,.9));
opacity: 0;
transform: translateX(-50%);
animation: bolt-strike 23s steps(1, end) infinite;
animation-delay: -4.7s;
}
.storm-flash {
position: absolute;
z-index: 6;
inset: 0;
background: rgba(225,242,255,.91);
mix-blend-mode: screen;
opacity: 0;
pointer-events: none;
animation: card-lightning 23s steps(1, end) infinite;
animation-delay: -4.7s;
}
@keyframes rays-turn { to { transform: translate(-50%, -50%) rotate(360deg); } }
@keyframes sun-breathe {
0%, 100% { transform: translate(-50%, -50%) scale(.96); box-shadow: 0 0 21px 6px rgba(255,222,127,.4), 0 0 60px 18px rgba(255,221,132,.21); }
50% { transform: translate(-50%, -50%) scale(1.045); box-shadow: 0 0 33px 11px rgba(255,228,145,.59), 0 0 83px 30px rgba(255,221,132,.31); }
}
@keyframes cloud-drift {
0% { transform: translate(-45px, -50%); opacity: 0; }
9% { opacity: .95; }
46% { opacity: .95; }
62% { opacity: .86; }
91% { opacity: 0; }
100% { transform: translate(310px, -50%); opacity: 0; }
}
@keyframes rain-fall {
0% { transform: translateY(-13px) scaleY(.65); opacity: 0; }
10% { opacity: .84; }
76% { opacity: .82; }
100% { transform: translateY(88px) scaleY(1); opacity: 0; }
}
@keyframes ripple-out {
0%, 25% { transform: scale(.24); opacity: 0; }
39% { opacity: .68; }
100% { transform: scale(1.35); opacity: 0; }
}
@keyframes snow-drift {
0% { transform: translate3d(0, -14px, 0) rotate(0deg); opacity: 0; }
11% { opacity: .92; }
39% { transform: translate3d(15px, 78px, 0) rotate(95deg); }
73% { transform: translate3d(-13px, 155px, 0) rotate(205deg); opacity: .88; }
100% { transform: translate3d(8px, 224px, 0) rotate(310deg); opacity: 0; }
}
@keyframes bolt-strike {
0%, 14.25%, 14.42%, 15.05%, 45.69%, 45.87%, 46.4%, 47%, 86.17%, 86.35%, 86.9%, 87.58%, 100% { opacity: 0; }
14.26%, 14.41%, 14.53%, 14.74%, 45.7%, 45.86%, 46.08%, 46.39%, 46.73%, 46.99%, 86.18%, 86.34%, 86.57%, 86.89%, 87.26%, 87.57% { opacity: 1; }
}
@keyframes card-lightning {
0%, 14.25%, 15.05%, 45.69%, 47%, 86.17%, 87.58%, 100% { opacity: 0; }
14.26% { opacity: .96; }
14.41% { opacity: .1; }
14.53% { opacity: .78; }
14.74% { opacity: .08; }
14.88% { opacity: .52; }
15.05% { opacity: 0; }
45.7% { opacity: .84; }
45.86% { opacity: .06; }
46.08% { opacity: .97; }
46.39% { opacity: .09; }
46.73% { opacity: .68; }
47% { opacity: 0; }
86.18% { opacity: .92; }
86.34% { opacity: .08; }
86.57% { opacity: .98; }
86.89% { opacity: .11; }
87.26% { opacity: .73; }
87.58% { opacity: 0; }
}
.page-foot {
display: flex;
justify-content: space-between;
gap: 12px;
margin: 17px 3px 0;
color: #8a979d;
font-size: 10px;
font-weight: 650;
letter-spacing: .12em;
text-transform: uppercase;
}
@media (max-width: 940px) {
.weather-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.weather-card { height: 370px; }
.scene { bottom: 105px; }
}
@media (max-width: 520px) {
body { padding: 30px 14px 22px; }
.intro { align-items: start; margin: 0 2px 22px; }
.intro-note { max-width: 132px; font-size: 11px; }
.weather-grid { gap: 10px; }
.weather-card { height: 338px; border-radius: 20px; }
.card-top { top: 15px; right: 13px; left: 13px; align-items: start; flex-direction: column; }
.condition { padding: 6px 8px 5px; }
.scene { top: 76px; bottom: 103px; }
.card-copy { right: 14px; bottom: 17px; left: 14px; }
.card-copy h2 { font-size: 10px; }
.temperature { font-size: 42px; }
.temperature sup { font-size: 18px; }
.summary { margin-top: 8px; font-size: 10px; }
.sun-rays { width: 158px; }
.sun-disc { width: 86px; }
.cloud { transform: translateX(-50%) scale(.84); }
.card-storm .cloud { transform: translateX(-50%) scale(.88); }
.page-foot { font-size: 8px; }
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: .01ms !important;
animation-iteration-count: 1 !important;
scroll-behavior: auto !important;
}
.sun-cloud, .rain-drop, .ripple, .flake, .bolt, .storm-flash { opacity: 0; }
}
</style>
</head>
<body>
<main class="page">
<header class="intro">
<div>
<p class="kicker">Atmosphere study · 04</p>
<h1>Weather, in motion.</h1>
</div>
<p class="intro-note">Four little windows into the sky, wherever it turns.</p>
</header>
<section class="weather-grid" aria-label="Animated weather forecast">
<article class="weather-card card-sun" aria-labelledby="sun-title">
<div class="card-top">
<p class="card-kicker">01 / Clear skies</p>
<span class="condition">Feels like 23°</span>
</div>
<div class="scene" aria-hidden="true">
<div class="sun-rays"></div>
<div class="sun-disc"></div>
<div class="sun-cloud"></div>
</div>
<div class="card-copy">
<h2 id="sun-title">SUN</h2>
<p class="temperature">23<sup>°</sup></p>
<p class="summary">Warm light all afternoon</p>
</div>
</article>
<article class="weather-card card-rain" aria-labelledby="rain-title">
<div class="card-top">
<p class="card-kicker">02 / Rain</p>
<span class="condition">Humidity 82%</span>
</div>
<div class="scene" aria-hidden="true">
<div class="cloud"></div>
<i class="rain-drop" style="--x: 19%; --delay: -.18s; --duration: 1.2s"></i>
<i class="rain-drop" style="--x: 31%; --delay: -.83s; --duration: 1.42s; --length: 23px"></i>
<i class="rain-drop" style="--x: 43%; --delay: -.51s; --duration: 1.08s"></i>
<i class="rain-drop" style="--x: 55%; --delay: -.97s; --duration: 1.34s; --length: 22px"></i>
<i class="rain-drop" style="--x: 68%; --delay: -.33s; --duration: 1.16s"></i>
<i class="rain-drop" style="--x: 79%; --delay: -.71s; --duration: 1.48s; --length: 21px"></i>
<i class="rain-drop" style="--x: 25%; --delay: -.62s; --duration: 1.38s; --length: 17px"></i>
<i class="rain-drop" style="--x: 62%; --delay: -.08s; --duration: 1.27s"></i>
<i class="rain-drop" style="--x: 85%; --delay: -1.11s; --duration: 1.31s; --length: 24px"></i>
<div class="puddle"></div>
<i class="ripple" style="--x: 24%; --delay: -.2s"></i>
<i class="ripple" style="--x: 49%; --delay: -1.06s"></i>
<i class="ripple" style="--x: 72%; --delay: -.63s"></i>
</div>
<div class="card-copy">
<h2 id="rain-title">RAIN</h2>
<p class="temperature">16<sup>°</sup></p>
<p class="summary">Steady drops, softer streets</p>
</div>
</article>
<article class="weather-card card-snow" aria-labelledby="snow-title">
<div class="card-top">
<p class="card-kicker">03 / Winter calm</p>
<span class="condition">Wind 8 km/h</span>
</div>
<div class="scene" aria-hidden="true">
<div class="cloud"></div>
<i class="flake crystal" style="--x: 16%; --size: 12px; --delay: -2.7s; --duration: 8.8s"></i>
<i class="flake" style="--x: 28%; --size: 5px; --delay: -5.1s; --duration: 7.2s"></i>
<i class="flake crystal" style="--x: 41%; --size: 9px; --delay: -1.3s; --duration: 9.7s"></i>
<i class="flake" style="--x: 52%; --size: 8px; --delay: -6.6s; --duration: 8.1s"></i>
<i class="flake crystal" style="--x: 66%; --size: 14px; --delay: -3.9s; --duration: 10.4s"></i>
<i class="flake" style="--x: 78%; --size: 4px; --delay: -7.4s; --duration: 7.7s"></i>
<i class="flake crystal" style="--x: 88%; --size: 10px; --delay: -4.5s; --duration: 9.2s"></i>
<i class="flake" style="--x: 22%; --size: 7px; --delay: -1.9s; --duration: 10.8s"></i>
<i class="flake crystal" style="--x: 59%; --size: 11px; --delay: -8.3s; --duration: 8.6s"></i>
<div class="snowbank"></div>
</div>
<div class="card-copy">
<h2 id="snow-title">SNOW</h2>
<p class="temperature">−2<sup>°</sup></p>
<p class="summary">A quiet drift through the day</p>
</div>
</article>
<article class="weather-card card-storm" aria-labelledby="storm-title">
<div class="card-top">
<p class="card-kicker">04 / Electric skies</p>
<span class="condition">Wind 34 km/h</span>
</div>
<div class="scene" aria-hidden="true">
<div class="cloud"></div>
<div class="bolt"></div>
<i class="rain-drop" style="--x: 13%; --delay: -.57s; --duration: .82s; --length: 25px"></i>
<i class="rain-drop" style="--x: 23%; --delay: -.14s; --duration: .71s; --length: 28px"></i>
<i class="rain-drop" style="--x: 34%; --delay: -.69s; --duration: .93s; --length: 24px"></i>
<i class="rain-drop" style="--x: 45%; --delay: -.38s; --duration: .76s; --length: 30px"></i>
<i class="rain-drop" style="--x: 57%; --delay: -.82s; --duration: .88s; --length: 25px"></i>
<i class="rain-drop" style="--x: 69%; --delay: -.22s; --duration: .69s; --length: 28px"></i>
<i class="rain-drop" style="--x: 81%; --delay: -.61s; --duration: .84s; --length: 31px"></i>
<i class="rain-drop" style="--x: 91%; --delay: -.31s; --duration: .73s; --length: 26px"></i>
<i class="rain-drop" style="--x: 28%; --delay: -.9s; --duration: .91s; --length: 22px"></i>
<i class="rain-drop" style="--x: 75%; --delay: -.48s; --duration: .79s; --length: 27px"></i>
<div class="puddle"></div>
<i class="ripple" style="--x: 21%; --delay: -.77s"></i>
<i class="ripple" style="--x: 52%; --delay: -.31s"></i>
<i class="ripple" style="--x: 77%; --delay: -1.22s"></i>
</div>
<div class="card-copy">
<h2 id="storm-title">STORM</h2>
<p class="temperature">11<sup>°</sup></p>
<p class="summary">Heavy rain, distant thunder</p>
</div>
<div class="storm-flash" aria-hidden="true"></div>
</article>
</section>
<footer class="page-foot">
<span>Local conditions</span>
<span>Updated just now · °C</span>
</footer>
</main>
</body>
</html>Same prompt, other models
One email when a new model lands on the board or in the showcase. Unsubscribe anytime.