/* The seasonal and time-of-day theme -- the layer that makes every page on the site
 agree about what month it is, what hour it is, and what the sky over Wakefield is
 currently doing.
 
 This was inline in index.html until the area pages existed. There is no sensible
 way for thirteen town pages to carry a second copy of it: the moment two copies
 exist, one of them is the one that gets the fix and the other is the one a visitor
 is looking at. So the rules that drive the palette, the seasonal furniture and the
 animated badge live here, index.html links this file at exactly the point in its
 own stylesheet where these rules used to sit, and the area pages link it too.
 
 Almost nothing here is a fixed colour. The runtime engine in assets/theme.js writes
 the palette tokens (--ink, --paper, --gold and the rest) straight onto :root from
 the real solar position, so a page that links this file and loads that script gets
 the whole day without declaring a single hue itself. What is left in here is the
 part CSS has to own: which selectors ease when the palette moves, what the seasons
 do to the hero wash, and the geometry of the badge the sun crosses.
 
 Edit here, not in a page. Both page types read this one file. */

/* ---------- THE HERO BADGE AND ITS FRAME ----------
   The badge is framed, and outlined the way the live weather chip across from it
   is (see .weather-now): the same hairline in --line, the same ice-to-white face
   and the same soft shadow under it, so the two panels in the hero read as one
   pair rather than two ideas -- either side of the headline on a wide screen,
   stacked on a phone.

   The frame is also what gives the badge its depth now, and that is why it
   exists rather than only why it looks like this. The artwork used to carry its
   own drop-shadow, and the <img> is masked (the flake cut, further down). CSS
   applies a filter before it applies a mask, so the mask was cutting the shadow
   as well as the artwork: the shadow came out clipped to the image's box -- a
   grey rectangle with a hard edge round the badge, which is the "border" it
   looked like it had -- and the cut's flake-shaped holes were punched straight
   through it, which on a heating day read as white snowflakes still hanging
   there in the shadow. The frame's box-shadow is drawn on this element instead,
   outside the masked one, so there is nothing left for the mask to cut. */
.hero-art{
  position:relative;display:flex;flex-direction:column;justify-content:center;align-items:center;
  /* 468 is the artwork's 440 plus the padding either side: the frame is drawn
     around the badge rather than taking width off it */
  width:100%;max-width:468px;margin:0 auto;padding:14px;
  /* theme tokens, not fixed hexes -- the same pairing the chip uses, so the
     time-of-day script re-tints the frame along with the panel it echoes */
  background:linear-gradient(135deg,var(--ice-soft) 0%,var(--white) 68%);
  border:1px solid var(--line);border-radius:22px;
  box-shadow:0 18px 34px -26px var(--sky-deep);
}
/* The sky scene is sized to this frame rather than to .hero-art, so its box is exactly
   the artwork's box. Isolated because the badge's evening overlays blend (multiply and
   screen) with the artwork, and must not reach through to the page behind it. */
.hero-frame{position:relative;width:100%;max-width:440px;margin:0 auto;isolation:isolate;}
/* The artwork and every layer that blends with it, in a group of their own -- the
   sky scene above them in the markup is deliberately left outside it.

   A blend layer takes its backdrop from everything painted beneath it inside the
   nearest isolated group, and until this wrapper existed that group was the whole
   frame: the sun, the drawn cloud and the sun's blurred halo were all part of what
   the badge's shade layer (mix-blend-mode:multiply, see .badge-shade) had to
   multiply. Those three are the only things on the badge that move, and iOS Safari
   re-blends a masked layer like that one damage rectangle at a time -- so the
   rectangles the moving sky dirtied came back multiplied and were never cleared.
   That is the artefact: stepped dark bars in the shade layer's own warm tint, out
   on the cream past the edge of the badge where its mask should have stopped it
   dead, travelling with the cloud that dirtied them. It survived the clip-path
   coming out of the cloud artwork (see the note in the markup) because the clip
   was never what caused it.

   Isolating the painting and its overlays settles every blend against the painting
   alone, which is all the scene mask lets through in the first place: mask and
   artwork transparency overlap on a few hundred antialiased edge pixels out of
   half a million, so the sky was never part of the picture those layers make. The
   sky still sits behind the whole group, exactly as before. */
.badge-stack{position:relative;z-index:1;isolation:isolate;}
.hero-art img{
  display:block;width:100%;max-width:440px;height:auto;
}

/* ---------- SEASONAL THEMING ---------- */
.season-banner{
  background:linear-gradient(90deg,#C0392B,var(--gold));color:#fff;
  padding:10px 0;transition:background .4s ease;
}
.season-banner-inner{
  display:flex;align-items:center;justify-content:center;gap:10px;
  text-align:center;flex-wrap:wrap;
  font-family:'JetBrains Mono',monospace;font-size:0.82rem;font-weight:600;letter-spacing:0.01em;
}
.season-banner .season-icon{font-size:1.05rem;}
body[data-season="spring"] .season-banner{background:linear-gradient(90deg,#3E7C3A,#7CB86A);}
body[data-season="summer"] .season-banner{background:linear-gradient(90deg,#C0392B,var(--gold));}
body[data-season="autumn"] .season-banner{background:linear-gradient(90deg,#8A4B1E,#C97A2B);}
/* Fixed hexes like the other three seasons: --sky-deep/--sky invert to pale blues
   at night for use as link text, which would strand this banner's white text on a
   light strip. */
body[data-season="winter"] .season-banner{background:linear-gradient(90deg,#1F6E9E,#3E8FC1);}

/* Hero copy: render the season emoji as an oversized watermark behind the text,
   the same treatment the benefit cards give their icons. */
.hero-copy{position:relative;}
.season-badge{
  position:absolute;top:-0.16em;right:0;z-index:0;
  font-size:clamp(8rem,14vw,13rem);line-height:1;
  opacity:0.14;pointer-events:none;user-select:none;
}
.hero-copy .eyebrow,.hero-copy h1,.hero-copy p.lede,.hero-copy .hero-ctas,
.hero-copy .weather-now{
  position:relative;z-index:1;
}
/* ---------- THE LIVE WEATHER PANEL ---------- */
/* The live reading under the eyebrow -- the one thing in the hero that is
   measurably true at the moment it is read, and for a long while the easiest thing
   on the page to miss. It was a single mono line in a pill, which is the wrong
   weight for it: the argument for air conditioning is the weather, and this is the
   weather, now, over the town the page is about. So it is a panel, it leads with
   the temperature at display size, and it says out loud that it is a feed -- the
   pill, the beating dot beside it, and the line naming where the numbers come from
   and how often they are re-read.

   Four rows, in the order somebody actually reads them: what this is and where,
   what it is doing, what the rest of today does, and who says so. The forecast has
   a row of its own now rather than being a "high 24" hidden among the qualifiers,
   because the day ahead is the part of the reading that argues for fitting
   something.

   The tile on the left is the hero badge's weather in miniature. It carries the
   same sheets of rain, sleet, snow and hail the artwork does, switched by the same
   body[data-precip] attribute and faded by the same custom properties, so there is
   one implementation of falling weather on the site and the panel can never
   disagree with the logo above it. Its sky is a fixed dusk blue rather than a
   theme token: the drops are drawn in a pale cool ink and the flakes in white, and
   both need something dark behind them at every hour of the day. */
.weather-now{
  position:relative;display:flex;align-items:stretch;gap:14px;
  font-family:'JetBrains Mono',monospace;font-size:0.74rem;font-weight:600;
  letter-spacing:0.04em;color:var(--ink-soft);line-height:1.3;
  /* theme tokens, not fixed hexes: the time-of-day script re-tints these at
     night, so the panel stays legible after dark like the town chips do */
  background:linear-gradient(135deg,var(--ice-soft) 0%,var(--white) 68%);
  border:1px solid var(--line);border-radius:18px;
  padding:13px 18px 13px 13px;margin:0 0 22px;max-width:440px;
  box-shadow:0 18px 34px -26px var(--sky-deep);
}
.weather-now[hidden]{display:none;}
/* The miniature sky. Clipped and isolated for the same reason the hero frame is:
   the flash inside it is screened over the tile and must not reach the panel. */
.wx-scene{
  position:relative;flex:0 0 auto;width:72px;min-height:68px;
  border-radius:13px;overflow:hidden;isolation:isolate;
  display:flex;align-items:center;justify-content:center;
  background:linear-gradient(180deg,#3C678E 0%,#1B3855 78%);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,0.16);
}
/* What the sky is doing, as one glyph: the state the badge dresses itself from,
   said in the space the tile has for it -- sun, moon, cloud, rain, snow, fog or a
   storm, picked from the same `sky` label the artwork is lit by. */
.wx-glyph{
  position:relative;z-index:1;font-size:1.5rem;line-height:1;
  filter:drop-shadow(0 2px 5px rgba(8,22,38,0.5));
}
/* The wind's lean, as on the badge: the drops fall straight down inside this box
   and the box is what rotates. Oversized so a rotated rectangle still covers the
   tile's corners; .wx-scene clips the overhang. */
.wx-tilt{
  position:absolute;inset:-40%;z-index:2;
  transform:rotate(var(--dt-precip-slant,10deg));
  transition:transform 8s ease;
}
/* Lightning, on the same footing as the badge's: an event rather than a state, so
   the strike class is put on from the theming engine and this is only what one
   looks like. Same keyframes, so both flash together. */
.wx-flash{
  position:absolute;inset:0;z-index:3;mix-blend-mode:screen;opacity:0;
  background:radial-gradient(64% 42% at 50% 6%, rgba(232,244,255,0.95) 0%, rgba(186,214,250,0.36) 48%, rgba(150,186,240,0) 100%);
}
.wx-flash.strike{animation:badge-strike 1.05s linear 1;}
.wx-text{display:flex;flex-direction:column;justify-content:center;gap:5px;min-width:0;}
.wx-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
/* The claim the panel is making about itself. Gold on navy, the same pairing the
   season flags use, because this is the one label on the page that is worth
   interrupting the mono grey for. */
.wx-live{
  display:inline-flex;align-items:center;gap:6px;flex-shrink:0;
  font-size:0.6rem;font-weight:700;letter-spacing:0.13em;text-transform:uppercase;
  background:var(--gold);color:var(--navy);
  border-radius:999px;padding:3px 10px 3px 8px;
}
.wx-beat{
  width:6px;height:6px;border-radius:50%;background:var(--navy);
  animation:wx-beat 2.4s ease-in-out infinite;
}
@keyframes wx-beat{
  0%,100%{opacity:1;transform:scale(1);}
  50%{opacity:0.3;transform:scale(0.7);}
}
.wx-when{display:inline-flex;align-items:baseline;gap:8px;flex-wrap:wrap;}
.wx-place{
  font-size:0.66rem;letter-spacing:0.14em;text-transform:uppercase;color:var(--stone);
}
/* Tabular figures so neither the clock nor the temperature shuffles sideways every
   time a 1 ticks over to a 2. */
.wx-clock{
  color:var(--ink);font-weight:700;font-size:0.8rem;
  font-variant-numeric:tabular-nums;letter-spacing:0.05em;
}
.wx-read{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;}
.wx-temp{
  color:var(--ink);font-weight:700;font-size:1.5rem;line-height:1;
  font-variant-numeric:tabular-nums;letter-spacing:0;
}
.wx-detail{font-size:0.72rem;font-weight:500;color:var(--ink-soft);}
/* The day ahead, on its own hairline-separated row. */
.wx-next{
  display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;
  font-size:0.7rem;font-weight:600;color:var(--ink-soft);
  padding-top:6px;border-top:1px solid var(--line);
}
.wx-next b{
  font-size:0.6rem;font-weight:700;letter-spacing:0.12em;text-transform:uppercase;
  color:var(--stone);
}
.wx-high{color:var(--ink);font-weight:700;font-variant-numeric:tabular-nums;}
.wx-low{font-variant-numeric:tabular-nums;}
/* On a phone the tile keeps its size and the type comes down: the panel is the
   width of the screen either way, and shrinking the reading is what stops the
   forecast row wrapping into three lines. */
@media (max-width: 620px){
  .weather-now{gap:12px;padding:12px 14px 12px 12px;border-radius:16px;}
  /* and the badge's frame comes in with it, so the two keep the same corner */
  .hero-art{padding:11px;border-radius:18px;}
  .wx-scene{width:64px;}
  .wx-temp{font-size:1.32rem;}
  .wx-next{font-size:0.67rem;}
}
/* The wash across the top of the hero: the season picks the hue, the hour decides
   how light it is. All four seasonal tints are near-white, and left to themselves
   they held a pale band across the top of the hero at midnight while the rest of the
   page went navy -- which is what made the stars look dull, because a white star on
   a near-white ground has nothing to show against. --hero-wash is the season's own
   colour and the script carries it toward night navy on the same daylight figure as
   the palette (see --dt-hero-wash), so the band is the season by day and gone by the
   time the stars are out. */
body[data-season="spring"]{--hero-wash:#F2FAEE;}
body[data-season="summer"]{--hero-wash:#FFF6DF;}
body[data-season="autumn"]{--hero-wash:#FDF1E6;}
body[data-season="winter"]{--hero-wash:#EAF5FC;}
.hero{
  background:linear-gradient(180deg,
    var(--dt-hero-wash, var(--hero-wash,#EAF5FC)) 0%,
    var(--dt-hero-wash-out, rgba(255,255,255,0)) 65%);
}

/* Which of the two stories the page leads with. Spring and summer lead with the
   heat: the trend section is the tinted panel and carries the accent rule. Autumn
   and winter lead with the heating: the reverse-cycle panel inside the benefits
   section takes the tint and the accent rule. (The trend section keeps its tint
   all year in index.html so the page's bands still alternate.) The emphasis moves, the DOM does not -- reordering these with flex `order` would have left the visual sequence
   disagreeing with the reading order screen readers and keyboard tabbing follow. */
[data-season-feature]{background:var(--paper);position:relative;}
body[data-season="spring"] [data-season-feature="cool"],
body[data-season="summer"] [data-season-feature="cool"],
body[data-season="autumn"] [data-season-feature="warm"],
body[data-season="winter"] [data-season-feature="warm"]{
  background:var(--ice-soft);
}
body[data-season="spring"] [data-season-feature="cool"]::before,
body[data-season="summer"] [data-season-feature="cool"]::before,
body[data-season="autumn"] [data-season-feature="warm"]::before,
body[data-season="winter"] [data-season-feature="warm"]::before{
  content:"";position:absolute;top:0;left:0;right:0;height:4px;
  background:linear-gradient(90deg,var(--gold) 0%,var(--sky-deep) 52%,var(--gold) 100%);
}
/* The in-season section's heading and the featured benefit card each carry the
   season's chip. Declared against both parents rather than on its own: `.card p`
   and `.section-head p` are each a class plus a type, so a bare `.season-flag`
   would lose to them on specificity and the chip would come out as body copy. */
.card .season-flag, .section-head .season-flag{
  display:inline-flex;align-items:center;gap:6px;
  font-family:'JetBrains Mono',monospace;font-size:0.66rem;font-weight:600;
  letter-spacing:0.1em;text-transform:uppercase;
  background:var(--gold);color:var(--navy);
  padding:4px 11px;border-radius:999px;margin:0 0 14px;
  position:relative;z-index:1;
}

/* One of the six benefit cards is the reason to ring us *today*: cooling in summer,
   filtered air through the pollen months, cheap warmth once it turns. The season
   picks it and it is lifted out of the grid rather than reworded, so the other five
   still read as the full year-round case. */
.benefits-grid .card.is-featured{
  border-color:var(--gold);
  background:linear-gradient(180deg,var(--ice-soft) 0%,var(--white) 58%);
  box-shadow:0 16px 34px -22px var(--sky-deep);
}
.benefits-grid .card.is-featured::after{height:5px;}


/* ---------- TIME OF DAY THEMING ---------- */
/* colours above are re-tinted at runtime by real Wakefield sun position; these
   rules just make the change glide instead of snap, and render the sun itself */
body, header, .card, .testi, footer, .cta-band, .form-card, .map-frame,
.town-chip, .weather-now, .hero-art, .trust, .heat-stat, .heat-chart, .faq-item,
input, textarea{
  transition:background-color 6s ease, color 6s ease, border-color 6s ease, box-shadow 6s ease;
}
.sky-scene{
  position:absolute;inset:-8% -10% -2% -10%;
  overflow:visible;pointer-events:none;z-index:0;
}
.sky-scene::before{
  content:'';position:absolute;inset:0;
  background:radial-gradient(64% 58% at var(--dt-sun-wash-left,50%) var(--dt-sun-wash-top,18%), var(--dt-sky-bottom,#EAF6FF) 0%, transparent 74%);
  opacity:0.62;filter:blur(22px);
  /* no background transition: this halo is anchored to the sun's resting coordinates,
     and easing it separately left it lagging behind the disc on every move. The
     colour it fades through only changes by a hair between ticks, so nothing snaps. */
  transition:opacity 6s ease;
}
.hero-art img{position:relative;z-index:1;}
/* What carries the sun across the sky. The disc's position could be written straight
   onto it as left/top, but left/top are layout: every step of the walk relaid out the
   disc and repainted it along with the 60px glow around it, and on iOS that repaint
   is what left a stale wedge of the disc stranded on the badge. A transform is
   composited instead, so the disc is rasterised once and then simply moved.
   The track fills the scene exactly, which is the whole trick -- a percentage in
   translate() is a percentage of the moving box, so filling the scene makes
   --dt-sun-left/top mean the same thing here as they did as left/top, with no
   pixels to measure and nothing to recompute when the window changes size.
   The transform is deliberately not transitioned: easing it would ease the two
   coordinates independently and drag the disc along a straight chord, straight
   through the badge, which is what moveSun's own tween exists to avoid. */
.sky-sun-track{
  position:absolute;inset:0;
  transform:translate3d(var(--dt-sun-left,50%),var(--dt-sun-top,18%),0);
}
.sky-sun{
  position:absolute;
  width:var(--dt-sun-size,36px);height:var(--dt-sun-size,36px);
  border-radius:50%;
  /* Cartoon ink line so the disc reads against a pale sky instead of dissolving
     into it. box-sizing is border-box (see *{} above), so the outer diameter is
     still exactly --dt-sun-size and the tangency tables in the theming script
     keep placing the sun on the badge's horizon correctly. The line thickens
     with the disc, with a floor so it survives the small dawn/dusk sun. */
  border:max(2px, calc(var(--dt-sun-size,36px) * 0.085)) solid var(--dt-sun-ink,#0A1622);
  /* The disc sits at the origin of .sky-sun-track and the track is what moves; see
     the note there. Only the centring offset lives here. */
  left:0;top:0;
  transform:translate(-50%,-50%);
  /* a tight highlight rather than a long fade -- flatter fill, like inked artwork */
  background:radial-gradient(circle at 34% 32%, #FFF6C0 0%, var(--dt-sun-color,#FFD452) 44%, var(--dt-sun-color,#FFD452) 100%);
  box-shadow:var(--dt-sun-glow, 0 0 50px 16px rgba(255,206,92,0.55));
  opacity:var(--dt-sun-opacity,1);
  /* left/top are deliberately NOT transitioned. A CSS transition eases the two
     independently, which draws a straight chord from wherever the disc is to
     wherever it belongs -- straight through the badge, so the sun crossed behind
     the logo and disappeared instead of skirting it. The script tweens the
     position itself, recomputing the contour height at every frame (see moveSun),
     so each intermediate frame is still tangent to the silhouette.

     Only opacity is eased, because opacity is the one property here the compositor
     can animate without redrawing the disc. Fill, glow and diameter are quantised
     (a rounded pixel, a rounded blur radius), so they already arrive in steps far
     too small to see; easing them only kept the disc re-rasterising for eight
     seconds out of every fifteen for no visible gain. */
  transition:opacity 6s ease;
}
/* The cloud that comes over the sun when Wakefield is under real cover. The disc
   used to be faded out instead, which read as the artwork dimming rather than as
   weather; a drawn cloud says the same thing about the sky and keeps the sun the
   same painted object it is on a clear day.

   It rides inside .sky-sun-track, so it is carried across the badge's horizon by
   the same transform as the disc and needs no coordinates of its own. Two numbers
   from the live sky drive it: --dt-sun-cloud fades it in once there is enough
   cover to be worth drawing, and --dt-cloud-x/-k slide and grow it across the
   disc as the sky fills in -- so a partly cloudy afternoon takes a bite out of one
   side of the disc and leaves most of it out in the open, while a cloudy one has it
   fully behind the cloud. Cover is mostly told by where the cloud is rather than by
   how solid it is drawn, though not entirely: the body is left a little see-through
   while it is still off to one side, so passing cloud reads as thin, and it paints
   out solid over the last of the walk across.

   Sized off the disc's largest setting so it stays in proportion to the disc as that
   swells toward sunset -- but as a fixed box with the hour's size folded into the
   scale below, not as a box measured off --dt-sun-size. The tick rewrites that
   variable, and a composited layer that has its bounds relaid out under it while a
   transform transition is still running is the other thing WebKit is known to leave
   stale pixels behind for. The drawn size is the same either way.
   transform-origin sits on the disc's centre (the same 38.75%/57.6% as the offset
   below), so the scale step grows the cloud around the sun rather than sliding it
   off it. */
.sky-cloud{
  position:absolute;left:0;top:0;
  /* 48px is the disc at its largest (see sunPx in apply), by the same four and 1.65
     the box has always been; --dt-cloud-k carries the hour's fraction of that 48
     multiplied by the cover's own growth, so one scale does both. */
  width:192px;
  height:79.2px;
  /* The disc's centre sits at 124,76 of the 320x132 artwork below -- inside the big
     lobe, whose radius (62 units against the disc's 40) is what covers the sun on
     its own, so full cover never depends on where the smaller lobes fall. */
  transform-origin:38.75% 57.6%;
  transform:translate(calc(-38.75% + var(--dt-cloud-x,0%)), -57.6%) scale(var(--dt-cloud-k,0.75));
  opacity:var(--dt-sun-cloud,0);
  visibility:var(--dt-sun-cloud-vis,hidden);
  /* opacity and the slide ease together over the same 6s as every other weather
     layer, so cover thickening or breaking up is a drift rather than a jump */
  transition:opacity 6s ease, visibility 6s ease, transform 6s ease;
}
.sky-cloud svg{display:block;width:100%;height:100%;}
/* Flat cartoon cloud, like the painted badge it floats over: white body, a hard
   flat base, and a cool band under the bumps doing the shading. One path each,
   stated as outlines rather than assembled out of overlapping lobes and clipped to
   shape -- see the note on the artwork in the markup for why Safari insisted on
   that. Each is a single opaque silhouette, so --dt-sun-cloud fades the cloud
   without a seam showing anywhere inside it.
   All three fills are re-lit every tick by the hour and the cover (see apply). */
.sky-cloud .cl-body{fill:var(--dt-cloud-body,#FFFFFF);transition:fill 6s ease;}
.sky-cloud .cl-shade{fill:var(--dt-cloud-shade,#D3E3F1);transition:fill 6s ease;}
.sky-cloud .cl-shade-deep{fill:var(--dt-cloud-shade-deep,#BFD5E8);transition:fill 6s ease;}
/* The moon, the sun's night-time counterpart. Built by the theming script (see
   buildMoon) and carried across the badge exactly as the sun is: a track filling the
   scene, moved by one composited transform, with the disc centred on its origin.
   The same ink line as the sun keeps it one of the badge's drawn objects. The disc
   itself is the unlit side -- earthshine, a shade lighter than the night sky -- and
   the svg paints tonight's lit phase over it. */
.sky-moon-track{
  position:absolute;inset:0;
  transform:translate3d(var(--dt-moon-left,50%),var(--dt-moon-top,18%),0);
}
.sky-moon{
  position:absolute;left:0;top:0;
  width:var(--dt-moon-size,36px);height:var(--dt-moon-size,36px);
  border-radius:50%;overflow:hidden;
  border:max(2px, calc(var(--dt-moon-size,36px) * 0.085)) solid var(--dt-sun-ink,#0A1622);
  transform:translate(-50%,-50%);
  background:#2A3752;
  box-shadow:var(--dt-moon-glow, 0 0 30px 8px rgba(214,226,255,0.3));
  opacity:var(--dt-moon,0);
  visibility:var(--dt-moon-vis,hidden);
  transition:opacity 6s ease, visibility 6s ease;
}
.sky-moon svg{display:block;width:100%;height:100%;}
.sky-moon .mn-lit{fill:#F3EFDD;}
.sky-moon .mn-mare{fill:rgba(92,100,126,0.2);}
/* its own copy of the sun's cloud, driven by the moon's numbers instead */
.sky-moon-cloud{
  transform:translate(calc(-38.75% + var(--dt-moon-cloud-x,0%)), -57.6%) scale(var(--dt-moon-cloud-k,0.75));
  opacity:var(--dt-moon-cloud,0);
  visibility:var(--dt-moon-cloud-vis,hidden);
}
/* Stars in the hero's sky. One element per star rather than one layer carrying
   eight gradients: a layer can only fade all of them at once, which reads as a
   panel flashing rather than a sky. Each star gets its own period, phase and
   brightness range, so the field never pulses in step -- and the range is shallow
   on purpose. A star dips toward its dimmer value and back, never out; the point
   is that you notice the sky is alive, not that anything blinks. Sizes and
   positions are the ones the gradients used, so the constellation is unchanged. */
/* visibility, not just opacity: a layer left at opacity 0 is still a layer, holding
   its place in the hero's compositing stack and its own backing store all day. Every
   overlay in here takes its visibility from the same number as its opacity -- apply()
   writes --dt-<name> and --dt-<name>-vis together -- so a layer contributing nothing
   is not in the stack at all. Both are transitioned: visibility is a discrete
   property, so it flips to visible at the start of a fade-in and back to hidden only
   once a fade-out has finished, which leaves both 6s fades exactly as they were. */
.sky-stars{
  position:absolute;inset:0 6% 56% 6%;opacity:var(--dt-stars-opacity,0);
  visibility:var(--dt-stars-opacity-vis,hidden);
  transition:opacity 6s ease, visibility 6s ease;
}
.sky-stars i{
  position:absolute;display:block;border-radius:50%;background:#fff;
  /* centred on its coordinates, like the gradient stop it replaces */
  transform:translate(-50%,-50%) scale(1);
  width:3.6px;height:3.6px;
  /* A bare 3px dot reads as a speck of dust. The halo is what makes it a star, and
     it is what the eye actually catches when the brightness swings -- the glow
     grows and shrinks with the dot, which is the sparkle. */
  box-shadow:0 0 4px 1px rgba(255,255,255,0.72), 0 0 11px 2px rgba(255,255,255,0.30);
  opacity:var(--tw-hi,1);
  /* No animation at all until the page calls it night -- only the name is switched
     on, so each star keeps the period and phase its own rule gives it below. Pausing
     the animation instead, which is what this used to do, still counts as animating:
     the element keeps its own composited layer and backing store, and eight of those
     sat in the hero all day with nothing to draw. That is where the stray dark mark
     on the badge was coming from -- one of these layers, at star 6's position, being
     composited with whatever its backing store happened to hold. */
  animation:none 5.6s ease-in-out infinite;
}
body[data-daytime="night"] .sky-stars i{animation-name:sky-twinkle;}
.sky-stars i:nth-child(1){left:12%;top:20%;--tw-hi:1.00;--tw-lo:0.40;--tw-min:0.74;animation-duration:6.1s;animation-delay:-0.7s;}
.sky-stars i:nth-child(2){left:28%;top:40%;width:3.2px;height:3.2px;--tw-hi:0.96;--tw-lo:0.48;--tw-min:0.80;animation-duration:4.6s;animation-delay:-2.9s;}
.sky-stars i:nth-child(3){left:45%;top:15%;width:2.8px;height:2.8px;--tw-hi:0.92;--tw-lo:0.36;--tw-min:0.72;animation-duration:5.4s;animation-delay:-1.6s;}
.sky-stars i:nth-child(4){left:62%;top:32%;width:3.2px;height:3.2px;--tw-hi:1.00;--tw-lo:0.52;--tw-min:0.82;animation-duration:7.2s;animation-delay:-3.8s;}
.sky-stars i:nth-child(5){left:78%;top:12%;width:2.8px;height:2.8px;--tw-hi:0.88;--tw-lo:0.34;--tw-min:0.70;animation-duration:4.1s;animation-delay:-0.9s;}
.sky-stars i:nth-child(6){left:88%;top:28%;--tw-hi:1.00;--tw-lo:0.58;--tw-min:0.86;animation-duration:6.7s;animation-delay:-4.6s;}
/* 7 and 8 used to sit at 20%/55% and 70%/50%, which is on the badge: the artwork
   is opaque and painted over the sky layer, so one was hidden outright and the
   other had 2px of clear sky around it. Both moved into open sky. */
.sky-stars i:nth-child(7){left:10%;top:52%;width:2.8px;height:2.8px;--tw-hi:0.90;--tw-lo:0.42;--tw-min:0.76;animation-duration:5.9s;animation-delay:-2.2s;}
.sky-stars i:nth-child(8){left:76%;top:46%;width:3.2px;height:3.2px;--tw-hi:0.98;--tw-lo:0.50;--tw-min:0.80;animation-duration:4.9s;animation-delay:-3.3s;}
/* The range lives on the element, not in the keyframes, so eight stars share one
   animation and still each fade between their own two values -- brightness and
   size together, because a star that only dims looks like a fading light rather
   than one that is glinting. */
@keyframes sky-twinkle{
  0%,100%{opacity:var(--tw-hi,1);transform:translate(-50%,-50%) scale(1);}
  50%{opacity:var(--tw-lo,0.45);transform:translate(-50%,-50%) scale(var(--tw-min,0.78));}
}

/* The badge is painted as a bright midday scene, so the sun that repaints the
   page relights the landscape inside it too -- and so does the weather. Four
   overlay layers sit on top of the artwork, all masked to logo-scene-mask.png
   -- an alpha map of the painted landscape and the mast alone, so the white
   rose, the wordmark and the badge keyline keep their brand colours whatever
   the hour. The shade multiplies the hour's own tint (dawn blue, sunrise rose,
   clean daylight, golden afternoon, sunset amber, twilight violet, night navy,
   with the land taking a deeper cut than the sky), the dull layer drains
   saturation when it is cloudy, the veil screens a milky haze over rain, fog
   and snow, and the glow screens a soft ellipse of horizon light back in at the
   sun's own azimuth. On a clear day at noon all four are near-nothing, which is
   the artwork exactly as drawn. The stars sit above all four (see .badge-stars),
   so the weather never dims them -- only a painted cloud in front of one hides it. */
.badge-shade, .badge-dull, .badge-veil, .badge-glow, .badge-stars, .mast-lights,
.badge-precip, .badge-flash, .badge-settle{
  position:absolute;inset:0;pointer-events:none;
}
/* Every url() here is written from the site root, not from the stylesheet. A
   relative one looks tidier and is wrong: this file is served from /assets/, so
   url("assets/logo-scene-mask.png") asks for /assets/assets/... and 404s -- and
   because the @supports test below is itself a url(), the whole weather stack
   failed the test and stayed at display:none. No errors in the console, no
   layers on the badge: just a hero that never clouded over. */
.badge-shade, .badge-dull, .badge-veil, .badge-glow, .badge-stars,
.badge-precip, .badge-flash{display:none;}
@supports ((-webkit-mask-image:url("/assets/logo-scene-mask.png")) or (mask-image:url("/assets/logo-scene-mask.png"))){
  .badge-shade, .badge-dull, .badge-veil, .badge-glow, .badge-stars,
  .badge-precip, .badge-flash{
    display:block;
    -webkit-mask-image:url("/assets/logo-scene-mask.png");
            mask-image:url("/assets/logo-scene-mask.png");
    -webkit-mask-size:100% 100%;
            mask-size:100% 100%;
    -webkit-mask-repeat:no-repeat;
            mask-repeat:no-repeat;
  }
}
/* ---------- WHICH WAY THE AIR IS BLOWING ----------
   The badge is painted blowing cold: a blue ribbon of air out of the wall unit
   with snowflakes hanging in it. Half the Wakefield year the machine in that
   picture would be running the other way round -- we fit heat pumps as well --
   so on a heating day the badge does too. body[data-flow] is written from the
   live reading (see setFlow in assets/theme.js) and there are four layers
   behind it, all of them generated from the artwork's own pixels by
   tools/logo-flow.mjs, none of them touching assets/logo.png itself: the same
   file is the nav logo, the footer logo and the quote form's, and those stay
   blue whatever the weather is doing.

   1. the cut, which masks the two loose snowflakes and the five loose dots off
      the artwork -- those hang on transparency, so they can be masked; the pale
      flakes over the unit's pocket cannot (there is opaque badge behind them)
      and are painted out in the warm overlay instead. It is applied on every
      day of the year, not only heating ones, which is what makes the two moods
      able to cross-fade: see .badge-cool.
   2. .badge-cool, the cut pixels put straight back. It is the exact complement
      of the cut, so a cooling day is the artwork as drawn and not a copy of it,
      and the flakes are on a layer of their own that can be faded rather than
      part of the <img> underneath, which cannot.
   3. .badge-warm, the same region remapped to orange and red, laid exactly over
      the blue one.
   4. .badge-flow, the marks that move: flakes and specks of cold drifting out
      along the ribbon on a cooling day, curls of rising heat and embers where
      the flakes were on a heating one. Drawn in the artwork's own 880x577, as
      the snowman is, so a coordinate here is a pixel in logo.png.

   The mood change is one cross-fade over all of it, both overlays and both sets
   of marks on the same 2.2s: the flakes dissolve into the warm ribbon as the
   warm ribbon arrives. Fading 2 out while 3 fades in works because the two
   overlays cover the same pixels, so through the middle of it the badge is a
   mixture of the two rather than a hole between them.

   The curve is a hard ease-in-out rather than a plain ease, and that is worth a
   line. Half way through, half an orange ribbon is lying over a blue one, and
   two opposite hues at half strength make silver -- there is no route from one
   to the other that does not pass through it, because the blue is the <img>
   underneath and is not going anywhere. So the curve holds at each end and
   crosses the middle quickly: long enough to read as a dissolve, brief enough
   that the silver is a sheen going over rather than a colour the badge was.

   All of it sits at z-index 1, in front of the artwork and behind everything
   the hour and the weather draw over the landscape (see .badge-shade). Those
   layers are masked to the painted scene and have never reached the airflow,
   which is brand artwork rather than landscape, so the ribbon is as bright at
   midnight as it is at noon -- warm or cold, that does not change. */
.badge-cool, .badge-warm, .badge-flow{
  position:absolute;inset:0;z-index:1;pointer-events:none;
}
.badge-flow{width:100%;height:100%;overflow:visible;}
.badge-cool, .badge-warm{
  background-position:0 0;background-size:100% 100%;background-repeat:no-repeat;
  transition:opacity 2.2s cubic-bezier(.7,0,.3,1);
}
.badge-cool{background-image:url("/assets/logo-flow-cool.png");opacity:1;}
.badge-warm{background-image:url("/assets/logo-flow-warm.png");opacity:0;}
body[data-flow="heat"] .badge-cool{opacity:0;}
body[data-flow="heat"] .badge-warm{opacity:1;}
/* The cut is guarded, as the scene overlays are, and the cool overlay is not:
   a browser without mask support keeps the artwork's own flakes and has the
   cool overlay laid back over the top of them, which is the same pixels twice
   and looks like nothing at all. A heating day there keeps its snowflakes --
   cold decoration on a warm ribbon, which is wrong but is a picture, where a
   badge full of holes is not. */
@supports ((-webkit-mask-image:url("/assets/logo-flake-cut.png")) or (mask-image:url("/assets/logo-flake-cut.png"))){
  .hero-art img{
    -webkit-mask-image:url("/assets/logo-flake-cut.png");
            mask-image:url("/assets/logo-flake-cut.png");
    -webkit-mask-size:100% 100%;
            mask-size:100% 100%;
    -webkit-mask-repeat:no-repeat;
            mask-repeat:no-repeat;
  }
}
/* Both sets of marks stay in the document and fade with the overlays -- the
   same 2.2s and the same curve, so a mark of the mood that is leaving is still
   on its way out while the ribbon behind it is still on its way over.
   visibility comes along for the ride so the set that is not showing is not
   composited between changes, and the animation names below are switched on per
   mood, so it is not animating either. */
.flow-cool, .flow-heat{
  opacity:0;visibility:hidden;
  transition:opacity 2.2s cubic-bezier(.7,0,.3,1), visibility 2.2s linear;
}
body[data-flow="cool"] .flow-cool,
body[data-flow="heat"] .flow-heat{opacity:1;visibility:visible;}
/* --dur, --delay and --hi come off each mark's own style attribute, which is
   what lets one keyframe rule carry twenty marks that all move differently.
   animation-delay is negative in the markup -- every mark starts mid-flight, so
   the badge is never caught with all of them at the same point of the loop.
   Name only on the switch, as the rain sheets and the stars do it: a badge that
   has scrolled away, or a visitor who has asked for less motion, leaves nothing
   animating and nothing composited (setFlow drops the attribute for both). */
.flow-mote, .flow-speck, .flow-curl, .flow-ember{
  animation:none var(--dur,8s) linear infinite;
  animation-delay:var(--delay,0s);
}
body[data-flow-motion][data-flow="cool"] .flow-mote,
body[data-flow-motion][data-flow="cool"] .flow-speck{animation-name:flow-drift;}
body[data-flow-motion][data-flow="heat"] .flow-curl{
  animation-name:flow-rise, flow-shimmer;
  animation-duration:var(--dur,8s), calc(var(--dur,8s) / 4);
}
body[data-flow-motion][data-flow="heat"] .flow-ember{animation-name:flow-ember;}
/* The air in the ribbon. Each line in .flow-streams is one of the ribbon's
   bands traced from the outlet outwards (#flowStreamA to E), dashed so only
   a single stroke of it shows at a time, and flow-stream carries that stroke
   the whole way along -- out of the unit, down through the dip and up off the
   tip -- fading in as it leaves and out as it goes. The gusts are the same
   trip slower, broad and faint, so the ribbon swells as the glints run
   through it. Cold is white and ice-blue, warm is pale gold and orange.
   Invisible until they move, as the flakes are: a still dash is a scratch. */
.flow-stream, .flow-gust{
  fill:none;stroke-linecap:round;opacity:0;
  animation:none var(--dur,3s) linear infinite;
  animation-delay:var(--delay,0s);
}
.flow-stream{stroke-width:3.4;stroke-dasharray:22 140;stroke-dashoffset:22px;}
.flow-gust{stroke-width:var(--w,12);stroke-dasharray:40 150;stroke-dashoffset:40px;}
.stream-cool .flow-stream{stroke:#FFFFFF;}
.stream-cool .flow-gust{stroke:#BFE6FF;}
.stream-warm .flow-stream{stroke:#FFF1C2;}
.stream-warm .flow-gust{stroke:#FFB347;}
body[data-flow-motion][data-flow="cool"] .stream-cool .flow-stream,
body[data-flow-motion][data-flow="heat"] .stream-warm .flow-stream{animation-name:flow-stream;}
body[data-flow-motion][data-flow="cool"] .stream-cool .flow-gust,
body[data-flow-motion][data-flow="heat"] .stream-warm .flow-gust{animation-name:flow-gust;}
/* Cold that is on its way out: pale as the artwork's own flakes, and invisible
   until it is moving -- the ribbon already has flakes drawn in it, and a second
   set of them sitting still is just a heavier picture. */
.flow-mote{fill:none;stroke:#5BB8EE;stroke-width:1.5;stroke-linecap:round;opacity:0;}
.flow-speck{fill:#5BB8EE;opacity:0;}
/* Heat, which is the opposite case: these marks are standing in for the flakes
   the cut took away, so they hold their place whether they are animating or
   not. Two oranges and a red, off the unit's own warm end of the artwork; the
   ones over the pocket are lighter, because a mid orange on that red is a
   smudge. */
/* The heat waves: a broad haze at a third strength with the bright line inside
   it, both stroked with the same fade (#flowHeatFade, red at the foot to clear at
   the top). The line is dashed, and while the badge is animating the dashes run
   up the wave -- stroke-dashoffset is inherited, so flow-shimmer on the <use>
   reaches both paths and only the dashed one shows it. */
.flow-haze{stroke-width:11;opacity:0.32;}
.flow-line{stroke-width:4.2;stroke-dasharray:34 6;}
.flow-ember{fill:#F2871E;}
.flow-ember.hot{fill:#E8420C;}
.flow-ember.in-pocket{fill:#FFA23A;}
.flow-ember.in-pocket.hot{fill:#FF6A1E;}
/* Right to left, along the ribbon: the air is leaving the unit, not arriving at
   it. Translate only, never scale or rotate -- an SVG transform-origin is the
   middle of the viewBox unless it is told otherwise, and a flake spun around
   the middle of the badge is a flake in orbit. */
@keyframes flow-drift{
  0%{opacity:0;transform:translate(40px,-8px);}
  16%{opacity:var(--hi,0.9);}
  74%{opacity:var(--hi,0.9);}
  100%{opacity:0;transform:translate(-110px,22px);}
}
/* One run of the ribbon per loop: the offsets are in the paths' own
   pathLength of 100, from the dash sitting just before the outlet to just past
   the tip, so it is born inside the unit and dies in the open air. */
@keyframes flow-stream{
  0%{stroke-dashoffset:22px;opacity:0;}
  12%{opacity:0.95;}
  78%{opacity:0.8;}
  100%{stroke-dashoffset:-100px;opacity:0;}
}
@keyframes flow-gust{
  0%{stroke-dashoffset:40px;opacity:0;}
  20%{opacity:0.34;}
  70%{opacity:0.26;}
  100%{stroke-dashoffset:-100px;opacity:0;}
}
/* Rising heat, and the shape of the climb is in where the keyframes fall rather
   than in a timing function: every mark here runs linear, and the steps get
   longer as it goes up, so a wave lifts away gently and is thinning out by the
   time it reaches the ribbon. It sways as it climbs -- left, back past centre,
   left again -- the way warm air wavers over a radiator, and the sway is a
   translate like everything else here, never a rotate (see flow-drift). Both
   ends fade, so nothing appears or vanishes on a hard edge. */
@keyframes flow-rise{
  0%{opacity:0;transform:translate(1px,14px);}
  18%{opacity:0.95;transform:translate(-1px,8px);}
  42%{opacity:0.9;transform:translate(2px,-2px);}
  70%{opacity:0.62;transform:translate(-4px,-14px);}
  100%{opacity:0;transform:translate(-8px,-28px);}
}
/* The dashes travelling up the line, one pattern length (34 + 6) per loop.
   Negative, because the wave is drawn from its foot: a growing offset would run
   the dashes back down into the ribbon. */
@keyframes flow-shimmer{
  from{stroke-dashoffset:0;}
  to{stroke-dashoffset:-40px;}
}
/* The embers drift and go out, rather than pulsing where they lie: a dot that
   brightens and dims in place reads as a light being switched, and a dot that
   lifts and fades reads as air. */
@keyframes flow-ember{
  0%{opacity:0;transform:translate(0,5px);}
  22%{opacity:var(--hi,0.95);transform:translate(0,1px);}
  60%{opacity:0.66;transform:translate(-2px,-7px);}
  100%{opacity:0;transform:translate(-4px,-15px);}
}

/* ---------- WHAT HAS ALREADY LANDED ----------
   The sheets further down draw snow falling; this draws the snow that fell an
   hour ago and stayed. It is the first thing over the artwork and everything
   else is over it, which is the whole point of where it sits: the shade tints
   it, the cloud dulls it, the haze hangs in front of it and the mast's lamps
   light it, so a snowy midnight is a badge full of blue snow under a navy sky
   rather than a white cut-out pasted on the front of one.

   The cover itself is generated, not drawn -- see tools/snow-cover.mjs. Every
   pixel of the artwork is classified off its own colour, the fields take a
   full sheet tinted by the grass under them so the hills keep their light and
   shade, and every wall, hedge, tree and roofline takes a crest along its top
   edge only. It is written out already masked to logo-scene-mask.png, so
   unlike the five layers above it needs no mask of its own -- which also means
   a browser with no mask support still gets a white Wakefield.

   Slower than everything else in the badge, both ways. Six seconds is right
   for a cloud crossing the sun; snow arrives over an afternoon and is still
   lying there after the shower has stopped, and a field that whitens as fast
   as the light changes reads as a layer being switched on. */
.badge-settle{
  z-index:2;
  background:url("/assets/logo-snow-cover.png") 0 0 / 100% 100% no-repeat;
  opacity:var(--dt-settle,0);
  visibility:var(--dt-settle-vis,hidden);
  transition:opacity 18s ease, visibility 18s ease;
}
/* The clouds painted into the artwork's sky, taken out on a clear day. The
   overlay is that sky with the clouds painted out -- generated from logo.png by
   tools/sky-clear.mjs, transparent everywhere but over the clouds, keyline
   repainted where a cloud ran up into the ring -- so at full strength the badge
   has a cloudless sky and at nothing it is the artwork as drawn. --dt-clear-sky
   comes off the live cover (clearSky in conditions(), assets/theme.js) and is 0
   until a reading lands. It sits directly on the artwork, under the snow and
   under every tint, so the hour and the weather light the clear sky exactly as
   they light the painted one. The fade is slow, as a sky clearing is: the
   clouds thin out and go rather than switching off. */
.badge-clear{
  position:absolute;inset:0;pointer-events:none;z-index:1;
  background:url("/assets/logo-sky-clear.png") 0 0 / 100% 100% no-repeat;
  opacity:var(--dt-clear-sky,0);
  visibility:var(--dt-clear-sky-vis,hidden);
  transition:opacity 12s ease, visibility 12s ease;
}
/* And the one thing in the badge that is not weather: a snowman, out in the
   field the artwork leaves open between the near wall and the wordmark -- the
   only clear run of grass in the picture tall enough to stand one in, which is
   what fixes both his size and his spot. Drawn against the artwork's own
   880x577 so every number here is a coordinate you can find in logo.png, and
   lit from the right, because the barn's sunlit face is its right one. He
   fades up with the field he is standing in. */
.snowman{position:absolute;inset:0;width:100%;height:100%;overflow:visible;}
.sm-cast{fill:#7E9BBE;opacity:0.6;}
.sm-foot{fill:#FFFFFF;opacity:0.9;}
.sm-shade{fill:#A6BED9;stroke:#7E9BBC;stroke-width:0.38;}
.sm-lit{fill:#FFFFFF;}
/* Fixed hexes, not --ink and --gold. Those two are seasonal and --ink inverts
   to near-white after dark, which is a snowman in a white hat at midnight; the
   badge is a painting and its own navy and gold do not follow the page's. */
.sm-twig{fill:none;stroke:#0B2A4A;stroke-width:0.58;stroke-linecap:round;}
.sm-scarf{fill:#F2B705;}
.sm-hat{fill:#0B2A4A;}
.sm-hat-snow{fill:#F2F8FF;}
.sm-coal{fill:#0B2A4A;}
.sm-nose{fill:#E2611C;}
.badge-shade{
  z-index:3;mix-blend-mode:multiply;
  /* 24%-46% of the artwork's height is its horizon, where sky hands over to land */
  background:linear-gradient(180deg,
    var(--dt-scene-sky,#FFFFFF) 24%, var(--dt-scene-land,#FFFFFF) 46%);
  opacity:var(--dt-scene-shade,0);
  visibility:var(--dt-scene-shade-vis,hidden);
  transition:opacity 6s ease, visibility 6s ease, background 8s ease;
}
/* Cloud takes the colour out of a scene before it takes the light. A flat neutral
   grey blended in `saturation` hands the artwork underneath its own hue and
   luminosity back but with this layer's saturation -- none -- so the opacity is
   literally "how overcast is it": a solid grey Wakefield afternoon reads as the
   same painting with the colour drained out of it, without touching brightness. */
.badge-dull{
  z-index:4;mix-blend-mode:saturation;
  background:#808080;
  opacity:var(--dt-scene-dull,0);
  visibility:var(--dt-scene-dull-vis,hidden);
  transition:opacity 6s ease, visibility 6s ease;
}
/* The milky sheet that rain, fog and snow hang in front of a landscape: screened
   in, so it lifts the artwork's darks and flattens its contrast rather than
   simply greying it over. Fog drives this hardest, snow lifts it slightly. */
.badge-veil{
  z-index:5;mix-blend-mode:screen;
  background:var(--dt-scene-veil,#FFFFFF);
  opacity:var(--dt-scene-veil-op,0);
  visibility:var(--dt-scene-veil-op-vis,hidden);
  transition:opacity 6s ease, visibility 6s ease, background 8s ease;
}
/* Stars in the badge's own sky, once its scene is dark enough to hold them. Three
   layers rather than one so they twinkle out of step with each other, each with its
   own brightness range as in the hero's sky above. Each dot carries a soft halo
   under it, which is what turns a 1px point into something that glints.
   Deliberately the last thing painted over the scene apart from the mast's lamps:
   above the shade, the cloud-dulling, the haze and the horizon glow, so no weather
   layer and no sun layer can wash them out. They are screened in and their own
   opacity no longer scales with cloud cover, so a star is either out or it is not.
   What does hide one is a painted cloud in front of it: the artwork's four clouds
   are faded in and out with the cover (see .badge-clear), and a star shining
   through the middle of one gave the game away. So the layer is masked to the sky
   between the clouds as well as to the scene (see the mask below). */
/* Out of the stack until the badge's sky is dark enough to hold stars, as with the
   sky's own stars above: one screen-blended layer fewer for the whole of the day. */
.badge-stars{
  z-index:7;mix-blend-mode:screen;
  opacity:var(--dt-badge-stars,0);
  visibility:var(--dt-badge-stars-vis,hidden);
  /* A local copy of --dt-clear-sky, registered below so it can take the same 12s
     fade as .badge-clear: the clouds thin out over the stars at the pace they
     thin out over the sky, rather than the stars blinking on ahead of them. */
  --stars-clear:var(--dt-clear-sky,0);
  transition:opacity 6s ease, visibility 6s ease, --stars-clear 12s ease;
}
@property --stars-clear{syntax:'<number>';inherits:false;initial-value:0;}
/* Stars go where the painted clouds are not. logo-sky-clear.png is transparent
   everywhere but over the clouds, so its alpha is the clouds' own silhouette,
   antialiased rim and all. Read bottom-up, the stack is: a solid layer, with that
   silhouette cut out of it (exclude) -- the sky between the clouds; a flat layer at
   --stars-clear laid over it (add) -- the share of the clouds .badge-clear has
   painted out, so a cloudless night has stars across the whole sky and a cloudy one
   has them only in the gaps; and the scene mask over the lot (intersect), which is
   what keeps them off the rose and the keyline as it does for every other layer.
   A browser without mask-composite ignores the declaration and keeps the scene
   mask on its own: stars as they were, never a sky without any. */
@supports ((mask-composite:exclude) or (-webkit-mask-composite:xor)){
  .badge-stars{
    -webkit-mask-image:url("/assets/logo-scene-mask.png"),
      linear-gradient(rgb(0 0 0 / var(--stars-clear)), rgb(0 0 0 / var(--stars-clear))),
      url("/assets/logo-sky-clear.png"), linear-gradient(#000, #000);
            mask-image:url("/assets/logo-scene-mask.png"),
      linear-gradient(rgb(0 0 0 / var(--stars-clear)), rgb(0 0 0 / var(--stars-clear))),
      url("/assets/logo-sky-clear.png"), linear-gradient(#000, #000);
    -webkit-mask-composite:source-in, source-over, xor, source-over;
            mask-composite:intersect, add, exclude, add;
  }
}
.badge-stars i{
  position:absolute;inset:0;display:block;
  opacity:var(--tw-hi,1);
  /* the name is switched on at night and not before, so nothing here is animating --
     or composited -- while the layer is invisible; see the sky's stars above */
  animation:none 4.4s ease-in-out infinite;
}
body[data-daytime="night"] .badge-stars i{animation-name:badge-twinkle;}
.badge-stars i:nth-child(1){
  animation-duration:5.3s;--tw-hi:1.00;--tw-lo:0.42;
  background-image:
    radial-gradient(1px 1px at 40% 17%, #fff 100%, transparent),
    radial-gradient(0.9px 0.9px at 54% 13%, #fff 100%, transparent),
    radial-gradient(1px 1px at 66% 19%, #fff 100%, transparent),
    radial-gradient(3.4px 3.4px at 40% 17%, rgba(255,255,255,0.42) 0%, rgba(255,255,255,0) 100%),
    radial-gradient(3.1px 3.1px at 54% 13%, rgba(255,255,255,0.42) 0%, rgba(255,255,255,0) 100%),
    radial-gradient(3.4px 3.4px at 66% 19%, rgba(255,255,255,0.42) 0%, rgba(255,255,255,0) 100%);
}
.badge-stars i:nth-child(2){
  animation-duration:3.7s;animation-delay:-1.9s;--tw-hi:0.94;--tw-lo:0.36;
  background-image:
    radial-gradient(0.9px 0.9px at 47% 22%, #fff 100%, transparent),
    radial-gradient(1.1px 1.1px at 60% 15%, #fff 100%, transparent),
    radial-gradient(0.9px 0.9px at 69% 20%, #fff 100%, transparent),
    radial-gradient(3.1px 3.1px at 47% 22%, rgba(255,255,255,0.42) 0%, rgba(255,255,255,0) 100%),
    radial-gradient(3.7px 3.7px at 60% 15%, rgba(255,255,255,0.42) 0%, rgba(255,255,255,0) 100%),
    radial-gradient(3.1px 3.1px at 69% 20%, rgba(255,255,255,0.42) 0%, rgba(255,255,255,0) 100%);
}
.badge-stars i:nth-child(3){
  animation-duration:6.1s;animation-delay:-3.4s;--tw-hi:0.98;--tw-lo:0.48;
  background-image:
    radial-gradient(1px 1px at 45% 13%, #fff 100%, transparent),
    radial-gradient(0.9px 0.9px at 57% 25%, #fff 100%, transparent),
    radial-gradient(3.4px 3.4px at 45% 13%, rgba(255,255,255,0.42) 0%, rgba(255,255,255,0) 100%),
    radial-gradient(3.1px 3.1px at 57% 25%, rgba(255,255,255,0.42) 0%, rgba(255,255,255,0) 100%);
}
@keyframes badge-twinkle{
  0%,100%{opacity:var(--tw-hi,1);}
  50%{opacity:var(--tw-lo,0.42);}
}
.badge-glow{
  z-index:6;mix-blend-mode:screen;
  background:radial-gradient(30% 13% at var(--dt-sun-wash-left,50%) 31%,
    var(--dt-scene-glow,#FF8A3C) 0%, rgba(255,138,60,0) 100%);
  opacity:var(--dt-scene-glow-op,0);
  visibility:var(--dt-scene-glow-op-vis,hidden);
  /* as with the sky halo: pinned to the sun's azimuth, so it moves when the sun does */
  transition:opacity 6s ease, visibility 6s ease;
}
/* Emley Moor's aviation lights: one beacon on top of the gallery pod, then five
   down the shaft on alternating sides, the lowest above the base platform -- the
   layout the real mast shows at night. Percentages, so they stay on the tower at
   any rendered width.

   The lamps are their own light source rather than a wash over the scene, so the
   layer composites normally instead of screening. Screening pulled the mast's own
   tint straight through them: against the night navy a red beacon came out violet,
   and wherever fog's veil had lifted the artwork underneath, the red bleached out
   toward white. The gradients are unchanged, so the glow is the same size and
   softness -- only its outermost, near-transparent fringe still picks up the
   hour's colour, which is right for light spilling into the air around a lamp. */
.mast-lights{
  z-index:8;
  opacity:var(--dt-mast-lights,0);
  visibility:var(--dt-mast-lights-vis,hidden);
  transition:opacity 6s ease, visibility 6s ease;
  background:
    radial-gradient(1.35% 2.06% at 72.27% 6.85%, rgba(255,206,170,0.98) 0%, rgba(255,86,40,0.80) 22%, rgba(232,32,16,0.30) 58%, rgba(232,32,16,0) 100%),
    radial-gradient(1.05% 1.60% at 72.39% 11.09%, rgba(255,180,140,0.95) 0%, rgba(255,70,34,0.78) 20%, rgba(228,30,14,0.28) 56%, rgba(228,30,14,0) 100%),
    radial-gradient(1.05% 1.60% at 71.98% 14.73%, rgba(255,180,140,0.95) 0%, rgba(255,70,34,0.78) 20%, rgba(228,30,14,0.28) 56%, rgba(228,30,14,0) 100%),
    radial-gradient(1.05% 1.60% at 72.34% 18.37%, rgba(255,180,140,0.95) 0%, rgba(255,70,34,0.78) 20%, rgba(228,30,14,0.28) 56%, rgba(228,30,14,0) 100%),
    radial-gradient(1.05% 1.60% at 71.81% 22.01%, rgba(255,180,140,0.95) 0%, rgba(255,70,34,0.78) 20%, rgba(228,30,14,0.28) 56%, rgba(228,30,14,0) 100%),
    radial-gradient(1.10% 1.68% at 72.32% 25.65%, rgba(255,180,140,0.95) 0%, rgba(255,70,34,0.78) 20%, rgba(228,30,14,0.28) 56%, rgba(228,30,14,0) 100%);
}
/* The farmhouse's one window, lit from inside once it is getting dark. The pane is
   the dark rectangle on the house's gable end, x 377-383 / y 211-221 in logo.png's
   880x577, as percentages so it stays on the window at any rendered width. Above
   the shade, like the mast lights, because a lamp in a window is its own light and
   should not be dimmed into the night navy with the stone around it; the ::after is
   the soft spill of that light onto the wall and the air in front of it. */
.window-light{
  position:absolute;pointer-events:none;z-index:8;
  left:42.84%;top:36.57%;width:0.68%;height:1.73%;
  background:linear-gradient(180deg, #FFE7A6 0%, #FFC861 55%, #F29B32 100%);
  opacity:var(--dt-window-light,0);
  visibility:var(--dt-window-light-vis,hidden);
  transition:opacity 4s ease, visibility 4s ease;
}
.window-light::after{
  content:"";position:absolute;inset:-160% -360%;
  background:radial-gradient(50% 50% at 50% 50%, rgba(255,196,96,0.55) 0%, rgba(255,170,64,0.22) 40%, rgba(255,150,50,0) 100%);
}
/* ---------- WHAT IS FALLING ON IT ----------
   Everything above lights the badge's landscape; these two put the weather
   itself in front of it. Same mask as the rest of the scene, so a shower falls
   across the painted fields, the barn and the mast and stops dead at the badge's
   keyline -- nothing ever rains on the white rose or the wordmark. Last in the
   stack, above even the mast lights, because rain is the nearest thing in the
   picture: it passes in front of the lamps rather than being lit by them.

   Each sheet is one element carrying a tiled scatter of drops drawn as
   background gradients, moved by a single transform. One element per drop would
   have been the honest way to do it -- it is how the stars above are done -- but
   a sheet of rain is eighty of them, and eighty composited layers in the hero is
   not a trade worth making for a shape one pixel wide. A tile that travels
   exactly its own height per cycle lands back on the frame it started from, so
   the loop has no seam and the compositor never redraws a drop: it moves the
   sheet it rasterised once. */
.badge-precip{overflow:hidden;z-index:9;}
/* The wind's own lean. The drops fall straight down inside this box and the box
   is what rotates, so every streak still points along its own line of travel
   instead of falling sideways while pointing down. Oversized because a rotated
   rectangle leaves its corners short of the one it came from; the parent clips
   the overhang. Eased over the same 8s as the other weather colours, so a wind
   getting up is a lean rather than a jump. */
.precip-tilt{
  position:absolute;inset:-30%;
  transform:rotate(var(--dt-precip-slant,10deg));
  transition:transform 8s ease;
}
/* Each sheet hangs one tile clear above the box it fills, which is the height it
   then travels: at the end of a cycle the pattern is exactly one tile further
   down and identical to the frame it began on. --tile and --dur are the two
   numbers that make a layer near or far -- a big tile moving quickly is close to
   the viewer, a small one drifting is at the back of the shower. */
.badge-precip i, .wx-tilt i{
  position:absolute;left:0;right:0;top:calc(var(--tile,100px) * -1);bottom:0;
  display:block;background-repeat:repeat;
  /* name only, as with the stars: a sheet with nothing falling on it is not left
     animating -- and so not left composited -- through every dry day of the year */
  animation:none var(--dur,0.3s) linear infinite;
}
/* Rain, in two sheets at different depths. The ink is a cool mid-tone rather than
   white (see --dt-rain-ink, set every tick): a white streak is invisible against
   the badge's pale sky and only shows over the fields, which reads as rain that
   stops half way up the picture. */
.p-rain{color:var(--dt-rain-ink,rgba(150,182,212,0.62));visibility:var(--dt-rain-vis,hidden);
  transition:opacity 6s ease, visibility 6s ease;}
.p-rain-far{
  --tile:54px;--dur:0.2s;
  opacity:calc(var(--dt-rain,0) * 0.62);
  background-size:43px 54px;
  background-image:
    radial-gradient(0.6px 6.5px at 4px 7px, currentColor 0%, transparent 100%),
    radial-gradient(0.6px 5.5px at 15px 33px, currentColor 0%, transparent 100%),
    radial-gradient(0.6px 6px at 25px 12px, currentColor 0%, transparent 100%),
    radial-gradient(0.6px 6.5px at 34px 46px, currentColor 0%, transparent 100%),
    radial-gradient(0.6px 5.5px at 9px 50px, currentColor 0%, transparent 100%),
    radial-gradient(0.6px 6px at 39px 23px, currentColor 0%, transparent 100%),
    radial-gradient(0.6px 6.5px at 21px 40px, currentColor 0%, transparent 100%),
    radial-gradient(0.6px 5.5px at 29px 3px, currentColor 0%, transparent 100%),
    radial-gradient(0.6px 6px at 12px 19px, currentColor 0%, transparent 100%);
}
.p-rain-near{
  --tile:72px;--dur:0.15s;
  opacity:var(--dt-rain,0);
  background-size:58px 72px;
  background-image:
    radial-gradient(0.9px 11px at 6px 10px, currentColor 0%, transparent 100%),
    radial-gradient(0.9px 9px at 17px 44px, currentColor 0%, transparent 100%),
    radial-gradient(0.9px 10px at 28px 20px, currentColor 0%, transparent 100%),
    radial-gradient(0.9px 11px at 39px 58px, currentColor 0%, transparent 100%),
    radial-gradient(0.9px 9px at 50px 32px, currentColor 0%, transparent 100%),
    radial-gradient(0.9px 10px at 11px 66px, currentColor 0%, transparent 100%),
    radial-gradient(0.9px 11px at 23px 5px, currentColor 0%, transparent 100%),
    radial-gradient(0.9px 9px at 34px 38px, currentColor 0%, transparent 100%),
    radial-gradient(0.9px 10px at 45px 14px, currentColor 0%, transparent 100%),
    radial-gradient(0.9px 11px at 55px 48px, currentColor 0%, transparent 100%),
    radial-gradient(0.9px 9px at 2px 30px, currentColor 0%, transparent 100%),
    radial-gradient(0.9px 10px at 19px 26px, currentColor 0%, transparent 100%);
}
/* Hail. Hard little pellets rather than streaks, and the fastest thing in the
   scene: what says hail rather than rain is that each one is a dot you can
   follow. Drawn in the same white as snow, with a solid core and one soft pixel
   of edge so it is a pellet and not a pinprick. */
.p-hail{
  --tile:70px;--dur:0.13s;
  color:var(--dt-flake-ink,rgba(255,255,255,0.92));
  opacity:var(--dt-hail,0);visibility:var(--dt-hail-vis,hidden);
  transition:opacity 6s ease, visibility 6s ease;
  background-size:56px 70px;
  background-image:
    radial-gradient(1.6px 2px at 5px 9px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.6px 2px at 16px 36px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.4px 1.8px at 27px 15px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.6px 2px at 38px 52px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.4px 1.8px at 48px 26px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.6px 2px at 10px 60px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.4px 1.8px at 31px 66px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.6px 2px at 44px 4px, currentColor 0%, currentColor 55%, transparent 100%);
}
/* Snow. Three sheets, an order of magnitude slower than the rain, and the only
   thing here that does not fall in a straight line: --sway carries each sheet a
   few pixels one way and back over a cycle, which is what turns falling into
   drifting. The near sheet is bigger, faster and swings widest, so the shower has
   depth rather than being one flat curtain of dots. */
.p-snow{color:var(--dt-flake-ink,rgba(255,255,255,0.92));visibility:var(--dt-snow-vis,hidden);
  transition:opacity 6s ease, visibility 6s ease;}
.p-snow-far{
  --tile:70px;--dur:3.9s;--sway:4px;
  opacity:calc(var(--dt-snow,0) * 0.7);
  background-size:50px 70px;
  background-image:
    radial-gradient(1.3px 1.3px at 4px 8px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.3px 1.3px at 14px 32px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.2px 1.2px at 24px 14px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.3px 1.3px at 33px 50px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.2px 1.2px at 43px 26px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.3px 1.3px at 9px 62px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.2px 1.2px at 29px 68px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.3px 1.3px at 45px 44px, currentColor 0%, currentColor 55%, transparent 100%);
}
.p-snow-mid{
  --tile:84px;--dur:3s;--sway:7px;
  opacity:calc(var(--dt-snow,0) * 0.85);
  background-size:62px 84px;
  background-image:
    radial-gradient(1.9px 1.9px at 7px 11px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.9px 1.9px at 20px 40px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.8px 1.8px at 32px 18px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.9px 1.9px at 44px 62px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.8px 1.8px at 55px 34px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.9px 1.9px at 14px 72px, currentColor 0%, currentColor 55%, transparent 100%),
    radial-gradient(1.8px 1.8px at 38px 80px, currentColor 0%, currentColor 55%, transparent 100%);
}
.p-snow-near{
  --tile:104px;--dur:2.5s;--sway:10px;
  opacity:var(--dt-snow,0);
  background-size:78px 104px;
  background-image:
    radial-gradient(2.7px 2.7px at 9px 14px, currentColor 0%, currentColor 52%, transparent 100%),
    radial-gradient(2.6px 2.6px at 26px 50px, currentColor 0%, currentColor 52%, transparent 100%),
    radial-gradient(2.7px 2.7px at 41px 22px, currentColor 0%, currentColor 52%, transparent 100%),
    radial-gradient(2.6px 2.6px at 58px 80px, currentColor 0%, currentColor 52%, transparent 100%),
    radial-gradient(2.7px 2.7px at 70px 44px, currentColor 0%, currentColor 52%, transparent 100%),
    radial-gradient(2.6px 2.6px at 18px 92px, currentColor 0%, currentColor 52%, transparent 100%);
}
/* One cycle is one tile down, which is what makes the loop seamless; the sheets
   share these two rules and each brings its own tile height, so a fast near
   shower and a slow far one are two custom properties apart. */
@keyframes badge-rainfall{
  to{transform:translate3d(0,var(--tile,100px),0);}
}
@keyframes badge-snowfall{
  25%{transform:translate3d(var(--sway,6px),calc(var(--tile,120px) * 0.25),0);}
  50%{transform:translate3d(0,calc(var(--tile,120px) * 0.5),0);}
  75%{transform:translate3d(calc(var(--sway,6px) * -1),calc(var(--tile,120px) * 0.75),0);}
  to{transform:translate3d(0,var(--tile,120px),0);}
}
/* Which sheets are running is the weather's decision, and it is made here rather
   than by fading a layer that keeps animating behind it: an invisible sheet still
   holds a composited layer and a backing store, and there are six of them.
   Drizzle, rain, sleet, a thunderstorm and a hailstorm all have rain in them --
   hail arrives with the shower it is part of, not on its own. */
body[data-precip="drizzle"] .p-rain,
body[data-precip="rain"] .p-rain,
body[data-precip="sleet"] .p-rain,
body[data-precip="hail"] .p-rain,
body[data-precip="storm"] .p-rain{animation-name:badge-rainfall;}
body[data-precip="hail"] .p-hail{animation-name:badge-rainfall;}
body[data-precip="snow"] .p-snow,
body[data-precip="sleet"] .p-snow{animation-name:badge-snowfall;}
/* Lightning. Not a state the clock can drive like everything else in the scene
   but a discrete event, so the strike is started from script (see the storm watch
   in the theming engine) and this is only what one looks like: a sheet of light
   screened over the whole landscape from a source up in the cloud, doubling and
   guttering the way a real strike does rather than a single clean flash. Above
   the rain, because the rain is lit by it too. */
.badge-flash{
  z-index:10;mix-blend-mode:screen;opacity:0;
  background:
    radial-gradient(42% 30% at 50% 12%, rgba(232,244,255,0.92) 0%, rgba(186,214,250,0.34) 46%, rgba(150,186,240,0) 100%),
    linear-gradient(180deg, rgba(206,228,255,0.42) 0%, rgba(170,200,240,0.10) 44%, rgba(150,186,235,0) 76%);
}
.badge-flash.strike{animation:badge-strike 1.05s linear 1;}
@keyframes badge-strike{
  0%{opacity:0;}
  3%{opacity:0.92;}
  9%{opacity:0.16;}
  13%{opacity:0.78;}
  22%{opacity:0.08;}
  26%{opacity:0.42;}
  46%{opacity:0.03;}
  100%{opacity:0;}
}
@media (prefers-reduced-motion: reduce){
  .sky-sun{transition:opacity 2s ease;}
  .sky-moon{transition:opacity 2s ease, visibility 2s ease;}
  body, header, .card, .testi, footer, .cta-band, .form-card, .map-frame,
  .town-chip, .weather-now, .hero-art, .trust, .heat-stat, .heat-chart, .faq-item,
  input, textarea, .sky-scene, .sky-scene::before, .sky-stars,
  .sky-cloud, .sky-cloud .cl-body, .sky-cloud .cl-shade, .sky-cloud .cl-shade-deep,
  .badge-shade, .badge-dull, .badge-veil, .badge-glow, .badge-stars,
  .badge-settle, .badge-clear, .mast-lights, .window-light, .precip-tilt, .badge-precip i,
  .wx-scene, .wx-tilt, .wx-tilt i{transition:none;}
  /* stars still show at night, they just hold still. Listed with the night selector
     as well, because that is what switches the animation name on. */
  .sky-stars i, .badge-stars i,
  body[data-daytime="night"] .sky-stars i,
  body[data-daytime="night"] .badge-stars i{animation-name:none;opacity:0.85;}
  /* Same for the weather: it is still raining, and the badge still says so --
     the drops simply hang where they are. Lightning is the one effect that
     goes altogether, because a strobe over the artwork is exactly what this
     setting is asking us not to do (the storm watch never books one either). */
  body[data-precip] .badge-precip i,
  body[data-precip] .wx-tilt i{animation-name:none;}
  .badge-flash, .wx-flash{display:none;}
  /* and the feed's own pulse, which is decoration rather than information: the
     word LIVE is doing the work whether the dot beats or not */
  .wx-beat{animation-name:none;}
  /* The airflow still says which job the day needs doing -- the ribbon is warm
     or cold and the heat waves hold their place -- it simply says it as a
     picture. setFlow never sets the motion attribute for this setting, so these
     are belt and braces; they carry [data-flow] as well only to match the
     specificity of the per-mood rules that switch the names on. */
  body[data-flow-motion][data-flow] .flow-mote,
  body[data-flow-motion][data-flow] .flow-speck,
  body[data-flow-motion][data-flow] .flow-curl,
  body[data-flow-motion][data-flow] .flow-ember{animation-name:none;}
  body[data-flow-motion][data-flow] .flow-streams .flow-stream,
  body[data-flow-motion][data-flow] .flow-streams .flow-gust{animation-name:none;}
  .badge-cool, .badge-warm, .flow-cool, .flow-heat{transition:none;}
}

