Dots3-Note Preview (free)
by Dots StudioReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 2 min 23 s
- Cost
- $0
- Output tokens
- 13,330
- Spent thinking
- 8,927 tokens
- Speed
- 93.5 tok/s
- Console errors
- 0
- First token after
- 825 ms
- First visible text after
- 1 min 55 s
- Prompt tokens
- 498
- Code size
- 8.6 KB
- Finish reason
- stop
- Served by
- AtlasCloud
- Model id
dots-studio/dots-3-note-preview:free- Reasoning sent
model default- Max output
- 32,000 tokens
- Generated
- Nov 9, 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 · 329 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Weather Cards</title>
<style>
/* Reset & base */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: Arial, sans-serif;
background: #f0f2f5;
padding: 20px;
color: #333;
overflow-x: hidden;
}
/* Grid container */
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
max-width: 1200px;
margin: 0 auto;
}
/* Card styles */
.card {
border-radius: 15px;
padding: 20px;
color: #fff;
text-shadow: 0 1px 2px rgba(0,0,0,0.3);
box-shadow: 0 10px 20px rgba(0,0,0,0.1);
transition: transform 0.3s ease, box-shadow 0.3s ease;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
min-height: 280px;
}
.card:hover {
transform: translateY(-10px) scale(1.02);
box-shadow: 0 15px 30px rgba(0,0,0,0.2);
}
/* Info section */
.info {
text-align: center;
margin-top: 15px;
}
.city {
font-size: 1.5rem;
margin-bottom: 5px;
}
.temp {
font-size: 2rem;
font-weight: bold;
margin: 5px 0;
}
.desc {
font-size: 1rem;
opacity: 0.9;
}
/* Icon container */
.icon {
width: 100%;
height: 150px;
display: flex;
align-items: center;
justify-content: center;
}
/* Background gradients */
.sunny { background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%); }
.rainy { background: linear-gradient(135deg, #a1c4fd 0%, #c2e9fb 100%); }
.snowy { background: linear-gradient(135deg, #e0fcff 0%, #bebebe 100%); }
.stormy { background: linear-gradient(135deg, #2c3e50 0%, #4ca1af 100%); }
/* ---------- SUNNY ICON ---------- */
.sun {
position: relative;
width: 100px;
height: 100px;
animation: spin 20s linear infinite;
}
.core {
position: absolute;
top: 50%; left: 50%;
width: 40px; height: 40px;
background: #ffcc00;
border-radius: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 0 20px #ff9900;
}
.ray {
position: absolute;
top: 50%; left: 50%;
width: 6px; height: 20px;
background: #ffcc00;
border-radius: 3px;
transform-origin: center center;
margin-top: -10px;
margin-left: -3px;
}
.r1 { transform: translate(-50%, -50%) rotate(0deg); }
.r2 { transform: translate(-50%, -50%) rotate(45deg); }
.r3 { transform: translate(-50%, -50%) rotate(90deg); }
.r4 { transform: translate(-50%, -50%) rotate(135deg); }
.r5 { transform: translate(-50%, -50%) rotate(180deg); }
.r6 { transform: translate(-50%, -50%) rotate(225deg); }
.r7 { transform: translate(-50%, -50%) rotate(270deg); }
.r8 { transform: translate(-50%, -50%) rotate(315deg); }
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* ---------- RAINY ICON ---------- */
.rain {
position: relative;
width: 100px;
height: 120px;
}
.cloud {
position: absolute;
top: 0; left: 50%;
transform: translateX(-50%);
width: 80px; height: 30px;
background: #e0f7fa;
border-radius: 50px;
box-shadow: 0 0 0 10px #e0f7fa,
0 0 0 20px #b2ebf2,
0 0 0 30px #80deea;
}
.drop {
position: absolute;
top: 30px;
width: 4px; height: 12px;
background: #4a90e2;
border-radius: 50%;
animation: fall 1.5s linear infinite;
}
.d1 { left: 20%; animation-delay: 0s; }
.d2 { left: 40%; animation-delay: 0.2s; }
.d3 { left: 60%; animation-delay: 0.4s; }
.d4 { left: 80%; animation-delay: 0.6s; }
.d5 { left: 50%; animation-delay: 0.8s; }
@keyframes fall {
0% { transform: translateY(0); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateY(80px); opacity: 0; }
}
/* ---------- SNOWY ICON ---------- */
.snow {
position: relative;
width: 100px;
height: 120px;
}
.snowflake {
position: absolute;
width: 12px; height: 12px;
background: #fff;
border-radius: 50%;
box-shadow: 0 0 0 2px #fff;
animation: drift 6s linear infinite;
}
.snowflake::before,
.snowflake::after {
content: '';
position: absolute;
background: #fff;
}
.snowflake::before {
top: 50%; left: 0;
width: 100%; height: 2px;
transform: translateY(-50%);
}
.snowflake::after {
left: 50%; top: 0;
width: 2px; height: 100%;
transform: translateX(-50%);
}
.sf1 { top: 10%; left: 20%; animation-delay: 0s; }
.sf2 { top: 30%; left: 50%; animation-delay: 1s; }
.sf3 { top: 50%; left: 80%; animation-delay: 2s; }
.sf4 { top: 70%; left: 30%; animation-delay: 3s; }
.sf5 { top: 90%; left: 60%; animation-delay: 4s; }
@keyframes drift {
0% { transform: translateX(-20px) rotate(0deg); opacity: 0; }
10% { opacity: 1; }
50% { transform: translateX(20px) rotate(180deg); }
90% { opacity: 1; }
100% { transform: translateX(0) rotate(360deg); opacity: 0; }
}
/* ---------- STORMY ICON ---------- */
.storm {
position: relative;
width: 100px;
height: 120px;
}
.cloud.storm-cloud {
position: absolute;
top: 0; left: 50%;
transform: translateX(-50%);
width: 80px; height: 30px;
background: #37474f;
border-radius: 50px;
box-shadow: 0 0 0 10px #37474f,
0 0 0 20px #455a64,
0 0 0 30px #546e7a;
}
.bolt {
position: absolute;
bottom: 20px; left: 50%;
transform: translateX(-50%);
width: 30px; height: 40px;
background: #ffcc00;
clip-path: polygon(50% 0%, 0% 100%, 50% 75%, 100% 100%);
animation: flash 2s infinite alternate;
}
@keyframes flash {
0% { opacity: 0; }
100% { opacity: 1; }
}
/* Respect prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
.sun, .drop, .snowflake, .bolt {
animation: none !important;
}
.card {
transition: none !important;
}
}
/* Responsive tweak: force 4 columns on wide screens */
@media (min-width: 1200px) {
.cards {
grid-template-columns: repeat(4, 1fr);
}
}
</style>
</head>
<body>
<div class="cards">
<!-- Sunny Card -->
<div class="card sunny">
<div class="icon">
<div class="sun">
<div class="core"></div>
<div class="ray r1"></div>
<div class="ray r2"></div>
<div class="ray r3"></div>
<div class="ray r4"></div>
<div class="ray r5"></div>
<div class="ray r6"></div>
<div class="ray r7"></div>
<div class="ray r8"></div>
</div>
</div>
<div class="info">
<h2 class="city">New York</h2>
<p class="temp">28°C</p>
<p class="desc">Sunny</p>
</div>
</div>
<!-- Rainy Card -->
<div class="card rainy">
<div class="icon">
<div class="rain">
<div class="cloud"></div>
<span class="drop d1"></span>
<span class="drop d2"></span>
<span class="drop d3"></span>
<span class="drop d4"></span>
<span class="drop d5"></span>
</div>
</div>
<div class="info">
<h2 class="city">London</h2>
<p class="temp">15°C</p>
<p class="desc">Rainy</p>
</div>
</div>
<!-- Snowy Card -->
<div class="card snowy">
<div class="icon">
<div class="snow">
<span class="snowflake sf1"></span>
<span class="snowflake sf2"></span>
<span class="snowflake sf3"></span>
<span class="snowflake sf4"></span>
<span class="snowflake sf5"></span>
</div>
</div>
<div class="info">
<h2 class="city">Toronto</h2>
<p class="temp">-5°C</p>
<p class="desc">Snowy</p>
</div>
</div>
<!-- Stormy Card -->
<div class="card stormy">
<div class="icon">
<div class="storm">
<div class="cloud storm-cloud"></div>
<div class="bolt"></div>
</div>
</div>
<div class="info">
<h2 class="city">Miami</h2>
<p class="temp">22°C</p>
<p class="desc">Stormy</p>
</div>
</div>
</div>
</body>
</html>Reasoning trace (8,927 tokens)
We need to create a set of four animated weather cards using only HTML and CSS, no JS, no images, no SVG, no icon fonts. Icons built from HTML elements and pseudo-elements styled with CSS. Each card shows animated icon (rotating sun rays, falling rain drops, drifting snowflakes, flashing lightning), city name, temperature, short description. Each card has its own background gradient matching weather. Responsive grid: 4 per row on desktop, stacked on mobile, lift up on hover. Smooth infinite animations using @keyframes, respect prefers-reduced-motion.
We need to output a single fenced code block with HTML (or SVG, but they ask HTML and CSS). So we output an HTML file containing <style> and <body> etc.
Constraints: No script tag, no inline event handlers. No images, SVG, icon fonts. So we need to create icons using HTML elements (div, span, etc.) and CSS.
We need four cards: sunny, rainy, snowy, stormy.
Each card should have background gradient matching weather.
Icons:
- Sunny: rotating sun rays. Could be a circle (sun) with rays (lines) rotating. Use a container with a circle and multiple divs for rays, rotate container.
- Rainy: falling rain drops. Could be multiple drop shapes (like narrow rectangles with border-radius) falling from top to bottom, maybe with animation.
- Snowy: drifting snowflakes. Could be multiple snowflake shapes (like asterisk) moving horizontally, maybe with rotation.
- Stormy: flashing lightning. Could be a lightning bolt shape using clip-path or border, but we cannot use SVG, but we can use CSS shapes with border-radius or transform. Could create a lightning bolt using a div with border-radius and rotation, or use pseudo-elements to create zigzag. Or use a triangle with border. Or use a series of divs to form lightning.
But we must avoid SVG, so we need to create shapes with CSS.
We can use border-radius to create circles, ellipses, etc. For lightning, we can create a polygon using clip-path with polygon() function, but is that allowed? It's CSS, not SVG. Using clip-path: polygon(...) is fine. Or we can use transform: skew, etc.
We also need to respect prefers-reduced-motion: we should disable animations if user prefers reduced motion. Use @media (prefers-reduced-motion: reduce) to set animation: none.
We need responsive grid: 4 per row on desktop, stacked on mobile. Use CSS Grid or Flexbox. Probably Grid with repeat(auto-fit, minmax(...)).
Each card lifts up on hover: transform: translateY(-5px) or scale.
We need smooth infinite animations using @keyframes.
We also need each card to show city name, temperature, short description.
We need to build icons using HTML elements and pseudo-elements.
Let's design each card:
Card structure:
<div class="card sunny">
<div class="icon"> ... </div>
<div class="info">
<h2 class="city">City</h2>
<p class="temp">25°C</p>
<p class="desc">Sunny</p>
</div>
</div>
But we need to include the icon inside.
We can use separate elements for the icon.
For sunny: a sun with rays. We can have a container .sun with a circle inside, and rays as ::before or ::after? Or multiple span elements.
We can create a sun with a yellow circle and 8 rays around it. The rays can be lines (divs) that rotate together with the sun.
Simplify: Use a div with class="sun" that has a pseudo-element for the circle, and uses animation to rotate. The rays can be created using conic-gradient or repeating-linear-gradient? But we need to avoid images, but CSS gradients are allowed. Could use background: repeating-linear-gradient to create rays? But that might be complex.
We can create a sun with a central circle and 8 lines around it, each line is a div with position absolute, and then rotate the whole container.
E.g., <div class="sun"><span class="ray"></span>...8 times...</div>
But we need to avoid too many extra elements? It's okay.
Alternatively, use a single element with border-radius: 50% and box-shadow to create rays? Could use multiple box-shadows to create rays. But we need rotation animation.
Simplify: Use a div with class="sun" that has a yellow background circle, and uses animation to rotate. For rays, we can use 8 divs inside, each positioned around, and they rotate with the container.
But we need to avoid JS, so we can use CSS animation on the container.
Let's design:
Sun icon:
<div class="sun">
<div class="core"></div>
<div class="ray r1"></div>
<div class="ray r2"></div>
...
</div>
Style:
.sun {
position: relative;
width: 80px;
height: 80px;
margin: auto;
}
.core {
position: absolute;
top: 50%;
left: 50%;
width: 40px;
height: 40px;
background: #ffcc00;
border-radius: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 0 20px #ff9900;
}
.ray {
position: absolute;
top: 50%;
left: 50%;
width: 6px;
height: 20px;
background: #ffcc00;
border-radius: 3px;
transform-origin: center center;
margin-top: -10px;
margin-left: -3px;
}
.r1 { transform: translate(-50%, -50%) rotate(0deg); }
.r2 { transform: translate(-50%, -50%) rotate(45deg); }
...
.r8 { transform: translate(-50%, -50%) rotate(315deg); }
Then we can animate rotation of the entire .sun container:
.sun {
animation: spin 20s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
But we need to respect prefers-reduced-motion: disable animation.
Alternatively, we could use a single element with conic-gradient to create rays, but rotation might be easier.
But we need to avoid JS, but CSS animation is fine.
Now rainy icon: falling rain drops.
We can create a cloud shape and then drops falling from it.
Cloud: could be a white/light blue rounded shape using border-radius.
E.g., <div class="cloud"><span class="drop d1"></span>...</div>
But we need multiple drops falling.
We can create a container .rain with a cloud at top and drops inside that fall.
Cloud: use a div with border-radius: 50% and multiple circles to form cloud shape, but we can simplify with a single rounded rectangle.
Alternatively, we can use a pseudo-element for cloud.
But we need to avoid too many elements.
Simplify: Use a div with class="cloud" that has a light blue background and border-radius: 50% 50% 50% 50% / 60% 60% 40% 40% maybe.
Then inside, we have drops: each drop is a narrow rectangle with border-radius: 50% 50% 50% 50% / 100% 100% 100% 100%? Actually a raindrop shape can be a teardrop: use border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%? Or just use a narrow ellipse.
Simplify: use a div with width: 4px; height: 12px; background: #4a90e2; border-radius: 50%; and animate falling from top to bottom with some horizontal drift.
We can create multiple drops positioned at different horizontal positions, each with different animation delays and durations.
We need to avoid JS, so we can use multiple elements with different animation delays.
We can create maybe 5 drops.
Each drop: <span class="drop"></span> inside .rain.
Style:
.rain {
position: relative;
width: 100px;
height: 120px;
}
.cloud {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 80px;
height: 30px;
background: #e0f7fa;
border-radius: 50px;
box-shadow: 0 0 0 10px #e0f7fa, 0 0 0 20px #b2ebf2, 0 0 0 30px #80deea;
}
.drop {
position: absolute;
bottom: 0;
width: 4px;
height: 12px;
background: #4a90e2;
border-radius: 50%;
animation: fall 1.5s linear infinite;
}
.drop:nth-child(2) { left: 20%; animation-delay: 0.2s; }
.drop:nth-child(3) { left: 40%; animation-delay: 0.4s; }
.drop:nth-child(4) { left: 60%; animation-delay: 0.6s; }
.drop:nth-child(5) { left: 80%; animation-delay: 0.8s; }
@keyframes fall {
0% { transform: translateY(0); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateY(80px); opacity: 0; }
}
But we need to position drops relative to cloud. Maybe better to have a container with cloud at top and drops inside that fall from cloud.
Simplify: Use a container .rain with relative positioning. Place cloud at top. Place drops inside, each absolutely positioned at top of container, then animate them to move down.
We can set .rain { position: relative; width: 100px; height: 120px; } .cloud { position: absolute; top: 0; left: 50%; transform: translateX(-50%); } .drop { position: absolute; top: 30px; width: 4px; height: 12px; background: #4a90e2; border-radius: 50%; animation: fall 1.5s linear infinite; }
Then define animation fall with transform: translateY(80px).
But we need to ensure they loop.
Alternatively, we can use a single element with repeating-linear-gradient to simulate rain, but that might be considered an image? It's a gradient, allowed. But we need to build icons from HTML elements and pseudo-elements. Using gradients is allowed? The requirement says "every weather icon is built from HTML elements and pseudo-elements styled with CSS." So we can use CSS gradients as styling, but the shape must be from HTML elements. So we can use divs.
Thus using multiple drop elements is fine.
Now snowy icon: drifting snowflakes.
We can create a snowflake shape using a div with border-radius and maybe pseudo-elements to create arms. Or use a single element with background: radial-gradient? But we need to create a snowflake shape.
Simplify: Use a star shape with 6 arms. Could use a div with border-radius and transform to create a star? Or use multiple divs to form a snowflake.
We can create a snowflake using a base circle and 6 lines crossing, but that would require multiple elements.
Simplify: Use a single div with class="snowflake" that has a circle and uses box-shadow to create arms? Or use a pseudo-element with conic-gradient.
But we need to avoid images, but CSS gradients are allowed.
Maybe we can create a snowflake using a div with border-radius: 50% and background: radial-gradient(circle, #fff 0%, #fff 10%, transparent 10%)? That would create a dotted pattern, not a snowflake.
Alternatively, we can use a single element with multiple backgrounds to create a snowflake shape. But it's complex.
Simplify: Use a star shape with 6 points using border-radius and transform: rotate. For example, create a div with width: 0; height: 0; border-left: 5px solid transparent; border-right: 5px solid transparent; border-bottom: 10px solid #fff; etc. But that creates a triangle.
We can create a snowflake using 6 triangles arranged in a circle.
But we can also use a simple circle with a cross inside using pseudo-elements.
But the requirement says "every weather icon is built from HTML elements and pseudo-elements styled with CSS." So we can use pseudo-elements to create parts.
Maybe we can create a snowflake with a central circle and 6 lines (like a star) using ::before and ::after and additional elements.
But we need multiple snowflakes drifting. So we can create a container with multiple snowflake elements.
Simplify: Use a single snowflake shape that is a circle with a cross (two lines) and maybe four diagonal lines. We can create a base div with border-radius: 50% and background: #fff, then use ::before and ::after to create lines.
But we need to animate them drifting horizontally.
We can create a snowflake using a div with class="snowflake" that has a circle and uses box-shadow to create arms. For example:
.snowflake {
width: 10px;
height: 10px;
background: #fff;
border-radius: 50%;
box-shadow: 0 0 0 2px #fff, 0 0 0 4px #fff, 0 0 0 6px #fff, 0 0 0 8px #fff;
}
But that creates a dotted circle, not a snowflake.
Better: Use a star shape with 6 points using multiple box-shadows.
But we can also use a single element with a repeating-conic-gradient to create a star pattern. For example:
.snowflake {
width: 20px;
height: 20px;
background: repeating-conic-gradient(#fff 0 10deg, transparent 10deg 20deg);
border-radius: 50%;
}
That would create a starburst pattern. But is that considered an image? It's a gradient, allowed.
But we need to create multiple snowflakes.
Simplify: Use a simple circle for snowflake and animate it moving horizontally.
But the requirement says "drifting snowflakes", so they should look like snowflakes. Could be simple circles.
But we can try to create a more detailed snowflake using a combination of a circle and lines.
Given time, maybe use a simple circle with a cross inside using pseudo-elements.
Example:
.snowflake {
position: relative;
width: 16px;
height: 16px;
background: #fff;
border-radius: 50%;
}
.snowflake::before,
.snowflake::after {
content: '';
position: absolute;
background: #fff;
}
.snowflake::before {
top: 50%;
left: 0;
width: 100%;
height: 2px;
transform: translateY(-50%);
}
.snowflake::after {
left: 50%;
top: 0;
width: 2px;
height: 100%;
transform: translateX(-50%);
}
That creates a circle with a cross. Then we can add diagonal lines with additional pseudo-elements? But we only have ::before and ::after. Could use box-shadow to create diagonal lines.
Alternatively, use a single element with multiple box-shadows to create a star.
Simplify: Use a star shape with 6 points using border-radius and transform.
We can create a snowflake using a div with class="snowflake" that has 6 children elements for arms.
But we need multiple snowflakes, so maybe create a container with many snowflakes.
Given the constraints, we can create a simple snowflake using a circle with a cross, and then animate it drifting.
But the requirement says "drifting snowflakes", so we can have multiple snowflakes moving horizontally.
We'll create a container .snow with many snowflake elements.
Each snowflake: <span class="snowflake"></span>
Style:
.snowflake {
position: absolute;
width: 12px;
height: 12px;
background: #fff;
border-radius: 50%;
box-shadow: 0 0 0 2px #fff, 0 0 0 4px #fff;
animation: drift 6s linear infinite;
}
But that's just a circle with rings.
Alternatively, use a star shape with 6 points using border-radius: 50% and background: radial-gradient? Hmm.
Maybe we can create a snowflake using a single element with a repeating-conic-gradient to create a star pattern, then animate it.
Example:
.snowflake {
width: 20px;
height: 20px;
background: repeating-conic-gradient(#fff 0 10deg, transparent 10deg 20deg);
border-radius: 50%;
animation: spin 10s linear infinite;
}
But we need drifting, not spinning.
We can combine.
But we need to keep it simple.
Given the time, I'll create a snowflake as a circle with a cross using pseudo-elements, and then animate it horizontally.
But we need multiple snowflakes, so we can create a container with several spans.
We'll define .snowflake with a circle and cross.
Now stormy icon: flashing lightning.
We need a lightning bolt shape. We can create it using a div with clip-path: polygon(...). That's allowed (CSS). Or use border-radius to create a zigzag.
Simplify: Use a div with class="lightning" that has a polygon shape.
Example:
.lightning {
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 20px solid #ffcc00;
transform: rotate(180deg);
}
But that's a triangle.
We can create a lightning bolt using multiple triangles stacked.
Or use clip-path: polygon(50% 0%, 0% 100%, 50% 75%, 100% 100%);
That creates a lightning shape.
We can then animate it flashing (opacity changes).
So we can have a div with class="lightning" and animate opacity.
But we also need a cloud maybe.
We can create a stormy card with a cloud and lightning.
Simplify: Use a cloud and a lightning bolt.
Cloud similar to rainy.
Lightning bolt: use clip-path.
We'll create a container .storm with cloud and lightning.
Lightning: <div class="bolt"></div>
Style:
.bolt {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
width: 30px;
height: 40px;
background: #ffcc00;
clip-path: polygon(50% 0%, 0% 100%, 50% 75%, 100% 100%);
animation: flash 2s infinite alternate;
}
@keyframes flash {
0% { opacity: 0; }
100% { opacity: 1; }
}
But we need to respect prefers-reduced-motion.
Now card layout.
We'll create four cards with classes: sunny, rainy, snowy, stormy.
Each card will have a background gradient.
Sunny: gradient yellow to orange.
Rainy: gradient blue to gray.
Snowy: gradient light blue to white.
Stormy: gradient dark gray to black.
Each card will have a lift effect on hover: transform: translateY(-10px) scale(1.02) maybe.
We'll use CSS grid for layout.
Container: display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px;
At max width 1280px, 4 per row.
We'll also add media query for mobile: maybe grid-template-columns: 1fr.
But auto-fit with minmax will automatically adjust.
We need to ensure 4 per row on desktop. So we can set grid-template-columns: repeat(4, 1fr) on large screens, and on smaller screens, stack.
But auto-fit with minmax(250px, 1fr) will show as many as fit, so on large screens it will show 4 if each minmax is 250px and container width allows 4.
We can set max-width: 1200px and margin auto.
We'll also need to ensure the cards are responsive.
Now, each card will contain an icon and info.
We'll structure each card as:
<div class="card sunny">
<div class="icon">
<!-- icon elements -->
</div>
<div class="info">
<h2 class="city">New York</h2>
<p class="temp">28°C</p>
<p class="desc">Sunny</p>
</div>
</div>
We need to ensure the icon is built from HTML elements.
For sunny, we'll create a sun with rays.
We'll create:
<div class="sun">
<div class="core"></div>
<div class="ray r1"></div>
<div class="ray r2"></div>
<div class="ray r3"></div>
<div class="ray r4"></div>
<div class="ray r5"></div>
<div class="ray r6"></div>
<div class="ray r7"></div>
<div class="ray r8"></div>
</div>
But we can simplify by using 8 rays.
We'll style .sun as position: relative; width: 100px; height: 100px; margin: 0 auto; animation: spin 20s linear infinite; (but respect prefers-reduced-motion).
.core: circle.
.ray: each positioned around.
We'll use absolute positioning.
Alternatively, we can use a single element with conic-gradient to create rays, but we need to rotate.
But using multiple elements is fine.
Now rainy icon:
<div class="rain">
<div class="cloud"></div>
<span class="drop d1"></span>
<span class="drop d2"></span>
<span class="drop d3"></span>
<span class="drop d4"></span>
<span class="drop d5"></span>
</div>
Style .rain as position: relative; width: 100px; height: 120px; margin: 0 auto;
.cloud: positioned at top.
.drops: positioned absolutely, top: 30px; left: ...; animation: fall 1.5s linear infinite;
We'll define fall animation.
Now snowy icon:
<div class="snow">
<span class="snowflake sf1"></span>
<span class="snowflake sf2"></span>
<span class="snowflake sf3"></span>
<span class="snowflake sf4"></span>
<span class="snowflake sf5"></span>
</div>
Each snowflake will be a circle with cross.
We'll style .snow as position: relative; width: 100px; height: 120px; margin: 0 auto;
.snowflake: position: absolute; width: 12px; height: 12px; background: #fff; border-radius: 50%; box-shadow: 0 0 0 2px #fff; animation: drift 6s linear infinite;
But we need cross. We can add ::before and ::after for each snowflake.
But each snowflake is a separate element, so we can use its own ::before and ::after.
Define .snowflake::before and .snowflake::after to create cross.
But we need to position them correctly.
Alternatively, we can create a snowflake using a single element with a star shape via background.
Simplify: Use a star shape with 6 points using border-radius and background: radial-gradient? Hmm.
Maybe we can use a single element with a repeating-conic-gradient to create a star pattern, then animate it.
But we need multiple snowflakes, so we can use the same class.
I'll use a simple circle with a cross.
Define .snowflake as a circle, then ::before and ::after as lines.
But each .snowflake will have its own pseudo-elements.
We'll set:
.snowflake {
position: absolute;
width: 12px;
height: 12px;
background: #fff;
border-radius: 50%;
box-shadow: 0 0 0 2px #fff;
}
.snowflake::before,
.snowflake::after {
content: '';
position: absolute;
background: #fff;
}
.snowflake::before {
top: 50%;
left: 0;
width: 100%;
height: 2px;
transform: translateY(-50%);
}
.snowflake::after {
left: 50%;
top: 0;
width: 2px;
height: 100%;
transform: translateX(-50%);
}
But this creates a circle with a cross. However, the box-shadow adds a ring.
We can also add diagonal lines with additional pseudo-elements? Only two.
But maybe it's enough.
Now stormy icon:
<div class="storm">
<div class="cloud storm-cloud"></div>
<div class="bolt"></div>
</div>
Style .storm as position: relative; width: 100px; height: 120px; margin: 0 auto;
.cloud similar to rainy but maybe darker.
.bolt: as described.
Now we need to ensure each card has its own background gradient.
We'll set .card { padding: 20px; border-radius: 15px; box-shadow: 0 10px 20px rgba(0,0,0,0.1); transition: transform 0.3s ease; }
.card:hover { transform: translateY(-10px) scale(1.02); }
Each card will have a specific gradient:
.sunny { background: linear-gradient(135deg, #ffd89b 0%, #19547b 100%); }
But we need matching weather: sunny should be warm colors, rainy blue, snowy light blue, stormy dark.
We can use:
.sunny { background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%); }
.rainy { background: linear-gradient(135deg, #a1c4fd 0%, #c2e9fb 100%); }
.snowy { background: linear-gradient(135deg, #e0fcff 0%, #bebebe 100%); }
.stormy { background: linear-gradient(135deg, #2c3e50 0%, #4ca1af 100%); }
But we can adjust.
Now we need to ensure icons are visible against background.
We'll set icon colors accordingly.
Sun: yellow/orange.
Rain: blue drops, white cloud.
Snow: white snowflakes.
Storm: yellow lightning, dark cloud.
Now we need to add city name, temperature, description.
We'll use simple text.
Now we need to ensure no JavaScript.
We also need to respect prefers-reduced-motion.
We'll add:
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
}
}
But we need to be careful with !important.
Alternatively, we can set animation: none; for those elements.
But we can use:
@media (prefers-reduced-motion: reduce) {
.sun, .rain, .snow, .storm, .drop, .snowflake, .bolt {
animation: none;
}
}
But also for hover transitions.
We'll include a general rule.
Now we need to ensure the page looks right in 1280x800 viewport and adapt down to 375px.
We'll set width: 100%; max-width: 1200px; margin: 0 auto; padding: 20px.
Grid will adjust.
Now we need to output the HTML file.
We'll create a complete HTML document with <html>, <head>, <style>, <body>.
No script tags.
We'll include the four cards.
We need to ensure each icon is built from HTML elements.
Let's write the HTML structure.
We'll create a container .cards.
Inside, four .card elements.
Each .card has .icon and .info.
For sunny:
<div class="card sunny">
<div class="icon">
<div class="sun">
<div class="core"></div>
<div class="ray r1"></div>
<div class="ray r2"></div>
<div class="ray r3"></div>
<div class="ray r4"></div>
<div class="ray r5"></div>
<div class="ray r6"></div>
<div class="ray r7"></div>
<div class="ray r8"></div>
</div>
</div>
<div class="info">
<h2 class="city">New York</h2>
<p class="temp">28°C</p>
<p class="desc">Sunny</p>
</div>
</div>
For rainy:
<div class="card rainy">
<div class="icon">
<div class="rain">
<div class="cloud"></div>
<span class="drop d1"></span>
<span class="drop d2"></span>
<span class="drop d3"></span>
<span class="drop d4"></span>
<span class="drop d5"></span>
</div>
</div>
<div class="info">
<h2 class="city">London</h2>
<p class="temp">15°C</p>
<p class="desc">Rainy</p>
</div>
</div>
For snowy:
<div class="card snowy">
<div class="icon">
<div class="snow">
<span class="snowflake sf1"></span>
<span class="snowflake sf2"></span>
<span class="snowflake sf3"></span>
<span class="snowflake sf4"></span>
<span class="snowflake sf5"></span>
</div>
</div>
<div class="info">
<h2 class="city">Toronto</h2>
<p class="temp">-5°C</p>
<p class="desc">Snowy</p>
</div>
</div>
For stormy:
<div class="card stormy">
<div class="icon">
<div class="storm">
<div class="cloud storm-cloud"></div>
<div class="bolt"></div>
</div>
</div>
<div class="info">
<h2 class="city">Miami</h2>
<p class="temp">22°C</p>
<p class="desc">Stormy</p>
</div>
</div>
Now we need to style these.
We'll write CSS.
First, base styles:
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Arial, sans-serif;
background: #f0f2f5;
padding: 20px;
}
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
max-width: 1200px;
margin: 0 auto;
}
.card {
border-radius: 15px;
padding: 20px;
color: #fff;
text-shadow: 0 1px 2px rgba(0,0,0,0.3);
box-shadow: 0 10px 20px rgba(0,0,0,0.1);
transition: transform 0.3s ease, box-shadow 0.3s ease;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
min-height: 280px;
}
.card:hover {
transform: translateY(-10px) scale(1.02);
box-shadow: 0 15px 30px rgba(0,0,0,0.2);
}
.info {
text-align: center;
margin-top: 15px;
}
.city {
margin: 0;
font-size: 1.5rem;
}
.temp {
font-size: 2rem;
font-weight: bold;
margin: 5px 0;
}
.desc {
margin: 0;
font-size: 1rem;
opacity: 0.9;
}
Now icon containers:
.icon {
width: 100%;
height: 150px;
display: flex;
align-items: center;
justify-content: center;
}
Now specific card backgrounds:
.sunny {
background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%);
}
.rainy {
background: linear-gradient(135deg, #a1c4fd 0%, #c2e9fb 100%);
}
.snowy {
background: linear-gradient(135deg, #e0fcff 0%, #bebebe 100%);
}
.stormy {
background: linear-gradient(135deg, #2c3e50 0%, #4ca1af 100%);
}
Now style icons.
Sun:
.sun {
position: relative;
width: 100px;
height: 100px;
animation: spin 20s linear infinite;
}
.core {
position: absolute;
top: 50%;
left: 50%;
width: 40px;
height: 40px;
background: #ffcc00;
border-radius: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 0 20px #ff9900;
}
.ray {
position: absolute;
top: 50%;
left: 50%;
width: 6px;
height: 20px;
background: #ffcc00;
border-radius: 3px;
transform-origin: center center;
margin-top: -10px;
margin-left: -3px;
}
.r1 { transform: translate(-50%, -50%) rotate(0deg); }
.r2 { transform: translate(-50%, -50%) rotate(45deg); }
.r3 { transform: translate(-50%, -50%) rotate(90deg); }
.r4 { transform: translate(-50%, -50%) rotate(135deg); }
.r5 { transform: translate(-50%, -50%) rotate(180deg); }
.r6 { transform: translate(-50%, -50%) rotate(225deg); }
.r7 { transform: translate(-50%, -50%) rotate(270deg); }
.r8 { transform: translate(-50%, -50%) rotate(315deg); }
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
Rain:
.rain {
position: relative;
width: 100px;
height: 120px;
}
.cloud {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 80px;
height: 30px;
background: #e0f7fa;
border-radius: 50px;
box-shadow: 0 0 0 10px #e0f7fa, 0 0 0 20px #b2ebf2, 0 0 0 30px #80deea;
}
.drop {
position: absolute;
top: 30px;
width: 4px;
height: 12px;
background: #4a90e2;
border-radius: 50%;
animation: fall 1.5s linear infinite;
}
.d1 { left: 20%; animation-delay: 0s; }
.d2 { left: 40%; animation-delay: 0.2s; }
.d3 { left: 60%; animation-delay: 0.4s; }
.d4 { left: 80%; animation-delay: 0.6s; }
.d5 { left: 50%; animation-delay: 0.8s; }
@keyframes fall {
0% { transform: translateY(0); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateY(80px); opacity: 0; }
}
Snow:
.snow {
position: relative;
width: 100px;
height: 120px;
}
.snowflake {
position: absolute;
width: 12px;
height: 12px;
background: #fff;
border-radius: 50%;
box-shadow: 0 0 0 2px #fff;
animation: drift 6s linear infinite;
}
.snowflake::before,
.snowflake::after {
content: '';
position: absolute;
background: #fff;
}
.snowflake::before {
top: 50%;
left: 0;
width: 100%;
height: 2px;
transform: translateY(-50%);
}
.snowflake::after {
left: 50%;
top: 0;
width: 2px;
height: 100%;
transform: translateX(-50%);
}
.sf1 { top: 10%; left: 20%; animation-delay: 0s; }
.sf2 { top: 30%; left: 50%; animation-delay: 1s; }
.sf3 { top: 50%; left: 80%; animation-delay: 2s; }
.sf4 { top: 70%; left: 30%; animation-delay: 3s; }
.sf5 { top: 90%; left: 60%; animation-delay: 4s; }
@keyframes drift {
0% { transform: translateX(0) rotate(0deg); opacity: 0; }
10% { opacity: 1; }
50% { transform: translateX(20px) rotate(180deg); }
90% { opacity: 1; }
100% { transform: translateX(0) rotate(360deg); opacity: 0; }
}
But we need them to drift across. Maybe simpler: move horizontally from left to right.
We can define:
@keyframes drift {
0% { transform: translateX(-20px); opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { transform: translateX(120px); opacity: 0; }
}
But we need to loop.
We'll adjust.
Storm:
.storm {
position: relative;
width: 100px;
height: 120px;
}
.cloud.storm-cloud {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 80px;
height: 30px;
background: #37474f;
border-radius: 50px;
box-shadow: 0 0 0 10px #37474f, 0 0 0 20px #455a64, 0 0 0 30px #546e7a;
}
.bolt {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
width: 30px;
height: 40px;
background: #ffcc00;
clip-path: polygon(50% 0%, 0% 100%, 50% 75%, 100% 100%);
animation: flash 2s infinite alternate;
}
@keyframes flash {
0% { opacity: 0; }
100% { opacity: 1; }
}
Now we need to respect prefers-reduced-motion.
Add:
@media (prefers-reduced-motion: reduce) {
.sun, .rain, .snow, .storm, .drop, .snowflake, .bolt {
animation: none;
}
.card {
transition: none;
}
}
But we also need to ensure that the spin, fall, drift, flash are disabled.
We can set animation: none !important; for those.
But we need to be careful with the hover transition.
We'll add:
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
}
}
But that might affect all.
Alternatively, we can simply set animation: none; for the specific classes.
I'll use:
@media (prefers-reduced-motion: reduce) {
.sun, .drop, .snowflake, .bolt {
animation: none;
}
.card {
transition: none;
}
}
But also the spin animation on .sun, fall on .drop, drift on .snowflake, flash on .bolt.
We'll include those.
Now we need to ensure the icons are built from HTML elements and pseudo-elements. We have used pseudo-elements for snowflake cross. For sun, we used multiple divs. For rain, we used divs and spans. For storm, we used divs.
We haven't used any SVG or images.
We need to ensure no script tags.
Now we need to output the HTML.
We'll combine everything.
We also need to ensure the page is self-contained.
We'll include the CSS in <style>.
Now let's write the full HTML.
We'll structure:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Weather Cards</title>
<style>
... all CSS ...
</style>
</head>
<body>
<div class="cards">
... four cards ...
</div>
</body>
</html>
Now we need to ensure the grid is responsive: 4 per row on desktop, stacked on mobile.
Our grid with auto-fit and minmax(250px, 1fr) will show 4 per row if the viewport width allows at least 4*250px = 1000px plus gaps. On 1280px, it will show 4. On smaller, it will reduce columns.
We can also add a media query to ensure exactly 4 on large screens:
@media (min-width: 1200px) {
.cards {
grid-template-columns: repeat(4, 1fr);
}
}
But auto-fit will also do that.
But to be safe, we can set:
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
max-width: 1200px;
margin: 0 auto;
}
On screens wider than 1200px, it will still be 4 because minmax will allow 4.
But we might want to limit max-width to 1200px.
We'll set max-width: 1200px.
Now we need to ensure the cards lift on hover.
We have that.
Now we need to ensure the animations are smooth and infinite.
We have infinite.
Now we need to ensure the page looks right in 1280x800 viewport.
We'll set body margin: 0; padding: 20px; background: #f0f2f5; color: #333; but cards have their own colors.
We need to ensure the text is readable.
We'll set .info color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,0.3); as above.
Now we need to ensure no horizontal scrollbar.
We'll set overflow-x: hidden; on body.
But we can just ensure width: 100% and box-sizing.
Now we need to output only the code block.
We'll produce the HTML.
Let's write the CSS in detail.
We'll include all styles.
Potential issues:
- The snowflake pseudo-elements might not be visible if the snowflake is small. We'll adjust.
- The lightning bolt clip-path might not be supported in older browsers, but it's fine for Chrome.
- We need to ensure the animations are prefixed? Not necessary for Chrome.
- We need to respect prefers-reduced-motion.
We'll include the media query.
Now let's write the full code.
We'll create the HTML.
After writing, we'll review.
We'll also ensure that each icon is built from HTML elements, not using images.
We have used divs and spans.
We have used pseudo-elements for snowflake cross.
We have used clip-path for lightning.
All good.
Now we need to output exactly one fenced code block.
We'll output:
```html
... code ...
```
No extra text.
Let's write the code.