.weather-section {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0;
  padding: 1rem;
  color: rgb(var(--ink-rgb));
  font-family: MinionPro-Regular, Garamond, Georgia, serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

#weather-widget {
  opacity: 0;
  transition: opacity 0.5s ease-in-out;
}

#weather-widget.visible { opacity: 1; }

/* ── While the weather is on its way ───────────────────────────────────────
   A ring turning where the card will be, and nothing said: the space used to
   hold "Loading..." at opacity nought, which is to say nothing at all for as
   long as the API took. Laid over the section rather than in the flow, so it
   never takes a place beside the card and nothing moves when the card lands;
   it takes no clicks, since the card's link arrives underneath it. Faded as
   the card fades in, and paused rather than stopped so the ring does not
   jump on its way out. Shown once: a later refresh has weather on screen
   already and nothing to stand in for. */
.weather-loading {
  position: absolute;
  inset: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  pointer-events: none;
  /* Nothing until weather.js says the answer is taking a while: a ring that
     appears and is gone inside the time the API usually takes is a flash in
     front of the card, not a wait being shown */
  opacity: 0;
  transition: opacity 0.3s ease;
}

.weather-loading.is-waiting { opacity: 1; }
.weather-loading.is-done { opacity: 0; }

.weather-spinner {
  display: block;
  width: 26px;
  height: 26px;
  border: 2px solid rgba(var(--ink-rgb), 0.22);
  border-top-color: rgba(var(--ink-rgb), 0.85);
  border-radius: 50%;
  animation: weatherSpin 800ms linear infinite;
}

.weather-loading.is-done .weather-spinner { animation-play-state: paused; }

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

/* ── Through to the forecast ────────────────────────────────────────────────
   The card leads to the news and weather page, on its weather tab, without
   looking like it does: no underline, no colour, nothing but the pointer. It
   sits over the wrap rather than around it because the warning bar inside is a
   button, and a button can't live in an anchor. The bar lifts itself back above
   this (z-index on .weather-summary--warn) so it keeps its own job, leaving
   only the quiet parts of the card leading to the page. */
.weather-link {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: 10px;
  cursor: pointer;
}

/* Invisible until reached by keyboard, where it has to trace what it covers */
.weather-link:focus-visible {
  outline: 2px solid rgba(var(--ink-rgb), 0.75);
  outline-offset: 6px;
}

/* Nothing to click while the card is still fading in, or after it has failed
   and is waiting to be emptied */
#weather-widget:not(.visible) .weather-link { pointer-events: none; }

.weather-wrap {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  color: rgb(var(--ink-rgb));
  text-shadow: 2px 2px 6px rgba(var(--shade-rgb), 0.45);
}

/* ── Current conditions ─────────────────────────────────────────────────────
   Location, condition, temperature, feels-like and the readings row are a
   straight port of the control page's environmental card (.ctrl-temp-outdoor),
   sizes and colours included, so the two stacks read identically. */

.weather-current {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  /* No bottom padding: the summary's own top padding stands in for it, so the
     readings-to-summary gap matches the 7px between feels-like and readings */
  padding: 0.4rem 0 0;
}

.weather-location {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 0.65rem;
  color: rgba(var(--ink-rgb), 0.68);
  display: flex;
  align-items: center;
  gap: 4px;
  letter-spacing: 0.02em;
}

.weather-condition {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 0.92rem;
  color: rgb(var(--ink-rgb));
}

.weather-temp {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 2.6rem;
  font-weight: 300;
  color: rgb(var(--ink-rgb));
  letter-spacing: -0.03em;
  line-height: 1;
}

.weather-feels {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 0.78rem;
  color: rgba(var(--ink-rgb), 0.38);
  margin-top: -4px;
}

/* A flood alert or warning on the Thame here (KILN-77), a quiet line under
   the conditions, in the site's status colours: the Met Office's belong to
   the Met Office's warnings */
/* A span, not a paragraph: the hero sizes its paragraphs as lede text */
.weather-flood {
  display: block;
  margin: 0.5rem 0 0;
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
  color: rgb(var(--status-early-rgb));
}
.weather-flood--warning,
.weather-flood--severe { color: rgb(var(--status-late-rgb)); }
/* A power cut in or near the village (KILN-80): an alert bar under the
   summary, set like the Met Office's but standing still (owner, 29 Sep
   2026: the sweep is the Met Office's alone), and with no one's name over
   it, since the alert says it all. Tinted in late's colour for a fault and
   early's for planned work, with a warning triangle. A button that opens
   the details, so it sits above the link covering the card, as the warning
   bar does. */
.weather-power {
  --power-rgb: var(--status-late-rgb);
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  width: fit-content;
  max-width: min(560px, 88vw);
  min-width: min(16rem, 88vw);
  min-height: 2.6rem;
  margin: 0.5rem auto 0;
  padding: 0.3rem 0.9rem;
  border: 1px solid rgba(var(--power-rgb), 0.55);
  border-radius: 8px;
  background: rgba(var(--power-rgb), 0.16);
  color: rgb(var(--power-rgb));
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 0.8rem;
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color 0.2s ease;
}
.weather-power--planned { --power-rgb: var(--status-early-rgb); }
.weather-power:hover { background: rgba(var(--power-rgb), 0.24); }
.weather-power:focus-visible { outline: 2px solid rgb(var(--power-rgb)); outline-offset: 3px; }
.weather-power-icon { flex: none; width: 1.35rem; height: 1.35rem; }
.weather-power-main { text-wrap: balance; text-align: center; }

/* The power cut dialog borrows the warning popup, headed in its colours */
.weather-warn-header--power-unplanned { background: rgba(var(--status-late-rgb), 0.12); border-bottom-color: rgb(var(--status-late-rgb)); }
.weather-warn-header--power-planned { background: rgba(var(--status-early-rgb), 0.12); border-bottom-color: rgb(var(--status-early-rgb)); }
.weather-warn-header--power-unplanned .weather-warn-title { color: rgb(var(--status-late-rgb)); }
.weather-warn-header--power-planned .weather-warn-title { color: rgb(var(--status-early-rgb)); }

.weather-extra {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 2px;
}

.weather-extra-item {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 0.72rem;
  color: rgba(var(--ink-rgb), 0.42);
}

.weather-summary {
  position: relative;
  overflow: hidden;
  /* Matches .weather-extra's own top margin — with the padding below the
     readings row removed, the two gaps land within a fraction of a pixel */
  margin-top: 2px;
  /* An explicit width, not max-width: every ancestor up to .weather-section is a
     shrink-to-fit flex box, so without one the summary collapses onto its
     min-width floor and text-wrap: balance evens out three cramped lines */
  width: min(560px, 88vw);
  padding: 0.3rem 0.6rem;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: rgb(var(--ink-rgb));
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 0.85rem;
  line-height: 1.35;
  text-align: center;
  opacity: 0.85;
  text-shadow: 2px 2px 6px rgba(var(--shade-rgb), 0.45);
}

/* Even line lengths rather than a full line with a couple of orphans below */
.weather-summary-text {
  display: inline-block;
  text-wrap: balance;
}

/* ── Met Office warning sweep (NSWWS severity palette) ──────────────────── */

/* The bar is pulled in to the summary's longest rendered line by
   fitSummaryWidth(), which also floors it at the warning wording's own width.
   The min-width keeps a short summary from pinning the bar to a stub. */
.weather-summary--warn {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: min(16rem, 88vw);
  min-height: 2.6rem;
  opacity: 1;
  cursor: pointer;
  /* Above .weather-link, so the bar opens the warning rather than the page */
  z-index: 2;
}

.weather-summary--warn:focus-visible {
  outline: 2px solid rgba(var(--ink-rgb), 0.75);
  outline-offset: 3px;
}

/* Pace comes from the most severe warning; colour comes from whichever warning
   the sweep is currently showing, so rotating one can't restart the animation */
.weather-summary--yellow { --warn-cycle: 18s; }
.weather-summary--amber  { --warn-cycle: 14s; }
.weather-summary--red    { --warn-cycle: 10s; }

.weather-warning-sweep--yellow { --warn-colour: rgb(var(--nswws-yellow-rgb)); --warn-ink: rgb(var(--nswws-yellow-ink-rgb)); }
.weather-warning-sweep--amber  { --warn-colour: rgb(var(--nswws-amber-rgb)); --warn-ink: rgb(var(--nswws-amber-ink-rgb)); }
.weather-warning-sweep--red    { --warn-colour: rgb(var(--nswws-red-rgb)); --warn-ink: rgb(var(--nswws-red-ink-rgb)); }

/* Periodic attention wipe: the coloured bar sweeps across the summary,
   revealing the warning name, then wipes off to the right */
.weather-warning-sweep {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.1rem;
  padding: 0.2rem 0.6rem;
  border-radius: 8px;
  background: var(--warn-colour);
  color: var(--warn-ink);
  font-weight: 800;
  font-size: 0.8rem;
  line-height: 1.2;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-shadow: none;
  pointer-events: none;
  clip-path: inset(0 100% 0 0);
  animation: weatherWarnSweep var(--warn-cycle, 14s) ease-in-out infinite;
}

.weather-warning-sweep-eyebrow {
  font-size: 0.62em;
  font-weight: 700;
  letter-spacing: 0.22em;
  opacity: 0.7;
}

/* One phrase on the second line, wrapping evenly if it has to */
.weather-warning-sweep-main {
  text-wrap: balance;
}

/* In from the left, hold, then back out the way it came */
@keyframes weatherWarnSweep {
  0%, 6%    { clip-path: inset(0 100% 0 0); }
  14%, 34%  { clip-path: inset(0 0 0 0); }
  42%, 100% { clip-path: inset(0 100% 0 0); }
}

@media (prefers-reduced-motion: reduce) {
  .weather-warning-sweep { animation: none; }
  /* Still a ring, still saying "on its way", but breathing rather than turning */
  .weather-spinner {
    border-top-color: rgba(var(--ink-rgb), 0.22);
    animation: weatherBreathe 1.6s ease-in-out infinite;
  }
}

@keyframes weatherBreathe {
  0%, 100% { opacity: 0.45; }
  50% { opacity: 1; }
}

/* ── Weather warning popup ──────────────────────────────────────────────── */

/* Above #localFooter (z-index 1000), which is fixed and takes pointer events —
   below it, the popup's footer link was unreachable on mobile */
.weather-warn-overlay {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: rgba(var(--shade-rgb), 0.45);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
  padding-bottom: max(24px, env(safe-area-inset-bottom));
}

.weather-warn-overlay.is-open { display: flex; }

.weather-warn-popup {
  width: 100%;
  max-width: 460px;
  max-height: 78vh;
  /* dvh accounts for mobile browser chrome, which vh alone overshoots */
  max-height: 78dvh;
  overflow: hidden;
  background:
    radial-gradient(circle at top left, rgba(var(--ink-rgb), 0.1), transparent 14rem),
    rgba(var(--weather-deep-rgb), 0.92);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: 1px solid rgba(var(--ink-rgb), 0.18);
  border-radius: 1.1rem;
  box-shadow: 0 1px 0 rgba(var(--ink-rgb), 0.06), 0 24px 60px rgba(var(--shade-rgb), 0.5);
  display: flex;
  flex-direction: column;
  color: rgb(var(--ink-rgb));
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  text-align: left;
}

/* Header states severity and weather type in the warning's own colour */
.weather-warn-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-shrink: 0;
  padding: 1.2rem 1.2rem 1rem;
  background: rgba(var(--ink-rgb), 0.05);
  border-bottom: 2px solid rgba(var(--ink-rgb), 0.08);
}

.weather-warn-header--yellow { background: rgba(var(--nswws-yellow-rgb), 0.10); border-bottom-color: rgb(var(--nswws-yellow-rgb)); }
.weather-warn-header--amber  { background: rgba(var(--nswws-amber-rgb), 0.12);  border-bottom-color: rgb(var(--nswws-amber-rgb)); }
.weather-warn-header--red    { background: rgba(var(--nswws-red-rgb), 0.16);  border-bottom-color: rgb(var(--nswws-red-rgb)); }

.weather-warn-title {
  font-size: 0.66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  line-height: 1.4;
  color: rgba(var(--ink-rgb), 0.7);
}

.weather-warn-header--yellow .weather-warn-title { color: rgb(var(--nswws-yellow-rgb)); }
.weather-warn-header--amber  .weather-warn-title { color: rgb(var(--nswws-amber-rgb)); }
.weather-warn-header--red    .weather-warn-title { color: rgb(var(--nswws-red-rgb)); }

/* Light (KILN-76). The popup is the nav menu's glass (base.css .site-nav)
   over a scrim that only softens the page, where a near-white slab over a
   grey scrim stood apart from the rest of the site. The warning's title is
   ink on yellow and amber, whose lettering can't be read on a light page, as
   the guide sets black on those two; the tinted header and its solid rule
   carry the colour, which is fixed and unchanged. Red lettering reads. */
:root[data-theme="light"] .weather-warn-overlay {
  background: rgba(var(--shade-rgb), 0.16);
}

:root[data-theme="light"] .weather-warn-popup {
  background:
    linear-gradient(180deg, rgba(var(--ink-rgb), 0.1), rgba(var(--ink-rgb), 0.02) 40%),
    rgba(var(--page-raised-rgb), 0.5);
  border-color: rgba(var(--ink-rgb), 0.16);
  box-shadow:
    inset 0 1px 0 rgba(var(--ink-rgb), 0.14),
    0 24px 60px rgba(var(--shade-rgb), 0.2);
  backdrop-filter: blur(28px) saturate(150%);
  -webkit-backdrop-filter: blur(28px) saturate(150%);
}

:root[data-theme="light"] .weather-warn-footer {
  background: transparent;
}

:root[data-theme="light"] .weather-warn-header--yellow .weather-warn-title,
:root[data-theme="light"] .weather-warn-header--amber .weather-warn-title {
  color: rgb(var(--ink-rgb));
}

.weather-warn-close {
  appearance: none;
  -webkit-appearance: none;
  background: none;
  border: none;
  padding: 0 4px;
  color: rgba(var(--ink-rgb), 0.55);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  transition: color 0.15s;
}

.weather-warn-close:hover { color: rgb(var(--ink-rgb)); }

.weather-warn-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 1.1rem 1.2rem 1.3rem;
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

.weather-warn-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.4rem;
}

.weather-warn-meta-item {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 0.82rem;
  color: rgba(var(--ink-rgb), 0.85);
}

.weather-warn-meta-item b {
  font-size: 0.55rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: rgba(var(--ink-rgb), 0.45);
}

.weather-warn-headline {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.5;
  font-weight: 600;
  color: rgb(var(--ink-rgb));
}

.weather-warn-section {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}

.weather-warn-section-label {
  margin: 0;
  font-size: 0.55rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: rgba(var(--ink-rgb), 0.45);
}

.weather-warn-section p {
  margin: 0;
  font-size: 0.82rem;
  line-height: 1.65;
  color: rgba(var(--ink-rgb), 0.72);
}

.weather-warn-section p + p { margin-top: 0.5rem; }

.weather-warn-advice { font-style: italic; }
.weather-warn-advice a { color: rgb(var(--link-blue-rgb)); }

/* Affected areas */
.weather-warn-region + .weather-warn-region { margin-top: 0.7rem; }

.weather-warn-region-name {
  display: block;
  margin-bottom: 0.35rem;
  font-size: 0.72rem;
  font-weight: 600;
  color: rgba(var(--ink-rgb), 0.85);
}

.weather-warn-areas { display: flex; flex-wrap: wrap; gap: 4px; }

.weather-warn-area {
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(var(--ink-rgb), 0.06);
  border: 1px solid rgba(var(--ink-rgb), 0.08);
  font-size: 0.68rem;
  color: rgba(var(--ink-rgb), 0.65);
}

.weather-warn-area.is-home {
  background: rgba(var(--ink-rgb), 0.16);
  border-color: rgba(var(--ink-rgb), 0.35);
  color: rgb(var(--ink-rgb));
  font-weight: 600;
}

/* Impact / likelihood matrix — palette fixed by the NSWWS style guide v1.4,
   §2.1.2: the three warning colours, and the guide's green where the
   combination raises no warning. The axes carry one word and an arrow each,
   as the guide's diagram does. */
.weather-warn-matrix {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 6px 8px;
  align-items: center;
  max-width: 260px;
}

.weather-warn-matrix-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 3px;
}

.weather-warn-matrix-cell {
  aspect-ratio: 1;
  border-radius: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.7rem;
  font-weight: 800;
  color: rgb(var(--shade-rgb));
}

.weather-warn-matrix-cell--none   { background: rgb(var(--nswws-green-rgb)); }
.weather-warn-matrix-cell--yellow { background: rgb(var(--nswws-yellow-rgb)); }
.weather-warn-matrix-cell--amber  { background: rgb(var(--nswws-amber-rgb)); }
.weather-warn-matrix-cell--red    { background: rgb(var(--nswws-red-rgb)); color: rgb(var(--nswws-red-ink-rgb)); }

.weather-warn-matrix-cell.is-current { box-shadow: inset 0 0 0 2px rgba(var(--shade-rgb), 0.75); }
.weather-warn-matrix-cell--red.is-current { box-shadow: inset 0 0 0 2px rgb(var(--nswws-red-ink-rgb)); }

.weather-warn-matrix-ylabel,
.weather-warn-matrix-xlabel {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 0.5rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: rgba(var(--ink-rgb), 0.45);
}

/* Read bottom to top up the side, the arrow leading, as the guide draws it */
.weather-warn-matrix-ylabel {
  align-self: stretch;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
}

.weather-warn-matrix-xlabel { grid-column: 2; }

.weather-warn-matrix-axis {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.weather-warn-matrix-arrow {
  flex-shrink: 0;
  color: rgba(var(--ink-rgb), 0.55);
}

/* The arrow is drawn upright and the label is the thing turned, so it keeps
   its up-pointing shape rather than being rotated into pointing down */
.weather-warn-matrix-ylabel .weather-warn-matrix-arrow { transform: rotate(180deg); }

/* Footer: attribution left, Met Office link right */
.weather-warn-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
  padding: 0.8rem 1.2rem;
  background: rgba(var(--ink-rgb), 0.05);
  border-top: 1px solid rgba(var(--ink-rgb), 0.08);
}

.weather-warn-attribution {
  font-size: 0.55rem;
  line-height: 1.4;
  color: rgba(var(--ink-rgb), 0.45);
}

.weather-warn-more {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex-shrink: 0;
  font-size: 0.68rem;
  font-weight: 600;
  text-decoration: none;
  color: rgb(var(--link-blue-rgb));
}

@media (max-width: 520px) {
  /* The current-conditions stack keeps the control page's sizes at every
     width — it's already a phone-first layout there */
  .weather-extra { max-width: 90vw; }
  .weather-summary { font-size: 0.78rem; }
  .weather-warning-sweep { font-size: 0.72rem; }
  .weather-power { font-size: 0.72rem; }
  .weather-warn-popup {
    max-height: 84vh;
    max-height: 84dvh;
  }
  /* Tap targets sit clear of the fixed footer pill's usual resting place */
  .weather-warn-footer { padding: 0.9rem 1.2rem; }
  .weather-warn-more { padding: 6px 2px; }
}
