Models 44

GLM 5.3

by Z.aiReasoningClean
Open in new window

Running live in a sandboxed frame. Click inside it before using the keyboard.

How it went

Total time
51.2 s
Cost
$0.032
Output tokens
7,925
Spent thinking
3,566 tokens
Speed
155.8 tok/s
Console errors
0
First token after
385 ms
First visible text after
33.3 s
Prompt tokens
499
Code size
10.5 KB
Finish reason
stop
Served by
Friendli
Model id
z-ai/glm-5.3
Reasoning sent
{"effort":"high"}
Max output
943,718 tokens
Generated
Nov 12, 2026

What it was asked

The prompt
Create a set of four animated weather cards (sunny, rainy, snowy, stormy), made with HTML and CSS only. Requirements: - Absolutely no JavaScript: the file must not contain any <script> tag or inline event handler. - No images, no SVG, no icon fonts: every weather icon is built from HTML elements and pseudo-elements styled with CSS. - Each card shows an animated icon (rotating sun rays, falling rain drops, drifting snowflakes, flashing lightning), a city name, a temperature and a short description. - Each card has its own background gradient matching the weather. - The cards are displayed in a responsive grid (4 per row on desktop, stacked on mobile) and lift up on hover. - Smooth infinite animations using @keyframes, and respect prefers-reduced-motion.
System prompt, sent with every prompt
You are generating a self-contained web demo. It will be rendered automatically in a sandboxed iframe and compared side by side with the output of other AI models given the exact same task.

Output rules:
- Reply with exactly ONE fenced code block containing the complete file: ```html (or ```svg when the task asks for an SVG). No text before or after the code block.
- Everything must be inline: CSS in <style>, JavaScript in <script>. No external files, images, fonts or network requests, except the CDN URLs explicitly allowed by the task.
- Do not use localStorage, sessionStorage, cookies, IndexedDB, alert(), confirm(), prompt() or window.open(): they are blocked in the sandbox and will throw.
- The page must look right in a 1280×800 viewport and adapt gracefully down to 375px wide. No horizontal scrollbar.
- Something meaningful must be visible on first paint: a screenshot is taken automatically about 3 seconds after load, without any interaction.
- Everything that makes the demo interesting must be visible within the first seconds: nothing hidden behind a high score, a later level or a long play session.
- Games must start in a self-playing demo mode (a simple AI plays) behind a "Click or press a key to start" message, so the game can be judged in action without playing.
- The iframe only receives keyboard events after the user clicks it: if the demo uses the keyboard, display a clear "Click or press a key to start" message.
- The code must run with zero errors in the console of the latest Chrome.

Code run-1.html · 415 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Weather — Four Moods</title>
<style>
  /* ---------- base ---------- */
  *,
  *::before,
  *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
  }

  body {
    min-height: 100vh;
    padding: 48px 24px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 36px;
    font-family: "Avenir Next", "Segoe UI", system-ui, -apple-system, sans-serif;
    background: radial-gradient(1100px 620px at 50% -12%, #262e4d, #0c0e1a 72%);
    color: #eef0fa;
  }

  header {
    text-align: center;
  }

  header h1 {
    font-size: clamp(1.6rem, 3.5vw, 2.4rem);
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
  }

  header p {
    margin-top: 10px;
    font-size: 0.95rem;
    letter-spacing: 0.05em;
    color: #9aa3c4;
  }

  footer {
    font-size: 0.78rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: #5d6688;
  }

  /* ---------- grid ---------- */
  .grid {
    width: 100%;
    max-width: 1200px;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 22px;
  }

  @media (max-width: 1000px) {
    .grid { grid-template-columns: repeat(2, 1fr); }
  }

  @media (max-width: 560px) {
    .grid { grid-template-columns: 1fr; }
    body { padding: 32px 18px; }
  }

  /* ---------- card shell ---------- */
  .card {
    --ink: #fff;
    --sub: rgba(255, 255, 255, 0.72);
    --line: rgba(255, 255, 255, 0.28);
    position: relative;
    overflow: hidden;
    border-radius: 22px;
    padding: 30px 26px 28px;
    background: var(--bg);
    color: var(--ink);
    box-shadow: 0 14px 30px rgba(4, 6, 16, 0.35);
    transition: transform 0.45s cubic-bezier(0.2, 0.7, 0.3, 1.15),
                box-shadow 0.45s ease;
  }

  .card:hover {
    transform: translateY(-12px);
    box-shadow: 0 30px 55px rgba(4, 6, 16, 0.5);
  }

  .city {
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
  }

  .temp {
    margin-top: 14px;
    font-size: 3.3rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.02em;
  }

  .temp sup {
    font-size: 0.45em;
    vertical-align: 0.9em;
    font-weight: 500;
  }

  .desc {
    margin-top: 10px;
    font-size: 0.92rem;
    line-height: 1.5;
    color: var(--sub);
  }

  .hilo {
    margin-top: 18px;
    padding-top: 14px;
    border-top: 1px solid var(--line);
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--sub);
    display: flex;
    justify-content: space-between;
  }

  /* ---------- shared icon stage ---------- */
  .icon {
    position: relative;
    height: 104px;
    margin-bottom: 24px;
  }

  /* ---------- cloud (built from div + pseudo-elements) ---------- */
  .cloud {
    position: absolute;
    top: 16px;
    left: 12px;
    width: 86px;
    height: 28px;
    border-radius: 16px;
    background: var(--cloud);
  }

  .cloud::before,
  .cloud::after {
    content: "";
    position: absolute;
    border-radius: 50%;
    background: inherit;
  }

  .cloud::before {
    width: 38px;
    height: 38px;
    left: 13px;
    top: -19px;
  }

  .cloud::after {
    width: 28px;
    height: 28px;
    left: 48px;
    top: -13px;
  }

  /* ---------- SUN ---------- */
  .sun {
    position: absolute;
    left: 6px;
    top: 6px;
    width: 90px;
    height: 90px;
    animation: spin 20s linear infinite;
  }

  .sun::before {
    content: "";
    position: absolute;
    inset: 23px;
    border-radius: 50%;
    background: radial-gradient(circle at 35% 32%, #fff3b8, #ffd34e 52%, #ffb100);
    box-shadow: 0 0 26px rgba(255, 196, 70, 0.8);
    animation: pulse 3.2s ease-in-out infinite;
  }

  .ray {
    position: absolute;
    top: 0;
    left: calc(50% - 3px);
    width: 6px;
    height: 15px;
    border-radius: 3px;
    background: linear-gradient(#ffe28a, #ffb63d);
    transform-origin: 3px 45px;
  }

  .ray:nth-child(1) { transform: rotate(0deg); }
  .ray:nth-child(2) { transform: rotate(45deg); }
  .ray:nth-child(3) { transform: rotate(90deg); }
  .ray:nth-child(4) { transform: rotate(135deg); }
  .ray:nth-child(5) { transform: rotate(180deg); }
  .ray:nth-child(6) { transform: rotate(225deg); }
  .ray:nth-child(7) { transform: rotate(270deg); }
  .ray:nth-child(8) { transform: rotate(315deg); }

  /* ---------- RAIN DROPS ---------- */
  .drop {
    position: absolute;
    top: 54px;
    width: 4px;
    height: 16px;
    border-radius: 4px;
    background: linear-gradient(180deg, rgba(215,235,255,0), #d7ebff 55%, #9cc7f2);
    animation: fall 1.15s linear infinite;
  }

  .drop:nth-child(1) { left: 18px; }
  .drop:nth-child(2) { left: 38px; animation-delay: 0.24s; }
  .drop:nth-child(3) { left: 58px; animation-delay: 0.48s; }
  .drop:nth-child(4) { left: 78px; animation-delay: 0.1s; }
  .drop:nth-child(5) { left: 98px; animation-delay: 0.36s; }

  /* ---------- SNOWFLAKES ---------- */
  .flake {
    position: absolute;
    top: 50px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #ffffff;
    box-shadow: 0 0 7px rgba(255, 255, 255, 0.95);
    animation: drift 3.4s ease-in-out infinite;
  }

  .flake:nth-child(1) { left: 16px; animation-delay: 0s; }
  .flake:nth-child(2) { left: 40px; animation-delay: 0.9s; }
  .flake:nth-child(3) { left: 64px; animation-delay: 1.8s; }
  .flake:nth-child(4) { left: 88px; animation-delay: 0.5s; }
  .flake:nth-child(5) { left: 108px; animation-delay: 2.4s; }
  .flake:nth-child(6) { left: 30px; animation-delay: 2.9s; width: 6px; height: 6px; }

  /* ---------- LIGHTNING ---------- */
  .bolt {
    position: absolute;
    left: 46px;
    top: 44px;
    width: 36px;
    height: 54px;
    background: linear-gradient(180deg, #fff8b5, #ffd23c 45%, #ff9c2c);
    clip-path: polygon(38% 0%, 95% 0%, 48% 46%, 92% 46%, 8% 100%, 40% 54%, 5% 54%);
    filter: drop-shadow(0 0 10px rgba(255, 214, 92, 0.85));
    animation: flash 2.8s infinite;
  }

  .storm-drops .drop:nth-child(1) { left: 20px; animation-duration: 0.9s; }
  .storm-drops .drop:nth-child(2) { left: 96px; animation-duration: 1.05s; animation-delay: 0.4s; }

  /* ---------- card themes ---------- */
  .card--sunny {
    --bg: linear-gradient(168deg, #ffe49a 0%, #ffbe63 52%, #ff9752 100%);
    --ink: #50260a;
    --sub: rgba(80, 38, 10, 0.68);
    --line: rgba(80, 38, 10, 0.25);
  }

  .card--rainy {
    --bg: linear-gradient(168deg, #5d7fa6 0%, #3c5a7d 55%, #27405c 100%);
    --cloud: #e8f0f8;
  }

  .card--snowy {
    --bg: linear-gradient(168deg, #c9e6ff 0%, #93bfe8 55%, #6f9fd4 100%);
    --ink: #123a63;
    --sub: rgba(18, 58, 99, 0.68);
    --line: rgba(18, 58, 99, 0.25);
    --cloud: #f4faff;
  }

  .card--stormy {
    --bg: linear-gradient(168deg, #43466b 0%, #2b2c4c 55%, #17182e 100%);
    --cloud: #4b4f78;
  }

  .card--stormy .cloud::before,
  .card--stormy .cloud::after {
    filter: brightness(1.18);
  }

  /* ---------- keyframes ---------- */
  @keyframes spin {
    to { transform: rotate(360deg); }
  }

  @keyframes pulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.07); }
  }

  @keyframes fall {
    0%   { transform: translateY(0);    opacity: 0; }
    14%  { opacity: 1; }
    82%  { opacity: 1; }
    100% { transform: translateY(40px); opacity: 0; }
  }

  @keyframes drift {
    0%   { transform: translate(0, 0);        opacity: 0; }
    12%  { opacity: 1; }
    50%  { transform: translate(5px, 18px); }
    86%  { opacity: 1; }
    100% { transform: translate(-4px, 38px);   opacity: 0; }
  }

  @keyframes flash {
    0%, 40%, 47%, 60%, 100% { opacity: 0.12; }
    42%, 44%                 { opacity: 1; }
    57%                      { opacity: 0.85; }
  }

  /* ---------- reduced motion ---------- */
  @media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
      animation: none !important;
      transition: none !important;
    }

    .card:hover {
      transform: none;
    }

    .bolt { opacity: 1; }
    .drop { top: 78px; opacity: 1; }
    .flake { top: 84px; opacity: 1; }
  }
</style>
</head>
<body>

  <header>
    <h1>Weather · Four Moods</h1>
    <p>Animated forecasts built from pure HTML elements and CSS — no images, no SVG, no JavaScript.</p>
  </header>

  <main class="grid">

    <!-- SUNNY -->
    <article class="card card--sunny">
      <div class="icon" aria-hidden="true">
        <div class="sun">
          <span class="ray"></span><span class="ray"></span><span class="ray"></span><span class="ray"></span>
          <span class="ray"></span><span class="ray"></span><span class="ray"></span><span class="ray"></span>
        </div>
      </div>
      <h2 class="city">Valencia</h2>
      <p class="temp">29<sup>°C</sup></p>
      <p class="desc">Bright and cloudless with a warm breeze drifting in from the sea.</p>
      <div class="hilo"><span>H 31°</span><span>L 21°</span></div>
    </article>

    <!-- RAINY -->
    <article class="card card--rainy">
      <div class="icon" aria-hidden="true">
        <div class="cloud"></div>
        <span class="drop"></span><span class="drop"></span><span class="drop"></span>
        <span class="drop"></span><span class="drop"></span>
      </div>
      <h2 class="city">Portland</h2>
      <p class="temp">14<sup>°C</sup></p>
      <p class="desc">Steady showers all afternoon — keep the umbrella close at hand.</p>
      <div class="hilo"><span>H 16°</span><span>L 9°</span></div>
    </article>

    <!-- SNOWY -->
    <article class="card card--snowy">
      <div class="icon" aria-hidden="true">
        <div class="cloud"></div>
        <span class="flake"></span><span class="flake"></span><span class="flake"></span>
        <span class="flake"></span><span class="flake"></span><span class="flake"></span>
      </div>
      <h2 class="city">Reykjavík</h2>
      <p class="temp">-3<sup>°C</sup></p>
      <p class="desc">Gentle snow drifting down over quiet, frost-covered streets.</p>
      <div class="hilo"><span>H 0°</span><span>L -8°</span></div>
    </article>

    <!-- STORMY -->
    <article class="card card--stormy">
      <div class="icon" aria-hidden="true">
        <div class="cloud"></div>
        <span class="bolt"></span>
        <span class="drop"></span><span class="drop"></span>
      </div>
      <h2 class="city">New Orleans</h2>
      <p class="temp">22<sup>°C</sup></p>
      <p class="desc">Thunder rolling overhead with frequent lightning strikes nearby.</p>
      <div class="hilo"><span>H 26°</span><span>L 19°</span></div>
    </article>

  </main>

  <footer>Hover a card to lift it · 100% HTML + CSS</footer>

</body>
</html>
Reasoning trace (3,566 tokens)
Create HTML/CSS-only weather cards. Icons built from divs and pseudo-elements. Four cards: sunny, rainy, snowy, stormy. Animations: rotating sun rays, falling rain drops, drifting snowflakes, flashing lightning. Responsive grid, hover lift, prefers-reduced-motion.

Need rain drops and snowflakes from HTML elements — can add a few divs for drops/flakes inside the icon. No SVG, no images.

Let me design:

Sun: circle core with ::before/::after? Rays: a container div with 8 rays via pseudo-elements... Better: core circle (div.sun-core) plus ray container rotating, rays made from repeating child divs. I can use child divs for rays — 8 spans, each rotated. That's fine HTML.

Rain: cloud (div with ::before/::after bumps) plus drop spans animating translateY with staggered animation-delay.

Snow: cloud + snowflake dots drifting down with sway.

Storm: dark cloud + lightning bolt built from... a bolt shape via clip-path on a div, flashing with opacity keyframes.

Background gradients per card. Grid: repeat(auto-fit, minmax(240px,1fr)) — 4 per row desktop at 1280 (4 cards fit). Actually with fixed 4 cards, use grid-template-columns: repeat(4, 1fr) with media query to 1 column on mobile (or 2 at mid). Hover translateY lift.

Reduced motion: disable animations.

Keep it polished: nice typography, subtle details. Let me write the code.

Bolt via clip-path polygon: polygon(40% 0, 100% 0, 55% 45%, 85% 45%, 20% 100%, 45% 55%, 10% 55%) roughly. Let me craft: classic bolt: polygon(45% 0%, 100% 0%, 50% 50%, 90% 50%, 15% 100%, 40% 60%, 5% 60%). Good enough.

Sun rays: 8 spans each 6px tall bars positioned top center, transform rotate(i*45deg) translateY. Use nth-child to rotate. Also add pulse scale on core.

Rain drops: teardrop via border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%? Simpler: small rounded bar with border-radius 0 0 50% 50% — elongated drop. Animate translateY from cloud bottom down, fade.

Snowflakes: small white circles, translate down with horizontal sway (use two animations or single keyframe with translate both).

Card design: rounded cards, temperature big, city name, description. Maybe a "feels like" or hi/lo small detail. Add subtle animated background layers? Keep icons in an icon stage area.

Let me write.

CSS variables per card for accent colors.

Structure:

<section class="weather-grid">
  <article class="card card--sunny">
    <div class="icon icon--sun"> ... </div>
    <h2 class="city">...</h2>
    <p class="temp">...</p>
    <p class="desc">...</p>
    <div class="meta">...</div>
  </article>
  ...
</section>

Header with title.

Sun icon:
<div class="icon icon-sun">
  <div class="sun">
    <span class="ray"></span> ×8
  </div>
</div>
.sun { position relative, width/height 90px, core via ::before circle; rays positioned absolute at center, transform-origin bottom... } Each ray: position absolute, left 50%, top 0, width 6px, height 100%?? Simpler: ray is a child span: absolute, left calc(50% - 3px), top: 0, width 6, height 18, background, border-radius, transform-origin: center calc offset. Better: rays as full-height spans with a bar rendered via ::before at top? Hmm, each ray span: absolute inset 0? Alternative: ray span width 6px height 50% of container, top 0, left 50% - 3px, transform-origin: 3px 45px (center). Then rotate nth-child.

Container .sun: 90×90. Core: ::before circle 40px centered. Rays container: wrap all rays in .rays div that rotates slowly (spin). Each ray height 90px? Ray: position absolute; top:0; left:calc(50% - 3px); width:6px; height:90px; background transparent; ::before at top: bar 6×16 at top. Actually simpler: ray itself is 6px wide, 16px tall, positioned top:0 left calc(50% - 3px), transform-origin: 3px 45px. Then nth-child rotations 0,45,...315. The .rays wrapper spins 20s linear infinite. Rays could also pulse. Good.

Cloud shape: .cloud div width 80 height 26, border-radius 13px, background; ::before circle 34px at left top overlapping; ::after circle 26px right. Standard CSS cloud.

Cloud with ::before/::after needs background matching. Position: cloud base at bottom.

Rain drops: spans inside .icon-rain below cloud. .drop { width:5px; height:14px; border-radius: 0 0 6px 6px... } Actually classic: border-radius: 50% 50% 50% 50% / 30% 30% 70% 70% gives teardrop? Let me just use border-radius: 0 0 5px 5px with rounded top too: border-radius: 3px; simple bars look fine as rain streaks. Or teardrop: border-radius: 50% 50% 50% 50% / 25% 25% 75% 75%? A common CSS raindrop: border-radius: 0 50% 50% 50%; transform rotate(45deg) — that's a drop pointing up. Simplest attractive: rounded-bottom streaks. I'll use teardrops: width 8 height 8 background, border-radius 50% 50% 50% 50% / 60% 60% 40% 40%... Let me just do streak: width 4, height 16, border-radius 4px, with gradient fade. Fine.

Stagger delays via nth-child.

Snow: .flake spans, circles 8px, animate fall with sway using keyframes translate(0,0)→(4px,15px)→(-4px,30px)→... ends at translateY(40px), opacity fade.

Storm: dark cloud + bolt div with clip-path, flash animation opacity steps + maybe a flash overlay on card? Keep bolt flashing: keyframes flicker.

Backgrounds:
- sunny: linear-gradient warm amber/sky
- rainy: slate blue-gray
- snowy: pale ice blue
- stormy: dark indigo

Hover: translateY(-10px) + shadow, transition. Also maybe icon scales.

Reduced motion: @media (prefers-reduced-motion: reduce) { *,*::before,*::after { animation: none !important; transition: none !important } }

Responsive: grid-template-columns: repeat(4, 1fr); @media max-width 1024: 2 cols; max-width 560: 1 col. At 1280 wide four cards of ~280px each — fine.

Also demo note? No JS required, it's static animation — always visible. Fine.

Add fonts: system stack. Add a small footer hint? Keep header: "Weather — Four Moods" etc.

Let me write full code.

Extra details: temperature with degree symbol, hi/lo. Small tag like "H:24° L:16°".

Card text colors: white-ish on darker cards; for snowy light card maybe dark text? Snowy gradient light icy — use dark navy text? Keep snowy background as medium blue-to-pale with white text with shadow. Let's do:

- sunny: #FFB25E → #FF8A5C? Actually gradient top to bottom: linear-gradient(160deg, #ffd194, #ff8a59)? Text dark? White text with dark shadow works on orange. Use #2b1a3a? Let's make text white on all but add slight shadow; snowy: gradient #a8c8f0 → #e8f4ff too light for white. Use gradient #7fa8d9 → #b8d8f0 white text okay-ish. Or give snowy darker text: #16324f. I'll give each card a --text and --sub variable.

Sunny text: #5b2a12? On warm amber, dark brown text reads nice. Hmm mixed text colors fine since each card defines vars.

Sunny: bg linear-gradient(165deg, #FFE29A 0%, #FFA85C 100%)? text #6b2d0e... Let's pick: text #4a2508, sub rgba(74,37,8,.65). Nice.

Rainy: bg linear-gradient(165deg, #4b6cb7, #2b3a67)? Actually rain mood: #5C7C9E → #2F4858. text white.

Snowy: bg linear-gradient(165deg, #BFE3FF, #7FB3E8)? text #14406b.

Stormy: bg linear-gradient(165deg, #3a3a5c, #17172b)? Dark indigo. text #e8e8f5.

Alright, write it.

Bolt clip-path: polygon(32% 0%, 78% 0%, 52% 38%, 82% 38%, 22% 100%, 42% 52%, 12% 52%) — check: starts top-left-ish, top-right, mid-right going down... Common bolt: polygon(40% 0, 100% 0, 45% 50%, 90% 50%, 10% 100%, 35% 55%, 5% 55%). I'll use that. Yellow gradient background on bolt.

Flash animation: 
@keyframes flash { 0%,55%,60%,100% {opacity:.25} 56%,58% {opacity:1} 70%{opacity:.9} 72%{opacity:.3} } — something irregular.

Also add a subtle glow behind bolt via filter drop-shadow.

Also maybe rain card cloud drips... fine.

Icon stage: height 110px, display flex center, margin-bottom.

Rain drops positioning: absolute inside icon relative to stage. Place drops at left offsets 25%,45%,65% etc, top ~ cloud bottom. Use absolute positioning with left: calc(...). I'll position via nth-child left values.

Icon container: position relative; width 140px; height 110px; margin auto.

Rain icon: cloud centered top. Drops: 5 drops.

Let me code.

.card:hover .icon maybe slight scale? Add.

Also add small "wind lines" on sunny? Skip.

Write final HTML.

Ensure no <script>. Include header with page title and subtitle.

Reduced motion also pauses spin etc.

Code:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Four Moods of Weather</title>
<style>
:root{--radius:22px}
*{box-sizing:border-box;margin:0;padding:0}
body{
  font-family:'Avenir Next','Segoe UI',system-ui,sans-serif;
  min-height:100vh;
  background:#0e1220 radial-gradient? Actually background: #12141f with subtle gradient;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:40px 24px;
  background: radial-gradient(1200px 600px at 50% -10%, #232a44, #0d0f1a 70%);
}
header text-align center margin-bottom.
h1 letter-spacing etc color #f0ecf7.
.grid{display:grid;grid-template-columns:repeat(4,1fr);gap:22px;width:100%;max-width:1200px}
media queries.

.card{border-radius; padding:34px 26px 30px; position:relative; overflow:hidden; box-shadow:0 12px 28px rgba(0,0,0,.28); transition: transform .45s cubic-bezier(.2,.7,.3,1.2), box-shadow .45s; text-align:center? or left. Left-aligned with icon centered maybe. I'll center everything for cleanliness. Actually left-aligned looks designed. Let's do left: icon stage left-aligned too. Hmm centered icons simpler with absolute positioning? No, absolute positioning works regardless. I'll left-align content.

Hover: transform translateY(-12px); box-shadow bigger. Also a ::after highlight sheen? optional.

Text colors via vars:
.card{color:var(--ink)}
.city{font-size:1.15rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase}
.temp{font-size:3.4rem;font-weight:700;line-height:1}
sup ° smaller.
.desc{font-size:.95rem;color:var(--sub);line-height:1.45}
.hilo{font-size:.8rem;letter-spacing:.08em;text-transform:uppercase;color:var(--sub);margin-top:14px;padding-top:14px;border-top:1px solid var(--line)}

Icons.

.icon{position:relative;height:96px;margin-bottom:26px}

Sun:
.sun{position:absolute;left:8px;top:4px;width:88px;height:88px;animation:spin 18s linear infinite}
.sun::before core circle.
Actually core: .sun-core as ::before: content:'';position:absolute;inset:22px;background:radial-gradient(circle at 35% 35%, #fff2b0, #ffcf3f 55%, #ffb300);border-radius:50%;box-shadow:0 0 24px rgba(255,190,60,.75); animation: pulse 3.2s ease-in-out infinite.
.ray{position:absolute;top:0;left:calc(50% - 3px);width:6px;height:88px;transform-origin:50% 44px} — with rotate around center: origin should be center of 88 box: 44px. ray element height 88 but visible part only top bar via... hmm if height 88 and background full it'd be a line across. Instead: ray height 16px, top 0, transform-origin: 3px 44px (center). width 6, background gradient, border-radius 3px.
.ray:nth-child(1){transform:rotate(0deg)} ... 8 at 45deg steps. Also animation delay stagger? The whole .sun spins so no need.

Pulse core also scale slightly.

@keyframes spin{to{transform:rotate(360deg)}}

Cloud base class:
.cloud{position:absolute;width:84px;height:28px;border-radius:16px;top:14px;left:10px}
.cloud::before{content:'';position:absolute;width:36px;height:36px;border-radius:50%;left:12px;top:-18px}
.cloud::after{... width:28px;height:28px;left:46px;top:-12px}
Background set per card via variable --cloud.

Rain drops: 
.drop{position:absolute;top:52px;width:4px;height:15px;border-radius:4px;background:linear-gradient(#cfe8ff,#7fb8e8);animation:fall 1.1s linear infinite}
nth-child left/delay: 5 drops at left 16,36,56,76,96 px? Icon width ~140. cloud spans left 10 to 94. drops left: 18,38,58,78,98? width 140 okay. delays: 0,.22,.44,.1,.33.

@keyframes fall{0%{transform:translateY(0);opacity:0}15%{opacity:1}80%{opacity:1}100%{transform:translateY(38px);opacity:0}}

Snowflakes: .flake{position:absolute;top:50px;width:8px;height:8px;border-radius:50%;background:#fff;box-shadow:0 0 6px rgba(255,255,255,.9);animation:drift 3.2s ease-in-out infinite}
@keyframes drift{0%{transform:translate(0,0);opacity:0}12%{opacity:1}50%{transform:translate(5px,18px)}88%{opacity:1}100%{transform:translate(-4px,36px);opacity:0}}
nth-child lefts and delays.

Storm bolt:
.bolt{position:absolute;left:44px;top:46px;width:34px;height:52px;background:linear-gradient(#fff7ae,#ffd23c 45%,#ff9d2e);clip-path:polygon(38% 0,95% 0,48% 46%,92% 46%,8% 100%,40% 54%,5% 54%);animation:flash 2.6s infinite;filter:drop-shadow(0 0 10px rgba(255,214,92,.8))}
@keyframes flash{0%,42%,48%,56%,100%{opacity:.15}44%,46%{opacity:1}54%{opacity:.85}}

Check clip-path: polygon points (38%,0),(95%,0),(48%,46%),(92%,46%),(8%,100%),(40%,54%),(5%,54%). Sequence: top edge from 38 to 95; down-left to 48,46; right to 92,46; diagonal down-left to 8,100; up to 40,54; left to 5,54; back to 38,0? Closing back to first point (38,0) — the segment from (5,54) to (38,0) is the left slanted edge. Looks like a bolt. Good.

Also stormy rain? Add two drops maybe on storm too — yes add drops to storm card as well for interest. Sure, add 3 drops.

Cloud colors: rainy cloud #e6eef7 whiteish; storm cloud #3a3f5c darker with slightly lighter top? just #454b6e.

Icon container heights: storm bolt extends to ~98, height 100px fine. Set .icon height 108 maybe. Bolt top:46 +52=98. Fine.

Hi/Lo lines: --line rgba colors.

Also give cards decorative ::before radial glow? e.g., sunny card sun glow. Keep simple.

Media queries:
@media (max-width:1000px){.grid{grid-template-columns:repeat(2,1fr)}}
@media (max-width:560px){.grid{grid-template-columns:1fr}}

Reduced motion:
@media (prefers-reduced-motion:reduce){
 *,*::before,*::after{animation:none!important;transition:none!important}
 .card:hover{transform:none}
}

Header: h1 "Weather, in Four Moods" + p subtitle.

Also maybe footer small note "Pure HTML + CSS — no JavaScript". Nice touch.

Write it all out.