| 1 | /* estilo-sky — Calma's ambient nebula (sky.go). Quiet by default: |
| 2 | --estilo-sky-strength is one number for the whole effect. |
| 3 | |
| 4 | Placement is the host's: [estilo-sky-host] is a positioned, clipped box, |
| 5 | and a stacking context of its own, so the sky (z-index -1) paints above |
| 6 | the host's background and beneath everything else in it, without |
| 7 | touching how the host's other children are positioned — a sticky bar |
| 8 | stays sticky. Move the sky with --estilo-sky-top and |
| 9 | --estilo-sky-height, and set --estilo-sky-strength (0.5, Quiet) on the |
| 10 | host or anywhere above it. */ |
| 11 | [estilo-sky-host] { |
| 12 | position: relative; |
| 13 | overflow: hidden; |
| 14 | isolation: isolate; |
| 15 | } |
| 16 | |
| 17 | [estilo-sky] { |
| 18 | position: absolute; |
| 19 | inset-inline: 0; |
| 20 | top: var(--estilo-sky-top, -6%); |
| 21 | height: var(--estilo-sky-height, 80%); |
| 22 | pointer-events: none; |
| 23 | z-index: -1; |
| 24 | } |
| 25 | |
| 26 | /* Each layer overhangs the box so a drift never shows an edge, and fades |
| 27 | in and out vertically so the sky has no top or bottom. */ |
| 28 | [estilo-sky] img { |
| 29 | position: absolute; |
| 30 | left: -8%; |
| 31 | top: -12%; |
| 32 | width: 116%; |
| 33 | height: 124%; |
| 34 | max-width: none; |
| 35 | opacity: calc(var(--estilo-sky-strength, 0.5) * var(--estilo-sky-gain, 1) * var(--estilo-sky-k, 1)); |
| 36 | -webkit-mask-image: linear-gradient(#0000, #000 22%, #000 58%, #0000 92%); |
| 37 | mask-image: linear-gradient(#0000, #000 22%, #000 58%, #0000 92%); |
| 38 | user-select: none; |
| 39 | } |
| 40 | /* The sky's colour is the placeholder: the haze and clouds computed into a |
| 41 | few pixels and inlined, so it is there in the first frame (placeholder.go |
| 42 | has the measurements against the full SVG drawing: 3/255 light, 8/255 |
| 43 | dark). Stretched to cover as an SVG's xMidYMid slice would, and softened |
| 44 | so no pixel grid shows. The haze and clouds SVGs it replaced were |
| 45 | drawing almost nothing on top of it, so they are no longer linked |
| 46 | (impeccable's detector, 2026-09-29). Over it, two SVG layers carry what |
| 47 | a few pixels cannot: the clouds' grain — faint light and dark specks that |
| 48 | average to nothing — and the filaments. No script. */ |
| 49 | [estilo-sky] img { object-fit: cover; } |
| 50 | [estilo-sky-layer="placeholder"] { filter: blur(24px); } |
| 51 | [estilo-sky-layer="grain"] { --estilo-sky-k: 1; } |
| 52 | /* The weights haze and clouds had when they were linked, kept for a page |
| 53 | cached from then that still names them. */ |
| 54 | [estilo-sky-layer="haze"] { --estilo-sky-k: 0.175; } |
| 55 | [estilo-sky-layer="clouds"] { --estilo-sky-k: 0.25; } |
| 56 | [estilo-sky-layer="filaments"] { --estilo-sky-k: 1.3; } |
| 57 | |
| 58 | /* One placeholder per scheme; show the one that matches. An explicit |
| 59 | Appearance choice ([data-theme]) beats the OS, as it does for estilo's |
| 60 | theme. Both are inline, so neither costs a request. */ |
| 61 | [estilo-sky-tone="dark"] { display: none; --estilo-sky-gain: 1.55; } |
| 62 | :root[data-theme="dark"] [estilo-sky-tone="light"] { display: none; } |
| 63 | :root[data-theme="dark"] [estilo-sky-tone="dark"] { display: block; } |
| 64 | @media (prefers-color-scheme: dark) { |
| 65 | :root:not([data-theme="light"]) [estilo-sky-tone="light"] { display: none; } |
| 66 | :root:not([data-theme="light"]) [estilo-sky-tone="dark"] { display: block; } |
| 67 | } |
| 68 | |
| 69 | /* Drifting: the sky breathes, the grain with it, and the filaments |
| 70 | slide. Slow enough to notice only if you look. */ |
| 71 | @media (prefers-reduced-motion: no-preference) { |
| 72 | [estilo-sky-layer="placeholder"], [estilo-sky-layer="grain"] { animation: estilo-sky-breathe-near 64s ease-in-out infinite alternate; } |
| 73 | [estilo-sky-layer="filaments"] { animation: estilo-sky-drift 80s ease-in-out infinite alternate; } |
| 74 | } |
| 75 | @keyframes estilo-sky-breathe-near { to { transform: translate(-3%, 1.5%) scale(1.06); } } |
| 76 | @keyframes estilo-sky-drift { to { transform: translate(-4%, 1%); } } |
| 77 | |