/* One atmosphere for the opening and the forecast, available before first paint. */
:root {
  --sky-base:#080f22; --sky-color:linear-gradient(165deg,#10142d,#080f22 85%);
  --cloud-opacity:0; --cloud-filter:brightness(.48) saturate(.65);
  --intro-ink:#f3f8ff; --intro-muted:#c4d7f0; --sun-opacity:1;
  --rain-opacity:0; --rain-back-opacity:0; --lightning-opacity:.9;
  --stars-visibility:0;
  --twilight-color:radial-gradient(ellipse at 78% 35%,#ffe8ad99,transparent 48%),linear-gradient(180deg,#6577b6,#be99b7 24%,#f1bb99 48%,#e8c89e 100%);
}
:root[data-phase="day"] {
  --sky-base:#a7d7ec; --sky-color:linear-gradient(165deg,#57b0e2,#bce7f5 70%,#a7d7ec);
  --cloud-filter:none; --intro-ink:#143654; --intro-muted:#233e57;
  --lightning-opacity:.6;
}
:root[data-phase="night"] { --sky-base:#080f22; --sky-color:radial-gradient(ellipse at 80% 8%,#363b6440,transparent 42%),linear-gradient(165deg,#10142d,#080f22 85%); }
:root[data-weather="sun"][data-phase="day"] { --sky-color:radial-gradient(ellipse at 84% 10%,#ffebad66,transparent 42%),linear-gradient(165deg,#59b6e9,#bce7f5 70%,#a7d7ec); }
:root[data-weather="partly"] { --cloud-opacity:1; --sun-opacity:.92; }
:root[data-weather="cloud"] { --cloud-opacity:.86; }
:root[data-weather="rain"] { --cloud-opacity:.86; --sky-base:#0a1728; --sky-color:linear-gradient(165deg,#19263b,#0a1728 80%); }
:root[data-weather="storm"] { --cloud-opacity:1; --sky-base:#090f22; --sky-color:linear-gradient(165deg,#1c2037,#090f22 80%); }
:root[data-weather="cloud"][data-phase="day"] { --sky-base:#a6bccd; --sky-color:linear-gradient(165deg,#88a2bb,#cfdbe4 68%,#a6bccd); --cloud-filter:brightness(.94) saturate(.85); }
:root[data-weather="cloud"][data-phase="night"] { --sky-base:#0a1427; --sky-color:linear-gradient(165deg,#171f36,#0a1427 85%); }
:root[data-weather="rain"][data-phase="day"] { --sky-base:#8aa3b7; --sky-color:linear-gradient(165deg,#7290ab,#b5c6d4 68%,#8aa3b7); --cloud-filter:brightness(.8) saturate(.6); }
:root[data-weather="storm"][data-phase="day"] { --sky-base:#7e98b2; --sky-color:linear-gradient(165deg,#657f9e,#acbfd0 68%,#7e98b2); --cloud-filter:brightness(.68) saturate(.65); }
:root[data-phase="day"]:is([data-weather="rain"],[data-weather="storm"]) { --intro-ink:#041a2e; --intro-muted:#08243b; }
/* Chuva moderada/forte e trovoada de dia (1.26.3, pedido do usuário: "não era pra ficar cinza na chuva?"): cinza neutro,
   sem o azul-marinho/violeta de antes, que aparecia no fundo abaixo das nuvens. */
/* Rain clouds by condition. Drizzle/light rain stay grey under dark ink; moderate/heavy rain and
   thunderstorms (data-ink="light", set by sky-atmosphere outside twilight) darken the daytime sky
   like a rain deck and the reading switches to light ink. Heavier categories are darker. */
:root[data-phase="day"][data-ink="light"] { --sky-base:#26292d; --sky-color:linear-gradient(165deg,#30343a,#212428 70%,#26292d); --cloud-opacity:1; --cloud-filter:brightness(.44) saturate(.2); --intro-ink:#f3f8ff; --intro-muted:#c4d7f0; --lightning-opacity:.85; }
:root[data-phase="day"][data-ink="light"][data-rain="heavy"] { --cloud-filter:brightness(.42) saturate(.18); }
:root[data-phase="day"][data-ink="light"][data-weather="storm"] { --sky-base:#1f2125; --sky-color:linear-gradient(165deg,#2a2c31,#1a1c20 70%,#1f2125); --cloud-filter:brightness(.4) saturate(.15); }
/* Nublado, garoa e chuva fraca de dia (1.25, referência do usuário: o nublado do Apple Weather): céu cinza-chumbo,
   nuvens em textura cinza e tinta clara. Mais claro que a chuva forte e a trovoada, que continuam no teto escuro. */
:root[data-phase="day"][data-ink="light"][data-weather="cloud"] { --sky-base:#909db0; --sky-color:linear-gradient(180deg,#8796aa,#9eabbc 45%,#93a0b2); --intro-muted:#f3f7fc; --cloud-filter:brightness(.86) contrast(.95) saturate(.45); }
:root[data-phase="day"][data-ink="light"][data-weather="rain"]:not([data-rain="moderate"]):not([data-rain="heavy"]) { --sky-base:#4d5660; --sky-color:linear-gradient(180deg,#3b434c,#4b545e 55%,#57606a); --cloud-filter:brightness(.42) saturate(.2); }
:root[data-weather="fog"] { --sky-base:#111c2c; --sky-color:linear-gradient(180deg,#35405788,#111c2c); --cloud-opacity:.3; }
:root[data-weather="fog"][data-phase="day"] { --sky-base:#c0d1dd; --sky-color:linear-gradient(165deg,#aabfcf,#e0e9ef); --cloud-opacity:.5; }
:root[data-weather="snow"] { --sky-base:#0e1a2d; --sky-color:linear-gradient(165deg,#29364e,#0e1a2d); --cloud-opacity:.65; }
:root[data-weather="snow"][data-phase="day"] { --sky-base:#bed9e8; --sky-color:linear-gradient(165deg,#9ebfd5,#e5f0f5); }
:root:is([data-solar="sunrise"],[data-solar="sunset"]) { --intro-ink:#233656; --intro-muted:#233656; }
:root[data-phase="night"]:is([data-solar="sunrise"],[data-solar="sunset"]) { --intro-ink:#f3f8ff; --intro-muted:#c4d7f0; }
:root[data-solar="sunset"] { --twilight-color:radial-gradient(ellipse at 78% 35%,#ffd69899,transparent 48%),linear-gradient(180deg,#39446f,#9d789c 27%,#eaa286 52%,#cf9a84 100%); }
html,body { background:var(--sky-base); }
.pluvia-intro { background:var(--sky-color); color:var(--intro-ink); }
.pluvia-intro::before { background:linear-gradient(180deg,transparent 25%,#03142924); }
.pluvia-intro .intro-wordmark { color:var(--brand-blue,#2f6bff); }
/* Nublado de dia (1.26.6, pedido do usuário: o "PLUVIA" azul-claro sumia no céu prateado): o nome fica branco e,
   como o slogan e o "Feito no Norte", ganha a mesma sombra suave do topo da Home. Nos outros céus o azul da marca
   já se destaca (azul-claro no escuro, azul-marinho no céu claro). */
:root[data-phase="day"][data-ink="light"][data-weather="cloud"] .pluvia-intro .intro-wordmark { color:#fff; }
:root[data-phase="day"][data-ink="light"][data-weather="cloud"] .pluvia-intro :is(.intro-wordmark,.intro-tagline,.intro-kicker) { text-shadow:0 1px 3px rgba(20,32,52,.4),0 0 22px rgba(20,32,52,.32); }
.pluvia-intro .intro-tagline { color:var(--intro-ink); }
.pluvia-intro .intro-kicker { z-index:1; color:var(--intro-muted); }
.night-stage::before { content:""; position:absolute; inset:0 0 auto; z-index:-1; pointer-events:none; background-image:var(--sky-color); opacity:1; height:min(1450px,160vh); -webkit-mask-image:linear-gradient(#000 0%,#000 65%,transparent); mask-image:linear-gradient(#000 0%,#000 65%,transparent); }
.night-stage::after { display:none; }
/* Twilight belongs to the viewport, outside the masked weather effects.
   The same sky remains behind every section while the page scrolls. */
:root:is([data-solar="sunrise"],[data-solar="sunset"]) .night-stage::before { position:fixed; inset:0; height:auto; -webkit-mask-image:none; mask-image:none; }
.sky-effects { position:absolute; inset:0 0 auto; height:min(1450px,160vh); overflow:hidden; pointer-events:none; z-index:-1; }
.pluvia-intro .intro-sky { position:absolute; inset:0; width:100%; height:100%; overflow:hidden; pointer-events:none; }
.sky-effects,.intro-sky { isolation:isolate; contain:layout paint; --orbit-top:clamp(38px,6vw,52px); --orbit-height:260px; }
.intro-sky { --orbit-top:clamp(64px,10svh,120px); --orbit-height:clamp(180px,32svh,360px); }
.sky-effects::after { content:""; position:absolute; inset:0; z-index:5; background:linear-gradient(90deg,#06183026,transparent 75%); pointer-events:none; }
:root[data-phase="day"]:not([data-ink="light"]) .sky-effects::after { background:linear-gradient(90deg,#def2fa30,transparent 75%); }
.sky-twilight { display:none; position:absolute; inset:0; z-index:0; opacity:var(--twilight-opacity,0); background:var(--twilight-color); pointer-events:none; }
.sky-twilight-page { position:fixed; z-index:-1; }
:root[data-phase="night"] .sky-twilight-page,
/* A intro segue a mesma atenuação noturna da página: o texto claro do lado noturno do
   crepúsculo não pode depender de uma nuvem passar atrás dele. */
:root[data-phase="night"] .intro-sky .sky-twilight { background:linear-gradient(#080f2294,#080f2294),var(--twilight-color); }
/* Lado noturno do pôr/nascer do sol: índigo → ameixa → brasa só no horizonte. A película escura
   sobre o degradê laranja virava um marrom lamacento; estes tons já são escuros o bastante para a
   tinta clara (verify-contrast) sem a película. */
:root[data-phase="night"][data-solar="sunset"] .sky-twilight-page,
:root[data-phase="night"][data-solar="sunset"] .intro-sky .sky-twilight { background:radial-gradient(ellipse at 50% 112%,#f08a5c24,transparent 56%),linear-gradient(180deg,#121a45 0%,#262b66 32%,#463a78 58%,#5f3f6e 82%,#5f3d66 100%); }
:root[data-phase="night"][data-solar="sunrise"] .sky-twilight-page,
:root[data-phase="night"][data-solar="sunrise"] .intro-sky .sky-twilight { background:radial-gradient(ellipse at 50% 112%,#f4a87024,transparent 56%),linear-gradient(180deg,#101a44 0%,#232f69 34%,#41427f 60%,#584a78 84%,#5d4770 100%); }
:root:is([data-solar="sunrise"],[data-solar="sunset"]) .sky-twilight { display:block; }
:root:is([data-weather="cloud"],[data-weather="rain"],[data-weather="fog"],[data-weather="snow"]) .sky-twilight { opacity:calc(var(--twilight-opacity,0) * .6); }
:root[data-weather="storm"] .sky-twilight { opacity:calc(var(--twilight-opacity,0) * .3); }
/* Campo de estrelas atrás das nuvens e dos astros. Desde a 1.26 (pedido do usuário, como no Apple Weather) o campo
   desliza bem devagar para a esquerda (um tile de 900 px em 20 min, só transform na camada, que tem a largura da tela
   mais um tile, para o laço não ter emenda) e duas camadas de pontos brilhantes, defasadas e em posições diferentes,
   acendem e apagam em ritmos próprios: cada estrela parece piscar sozinha. Sem timer nem DOM por estrela. */
.sky-stars { position:absolute; inset:0 auto 0 0; width:calc(100% + 900px); z-index:0; animation:sky-star-drift 1200s linear infinite; animation-play-state:paused; pointer-events:none; background:url("./assets/sky-stars.svg?v=stars-2") center top / 900px 1100px repeat; opacity:var(--stars-visibility,0); transition:opacity 4s ease,visibility 0s; } /* tile 1:1 em px reais; a cena (sky-effects) já esmaece embaixo */
.sky-stars::before,.sky-stars::after { content:""; position:absolute; inset:0; background:url("./assets/sky-stars-shimmer.svg?v=stars-2") center top / 900px 1108px repeat; animation:sky-star-shimmer 6.5s ease-in-out infinite alternate; animation-delay:-3s; animation-play-state:paused; }
.sky-stars::before { background-position:calc(50% + 450px) 554px; animation-name:sky-star-twinkle; animation-duration:4.7s; animation-delay:-1.2s; }
:root[data-phase="night"]:is([data-weather="sun"],[data-weather="partly"]) .sky-stars,
:root[data-phase="night"]:is([data-weather="sun"],[data-weather="partly"]) .sky-stars::before,
:root[data-phase="night"]:is([data-weather="sun"],[data-weather="partly"]) .sky-stars::after { animation-play-state:running; }
:root[data-sky-transition="live"] .sky-stars { transition:opacity 28s linear,visibility 0s; }
:root:not([data-phase="night"]) .sky-stars,
:root:not([data-weather="sun"]):not([data-weather="partly"]) .sky-stars { opacity:0; visibility:hidden; transition:opacity 4s ease,visibility 0s 4s; }
:root[data-sky-transition="live"]:not([data-phase="night"]) .sky-stars,
:root[data-sky-transition="live"]:not([data-weather="sun"]):not([data-weather="partly"]) .sky-stars { transition:opacity 28s linear,visibility 0s 28s; }
/* A luminous photosphere and atmospheric glow travel as one object.
   Static gradients keep the light steady and avoid animated blur on mobile. */
.sky-sun { display:none; position:absolute; z-index:1; top:0; left:0; width:108px; aspect-ratio:1; opacity:calc(var(--sun-opacity) * var(--sun-visibility,0)); transform:translate3d(calc(var(--sun-orbit-x,.5) * 100vw - 50%),calc(env(safe-area-inset-top,0px) + var(--orbit-top) + var(--sun-orbit-y,0) * var(--orbit-height) - 50%),0); background:url("./assets/sky-sun.svg?v=sun-2") center / contain no-repeat; }
.sky-sun::before { content:""; position:absolute; inset:-120%; z-index:-1; border-radius:50%; background:radial-gradient(circle,#fff8da55 0%,#fff0bf38 13%,#ffe6a41c 27%,#ffdea309 44%,transparent 68%); }
.sky-sun::after { content:""; position:absolute; inset:24.45%; border-radius:50%; background:radial-gradient(circle,#ffde87 0%,#ffc461 70%,#ff9f49 96%,#ff9f4900 100%); opacity:0; }
:root:is([data-solar="sunrise"],[data-solar="sunset"]) .sky-sun::after { opacity:calc(var(--twilight-opacity,0) * .8); }
:root[data-phase="day"]:is([data-weather="sun"],[data-weather="partly"],[data-weather="unknown"]) .sky-sun { display:block; }
.intro-sky .sky-sun { width:clamp(84px,22vw,108px); }
.moon-definitions { position:absolute; width:0; height:0; overflow:hidden; pointer-events:none; }
.sky-moon { display:none; position:absolute; z-index:1; top:0; left:0; width:64px; aspect-ratio:1; opacity:var(--moon-visibility,0); transform:translate3d(calc(var(--moon-orbit-x,.5) * 100vw - 50%),calc(env(safe-area-inset-top,0px) + var(--orbit-top) + var(--moon-orbit-y,0) * var(--orbit-height) - 50%),0); }
:root[data-sky-transition="live"] :is(.sky-sun,.sky-moon) { transition:transform 28s linear,opacity 28s linear; }
.sky-moon > svg { display:block; position:relative; width:100%; height:100%; }
.sky-moon::before { content:""; position:absolute; inset:-65%; border-radius:50%; background:radial-gradient(circle,#c3dfff1f,transparent 64%); opacity:var(--moon-light,0); }
:root[data-phase="night"] .sky-moon { display:block; }
.intro-sky .sky-moon { width:64px; }
/* Two generated cloud layers (scripts/generate-soft-clouds.py): a distant veil and a volumetric foreground.
   Each 3:1 texture tiles seamlessly in x, so the layer drifts continuously by exactly one tile
   (repeat-x, transform only) and loops without a jump. The near layer drifts faster (parallax).
   No turbulence, canvas loop or animated blur; nodes stay painted so weather changes fade. */
.sky-clouds { --cloud-height:clamp(440px,min(70vw,113vh),640px); --cloud-tile:calc(var(--cloud-height) * 3); display:block; position:absolute; z-index:2; left:0; width:calc(100% + var(--cloud-tile)); height:var(--cloud-height); top:-60px; background:url("./assets/sky-cloud-veil.webp?v=clouds-5") 0 0 / var(--cloud-tile) 100% repeat-x; opacity:var(--cloud-opacity); filter:var(--cloud-filter); -webkit-mask-image:linear-gradient(transparent,#000 18%,#000 70%,transparent); mask-image:linear-gradient(transparent,#000 18%,#000 70%,transparent); animation:clouds-back 460s linear infinite; animation-delay:-172s; transition:opacity 4s ease,visibility 0s; }
.sky-clouds-front { top:17%; background-image:url("./assets/sky-cloud-volume.webp?v=clouds-5"); opacity:calc(var(--cloud-opacity) * .48); animation:clouds-front 300s linear infinite; animation-delay:-77s; }
/* Texture alpha carries the real gaps. Fading an entire partially cloudy layer
   makes the celestial disks bleed through even its dense, opaque interiors. */
:root[data-weather="partly"] .sky-clouds-front { opacity:var(--cloud-opacity); }
:root[data-weather="partly"][data-phase="night"] { --cloud-filter:brightness(.33) sepia(.45) hue-rotate(185deg) saturate(1.3); }
/* Night clouds cover the illustrated Moon with their texture alpha instead of
   removing its element or letting it bleed through translucent cloud bodies. */
:root[data-phase="night"]:is([data-weather="cloud"],[data-weather="rain"],[data-weather="storm"],[data-weather="snow"]) { --cloud-opacity:1; --cloud-filter:brightness(.33) sepia(.45) hue-rotate(185deg) saturate(1.3); }
:root[data-phase="night"]:is([data-weather="cloud"],[data-weather="rain"],[data-weather="storm"],[data-weather="snow"]) .sky-clouds-front { opacity:var(--cloud-opacity); }
:root[data-phase="night"][data-weather="rain"] { --cloud-filter:brightness(.29) sepia(.45) hue-rotate(185deg) saturate(1.2); }
:root[data-phase="night"]:is([data-rain="heavy"],[data-weather="storm"]) { --cloud-filter:brightness(.28) sepia(.4) hue-rotate(195deg) saturate(1.15); }
/* Overcast: the defined veil keeps gaps, so a uniform haze behind its texture (same layer,
   same filter, invisible while drifting) closes the deck; the near masses get denser by day. */
/* Each cloudy condition has its own deck texture (scripts/generate-soft-clouds.py), downloaded and
   cached by the SW only when that sky is shown; the haze behind keeps the sky closed meanwhile.
   Overcast and snow: soft stratus; rain: darker nimbostratus; storm: heavy ceiling; fog: low bands. */
:root[data-weather="snow"] .sky-clouds:not(.sky-clouds-front) { background-image:url("./assets/sky-cloud-overcast.webp?v=clouds-6"),linear-gradient(#f2f5f980,#f2f5f966); }
/* Nublado (1.26.2, pedido do usuário com print do Apple Weather): nuvens cheias e com relevo no céu todo, em vez do
   cinza liso da névoa. O fundo empilha duas cópias do volume (deslocadas dentro do mesmo tile, o laço continua sem
   emenda) sobre o estrato, a camada da frente sobe para o topo e o filtro de dia ganha contraste. */
:root[data-weather="cloud"] .sky-clouds:not(.sky-clouds-front) { background-image:url("./assets/sky-cloud-overcast.webp?v=clouds-6"); background-size:var(--cloud-tile) var(--cloud-height); background-position:0 0; }
:root[data-weather="cloud"] .sky-effects > .sky-clouds-front { top:2%; }
:root[data-weather="rain"] .sky-clouds:not(.sky-clouds-front) { background-image:url("./assets/sky-cloud-rain.webp?v=clouds-5"),linear-gradient(#e4e9ef80,#e4e9ef66); }
:root[data-phase="day"]:is([data-weather="cloud"],[data-weather="rain"],[data-weather="storm"]) .sky-clouds-front { opacity:calc(var(--cloud-opacity) * .75); }
/* Rain decks (moderate/heavy rain and thunderstorms, day and night): a second copy of each
   texture, offset inside the same tile, closes the gaps so the sky reads as a dense deck while it
   drifts. Both copies repeat with the same period, so the one-tile loop stays seamless. */
:root:is([data-rain="moderate"],[data-rain="heavy"]) .sky-clouds:not(.sky-clouds-front) { background-image:url("./assets/sky-cloud-rain.webp?v=clouds-5"),url("./assets/sky-cloud-rain.webp?v=clouds-5"),linear-gradient(#c9d0d899,#c9d0d880); background-size:var(--cloud-tile) var(--cloud-height); background-position:0 0,calc(var(--cloud-tile) * .31) calc(var(--cloud-height) * .2),0 0; }
:root:is([data-rain="moderate"],[data-rain="heavy"]) .sky-clouds-front { background-image:url("./assets/sky-cloud-volume.webp?v=clouds-5"),url("./assets/sky-cloud-volume.webp?v=clouds-5"); background-size:var(--cloud-tile) var(--cloud-height); background-position:0 0,calc(var(--cloud-tile) * .47) calc(var(--cloud-height) * .16); }
:root:is([data-rain="moderate"],[data-rain="heavy"]) .sky-effects > .sky-clouds-front { top:6%; }
:root[data-weather="storm"] .sky-clouds:not(.sky-clouds-front) { background-image:url("./assets/sky-cloud-storm.webp?v=clouds-5"),url("./assets/sky-cloud-storm.webp?v=clouds-5"),linear-gradient(#b9c1cc99,#b9c1cc80); }
:root[data-weather="fog"] .sky-clouds { background-image:url("./assets/sky-cloud-fog.webp?v=clouds-5"); }
:root[data-weather="fog"] .sky-clouds-front { background-position:calc(var(--cloud-tile) * .43) 0; }
:root[data-phase="day"][data-ink="light"] .sky-clouds-front { opacity:var(--cloud-opacity); }
/* Camadas invisíveis também saem da composição (visibility depois do fade): no iPhone cada uma
   ocupava dezenas de MB de memória de vídeo mesmo com opacidade zero. */
:root:is([data-weather="sun"],[data-weather="unknown"]) .sky-clouds { animation-play-state:paused; visibility:hidden; transition:opacity 4s ease,visibility 0s 4s; }
/* Primeira abertura sem previsão salva: a intro já pinta um véu leve (decorativo) em vez de esperar a previsão
   para mostrar a nuvem do fundo (o LCP do PageSpeed esperava ~2 s por ela). Com a previsão, a condição real assume
   pela mesma transição de 4 s; a Home, ainda escondida atrás da intro, não recebe o véu. */
:root[data-weather="unknown"] .intro-sky { --cloud-opacity:.55; }
:root[data-weather="unknown"] .intro-sky .sky-clouds-back { visibility:visible; animation-play-state:running; }
.intro-sky .sky-clouds { top:-30px; }
/* LCP: o véu da intro aparece no primeiro paint e precisa ser a maior pintura; com a mesma altura,
   a camada da frente (inteira na tela) roubava a LCP ao chegar a previsão, vários segundos depois. */
.intro-sky .sky-clouds-back { --cloud-height:calc(clamp(440px,min(70vw,113vh),640px) * 1.08); }
/* Telas largas: a camada da frente fica mais baixa e mostrava mais área que o véu (cujo tamanho no LCP
   não cresce além da imagem, 2112 × 704). Quando a previsão chegava, ela virava o LCP do PageSpeed no
   computador (~1,4 s). Maior, a parte de baixo sai da tela e o LCP fica no primeiro desenho (900 a 3440 px). */
@media (min-width:900px) { .intro-sky .sky-clouds-front { --cloud-height:calc(clamp(440px,min(70vw,113vh),640px) * 1.25); } }
.intro-sky .sky-clouds-front { top:36%; }
/* Mainly clear (WMO 1): an elliptical mask, repeated twice per texture tile, reveals one
   bank of the same opaque texture every half tile; mask and texture drift together, so each
   bank keeps its shape while it crosses the sky. Reducing opacity would expose Sun/Moon
   through cloud interiors. The centers sit on dense regions of each generated texture. */
:root[data-weather="partly"][data-clouds="few"] .sky-clouds {
  --few-cloud-width:clamp(200px,min(58vw,58svh),680px);
  -webkit-mask-image:radial-gradient(calc(var(--few-cloud-width) / 2) calc(var(--few-cloud-width) / 4) at 39% 34%,#000 60%,transparent 100%);
  mask-image:radial-gradient(calc(var(--few-cloud-width) / 2) calc(var(--few-cloud-width) / 4) at 39% 34%,#000 60%,transparent 100%);
  -webkit-mask-size:calc(var(--cloud-tile) / 2) 100%;
  mask-size:calc(var(--cloud-tile) / 2) 100%;
  -webkit-mask-position:0 0;
  mask-position:0 0;
  -webkit-mask-repeat:repeat-x;
  mask-repeat:repeat-x;
}
:root[data-weather="partly"][data-clouds="few"] .sky-clouds-front {
  --few-cloud-width:clamp(180px,min(56vw,56svh),620px);
  -webkit-mask-image:radial-gradient(calc(var(--few-cloud-width) / 2) calc(var(--few-cloud-width) / 4) at 46% 34%,#000 60%,transparent 100%);
  mask-image:radial-gradient(calc(var(--few-cloud-width) / 2) calc(var(--few-cloud-width) / 4) at 46% 34%,#000 60%,transparent 100%);
}
/* Independent fine/distant and longer/near streaks. A whole 480px tile moves
   vertically, so looping has no seam; intensity never comes from probability. */
.sky-rain { display:block; position:absolute; z-index:4; inset:-480px 0 0; background:url("./assets/rain-near.svg?v=rain-1") 17px 0 / var(--rain-width,380px) 480px repeat; opacity:var(--rain-opacity); animation:sky-rain-fall var(--rain-speed,2.2s) linear infinite; animation-delay:-.7s; transition:opacity 2s ease,visibility 0s; }
.sky-rain-back { z-index:3; background-image:url("./assets/rain-far.svg?v=rain-1"); background-size:var(--rain-back-width,640px) 480px; background-position:83px 37px; opacity:var(--rain-back-opacity); animation-duration:var(--rain-back-speed,4.3s); animation-delay:-2.1s; }
:root:not([data-weather="rain"]):not([data-weather="storm"]) .sky-rain { opacity:0; animation-play-state:paused; visibility:hidden; transition:opacity 2s ease,visibility 0s 2s; }
/* Raio no estilo do Apple Weather (pedido do usuário, outubro/2026): um canal longo e ramificado
   (lightning-bolt.svg, scripts/generate-lightning.cjs) que cresce de cima para baixo em 80 ms, um
   clarão e um re-strike (no máximo dois clarões em um segundo) e o canal apagando em ~1,3 s, enquanto
   o céu e as nuvens inteiros clareiam e escurecem devagar (~2 s). Três quedas por ciclo de 39 s, cada
   uma noutro ponto (a terceira mais longe e fraca), trocadas enquanto estão invisíveis. Decoração da
   condição de trovoada, sem ligação com detecções reais. Só opacity/transform, sem filtro nem timer.
   O elemento não tem z-index: os pseudo-elementos entram na pilha da cena, na frente das nuvens (z 2)
   e atrás da chuva próxima (z 4); a cena inteira fica atrás do conteúdo. */
.sky-lightning { display:none; position:absolute; inset:0; }
.sky-lightning::before,.sky-lightning::after { content:""; position:absolute; z-index:3; opacity:0; pointer-events:none; mix-blend-mode:screen; animation:storm-glow 39s linear infinite; }
/* Clarão: o céu inteiro clareia, mais forte em cima (a cena já esmaece embaixo). */
.sky-lightning::before { inset:0; background:linear-gradient(180deg,#d5ddef 0%,#bcc8e2 40%,#94a4c8 70%,transparent 95%); }
/* Canal: halo suave próprio, origem no alto para crescer para baixo. */
.sky-lightning::after { top:calc(env(safe-area-inset-top,0px) - 24px); left:0; height:clamp(420px,62svh,700px); aspect-ratio:440 / 800; background:url("./assets/lightning-bolt.svg?v=lightning-2") center / 100% 100% no-repeat,radial-gradient(closest-side,#c7d6ff38,transparent); transform-origin:50% 0; animation-name:storm-bolt; }
:root[data-weather="storm"] .sky-lightning { display:block; }
.sky-effects { -webkit-mask-image:linear-gradient(#000 0%,#000 65%,transparent); mask-image:linear-gradient(#000 0%,#000 65%,transparent); }
@keyframes clouds-back { from { transform:translate3d(0,0,0); } to { transform:translate3d(calc(-1 * var(--cloud-tile)),0,0); } }
@keyframes clouds-front { from { transform:translate3d(0,0,0); } to { transform:translate3d(calc(-1 * var(--cloud-tile)),0,0); } }
@keyframes sky-star-shimmer { 0% { opacity:.12; } 35% { opacity:.9; } 65% { opacity:.4; } 100% { opacity:1; } }
@keyframes sky-star-twinkle { 0% { opacity:.85; } 45% { opacity:.08; } 100% { opacity:.7; } }
@keyframes sky-star-drift { from { transform:translate3d(0,0,0); } to { transform:translate3d(-900px,0,0); } }
@keyframes sky-rain-fall { to { transform:translate3d(0,480px,0); } }
@keyframes storm-bolt {
  0% { opacity:0; transform:translate3d(calc(34vw - 50%),0,0) scale(1,0.3); }
  12% { opacity:0; transform:translate3d(calc(34vw - 50%),0,0) scale(1,0.3); }
  12.205% { opacity:calc(var(--lightning-opacity) * 1); transform:translate3d(calc(34vw - 50%),0,0) scale(1,1); }
  12.41% { opacity:calc(var(--lightning-opacity) * 0.45); }
  12.59% { opacity:calc(var(--lightning-opacity) * 1); }
  13.154% { opacity:calc(var(--lightning-opacity) * 0.75); }
  14.308% { opacity:calc(var(--lightning-opacity) * 0.25); }
  15.333% { opacity:0; transform:translate3d(calc(34vw - 50%),0,0) scale(1,1); }
  46% { opacity:0; transform:translate3d(calc(76vw - 50%),0,0) scale(-0.92,0.276); }
  46.205% { opacity:calc(var(--lightning-opacity) * 0.95); transform:translate3d(calc(76vw - 50%),0,0) scale(-0.92,0.92); }
  46.41% { opacity:calc(var(--lightning-opacity) * 0.427); }
  46.59% { opacity:calc(var(--lightning-opacity) * 0.95); }
  47.154% { opacity:calc(var(--lightning-opacity) * 0.712); }
  48.308% { opacity:calc(var(--lightning-opacity) * 0.237); }
  49.333% { opacity:0; transform:translate3d(calc(76vw - 50%),0,0) scale(-0.92,0.92); }
  80% { opacity:0; transform:translate3d(calc(18vw - 50%),0,0) scale(0.8,0.24); }
  80.205% { opacity:calc(var(--lightning-opacity) * 0.7); transform:translate3d(calc(18vw - 50%),0,0) scale(0.8,0.8); }
  80.41% { opacity:calc(var(--lightning-opacity) * 0.315); }
  80.59% { opacity:calc(var(--lightning-opacity) * 0.7); }
  81.154% { opacity:calc(var(--lightning-opacity) * 0.525); }
  82.308% { opacity:calc(var(--lightning-opacity) * 0.175); }
  83.333% { opacity:0; transform:translate3d(calc(18vw - 50%),0,0) scale(0.8,0.8); }
  100% { opacity:0; transform:translate3d(calc(34vw - 50%),0,0) scale(1,0.3); }
}
@keyframes storm-glow {
  0%,100% { opacity:0; }
  12.103% { opacity:0; }
  12.282% { opacity:calc(var(--lightning-opacity) * 0.34); }
  12.462% { opacity:calc(var(--lightning-opacity) * 0.17); }
  12.641% { opacity:calc(var(--lightning-opacity) * 0.306); }
  13.538% { opacity:calc(var(--lightning-opacity) * 0.136); }
  15.333% { opacity:calc(var(--lightning-opacity) * 0.0408); }
  17.128% { opacity:0; }
  46.103% { opacity:0; }
  46.282% { opacity:calc(var(--lightning-opacity) * 0.323); }
  46.462% { opacity:calc(var(--lightning-opacity) * 0.162); }
  46.641% { opacity:calc(var(--lightning-opacity) * 0.291); }
  47.538% { opacity:calc(var(--lightning-opacity) * 0.129); }
  49.333% { opacity:calc(var(--lightning-opacity) * 0.0388); }
  51.128% { opacity:0; }
  80.103% { opacity:0; }
  80.282% { opacity:calc(var(--lightning-opacity) * 0.238); }
  80.462% { opacity:calc(var(--lightning-opacity) * 0.119); }
  80.641% { opacity:calc(var(--lightning-opacity) * 0.214); }
  81.538% { opacity:calc(var(--lightning-opacity) * 0.0952); }
  83.333% { opacity:calc(var(--lightning-opacity) * 0.0286); }
  85.128% { opacity:0; }
}
body.page-hidden :is(.sky-effects,.intro-sky) *,
body.page-hidden :is(.sky-effects,.intro-sky) *::before,
body.page-hidden :is(.sky-effects,.intro-sky) *::after,
:is(.sky-effects,.intro-sky)[data-motion="paused"] *,
:is(.sky-effects,.intro-sky)[data-motion="paused"] *::before,
:is(.sky-effects,.intro-sky)[data-motion="paused"] *::after { animation-play-state:paused !important; }
/* Em segundo plano o céu sai da composição (memória das camadas de nuvem/estrela liberada), o que
   torna o app instalado menos sujeito a ser encerrado pelo iOS. Só visibility: as animações
   continuam pausadas no mesmo ponto e voltam sem salto. Sem transição, para valer na hora. */
body.page-hidden :is(.sky-effects,.intro-sky) > * { visibility:hidden !important; transition:none !important; }
@media(max-width:720px) { .sky-effects .sky-sun { width:84px; } .sky-effects .sky-moon { width:46px; } }
@media(prefers-reduced-motion:reduce) {
  :is(.sky-effects,.intro-sky) *,
  :is(.sky-effects,.intro-sky) *::before,
  :is(.sky-effects,.intro-sky) *::after { animation:none !important; transition:none !important; }
  .sky-clouds { transform:translate3d(calc(var(--cloud-tile) * -.12),0,0); }
  .sky-clouds-front { transform:none; }
  .sky-lightning { display:none !important; }
}
