• Auntilz

    提示词:

    以 iOS 18 的设计风格做一个带有动画效果的天气卡片,要求是使用 HTML、CSS 和基础 JavaScript,使用横板天气页面(拥有 4 个天气卡片 (晴天,大风,暴雨,暴雪))。应足够美观,实现一定的交互效果。```

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>天气 · iOS 风格天气卡片</title>
    <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg&#039; viewBox='0 0 100 100'><text y='.9em' font-size='90'>⛅</text></svg>">
    <style>
    / ============ 基础 ============ /
    @property --amb-a { syntax:'<color>'; inherits:true; initial-value:rgba(30,120,210,.55); }
    @property --amb-b { syntax:'<color>'; inherits:true; initial-value:rgba(255,170,60,.35); }

    • { margin:0; padding:0; box-sizing:border-box; }

    :root{
    --ease: cubic-bezier(.32,.72,0,1);
    --font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text",
    "PingFang SC", "HarmonyOS Sans SC", "MiSans", "Microsoft YaHei", "Segoe UI", sans-serif;
    }
    html,body{ height:100%; }
    body{
    font-family:var(--font);
    background:#070b15;
    color:#fff;
    min-height:100vh;
    display:flex; flex-direction:column;
    overflow-x:hidden;
    -webkit-font-smoothing:antialiased;
    }
    ::selection{ background:rgba(120,170,255,.35); }
    button{ font-family:inherit; }

    / ============ 环境背景(随卡片变色) ============ /
    .ambient{
    position:fixed; inset:0; z-index:0; pointer-events:none;
    background:
    radial-gradient(900px 620px at 12% -8%, var(--amb-a), transparent 70%),
    radial-gradient(1000px 700px at 88% 110%, var(--amb-b), transparent 70%);
    transition: --amb-a 1.4s ease, --amb-b 1.4s ease;
    }
    .vignette{
    position:fixed; inset:0; z-index:1; pointer-events:none;
    background:radial-gradient(120% 95% at 50% 38%, transparent 58%, rgba(0,0,0,.52));
    }
    .grain{
    position:fixed; inset:0; z-index:1; pointer-events:none; opacity:.05;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg&#039; width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
    }

    / ============ 顶栏 ============ /
    .topbar{
    position:relative; z-index:3;
    display:flex; justify-content:space-between; align-items:flex-end;
    max-width:1560px; width:100%; margin:0 auto;
    padding:34px 36px 4px;
    animation:fadeDown .8s var(--ease) backwards;
    }
    .date-line{ font-size:12.5px; font-weight:600; letter-spacing:.16em; color:rgba(255,255,255,.5); }
    .topbar h1{ font-size:38px; font-weight:800; letter-spacing:.02em; margin-top:3px; }
    .topbar .sub{ font-size:11px; letter-spacing:.3em; color:rgba(255,255,255,.32); margin-top:4px; font-weight:600; }
    .controls{ display:flex; flex-direction:column; align-items:flex-end; gap:12px; }
    .clock{ font-size:30px; font-weight:200; font-variant-numeric:tabular-nums; letter-spacing:.03em; color:rgba(255,255,255,.92); }
    .seg{
    position:relative; display:flex; padding:2px; border-radius:10px;
    background:rgba(255,255,255,.1); border:1px solid rgba(255,255,255,.08);
    }
    .seg button{
    position:relative; z-index:1; width:56px; padding:6px 0; border:0; background:none;
    font-size:14px; font-weight:600; color:rgba(255,255,255,.6); cursor:pointer; transition:color .3s;
    }
    .seg button.on{ color:#0b0f1a; }
    .seg-thumb{
    position:absolute; top:2px; left:2px; width:56px; height:calc(100% - 4px);
    background:#fff; border-radius:8px; box-shadow:0 2px 8px rgba(0,0,0,.4);
    transition:transform .35s var(--ease);
    }
    .seg.f .seg-thumb{ transform:translateX(56px); }

    / ============ 卡片阵列 ============ /
    .deck{
    position:relative; z-index:3; flex:1;
    display:grid; grid-template-columns:repeat(4,1fr); gap:22px;
    max-width:1560px; width:100%; margin:0 auto;
    padding:26px 36px 6px; align-content:center;
    }
    .card{
    position:relative; height:520px; border-radius:30px; overflow:hidden;
    cursor:pointer; user-select:none;
    transform:perspective(1100px) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg))
    translateY(var(--lift,0px)) scale(var(--sc,1));
    transition:transform .6s var(--ease), box-shadow .5s ease;
    box-shadow:0 24px 50px -20px rgba(0,0,0,.6), inset 0 1px 0 rgba(255,255,255,.28);
    animation:cardIn .9s var(--ease) backwards;
    outline:none;
    }
    .card.tilting{ transition:transform .08s linear, box-shadow .5s ease; }
    .card:nth-child(1){ animation-delay:.08s; } .card:nth-child(2){ animation-delay:.18s; }
    .card:nth-child(3){ animation-delay:.28s; } .card:nth-child(4){ animation-delay:.38s; }
    .card:hover{ --lift:-10px; --sc:1.015; box-shadow:0 40px 70px -22px rgba(0,0,0,.7), inset 0 1px 0 rgba(255,255,255,.35); }
    .card:active{ --sc:.982; --lift:-4px; }
    .card:focus-visible{ box-shadow:0 0 0 3px rgba(140,190,255,.8), 0 24px 50px -20px rgba(0,0,0,.6); }
    .card::before{
    content:''; position:absolute; inset:0; border-radius:inherit; z-index:3; pointer-events:none;
    border:1px solid rgba(255,255,255,.16);
    }
    .ring{
    position:absolute; inset:0; border-radius:inherit; z-index:4; pointer-events:none;
    border:2px solid rgba(255,255,255,0); transition:border-color .35s, box-shadow .35s;
    }
    .card.active .ring{
    border-color:rgba(255,255,255,.85);
    box-shadow:0 0 0 4px rgba(255,255,255,.14), inset 0 0 26px rgba(255,255,255,.12);
    }

    / 卡片底色(四种天气) /
    .card[data-id="sunny"]{ background:linear-gradient(185deg,#1873cc 0%,#3f9fe8 40%,#7cc4f2 68%,#f7bd63 100%); }
    .card[data-id="windy"]{ background:linear-gradient(185deg,#2b5e6f 0%,#4f8a92 44%,#8fbcb0 74%,#cfe2d3 100%); }
    .card[data-id="rain"] { background:linear-gradient(185deg,#121a2c 0%,#28384f 42%,#41546f 74%,#5a6c88 100%); }
    .card[data-id="snow"] { background:linear-gradient(185deg,#4c71a1 0%,#7d9ec6 44%,#b0c7df 74%,#dfeaf6 100%); }

    .scene{
    position:absolute; inset:-3%; z-index:0; overflow:hidden;
    transform:translate3d(var(--px,0px), var(--py,0px), 0) scale(1.05);
    transition:transform .3s ease-out;
    }
    .scrim{
    position:absolute; inset:0; z-index:1; pointer-events:none;
    background:linear-gradient(180deg, rgba(8,14,26,.32) 0%, transparent 30%, transparent 60%, rgba(8,14,26,.36) 100%);
    }

    / ---- 卡片文字层 ---- /
    .inner{
    position:relative; z-index:2; height:100%;
    padding:22px 24px 20px; display:flex; flex-direction:column;
    text-shadow:0 1px 14px rgba(0,20,45,.28);
    }
    .row-top{ display:flex; justify-content:space-between; align-items:flex-start; }
    .city{ font-size:21px; font-weight:600; letter-spacing:.02em; }
    .en{ display:block; font-size:9.5px; font-weight:700; letter-spacing:.26em; opacity:.55; margin-top:3px; }
    .live{
    display:inline-flex; align-items:center; gap:6px;
    font-size:11px; font-weight:600; color:rgba(255,255,255,.8);
    padding:5px 10px; border-radius:14px; background:rgba(10,18,32,.22);
    -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px);
    }
    .live i{ width:6px; height:6px; border-radius:50%; background:#30d158; animation:pulseDot 1.8s ease-in-out infinite; }
    .pill{
    display:inline-flex; align-items:center; gap:6px; align-self:flex-start;
    margin-top:12px; padding:5px 12px; border-radius:20px;
    font-size:12px; font-weight:600; letter-spacing:.02em;
    -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px);
    transition:transform .3s var(--ease);
    }
    .card:hover .pill{ transform:translateY(-2px); }
    .pill.uv { background:rgba(175,82,222,.78); color:#fff; }
    .pill.wind{ background:rgba(255,214,10,.88); color:#4a3b00; text-shadow:none; }
    .pill.rain{ background:rgba(255,69,58,.82); color:#fff; }
    .pill.snow{ background:rgba(255,159,10,.88); color:#4a2b00; text-shadow:none; }
    .temp{ margin-top:10px; font-size:clamp(52px,4.4vw,66px); font-weight:200; line-height:1.05; letter-spacing:-.02em; }
    .temp .deg{ font-size:.48em; font-weight:300; vertical-align:14%; opacity:.9; }
    .t-val{ display:inline-block; font-variant-numeric:tabular-nums; }
    .t-val.roll{ animation:rollText .38s ease; }
    .cond{ font-size:17px; font-weight:500; opacity:.95; margin-top:2px; }
    .hilo{ font-size:13.5px; font-weight:500; opacity:.8; margin-top:5px; display:flex; gap:14px; }
    .spark-wrap{ margin-top:auto; }
    .spark{ height:46px; }
    .spark svg{ display:block; width:100%; height:46px; overflow:visible; }
    .spark-cap{ display:block; font-size:11px; font-weight:500; opacity:.66; margin-top:7px; letter-spacing:.04em; }

    / ============ 场景一:晴天 ============ /
    .sun-wrap{ position:absolute; top:52px; right:26px; width:104px; height:104px; }
    .sun-glow{
    position:absolute; top:-84px; right:-84px; width:360px; height:360px;
    background:radial-gradient(circle, rgba(255,205,90,.42), transparent 65%);
    transition:transform 1s ease, opacity 1s ease;
    }
    .card[data-id="sunny"]:hover .sun-glow{ transform:scale(1.25); opacity:1; }
    .sun-rays{
    position:absolute; inset:-96px; border-radius:50%;
    background:repeating-conic-gradient(from 0deg, rgba(255,255,255,.15) 0deg 6deg, transparent 6deg 18deg);
    -webkit-mask:radial-gradient(circle, transparent 21%, #000 22%, #000 60%, transparent 61%);
    mask:radial-gradient(circle, transparent 21%, #000 22%, #000 60%, transparent 61%);
    animation:spin 46s linear infinite;
    }
    .card[data-id="sunny"]:hover .sun-rays{ animation-duration:15s; }
    .sun{
    position:absolute; inset:0; border-radius:50%;
    background:radial-gradient(circle at 38% 34%, #fffbe8 0%, #ffe98a 34%, #ffc93d 68%, #ffb300 100%);
    box-shadow:0 0 44px 10px rgba(255,196,64,.65), 0 0 120px 42px rgba(255,180,60,.26);
    animation:sunPulse 5s ease-in-out infinite;
    transition:transform .8s var(--ease);
    }
    .card[data-id="sunny"]:hover .sun{ transform:scale(1.07); }
    .flare{ position:absolute; border-radius:50%; background:rgba(255,255,255,.5); filter:blur(2px); }
    .flare.f1{ top:196px; right:158px; width:13px; height:13px; opacity:.55; }
    .flare.f2{ top:238px; right:206px; width:8px; height:8px; opacity:.4; }
    .cloud{ position:absolute; background:#fff; border-radius:50px; filter:blur(1px); }
    .cloud::before,.cloud::after{ content:''; position:absolute; background:inherit; border-radius:50%; }
    .cloud.small{ width:88px; height:26px; opacity:.92; }
    .cloud.small::before{ width:38px; height:38px; top:-17px; left:14px; }
    .cloud.small::after{ width:26px; height:26px; top:-10px; left:46px; }
    .cloud.ca{ top:57%; animation:driftA 70s linear infinite; }
    .cloud.cb{ top:72%; scale:.68; opacity:.75; animation:driftB 95s linear infinite; }

    / ============ 场景二:大风 ============ /
    .wind-lines{ position:absolute; inset:0; width:100%; height:100%; }
    .wl{
    fill:none; stroke:rgba(255,255,255,.5); stroke-width:3.4; stroke-linecap:round;
    stroke-dasharray:82 440; animation:windash 3.4s linear infinite;
    }
    .wl.w1{ animation-duration:calc(var(--ws,1)*2.9s); }
    .wl.w2{ animation-duration:calc(var(--ws,1)*3.8s); animation-delay:-1.2s; opacity:.7; stroke-width:2.8; }
    .wl.w3{ animation-duration:calc(var(--ws,1)*3.2s); animation-delay:-2s; opacity:.55; }
    .wl.w4{ animation-duration:calc(var(--ws,1)*4.4s); animation-delay:-.6s; opacity:.4; stroke-width:2.4; }
    .card[data-id="windy"]:hover{ --ws:.45; }
    .streak{
    position:absolute; left:0; width:44%; height:10px; border-radius:999px;
    background:rgba(255,255,255,.5); filter:blur(6px);
    animation:streakMove calc(var(--ws,1)*5.2s) linear infinite;
    }
    .streak.s1{ top:24%; animation-delay:-1s; }
    .streak.s2{ top:50%; scale:1.25 .8; opacity:.7; animation-delay:-2.6s; animation-duration:calc(var(--ws,1)*4.2s); }
    .streak.s3{ top:72%; scale:.8 .7; opacity:.55; animation-delay:-.4s; animation-duration:calc(var(--ws,1)*6.4s); }
    .leaf{ position:absolute; left:0; font-size:20px; filter:drop-shadow(0 2px 4px rgba(0,0,0,.2));
    animation:leafFly calc(var(--ws,1)*7s) linear infinite; }
    .leaf.l1{ top:34%; }
    .leaf.l2{ top:58%; font-size:16px; animation-delay:-2.8s; animation-duration:calc(var(--ws,1)*8.4s); }
    .leaf.l3{ top:80%; font-size:15px; animation-delay:-5s; animation-duration:calc(var(--ws,1)*9.2s); }

    / ============ 场景三:暴雨 ============ /
    .storm-clouds i{ position:absolute; border-radius:50%; filter:blur(16px); animation:cloudSway 9s ease-in-out infinite alternate; }
    .storm-clouds i:nth-child(1){ width:250px; height:95px; top:-34px; left:-46px; background:#141c2e; }
    .storm-clouds i:nth-child(2){ width:320px; height:115px; top:-50px; left:26%; background:#1a2436; animation-delay:-3s; }
    .storm-clouds i:nth-child(3){ width:270px; height:100px; top:-30px; right:-60px; background:#16202f; animation-delay:-6s; }
    .rain{ position:absolute; inset:-12%; transform:rotate(12deg); }
    .rain span{
    position:absolute; top:-16%; width:2px; border-radius:2px;
    background:linear-gradient(180deg, transparent, rgba(186,212,255,.8));
    animation-name:fall; animation-timing-function:linear; animation-iteration-count:infinite;
    }
    .card[data-id="rain"]:hover{ --rs:.52; }
    .card[data-id="rain"]:hover .rain span{ opacity:1; }
    .flash{
    position:absolute; inset:0; opacity:0;
    background:radial-gradient(620px 320px at 62% 0%, rgba(255,255,255,.95), rgba(255,255,255,.28) 58%, transparent 80%);
    }
    .scene.flashing .flash{ animation:flashAnim .75s ease-out; }
    .bolt{
    position:absolute; top:7%; left:54%; width:58px; fill:#fff; opacity:0;
    filter:drop-shadow(0 0 14px rgba(190,215,255,.95));
    }
    .scene.flashing .bolt{ animation:boltAnim .75s ease-out; }
    .rain-fog{ position:absolute; left:0; right:0; bottom:0; height:30%;
    background:linear-gradient(180deg, transparent, rgba(130,152,185,.28)); }

    / ============ 场景四:暴雪 ============ /
    .snow-clouds i{ position:absolute; border-radius:50%; filter:blur(14px); background:#c7d6ea; opacity:.85;
    animation:cloudSway 11s ease-in-out infinite alternate; }
    .snow-clouds i:nth-child(1){ width:260px; height:90px; top:-36px; left:-40px; }
    .snow-clouds i:nth-child(2){ width:320px; height:105px; top:-48px; right:-70px; animation-delay:-4s; background:#d4e1f1; }
    .snow{ position:absolute; inset:0; transition:opacity 1s ease; }
    .snow.lb{ opacity:0; }
    .card[data-id="snow"]:hover .snow.lb{ opacity:1; }
    .flake{ position:absolute; top:-6%; animation:fallY var(--d) linear var(--del) infinite; }
    .flake i{
    display:block; width:var(--sz); height:var(--sz); border-radius:50%;
    background:#fff; opacity:var(--o); filter:blur(var(--bl));
    box-shadow:0 0 6px rgba(255,255,255,.55);
    animation:swayX var(--sd) ease-in-out infinite alternate;
    }
    .card[data-id="snow"]:hover .flake i{ box-shadow:0 0 10px rgba(255,255,255,.85); }
    .mist{
    position:absolute; left:-20%; width:140%; height:90px; filter:blur(18px);
    background:linear-gradient(90deg, transparent, rgba(255,255,255,.4), transparent);
    opacity:.55; transition:opacity 1s ease; animation:mistDrift 17s ease-in-out infinite alternate;
    }
    .card[data-id="snow"]:hover .mist{ opacity:.95; }
    .mist.m1{ bottom:15%; }
    .mist.m2{ bottom:34%; animation-duration:23s; animation-direction:alternate-reverse; }
    .frost{ position:absolute; left:0; right:0; bottom:0; height:24%;
    background:linear-gradient(180deg, transparent, rgba(240,247,255,.4) 68%, rgba(255,255,255,.58)); }

    / ============ 底部提示 ============ /
    .hint{
    position:relative; z-index:3; text-align:center;
    font-size:12.5px; letter-spacing:.06em; color:rgba(255,255,255,.42);
    padding:14px 20px 26px; animation:fadeDown 1s var(--ease) .5s backwards;
    }
    .hint b{ color:rgba(255,255,255,.66); font-weight:600; }

    / ============ 详情面板(iOS Sheet) ============ /
    .backdrop{
    position:fixed; inset:0; z-index:40; background:rgba(3,7,14,.52);
    -webkit-backdrop-filter:blur(5px); backdrop-filter:blur(5px);
    opacity:0; pointer-events:none; transition:opacity .45s ease;
    }
    .backdrop.open{ opacity:1; pointer-events:auto; }
    .sheet{
    position:fixed; left:50%; bottom:0; z-index:50;
    width:min(1080px,96vw); max-height:min(86vh,880px); overflow-y:auto;
    transform:translate(-50%,105%);
    transition:transform .62s var(--ease);
    background:linear-gradient(180deg, rgba(30,37,52,.88), rgba(13,17,27,.94));
    -webkit-backdrop-filter:blur(40px) saturate(1.6); backdrop-filter:blur(40px) saturate(1.6);
    border-radius:26px 26px 0 0; border-top:1px solid rgba(255,255,255,.16);
    box-shadow:0 -24px 90px rgba(0,0,0,.55);
    padding:10px 34px 24px;
    }
    .sheet.open{ transform:translate(-50%,0); }
    .sheet::-webkit-scrollbar{ width:8px; }
    .sheet::-webkit-scrollbar-thumb{ background:rgba(255,255,255,.16); border-radius:8px; }
    .grabber{ width:38px; height:5px; border-radius:3px; background:rgba(255,255,255,.28); margin:10px auto 20px; }

    .sh-head{ display:flex; justify-content:space-between; align-items:flex-start; animation:riseIn .55s var(--ease) .05s backwards; }
    .sh-city{ font-size:26px; font-weight:700; letter-spacing:.02em; }
    .sh-en{ font-size:10px; font-weight:700; letter-spacing:.3em; color:rgba(255,255,255,.42); margin-left:10px; vertical-align:3px; }
    .sh-temp{ display:flex; align-items:center; gap:14px; margin-top:6px; }
    .sh-icon{ font-size:42px; filter:drop-shadow(0 4px 10px rgba(0,0,0,.35)); animation:floatIcon 3.2s ease-in-out infinite; }
    .sh-t{ font-size:58px; font-weight:200; letter-spacing:-.02em; line-height:1; }
    .sh-cond{ font-size:14px; color:rgba(235,240,250,.66); margin-top:8px; font-weight:500; }
    .sh-close{
    width:34px; height:34px; border-radius:50%; border:0; cursor:pointer;
    background:rgba(255,255,255,.12); color:#fff; font-size:15px; line-height:1;
    transition:background .3s, transform .45s var(--ease);
    }
    .sh-close:hover{ background:rgba(255,255,255,.24); transform:rotate(90deg); }

    .sh-alert{
    display:inline-flex; align-items:center; gap:8px; margin-top:16px;
    padding:8px 16px; border-radius:22px; font-size:13px; font-weight:700; letter-spacing:.03em;
    animation:riseIn .55s var(--ease) .12s backwards;
    }
    .sh-alert.uv { background:rgba(175,82,222,.3); color:#e2b8ff; border:1px solid rgba(175,82,222,.5); }
    .sh-alert.wind{ background:rgba(255,214,10,.22); color:#ffe58a; border:1px solid rgba(255,214,10,.45); }
    .sh-alert.rain{ background:rgba(255,69,58,.25); color:#ffb0a8; border:1px solid rgba(255,69,58,.5); }
    .sh-alert.snow{ background:rgba(255,159,10,.22); color:#ffd39a; border:1px solid rgba(255,159,10,.45); }
    .sh-summary{
    margin-top:14px; font-size:15px; line-height:1.75; color:rgba(235,240,250,.85);
    max-width:64ch; animation:riseIn .55s var(--ease) .18s backwards;
    }
    .sh-sec{ animation:riseIn .55s var(--ease) backwards; }
    .sh-sec:nth-of-type(1){ animation-delay:.24s; }
    .sh-sec:nth-of-type(2){ animation-delay:.32s; }
    .sh-sec:nth-of-type(3){ animation-delay:.4s; }
    .sh-sec h4{
    display:flex; align-items:center; gap:8px; margin:28px 0 12px;
    font-size:12.5px; font-weight:700; letter-spacing:.14em; color:rgba(255,255,255,.45);
    }
    .sh-sec h4::after{ content:''; flex:1; height:1px; background:rgba(255,255,255,.09); }

    .hours{
    display:flex; gap:7px; overflow-x:auto; padding:4px 2px 12px;
    scrollbar-width:none;
    -webkit-mask-image:linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
    mask-image:linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
    }
    .hours::-webkit-scrollbar{ display:none; }
    .hour{
    min-width:66px; display:flex; flex-direction:column; align-items:center; gap:9px;
    padding:14px 6px 12px; border-radius:18px; background:rgba(255,255,255,.055);
    transition:background .3s, transform .3s var(--ease);
    }
    .hour:hover{ background:rgba(255,255,255,.14); transform:translateY(-4px); }
    .hour.now{ background:rgba(255,255,255,.16); }
    .h-time{ font-size:12px; color:rgba(255,255,255,.55); font-weight:600; }
    .h-ic{ font-size:22px; filter:drop-shadow(0 3px 6px rgba(0,0,0,.3)); }
    .h-bar{ width:4px; height:40px; border-radius:4px; background:rgba(255,255,255,.13);
    display:flex; align-items:flex-end; overflow:hidden; }
    .h-bar i{
    display:block; width:100%; border-radius:4px;
    background:linear-gradient(180deg, #fff, var(--acc,#7aa7ff));
    animation:barGrow .7s var(--ease) backwards;
    animation-delay:calc(var(--i)*38ms + .3s);
    }
    .h-t{ font-size:15px; font-weight:600; font-variant-numeric:tabular-nums; }

    .arc-wrap{ display:flex; flex-direction:column; align-items:center; }
    .arc-svg{ width:min(430px,100%); overflow:visible; }
    .arc-base{ fill:none; stroke:rgba(255,255,255,.16); stroke-width:2; stroke-dasharray:2 7; stroke-linecap:round; }
    .arc-prog{ fill:none; stroke:url(#arcG); stroke-width:3; stroke-linecap:round; }
    .horizon{ stroke:rgba(255,255,255,.12); stroke-width:1; }
    .sun-dot{ fill:#ffd76a; opacity:0; animation:dotIn .5s ease 1s forwards; }
    .arc-labels{ display:flex; justify-content:space-between; width:min(430px,100%);
    font-size:12.5px; color:rgba(255,255,255,.55); font-weight:600; margin-top:6px; }
    .arc-note{ font-size:11px; color:rgba(255,255,255,.35); margin-top:6px; letter-spacing:.08em; }

    .metrics{ display:grid; grid-template-columns:repeat(3,1fr); gap:12px; }
    .tile{
    background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.07);
    border-radius:18px; padding:14px 16px 13px;
    transition:background .3s, transform .3s var(--ease);
    }
    .tile:hover{ background:rgba(255,255,255,.11); transform:translateY(-3px); }
    .tile-h{ display:flex; align-items:center; gap:6px; font-size:11px; font-weight:700;
    letter-spacing:.1em; color:rgba(255,255,255,.45); }
    .tile-v{ font-size:21px; font-weight:650; margin-top:9px; letter-spacing:-.01em; }
    .tile-n{ font-size:11.5px; color:rgba(255,255,255,.45); margin-top:3px; }
    .sh-foot{ margin-top:26px; padding-top:16px; border-top:1px solid rgba(255,255,255,.08);
    font-size:11.5px; color:rgba(255,255,255,.32); text-align:center; letter-spacing:.06em; }

    / ============ 动画 ============ /
    @keyframes cardIn{ from{ opacity:0; transform:perspective(1100px) translateY(70px) scale(.9); }
    to{ opacity:1; transform:perspective(1100px) translateY(0) scale(1); } }
    @keyframes fadeDown{ from{ opacity:0; transform:translateY(-16px); } to{ opacity:1; transform:none; } }
    @keyframes riseIn{ from{ opacity:0; transform:translateY(22px); } to{ opacity:1; transform:none; } }
    @keyframes spin{ to{ transform:rotate(360deg); } }
    @keyframes sunPulse{ 0%,100%{ transform:scale(1); } 50%{ transform:scale(1.045); } }
    @keyframes driftA{ from{ left:-26%; } to{ left:112%; } }
    @keyframes driftB{ from{ left:112%; } to{ left:-26%; } }
    @keyframes windash{ to{ stroke-dashoffset:-522; } }
    @keyframes streakMove{ from{ transform:translateX(-130%); } to{ transform:translateX(310%); } }
    @keyframes leafFly{
    0%{ transform:translate(-60px,0) rotate(0); opacity:0; }
    8%{ opacity:.95; }
    30%{ transform:translate(120px,-36px) rotate(160deg); }
    55%{ transform:translate(260px,20px) rotate(320deg); }
    82%{ opacity:.9; }
    100%{ transform:translate(540px,-8px) rotate(620deg); opacity:0; }
    }
    @keyframes fall{ to{ transform:translateY(660px); } }
    @keyframes fallY{ to{ transform:translateY(590px); } }
    @keyframes swayX{ from{ transform:translateX(calc(var(--sw)*-1)); } to{ transform:translateX(var(--sw)); } }
    @keyframes flashAnim{ 0%{opacity:0} 6%{opacity:.9} 14%{opacity:.12} 22%{opacity:.55} 36%,100%{opacity:0} }
    @keyframes boltAnim{ 0%,100%{opacity:0} 5%,13%{opacity:1} 17%{opacity:.15} 22%,28%{opacity:.85} 38%{opacity:0} }
    @keyframes cloudSway{ from{ transform:translateX(-9px); } to{ transform:translateX(9px); } }
    @keyframes mistDrift{ from{ transform:translateX(-6%); } to{ transform:translateX(6%); } }
    @keyframes pulseDot{ 0%,100%{ box-shadow:0 0 0 0 rgba(48,209,88,.6); } 60%{ box-shadow:0 0 0 6px rgba(48,209,88,0); } }
    @keyframes rollText{ 0%{transform:translateY(0);opacity:1} 45%{transform:translateY(-16px);opacity:0}
    55%{transform:translateY(16px);opacity:0} 100%{transform:translateY(0);opacity:1} }
    @keyframes barGrow{ from{ height:0; } }
    @keyframes floatIcon{ 0%,100%{ transform:translateY(0); } 50%{ transform:translateY(-5px); } }
    @keyframes dotIn{ to{ opacity:1; } }

    / ============ 响应式 ============ /
    @media (max-width:1360px){
    .deck{ grid-template-columns:repeat(2,1fr); }
    .card{ height:500px; }
    }
    @media (max-width:720px){
    .deck{ grid-template-columns:1fr; padding:20px; gap:18px; }
    .card{ height:470px; }
    .topbar{ flex-direction:column; align-items:flex-start; gap:16px; padding:26px 20px 0; }
    .controls{ flex-direction:row; width:100%; justify-content:space-between; align-items:center; }
    .clock{ font-size:24px; }
    .topbar h1{ font-size:32px; }
    .metrics{ grid-template-columns:repeat(2,1fr); }
    .sheet{ padding:10px 20px 22px; }
    .sh-t{ font-size:48px; }
    }
    @media (prefers-reduced-motion:reduce){
    ,::before,*::after{ animation-duration:.01ms!important; animation-iteration-count:1!important; transition-duration:.01ms!important; }
    }
    </style>
    </head>
    <body>

    <div class="ambient"></div>
    <div class="vignette"></div>
    <div class="grain"></div>

    <header class="topbar">
    <div>
    <div class="date-line" id="dateLine">—</div>
    <h1>天气</h1>
    <div class="sub">WEATHER · iOS 18 STYLE</div>
    </div>
    <div class="controls">
    <div class="clock" id="clock">00:00:00</div>
    <div class="seg" id="unitSeg">
    <button class="on" data-u="C">°C</button>
    <button data-u="F">°F</button>
    <span class="seg-thumb"></span>
    </div>
    </div>
    </header>

    <main class="deck">

    <!-- 晴天 -->
    <article class="card" data-id="sunny" tabindex="0" role="button" aria-label="三亚 晴,点击查看详情">
    <div class="scene">
    <div class="sun-glow"></div>
    <div class="sun-wrap">
    <div class="sun-rays"></div>
    <div class="sun"></div>
    </div>
    <span class="flare f1"></span><span class="flare f2"></span>
    <div class="cloud small ca"></div>
    <div class="cloud small cb"></div>
    </div>
    <div class="scrim"></div>
    <div class="inner">
    <div class="row-top">
    <div><h2 class="city">—</h2><span class="en">—</span></div>
    <span class="live"><i></i>实时</span>
    </div>
    <span class="pill">—</span>
    <div class="temp"><span class="t-val">0</span><span class="deg">°</span></div>
    <p class="cond">—</p>
    <p class="hilo"><span class="hi">—</span><span class="lo">—</span></p>
    <div class="spark-wrap"><div class="spark"></div><span class="spark-cap">—</span></div>
    </div>
    <span class="ring"></span>
    </article>

    <!-- 大风 -->
    <article class="card" data-id="windy" tabindex="0" role="button" aria-label="青岛 大风,点击查看详情">
    <div class="scene">
    <svg class="wind-lines" viewBox="0 0 400 520" preserveAspectRatio="none">
    <path class="wl w1" d="M-40 110 C 60 80, 150 145, 240 112 S 420 84, 470 112"/>
    <path class="wl w2" d="M-40 205 C 80 238, 170 175, 260 208 S 430 238, 470 208"/>
    <path class="wl w3" d="M-40 315 C 60 285, 180 348, 280 312 S 440 288, 470 308"/>
    <path class="wl w4" d="M-40 425 C 90 455, 190 392, 300 428 S 450 452, 470 432"/>
    </svg>
    <div class="streak s1"></div><div class="streak s2"></div><div class="streak s3"></div>
    <span class="leaf l1">🍃</span><span class="leaf l2">🍃</span><span class="leaf l3">🍂</span>
    </div>
    <div class="scrim"></div>
    <div class="inner">
    <div class="row-top">
    <div><h2 class="city">—</h2><span class="en">—</span></div>
    <span class="live"><i></i>实时</span>
    </div>
    <span class="pill">—</span>
    <div class="temp"><span class="t-val">0</span><span class="deg">°</span></div>
    <p class="cond">—</p>
    <p class="hilo"><span class="hi">—</span><span class="lo">—</span></p>
    <div class="spark-wrap"><div class="spark"></div><span class="spark-cap">—</span></div>
    </div>
    <span class="ring"></span>
    </article>

    <!-- 暴雨 -->
    <article class="card" data-id="rain" tabindex="0" role="button" aria-label="深圳 暴雨,点击查看详情">
    <div class="scene">
    <div class="storm-clouds"><i></i><i></i><i></i></div>
    <div class="rain" id="rainBox"></div>
    <svg class="bolt" viewBox="0 0 100 200"><path d="M55 0 L18 98 L44 98 L30 200 L84 76 L54 76 Z"/></svg>
    <div class="flash"></div>
    <div class="rain-fog"></div>
    </div>
    <div class="scrim"></div>
    <div class="inner">
    <div class="row-top">
    <div><h2 class="city">—</h2><span class="en">—</span></div>
    <span class="live"><i></i>实时</span>
    </div>
    <span class="pill">—</span>
    <div class="temp"><span class="t-val">0</span><span class="deg">°</span></div>
    <p class="cond">—</p>
    <p class="hilo"><span class="hi">—</span><span class="lo">—</span></p>
    <div class="spark-wrap"><div class="spark"></div><span class="spark-cap">—</span></div>
    </div>
    <span class="ring"></span>
    </article>

    <!-- 暴雪 -->
    <article class="card" data-id="snow" tabindex="0" role="button" aria-label="哈尔滨 暴雪,点击查看详情">
    <div class="scene">
    <div class="snow-clouds"><i></i><i></i></div>
    <div class="snow la" id="snowA"></div>
    <div class="snow lb" id="snowB"></div>
    <div class="mist m1"></div><div class="mist m2"></div>
    <div class="frost"></div>
    </div>
    <div class="scrim"></div>
    <div class="inner">
    <div class="row-top">
    <div><h2 class="city">—</h2><span class="en">—</span></div>
    <span class="live"><i></i>实时</span>
    </div>
    <span class="pill">—</span>
    <div class="temp"><span class="t-val">0</span><span class="deg">°</span></div>
    <p class="cond">—</p>
    <p class="hilo"><span class="hi">—</span><span class="lo">—</span></p>
    <div class="spark-wrap"><div class="spark"></div><span class="spark-cap">—</span></div>
    </div>
    <span class="ring"></span>
    </article>

    </main>

    <p class="hint"><b>点按卡片</b> 查看逐小时预报与完整详情 · <b>悬停</b> 感受场景变化与 3D 视差 · 数据为演示样例</p>

    <div class="backdrop" id="backdrop"></div>
    <section class="sheet" id="sheet" aria-label="天气详情">
    <div class="grabber"></div>
    <div id="sheetBody"></div>
    </section>

    <script>
    const $ = s => document.querySelector(s);
    const $$ = s => [...document.querySelectorAll(s)];
    let unit = 'C', activeId = null;
    const conv = c => unit === 'C' ? Math.round(c) : Math.round(c * 9 / 5 + 32);

    / ================= 数据 ================= /
    const DATA = {
    sunny: {
    city:'三亚', en:'SANYA', condition:'晴', icon:'☀️',
    temp:33, feels:38, high:36, low:27,
    accent:'#ffcf5c', sunT:.58, sunrise:'06:12', sunset:'19:24',
    ambient:['rgba(30,120,210,.55)','rgba(255,170,60,.38)'],
    alert:{ cls:'uv', icon:'🔆', text:'紫外线指数 极强' },
    sparkCap:'未来 12 小时 · 持续晴好',
    summary:'全天晴朗,午后最高气温 36°,日落前后回落至 30° 左右。紫外线指数极强,外出请注意防晒并及时补充水分。',
    hours:[['现在','☀️',33],['14时','☀️',35],['15时','☀️',36],['16时','🌤️',35],['17时','🌤️',34],['18时','🌇',32],
    ['19时','🌙',30],['20时','🌙',29],['21时','🌙',29],['22时','🌙',28],['23时','🌙',28],['00时','🌙',27]],
    metrics:[['💧','湿度','55%','体感舒适'],['🌬️','风速','12 km/h','东南风 3 级'],['🔆','紫外线','11 极强','10–16 时避免暴晒'],
    ['🌀','气压','1006 hPa','持续平稳'],['👁️','能见度','25 km','视野清晰'],['☔','降水量','0 mm','未来 24 小时无降水']],
    },
    windy: {
    city:'青岛', en:'QINGDAO', condition:'大风', icon:'💨',
    temp:21, feels:18, high:23, low:16,
    accent:'#7fd4c1', sunT:.44, sunrise:'05:48', sunset:'19:02',
    ambient:['rgba(46,110,120,.55)','rgba(150,200,180,.3)'],
    alert:{ cls:'wind', icon:'⚠️', text:'大风黄色预警' },
    sparkCap:'未来 12 小时 · 风力逐渐减弱',
    summary:'西北风 6–7 级,沿海阵风可达 8 级,预计明晨逐渐减弱。请关好门窗,减少高空与户外作业。',
    hours:[['现在','💨',21],['14时','💨',22],['15时','🌤️',23],['16时','💨',22],['17时','💨',22],['18时','🌤️',21],
    ['19时','💨',20],['20时','💨',19],['21时','🌙',19],['22时','💨',18],['23时','🌙',18],['00时','🌙',17]],
    metrics:[['💧','湿度','42%','空气偏干燥'],['🌬️','风速','62 km/h','西北风 8 级阵风'],['🔆','紫外线','5 中等','建议涂抹防晒'],
    ['🌀','气压','1012 hPa','明显偏高'],['👁️','能见度','18 km','良好'],['☔','降水量','0 mm','无降水']],
    },
    rain: {
    city:'深圳', en:'SHENZHEN', condition:'暴雨', icon:'⛈️',
    temp:26, feels:29, high:28, low:24,
    accent:'#7aa7ff', sunT:.30, sunrise:'06:01', sunset:'19:10',
    ambient:['rgba(40,60,110,.6)','rgba(90,120,170,.35)'],
    alert:{ cls:'rain', icon:'🚨', text:'暴雨红色预警' },
    sparkCap:'未来 12 小时 · 降雨持续',
    summary:'受强降水云团影响,未来 3 小时降雨将持续,累计雨量可达 80 毫米以上,并伴有雷电。请远离低洼地带,减少外出。',
    hours:[['现在','⛈️',27],['14时','🌧️',26],['15时','⛈️',26],['16时','🌧️',25],['17时','🌧️',25],['18时','⛈️',24],
    ['19时','🌧️',24],['20时','🌧️',24],['21时','🌧️',23],['22时','🌦️',23],['23时','🌧️',23],['00时','🌧️',22]],
    metrics:[['💧','湿度','94%','非常潮湿'],['🌬️','风速','45 km/h','东南风 7 级'],['🔆','紫外线','1 最弱','云层遮蔽'],
    ['🌀','气压','996 hPa','明显偏低'],['👁️','能见度','3.2 km','较差'],['☔','降水量','86 mm','大暴雨量级']],
    },
    snow: {
    city:'哈尔滨', en:'HARBIN', condition:'暴雪', icon:'🌨️',
    temp:-9, feels:-16, high:-6, low:-15,
    accent:'#bfe0ff', sunT:.36, sunrise:'07:02', sunset:'16:45',
    ambient:['rgba(90,130,180,.5)','rgba(200,225,250,.28)'],
    alert:{ cls:'snow', icon:'❄️', text:'暴雪橙色预警' },
    sparkCap:'未来 12 小时 · 降雪持续',
    summary:'降雪将持续至夜间,新增积雪深度 12–15 厘米,伴随道路结冰。请注意防寒保暖,出行注意防滑。',
    hours:[['现在','🌨️',-9],['14时','🌨️',-10],['15时','❄️',-10],['16时','🌨️',-11],['17时','🌨️',-11],['18时','❄️',-12],
    ['19时','🌨️',-12],['20时','❄️',-13],['21时','🌨️',-13],['22时','❄️',-14],['23时','🌨️',-14],['00时','❄️',-15]],
    metrics:[['💧','湿度','82%','湿冷感明显'],['🌬️','风速','28 km/h','北风 5 级'],['🔆','紫外线','2 弱','雪面反射注意护眼'],
    ['🌀','气压','1021 hPa','偏高'],['👁️','能见度','1.5 km','受降雪影响'],['☔','降水量','12 mm','暴雪量级']],
    },
    };

    / ================= 卡片初始化 ================= /
    function buildSpark(el, temps, id){
    const w = 260, h = 46, pad = 4;
    const mn = Math.min(...temps), mx = Math.max(...temps), rg = (mx - mn) || 1;
    const pts = temps.map((t,i)=>[ pad + i(w-2pad)/(temps.length-1), h - 8 - ((t-mn)/rg)*(h-18) ]);
    let line = M${pts[0][0]},${pts[0][1]};
    for(let i=1;i<pts.length;i++){
    const [x0,y0]=pts[i-1], [x1,y1]=pts[i], mx2=(x0+x1)/2;
    line += C${mx2},${y0} ${mx2},${y1} ${x1},${y1};
    }
    const area = line + L${pts[pts.length-1][0]},${h} L${pts[0][0]},${h} Z;
    const last = pts[pts.length-1];
    el.innerHTML = `<svg viewBox="0 0 ${w} ${h}" preserveAspectRatio="none">
    <defs><linearGradient id="sg${id}" x1="0" y1="0" x2="0" y2="1">
    <stop offset="0" stop-color="rgba(255,255,255,.42)"/><stop offset="1" stop-color="rgba(255,255,255,0)"/>
    </linearGradient></defs>
    <path d="${area}" fill="url(#sg${id})"/>
    <path class="sline" d="${line}" fill="none" stroke="rgba(255,255,255,.95)" stroke-width="2.4" stroke-linecap="round"/>
    <circle cx="${last[0]}" cy="${last[1]}" r="3.4" fill="#fff"/>
    </svg>`;
    const path = el.querySelector('.sline'), len = path.getTotalLength();
    path.style.strokeDasharray = len; path.style.strokeDashoffset = len;
    requestAnimationFrame(()=>requestAnimationFrame(()=>{
    path.style.transition = 'stroke-dashoffset 1.4s cubic-bezier(.4,0,.2,1) .4s';
    path.style.strokeDashoffset = 0;
    }));
    }

    function animateTemp(el, target, delay){
    const start = performance.now() + delay, dur = 1100;
    (function frame(now){
    let t = (now - start) / dur;
    if(t < 0){ requestAnimationFrame(frame); return; }
    t = Math.min(1, t);
    el.textContent = Math.round(target * (1 - Math.pow(1 - t, 3)));
    if(t < 1) requestAnimationFrame(frame);
    })(performance.now());
    }

    $$('.card').forEach((card, idx)=>{
    const d = DATA[card.dataset.id];
    card.querySelector('.city').textContent = d.city;
    card.querySelector('.en').textContent = d.en;
    const pill = card.querySelector('.pill');
    pill.className = 'pill ' + d.alert.cls;
    pill.textContent = d.alert.icon + ' ' + d.alert.text;
    card.querySelector('.cond').textContent = ${d.condition} · 体感 ${conv(d.feels)}°;
    card.querySelector('.hi').textContent = 最高 ${conv(d.high)}°;
    card.querySelector('.lo').textContent = 最低 ${conv(d.low)}°;
    card.querySelector('.spark-cap').textContent = d.sparkCap;
    buildSpark(card.querySelector('.spark'), d.hours.map(h=>h[2]), card.dataset.id);
    animateTemp(card.querySelector('.t-val'), conv(d.temp), 380 + idx * 150);
    });

    / ================= 粒子:雨 & 雪 ================= /
    (function makeRain(){
    const box = $('#rainBox'); let html = '';
    for(let i=0;i<70;i++){
    const d = (0.55 + Math.random()*0.5).toFixed(2);
    html += <span style="left:${(Math.random()*118-9).toFixed(1)}%;height:${46+Math.random()*44|0}px; +
    opacity:${(0.25+Math.random()*0.55).toFixed(2)}; +
    animation-duration:calc(var(--rs,1)*${d}s);animation-delay:${(-Math.random()*2).toFixed(2)}s"></span>;
    }
    box.innerHTML = html;
    })();
    (function makeSnow(){
    const gen = n => {
    let html = '';
    for(let i=0;i<n;i++){
    const sz = 2.5 + Math.random()*4.5;
    html += <span class="flake" style="left:${(Math.random()*104-2).toFixed(1)}%;--d:${(6+Math.random()*7).toFixed(1)}s; +
    --del:${(-Math.random()*10).toFixed(1)}s;--sd:${(2.4+Math.random()*2).toFixed(1)}s;--sw:${12+Math.random()*22|0}px"> +
    <i style="--sz:${sz.toFixed(1)}px;--o:${(0.5+Math.random()*0.5).toFixed(2)};--bl:${sz<4?1.2:0.4}px"></i></span>;
    }
    return html;
    };
    $('#snowA').innerHTML = gen(36);
    $('#snowB').innerHTML = gen(30);
    })();

    / ================= 闪电调度 ================= /
    const rainScene = document.querySelector('.card[data-id="rain"] .scene');
    (function storm(){
    setTimeout(()=>{
    rainScene.classList.add('flashing');
    setTimeout(()=>rainScene.classList.remove('flashing'), 820);
    storm();
    }, 3600 + Math.random()*5200);
    })();

    / ================= 时钟 ================= /
    const WD = ['周日','周一','周二','周三','周四','周五','周六'];
    function tick(){
    const d = new Date(), p = n => String(n).padStart(2,'0');
    $('#clock').textContent = ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())};
    $('#dateLine').textContent = ${d.getFullYear()}年${d.getMonth()+1}月${d.getDate()}日 · ${WD[d.getDay()]};
    }
    tick(); setInterval(tick, 1000);

    / ================= 3D 倾斜 + 视差 ================= /
    if(matchMedia('(hover:hover) and (pointer:fine)').matches){
    $$('.card').forEach(card=>{
    card.addEventListener('pointerenter', ()=>card.classList.add('tilting'));
    card.addEventListener('pointermove', e=>{
    const r = card.getBoundingClientRect();
    const x = (e.clientX - r.left)/r.width - .5;
    const y = (e.clientY - r.top)/r.height - .5;
    card.style.setProperty('--ry', (x*9).toFixed(2)+'deg');
    card.style.setProperty('--rx', (-y*7).toFixed(2)+'deg');
    card.style.setProperty('--px', (x*-12).toFixed(1)+'px');
    card.style.setProperty('--py', (y*-9).toFixed(1)+'px');
    });
    card.addEventListener('pointerleave', ()=>{
    card.classList.remove('tilting');
    ['--rx','--ry'].forEach(v=>card.style.setProperty(v,'0deg'));
    ['--px','--py'].forEach(v=>card.style.setProperty(v,'0px'));
    setAmbient(DATA[activeId || 'sunny']);
    });
    card.addEventListener('pointerenter', ()=>setAmbient(DATA[card.dataset.id]));
    });
    }

    / ================= 环境色 ================= /
    function setAmbient(d){
    document.documentElement.style.setProperty('--amb-a', d.ambient[0]);
    document.documentElement.style.setProperty('--amb-b', d.ambient[1]);
    }

    / ================= 详情面板 ================= /
    const sheet = $('#sheet'), sheetBody = $('#sheetBody'), backdrop = $('#backdrop');

    function renderSheet(id){
    const d = DATA[id];
    const temps = d.hours.map(h=>h[2]);
    const mn = Math.min(...temps), mx = Math.max(...temps), rg = (mx-mn)||1;
    sheetBody.style.setProperty('--acc', d.accent);
    sheetBody.innerHTML = `
    <div class="sh-head">
    <div>
    <div class="sh-city">${d.city}<span class="sh-en">${d.en}</span></div>
    <div class="sh-temp"><span class="sh-icon">${d.icon}</span><span class="sh-t">${conv(d.temp)}°</span></div>
    <div class="sh-cond">${d.condition} · 体感 ${conv(d.feels)}° · 最高 ${conv(d.high)}° / 最低 ${conv(d.low)}°</div>
    </div>
    <button class="sh-close" id="shClose" aria-label="关闭">✕</button>
    </div>
    <div class="sh-alert ${d.alert.cls}">${d.alert.icon} ${d.alert.text}</div>
    <p class="sh-summary">${d.summary}</p>

    <section class="sh-sec">
    <h4>🕐 每小时预报</h4>
    <div class="hours">${d.hours.map((h,i)=>`
    <div class="hour ${i===0?'now':''}" style="--i:${i}">
    <span class="h-time">${h[0]}</span><span class="h-ic">${h[1]}</span>
    <div class="h-bar"><i style="height:${(14+((h[2]-mn)/rg)*86).toFixed(0)}%"></i></div>
    <span class="h-t">${conv(h[2])}°</span>
    </div>`).join('')}
    </div>
    </section>

    <section class="sh-sec">
    <h4>🌅 日出日落</h4>
    <div class="arc-wrap">
    <svg class="arc-svg" viewBox="0 0 320 132">
    <defs><linearGradient id="arcG" x1="0" y1="0" x2="1" y2="0">
    <stop offset="0" stop-color="#ffd76a"/><stop offset="1" stop-color="#ff9d3c"/>
    </linearGradient></defs>
    <line class="horizon" x1="8" y1="112" x2="312" y2="112"/>
    <path class="arc-base" d="M16 112 Q160 -26 304 112"/>
    <path class="arc-prog" id="arcProg" d="M16 112 Q160 -26 304 112"/>
    <circle class="sun-dot" id="sunDot" r="6.5" style="filter:drop-shadow(0 0 9px rgba(255,205,90,.95))"/>
    </svg>
    <div class="arc-labels"><span>↑ 日出 ${d.sunrise}</span><span>↓ 日落 ${d.sunset}</span></div>
    <div class="arc-note">— 太阳当前位置 —</div>
    </div>
    </section>

    <section class="sh-sec">
    <h4>📊 天气详情</h4>
    <div class="metrics">${d.metrics.map(m=>`
    <div class="tile">
    <div class="tile-h"><span>${m[0]}</span>${m[1]}</div>
    <div class="tile-v">${m[2]}</div>
    <div class="tile-n">${m[3]}</div>
    </div>`).join('')}
    </div>
    </section>
    <footer class="sh-foot">数据为演示样例 · iOS 18 风格天气卡片</footer>`;

    $('#shClose').addEventListener('click', closeSheet);

    const prog = $('#arcProg'), len = prog.getTotalLength();
    prog.style.strokeDasharray = len; prog.style.strokeDashoffset = len;
    requestAnimationFrame(()=>requestAnimationFrame(()=>{
    prog.style.transition = 'stroke-dashoffset 1.2s cubic-bezier(.4,0,.2,1) .35s';
    prog.style.strokeDashoffset = len * (1 - d.sunT);
    }));
    const p = prog.getPointAtLength(len * d.sunT);
    const dot = $('#sunDot');
    dot.setAttribute('cx', p.x); dot.setAttribute('cy', p.y);
    }

    function openSheet(id){
    activeId = id;
    $$('.card').forEach(c=>c.classList.toggle('active', c.dataset.id === id));
    setAmbient(DATA[id]);
    renderSheet(id);
    sheet.classList.add('open'); backdrop.classList.add('open');
    }
    function closeSheet(){
    sheet.classList.remove('open'); backdrop.classList.remove('open');
    }

    $$('.card').forEach(card=>{
    card.addEventListener('click', ()=>openSheet(card.dataset.id));
    card.addEventListener('keydown', e=>{
    if(e.key === 'Enter' || e.key === ' '){ e.preventDefault(); openSheet(card.dataset.id); }
    });
    });
    backdrop.addEventListener('click', closeSheet);
    document.addEventListener('keydown', e=>{ if(e.key === 'Escape') closeSheet(); });

    / ================= 单位切换 ================= /
    const seg = $('#unitSeg');
    seg.querySelectorAll('button').forEach(b=>b.addEventListener('click', ()=>{
    if(unit === b.dataset.u) return;
    unit = b.dataset.u;
    seg.classList.toggle('f', unit === 'F');
    seg.querySelectorAll('button').forEach(x=>x.classList.toggle('on', x === b));
    $$('.card').forEach(card=>{
    const d = DATA[card.dataset.id];
    const tv = card.querySelector('.t-val');
    tv.classList.remove('roll'); void tv.offsetWidth; tv.classList.add('roll');
    setTimeout(()=>{
    tv.textContent = conv(d.temp);
    card.querySelector('.cond').textContent = ${d.condition} · 体感 ${conv(d.feels)}°;
    card.querySelector('.hi').textContent = 最高 ${conv(d.high)}°;
    card.querySelector('.lo').textContent = 最低 ${conv(d.low)}°;
    }, 175);
    });
    if(activeId) setTimeout(()=>renderSheet(activeId), 200);
    }));
    </script>
    </body>
    </html>
    ```图片

    到了国模起飞的版本了嘛,家家都对标fable5

    图片

    主楼
  • Jerryi

    认真的吗^-^我上午试了试特别简单的问题都改不好

    #1
  • 金陵雪

    我在qoder里测试和grok4.5差不多,推理能力略低于grok4.5

    #2
  • kaisen

    qwen3.8在x上看到有人测试,效果并不是很理想哇

    #3
  • Kate_Tseng

    别老是测天气卡片啦,现在大家都是以长任务为主了,这种任务没啥意义了

    #4
  • zljbjh

    各家对于这种测试都过拟合了。阿里这模型明显是没有多少后训练的。

    #5
  • unsafetrait

    慢慢用,实际上幻觉率极高,我这边问几个问题,人家幻想一对有的没的内容,我觉得好神奇,要不是我们自己有REVIEW习惯就真信了,感觉这个版本幻觉率比QWEN3.7 PLUS高不止一点

    #6
  • unsafetrait

    感觉基本没有,真的有时候挺无语的

    #7
  • 摇摆熊

    那是不是意思说写短片小说一定很强了

    #8
  • 翠花上酸菜

    是刚才测试的吗?我看网上说昨天上的版本上错了,现在才改成真正要上的版本

    #9
  • zfy

    qwen 真的原地踏步 甚至是退步 看来还是没有找到方法

    #10
  • unsafetrait

    你可以试试,反正感觉这模型脑子不大好使的样子 ^-^ 不过前端强一般逻辑都差,但是QWEN 3.8好像逻辑不差,所以你们试试吧,我们只管代码

    #11
  • wintsa

    画个简单的前端而已。。。gpt5.3都能做的事

    #12
  • Xiwis_Homed

    听他吹牛逼呢,上模型还能上错你以为是过家家吗

    #13
  • 翠花上酸菜

    那不知道了,昨晚上了之后看类脑有网友测了流口水。刚才他重测说变牛逼了

    #14

发表回复

登录后回复