:root {
  --void: #080613;
  --observatory-ink: #130c23;
  --deep-aubergine: #24123f;
  --sky-violet: #4e2393;
  --electric-lilac: #bd79ff;
  --moon-cream: #fff2ce;
  --weather-white: #fbf7ff;
  --muted-lilac: #d2c1e2;
  --forecast-amber: #f6b84c;
  --forecast-pink: #ff74df;
  --forecast-blue: #8ec9ff;
  --fresh: #d7f0ba;
  --danger: #ffb5ae;
  --hairline: rgba(244, 222, 255, 0.3);
  --solar-transition: 0;
  --solar-progress: 0;
  --solar-brightness: 1;
  --solar-saturate: 1;
  --solar-contrast: 1;
  --solar-horizon-opacity: 0;
  --solar-reflection-opacity: 0;
  --solar-weather-cast: 0;
  --fog-opacity: 0;
  --fog-rest-opacity: 0;
  --lightning-peak: 0;
  --lightning-rest: 0;
  --lightning-echo: 0;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --layer-station: 30;
}

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
  margin: 0;
  background: var(--void);
  color: var(--weather-white);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

body {
  min-width: 20rem;
}

a {
  color: inherit;
}

button,
a {
  -webkit-tap-highlight-color: transparent;
}

button {
  font: inherit;
}

.skip-link {
  position: absolute;
  top: -6rem;
  left: 1rem;
  z-index: 50;
  padding: 0.75rem 1rem;
  border-radius: 0.4rem;
  background: var(--moon-cream);
  color: var(--observatory-ink);
}

.skip-link:focus {
  top: 1rem;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.observatory {
  position: relative;
  height: 100%;
  min-height: 34rem;
  overflow: hidden;
  background: var(--observatory-ink);
  isolation: isolate;
}

.environment,
.environment-plate,
.scene-transition-plate,
.scene-handoff,
.sky-color,
.window-glow,
.weather-canvas,
.fog-bank,
.horizon-weather,
.wet-reflections,
.snow-settle,
.lightning,
.cloud-bank {
  position: absolute;
  inset: 0;
}

.environment {
  z-index: -5;
  overflow: hidden;
  background: var(--deep-aubergine);
}

.environment-plate {
  background-image: url("/assets/scenes/v08/observatory-visor-twilight.jpg");
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  transform: scale(1.018);
  transform-origin: center;
  transition: filter 900ms var(--ease-out);
  will-change: auto;
}

/* A live condition or solar-phase change replaces one finished composition
   with another. The old plate cuts at the peak of a full-window weather beat,
   so the anchored Bear or GUGO characters never blend, hover, or ghost. */
.scene-transition-plate {
  z-index: 1;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  transform: scale(1.018);
  transform-origin: center;
  opacity: 0;
  pointer-events: none;
  will-change: opacity;
}

.scene-transition-plate[data-active="true"] {
  opacity: 1;
}

.observatory[data-scene-handoff-direction="left-to-right"] .scene-transition-plate[data-active="true"] {
  animation: scene-plate-release-left 1800ms linear 1 both;
}

.observatory[data-scene-handoff-direction="right-to-left"] .scene-transition-plate[data-active="true"] {
  animation: scene-plate-release-right 1800ms linear 1 both;
}

@media (prefers-reduced-motion: reduce) {
  .scene-transition-plate {
    animation: none !important;
  }
}

.scene-handoff {
  z-index: 8;
  inset: 0;
  width: auto;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
  will-change: opacity;
}

.scene-handoff-body,
.scene-handoff-edge {
  position: absolute;
  pointer-events: none;
}

.scene-handoff-body {
  inset: -8%;
  will-change: transform;
}

.scene-handoff-edge {
  inset: 0;
  width: auto;
  opacity: 0;
}

.scene-handoff[data-family="light"] .scene-handoff-body {
  background:
    radial-gradient(ellipse at 58% 50%, rgba(255, 218, 154, 0.36), transparent 32%),
    radial-gradient(ellipse at 42% 44%, rgba(218, 135, 255, 0.2), transparent 54%);
}

.scene-handoff[data-family="light"] .scene-handoff-edge {
  background: radial-gradient(ellipse at center, rgba(255, 247, 218, 0.44), rgba(255, 220, 166, 0.12) 54%, transparent 82%);
  mix-blend-mode: screen;
}

.scene-handoff[data-family="cloud"] .scene-handoff-body {
  background:
    radial-gradient(ellipse at 64% 25%, rgba(211, 193, 229, 0.34) 0 12%, transparent 34%),
    radial-gradient(ellipse at 50% 50%, rgba(114, 91, 145, 0.34) 0 23%, transparent 68%),
    radial-gradient(ellipse at 68% 78%, rgba(77, 61, 105, 0.3) 0 16%, transparent 42%);
}

.scene-handoff[data-family="cloud"] .scene-handoff-edge {
  background: linear-gradient(rgba(96, 72, 128, 0.26), rgba(67, 52, 92, 0.34));
}

.scene-handoff[data-family="fog"] .scene-handoff-body {
  background:
    radial-gradient(ellipse at 62% 28%, rgba(239, 232, 246, 0.38), transparent 42%),
    radial-gradient(ellipse at 48% 54%, rgba(190, 179, 207, 0.3) 0 24%, transparent 70%),
    radial-gradient(ellipse at 64% 78%, rgba(244, 238, 248, 0.3), transparent 48%);
}

.scene-handoff[data-family="fog"] .scene-handoff-edge {
  background: linear-gradient(90deg, rgba(235, 229, 242, 0.22), rgba(211, 197, 225, 0.42), rgba(235, 229, 242, 0.22));
}

.scene-handoff[data-family="rain"] .scene-handoff-body {
  background:
    repeating-linear-gradient(104deg, transparent 0 0.9rem, rgba(205, 229, 249, 0.58) 0.96rem 1.04rem, transparent 1.1rem 2.15rem),
    radial-gradient(ellipse at 52% 50%, rgba(42, 63, 84, 0.28), transparent 68%);
}

.scene-handoff[data-family="rain"] .scene-handoff-edge {
  background: linear-gradient(rgba(32, 51, 70, 0.34), rgba(53, 75, 94, 0.42));
}

.scene-handoff[data-family="snow"] .scene-handoff-body {
  background:
    radial-gradient(circle, rgba(255, 255, 255, 0.9) 0 0.15rem, transparent 0.22rem) 0 0 / 3.8rem 4.6rem,
    radial-gradient(circle, rgba(224, 238, 255, 0.82) 0 0.24rem, transparent 0.32rem) 1.7rem 2.1rem / 5.8rem 6.4rem,
    radial-gradient(ellipse at 50% 50%, rgba(225, 237, 249, 0.26), transparent 72%);
}

.scene-handoff[data-family="snow"] .scene-handoff-edge {
  background: linear-gradient(rgba(236, 244, 252, 0.42), rgba(207, 225, 241, 0.32));
  mix-blend-mode: screen;
}

.scene-handoff[data-family="storm"] .scene-handoff-body {
  background:
    repeating-linear-gradient(104deg, transparent 0 1rem, rgba(188, 177, 222, 0.24) 1.06rem 1.11rem, transparent 1.17rem 2.2rem),
    radial-gradient(ellipse at 56% 12%, rgba(94, 65, 130, 0.4) 0 13%, transparent 46%),
    radial-gradient(ellipse at 48% 48%, rgba(16, 13, 34, 0.3) 0 23%, transparent 72%);
}

.scene-handoff[data-family="storm"] .scene-handoff-edge {
  background: linear-gradient(rgba(235, 220, 255, 0.62), rgba(151, 113, 213, 0.3));
  mix-blend-mode: screen;
}

.scene-handoff[data-active="true"][data-direction="left-to-right"] {
  animation: scene-handoff-left-to-right 1800ms cubic-bezier(0.45, 0, 0.2, 1) 1 both;
}

.scene-handoff[data-active="true"][data-direction="right-to-left"] {
  animation: scene-handoff-right-to-left 1800ms cubic-bezier(0.45, 0, 0.2, 1) 1 both;
}

.scene-handoff[data-active="true"] .scene-handoff-edge {
  animation: scene-handoff-cut-veil 1800ms ease-in-out 1 both;
}

.scene-handoff[data-active="true"][data-direction="left-to-right"] .scene-handoff-body {
  animation: scene-weather-drift-left-to-right 1800ms ease-out 1 both;
}

.scene-handoff[data-active="true"][data-direction="right-to-left"] .scene-handoff-body {
  animation: scene-weather-drift-right-to-left 1800ms ease-out 1 both;
}

@keyframes scene-handoff-left-to-right {
  0% { opacity: 0; }
  18% { opacity: 0.28; }
  46% { opacity: 0.74; }
  54% { opacity: 0.62; }
  82% { opacity: 0.2; }
  100% { opacity: 0; }
}

@keyframes scene-handoff-right-to-left {
  0% { opacity: 0; }
  18% { opacity: 0.28; }
  46% { opacity: 0.74; }
  54% { opacity: 0.62; }
  82% { opacity: 0.2; }
  100% { opacity: 0; }
}

@keyframes scene-weather-drift-left-to-right {
  0% { transform: translate3d(-3.5%, 0, 0) scale(1.08); }
  100% { transform: translate3d(3.5%, 0, 0) scale(1.08); }
}

@keyframes scene-weather-drift-right-to-left {
  0% { transform: translate3d(3.5%, 0, 0) scale(1.08); }
  100% { transform: translate3d(-3.5%, 0, 0) scale(1.08); }
}

@keyframes scene-handoff-cut-veil {
  0%, 39%, 56%, 100% { opacity: 0; }
  45.8%, 50.2% { opacity: 0.72; }
}

@keyframes scene-plate-release-left {
  0%, 45.8% { opacity: 1; }
  46%, 100% { opacity: 0; }
}

@keyframes scene-plate-release-right {
  0%, 45.8% { opacity: 1; }
  46%, 100% { opacity: 0; }
}

.environment-plate-alt {
  background-image: none;
  opacity: 0;
  pointer-events: none;
}

.sky-color {
  background:
    linear-gradient(90deg, rgba(7, 5, 19, 0.71) 0%, rgba(16, 8, 38, 0.26) 36%, rgba(30, 12, 57, 0.02) 68%),
    linear-gradient(0deg, rgba(7, 5, 17, 0.52) 0%, transparent 36%);
  pointer-events: none;
}

.window-glow {
  background:
    radial-gradient(ellipse at 70% 28%, rgba(202, 132, 255, 0.16), transparent 29%),
    radial-gradient(ellipse at 55% 102%, rgba(255, 111, 211, 0.11), transparent 48%);
  mix-blend-mode: screen;
  opacity: 0.9;
}

.weather-canvas {
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.weather-canvas-far {
  z-index: 3;
}

.weather-canvas-near {
  z-index: 7;
}

.cloud-bank {
  z-index: 2;
  width: 34rem;
  height: 12rem;
  border-radius: 50%;
  background:
    radial-gradient(ellipse at 20% 70%, rgba(169, 119, 215, 0.35) 0 18%, transparent 19%),
    radial-gradient(ellipse at 43% 54%, rgba(147, 90, 198, 0.28) 0 25%, transparent 26%),
    radial-gradient(ellipse at 68% 70%, rgba(117, 69, 169, 0.26) 0 24%, transparent 25%);
  filter: blur(12px);
  opacity: 0;
  pointer-events: none;
}

.cloud-bank-far {
  top: 15%;
  left: 38%;
}

.cloud-bank-near {
  top: 28%;
  right: -8rem;
  transform: scale(1.4);
}

.fog-bank {
  z-index: 3;
  top: 31%;
  bottom: auto;
  height: 34%;
  background:
    linear-gradient(180deg, transparent, rgba(204, 189, 226, 0.19), transparent),
    repeating-linear-gradient(0deg, transparent 0 3rem, rgba(221, 210, 236, 0.06) 3.1rem 4.6rem);
  filter: blur(16px);
  opacity: var(--fog-opacity, 0);
  transition: opacity 1400ms var(--ease-out);
}

.lightning {
  z-index: 6;
  background:
    radial-gradient(ellipse at 70% 34%, rgba(244, 235, 255, 0.74), transparent 24%),
    linear-gradient(115deg, rgba(205, 193, 255, 0.18), rgba(245, 239, 255, 0.52));
  mix-blend-mode: screen;
  opacity: 0;
  pointer-events: none;
}

/* A storm has one open window bay and one occupied bay. Restrict the CSS flash
   to the former, then let the canvas draw reflected light on the wet floor.
   That preserves GUGO's original silhouette and makes the strike feel like a
   room event rather than a page-level visual effect. */
.scene-owns-companion.condition-storm .lightning {
  background:
    radial-gradient(ellipse at 46% 31%, rgba(244, 235, 255, 0.68), transparent 27%),
    linear-gradient(112deg, rgba(205, 193, 255, 0.13), rgba(232, 222, 255, 0.34));
  clip-path: polygon(0 0, 58% 0, 62% 39%, 56% 67%, 52% 100%, 0 100%);
  mask-image: linear-gradient(90deg, #000 0 47%, rgba(0, 0, 0, 0.72) 54%, transparent 62%);
  -webkit-mask-image: linear-gradient(90deg, #000 0 47%, rgba(0, 0, 0, 0.72) 54%, transparent 62%);
}

.horizon-weather,
.wet-reflections {
  pointer-events: none;
  opacity: 0;
}

.horizon-weather {
  z-index: 2;
  top: 48%;
  bottom: auto;
  height: 23%;
  background:
    linear-gradient(180deg, transparent, rgba(187, 180, 224, 0.13) 42%, transparent 88%),
    radial-gradient(ellipse at 64% 62%, rgba(166, 146, 213, 0.17), transparent 52%);
  filter: blur(13px);
  transform: scaleX(1.08);
}

.wet-reflections {
  z-index: 4;
  top: auto;
  bottom: -3%;
  height: 35%;
  background:
    linear-gradient(180deg, transparent 0 32%, rgba(62, 87, 132, 0.05) 44%, rgba(5, 8, 20, 0.16) 100%),
    radial-gradient(ellipse at 42% 82%, rgba(156, 144, 255, 0.13), transparent 26%),
    radial-gradient(ellipse at 74% 94%, rgba(255, 183, 108, 0.1), transparent 29%);
  filter: blur(3px);
  mix-blend-mode: screen;
  mask-image: linear-gradient(180deg, transparent, #000 38%, #000);
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 38%, #000);
  transform-origin: 65% 100%;
}

/* A quiet snowbank at the sill gives the winter plate a foreground to sit in.
   It never crosses the baked Bear above boot level. */
.snow-settle {
  z-index: 4;
  top: auto;
  bottom: -2%;
  height: 27%;
  opacity: 0;
  background:
    radial-gradient(ellipse 18% 10% at 77% 97%, rgba(243, 250, 255, 0.68), transparent 72%),
    radial-gradient(ellipse 27% 8% at 58% 100%, rgba(213, 234, 255, 0.32), transparent 70%),
    linear-gradient(180deg, transparent 0 62%, rgba(225, 241, 255, 0.11) 100%);
  filter: blur(1.2px);
  mix-blend-mode: screen;
  pointer-events: none;
}

.observatory-header {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  padding: 2.25rem 4.5rem 1rem;
}

.wordmark {
  font-size: 1.35rem;
  font-weight: 760;
  letter-spacing: -0.045em;
  text-decoration: none;
  text-shadow: 0 1px 12px rgba(7, 4, 15, 0.65);
}

.wordmark span {
  color: var(--electric-lilac);
}

.header-status {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  margin-left: auto;
  color: var(--muted-lilac);
  font-size: 0.78rem;
}

.freshness-dot {
  width: 0.42rem;
  height: 0.42rem;
  border-radius: 50%;
  background: var(--fresh);
  box-shadow: 0 0 0.65rem rgba(215, 240, 186, 0.65);
}

.settings-link {
  appearance: none;
  display: inline-flex;
  min-width: 4.75rem;
  min-height: 2.75rem;
  align-items: center;
  justify-content: center;
  margin-left: 0.6rem;
  border: 1px solid rgba(244, 222, 255, 0.45);
  border-radius: 1.5rem;
  background: rgba(13, 7, 27, 0.32);
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  transition: border-color 180ms ease-out, background-color 180ms ease-out, color 180ms ease-out;
}

.settings-link:focus-visible {
  border-color: var(--moon-cream);
  background: rgba(58, 29, 82, 0.76);
  color: var(--moon-cream);
}

@media (hover: hover) {
  .settings-link:hover {
    border-color: var(--moon-cream);
    background: rgba(58, 29, 82, 0.76);
    color: var(--moon-cream);
  }
}

.weather-reading {
  position: absolute;
  top: 18%;
  left: 4.5rem;
  z-index: 12;
  width: 31rem;
  max-width: 42%;
  text-shadow: 0 2px 20px rgba(5, 3, 14, 0.85);
}

.location-line {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1rem;
}

.location-trigger {
  min-height: 2.75rem;
  margin: 0;
  padding: 0;
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  border: 0;
  color: inherit;
  background: transparent;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.location-name {
  font-size: 0.92rem;
  font-weight: 650;
  letter-spacing: 0.34em;
  line-height: 1.2;
  text-transform: uppercase;
}

.location-action {
  margin-top: 0.22rem;
  color: var(--muted-lilac);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  line-height: 1;
  text-transform: uppercase;
}

.location-trigger:focus-visible .location-name {
  text-decoration: underline;
  text-decoration-color: var(--forecast-amber);
  text-decoration-thickness: 0.12em;
  text-underline-offset: 0.25em;
}

@media (hover: hover) {
  .location-trigger:hover .location-name {
    text-decoration: underline;
    text-decoration-color: var(--forecast-amber);
    text-decoration-thickness: 0.12em;
    text-underline-offset: 0.25em;
  }
}

.location-pin {
  position: relative;
  width: 1rem;
  height: 1.25rem;
  flex: 0 0 auto;
  border: 2px solid var(--weather-white);
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
}

.location-pin::after {
  position: absolute;
  top: 0.27rem;
  left: 0.27rem;
  width: 0.25rem;
  height: 0.25rem;
  border-radius: 50%;
  background: var(--weather-white);
  content: "";
}

.station-drawer {
  position: absolute;
  top: 5.75rem;
  right: 4.5rem;
  z-index: var(--layer-station);
  width: 22rem;
  max-width: calc(100% - 3rem);
  max-height: calc(100% - 7.5rem);
  overflow: auto;
  padding: 1.5rem;
  border: 1px solid rgba(253, 246, 255, 0.66);
  border-radius: 0.35rem;
  color: var(--moon-cream);
  background:
    linear-gradient(145deg, rgba(25, 13, 58, 0.96), rgba(53, 23, 92, 0.9)),
    var(--observatory-ink);
  box-shadow: 0 1.1rem 2.8rem rgba(8, 3, 25, 0.38);
}

.station-drawer[hidden] {
  display: none;
}

.station-drawer[data-open="true"] {
  animation: station-drawer-arrive 220ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
}

.station-drawer-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid rgba(253, 246, 255, 0.22);
}

.station-drawer-header > div {
  min-width: 0;
}

.station-kicker {
  margin: 0 0 0.35rem;
  color: var(--electric-lilac);
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  line-height: 1;
  text-transform: uppercase;
}

.station-drawer h2 {
  margin: 0;
  font-size: 1.12rem;
  line-height: 1.08;
  overflow-wrap: anywhere;
}

.station-close {
  min-width: 2.75rem;
  min-height: 2.75rem;
  padding: 0.6rem;
  border: 1px solid rgba(253, 246, 255, 0.45);
  border-radius: 50%;
  color: inherit;
  background: rgba(255, 255, 255, 0.06);
  font: inherit;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  cursor: pointer;
}

.station-current {
  margin: 1rem 0 1.25rem;
  color: var(--muted-lilac);
  font-size: 0.78rem;
  line-height: 1.4;
}

.station-search label {
  display: block;
  margin-bottom: 0.5rem;
  font-size: 0.76rem;
  font-weight: 800;
  letter-spacing: 0.03em;
}

.station-search-controls {
  display: flex;
  gap: 0.5rem;
}

.station-search input {
  min-width: 0;
  min-height: 2.75rem;
  flex: 1 1 auto;
  padding: 0.55rem 0.72rem;
  border: 1px solid rgba(253, 246, 255, 0.48);
  border-radius: 0.2rem;
  color: var(--moon-cream);
  background: rgba(5, 2, 20, 0.3);
  font: inherit;
  font-size: 0.88rem;
}

.station-search input::placeholder {
  color: rgba(231, 217, 251, 0.64);
}

.station-search input[aria-invalid="true"] {
  border-color: #ff8e9a;
}

.station-search-controls button {
  min-width: 4.25rem;
  min-height: 2.75rem;
  padding: 0.55rem 0.75rem;
  border: 1px solid var(--forecast-amber);
  border-radius: 0.2rem;
  color: #21102e;
  background: var(--forecast-amber);
  font: inherit;
  font-size: 0.76rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  cursor: pointer;
}

.station-search-controls button[disabled] {
  opacity: 0.62;
  cursor: progress;
}

.station-search-status {
  min-height: 1.2rem;
  margin: 0.65rem 0 0;
  color: var(--muted-lilac);
  font-size: 0.72rem;
  line-height: 1.35;
}

.station-search-status.is-error {
  color: #ffacb4;
}

.station-search-status.is-success {
  color: #a8efbd;
}

.station-results {
  margin: 1rem 0 0;
  padding: 0;
  border-top: 1px solid rgba(253, 246, 255, 0.22);
  list-style: none;
}

.station-result {
  margin: 0;
  border-bottom: 1px solid rgba(253, 246, 255, 0.18);
}

.station-result button {
  width: 100%;
  min-height: 3.25rem;
  padding: 0.7rem 0.15rem;
  display: block;
  border: 0;
  color: inherit;
  background: transparent;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.station-result-name,
.station-result-detail {
  display: block;
}

.station-result-name {
  font-size: 0.88rem;
  font-weight: 800;
  line-height: 1.2;
}

.station-result-detail {
  margin-top: 0.2rem;
  color: var(--muted-lilac);
  font-size: 0.72rem;
  line-height: 1.2;
}

.station-result button:focus-visible,
.station-close:focus-visible,
.station-search input:focus-visible,
.station-search-controls button:focus-visible {
  outline: 3px solid var(--forecast-amber);
  outline-offset: 3px;
}

@media (hover: hover) {
  .station-result button:hover {
    color: var(--forecast-amber);
  }

  .station-close:hover {
    background: rgba(255, 255, 255, 0.15);
  }

  .station-search-controls button:hover {
    background: #ffd277;
  }
}

@keyframes station-drawer-arrive {
  from {
    opacity: 0;
    transform: translate3d(0, -0.75rem, 0);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

.current-weather {
  display: flex;
  align-items: center;
}

.temperature {
  margin: 0;
  font-size: 8.7rem;
  font-variant-numeric: tabular-nums;
  font-weight: 230;
  letter-spacing: -0.105em;
  line-height: 0.83;
  text-shadow:
    0 0 0.35rem rgba(238, 205, 255, 0.45),
    0 0 1.8rem rgba(178, 86, 255, 0.42);
}

.temperature span {
  position: relative;
  top: -0.34em;
  left: 0.04em;
  color: var(--moon-cream);
  font-size: 0.52em;
  letter-spacing: 0;
}

.condition-stack {
  min-width: 8rem;
  margin-left: 1.9rem;
  padding-top: 0.4rem;
}

.weather-glyph {
  display: block;
  width: 3.25rem;
  height: 3.25rem;
  margin-bottom: 0.45rem;
}

.glyph-moon {
  position: relative;
  display: block;
  width: 2.4rem;
  height: 2.4rem;
  border: 0.18rem solid var(--weather-white);
  border-radius: 50%;
  filter: drop-shadow(0 0 0.55rem rgba(194, 119, 255, 0.74));
}

.glyph-moon::after {
  position: absolute;
  top: -0.42rem;
  right: -0.45rem;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 50%;
  background: #472085;
  content: "";
}

.glyph-storm,
.glyph-rain,
.glyph-snow,
.glyph-cloud,
.glyph-sun {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.4rem;
  height: 2.4rem;
  color: var(--moon);
  font-family: Georgia, "Times New Roman", serif;
  font-size: 2.35rem;
  font-style: normal;
  line-height: 1;
  text-shadow:
    0 0 0.55rem rgba(247, 222, 255, 0.75),
    0 0 1.4rem rgba(182, 104, 255, 0.55);
}

.glyph-storm {
  color: #ffd778;
}

.glyph-rain {
  color: #9ed8ff;
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.2rem;
  transform: rotate(-10deg);
}

.glyph-snow {
  color: #e7f7ff;
}

.glyph-sun {
  color: #ffd56e;
}

.condition-label,
.feels-like {
  margin: 0;
}

.condition-label {
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--hairline);
  font-size: 1rem;
  font-weight: 720;
}

.feels-like {
  padding-top: 0.6rem;
  color: var(--muted-lilac);
  font-size: 0.9rem;
}

.weather-details {
  display: flex;
  width: 27rem;
  flex-wrap: wrap;
  margin: 1.6rem 0 0;
  padding-top: 1rem;
  border-top: 1px solid var(--hairline);
}

.weather-details div {
  width: 50%;
  min-height: 3rem;
  padding: 0.1rem 1.2rem 0.45rem 0;
}

.weather-details div:nth-child(odd) {
  border-right: 1px solid rgba(244, 222, 255, 0.22);
}

.weather-details div:nth-child(even) {
  padding-left: 1.35rem;
}

.weather-details dt {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  color: var(--muted-lilac);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.weather-details dd {
  margin: 0.12rem 0 0 1.5rem;
  font-size: 1rem;
  font-variant-numeric: tabular-nums;
  font-weight: 650;
}

.detail-icon {
  position: relative;
  display: inline-block;
  width: 0.9rem;
  height: 0.9rem;
  flex: 0 0 auto;
}

.humidity-icon {
  border: 0.12rem solid var(--weather-white);
  border-radius: 70% 40% 70% 70%;
  transform: rotate(45deg);
}

.wind-icon::before,
.wind-icon::after {
  position: absolute;
  left: 0;
  width: 0.85rem;
  border-top: 0.12rem solid var(--weather-white);
  border-radius: 50%;
  content: "";
}

.wind-icon::before {
  top: 0.25rem;
}

.wind-icon::after {
  top: 0.62rem;
  width: 0.65rem;
}

.arrow-up,
.arrow-down {
  width: 0.9rem;
  color: var(--weather-white);
  font-size: 1rem;
  text-align: center;
}

.status-banner {
  max-width: 25rem;
  margin-top: 1rem;
  padding: 0.75rem 1rem;
  border-left: 0.18rem solid var(--forecast-amber);
  background: rgba(15, 8, 27, 0.72);
  font-size: 0.78rem;
  text-shadow: none;
}

.status-banner strong,
.status-banner span {
  display: block;
}

.status-banner span {
  margin-top: 0.2rem;
  color: var(--muted-lilac);
}

.status-banner button {
  min-height: 2.75rem;
  margin-top: 0.55rem;
  padding: 0 0.9rem;
  border: 1px solid rgba(255, 242, 206, 0.6);
  border-radius: 1.4rem;
  background: transparent;
  color: var(--moon-cream);
  cursor: pointer;
}

.weather-quip {
  width: 27rem;
  max-width: 100%;
  margin: 1.05rem 0 0;
  padding-top: 0.82rem;
  border-top: 1px solid rgba(244, 222, 255, 0.22);
  color: var(--moon-cream);
  font-size: 0.92rem;
  line-height: 1.3;
  text-align: left;
  text-shadow: 0 2px 14px rgba(6, 3, 12, 0.95);
}

.weather-quip span,
.weather-quip strong {
  display: block;
}

.weather-quip strong {
  color: var(--weather-white);
}

.scene-preview {
  display: flex;
  width: fit-content;
  max-width: 100%;
  margin: 0.75rem 0 0;
  gap: 0.45rem;
  align-items: baseline;
  padding: 0.38rem 0.6rem;
  border: 1px solid rgba(255, 242, 206, 0.32);
  border-radius: 0.25rem;
  background: rgba(11, 6, 23, 0.54);
  color: rgba(255, 242, 206, 0.78);
  font-size: 0.65rem;
  letter-spacing: 0.04em;
  line-height: 1.35;
  text-shadow: 0 2px 12px rgba(6, 3, 12, 0.9);
}

.scene-preview[hidden] {
  display: none;
}

.scene-preview strong {
  color: var(--moon-cream);
  font-weight: 760;
  text-transform: uppercase;
}

.scene-preview span {
  white-space: nowrap;
}

.forecast-orbit {
  position: absolute;
  right: 3%;
  bottom: 3.45rem;
  left: 3%;
  z-index: 15;
  height: 12.6rem;
}

.forecast-path {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 8.8rem;
  overflow: visible;
}

.orbit-shadow,
.orbit-line,
.orbit-comet {
  fill: none;
  stroke-linecap: round;
}

.orbit-shadow {
  stroke: rgba(12, 6, 24, 0.62);
  stroke-width: 16;
}

.orbit-line {
  stroke: url("#forecast-gradient");
  stroke-width: 4;
  filter: url("#forecast-glow");
}

.orbit-comet {
  stroke: rgba(255, 255, 255, 0.9);
  stroke-width: 2;
  stroke-dasharray: 18 220;
  filter: url("#forecast-glow");
}

.forecast-list {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

.forecast-stop {
  position: absolute;
  bottom: 0;
  display: flex;
  width: 7.2rem;
  flex-direction: column;
  align-items: center;
  color: var(--muted-lilac);
  font-size: 0.68rem;
  text-align: center;
  text-shadow: 0 2px 12px rgba(6, 3, 12, 0.95);
  transform: translateX(-50%);
}

.forecast-stop:nth-child(1) {
  left: 10%;
  bottom: 1.35rem;
}

.forecast-stop:nth-child(2) {
  left: 37%;
  bottom: 0.25rem;
}

.forecast-stop:nth-child(3) {
  left: 63%;
  bottom: 1.5rem;
}

.forecast-stop:nth-child(4) {
  left: 88%;
  bottom: 2.85rem;
}

.forecast-node {
  display: block;
  width: 1.15rem;
  height: 1.15rem;
  margin-bottom: 0.42rem;
  border: 0.18rem solid currentColor;
  border-radius: 50%;
  background: var(--observatory-ink);
  box-shadow: 0 0 0.85rem currentColor;
}

.forecast-stop:nth-child(1) {
  color: var(--forecast-amber);
}

.forecast-stop:nth-child(2),
.forecast-stop:nth-child(3) {
  color: var(--forecast-pink);
}

.forecast-stop:nth-child(4) {
  color: var(--forecast-blue);
}

.forecast-time {
  color: var(--weather-white);
  font-size: 0.85rem;
  font-weight: 730;
}

.forecast-temperature {
  color: var(--weather-white);
  font-size: 1.25rem;
  font-variant-numeric: tabular-nums;
  font-weight: 550;
}

.forecast-symbol {
  margin-top: 0.1rem;
  color: currentColor;
  font-size: 1.05rem;
}

.forecast-condition {
  max-width: 7rem;
  overflow: hidden;
  color: var(--muted-lilac);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.forecast-stop.is-now .forecast-node::after {
  display: block;
  width: 0.35rem;
  height: 0.35rem;
  margin: 0.22rem auto 0;
  border-radius: 50%;
  background: currentColor;
  content: "";
}

.observatory-footer {
  position: absolute;
  right: 3rem;
  bottom: 0;
  left: 3rem;
  z-index: 20;
  display: flex;
  min-height: 3.4rem;
  align-items: center;
  justify-content: space-between;
  border-top: 1px solid rgba(244, 222, 255, 0.18);
  color: rgba(236, 221, 244, 0.72);
  font-size: 0.68rem;
}

.observatory-footer a {
  color: var(--moon-cream);
  text-underline-offset: 0.18em;
}

.no-script {
  position: absolute;
  right: 1rem;
  bottom: 1rem;
  left: 1rem;
  z-index: 100;
  margin: 0;
  padding: 1rem;
  background: var(--moon-cream);
  color: var(--observatory-ink);
}

.environment,
.weather-reading,
.forecast-orbit,
.observatory-footer {
  opacity: 1;
  transition: opacity 620ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* First paint is intentionally quiet. The observatory only reveals a finished
   live reading, never the old fabricated clear-night sample. A background
   refresh leaves the current scene untouched while the new reading arrives. */
.is-booting .environment,
.is-booting .weather-reading,
.is-booting .forecast-orbit,
.is-booting .observatory-footer {
  opacity: 0;
}

.motion-on.is-refreshing .freshness-dot {
  animation: weather-refresh-breathe 1200ms ease-in-out infinite;
}

.motion-off .environment,
.motion-off .weather-reading,
.motion-off .forecast-orbit,
.motion-off .observatory-footer {
  transition: none;
}

.motion-off.is-refreshing .freshness-dot {
  animation: none;
}

@keyframes weather-refresh-breathe {
  0%,
  100% {
    opacity: 0.45;
    transform: scale(0.82);
  }

  50% {
    opacity: 1;
    transform: scale(1);
  }
}

.condition-clouds .cloud-bank,
.condition-mist .cloud-bank {
  opacity: 0.78;
}

.condition-rain .environment-plate {
  /* Crystal Wizard GUGO is redrawn into the rain-soaked terrace. His wet
     cloak, planted feet, crystals, and puddle light are part of one plate. */
  background-image: url("/assets/scenes/v08/observatory-wizard-rain.jpg");
  filter: none;
}

.condition-rain .environment-plate-alt {
  /* The alternate is deliberately cut to the distant left-hand window, where
     a rainfront can roll through without turning GUGO into an overlay. */
  background-image: url("/assets/scenes/observatory-rainfall-loop-b.jpg");
  background-position: center center;
  background-size: cover;
  clip-path: polygon(0 0, 66% 0, 65% 43%, 59% 62%, 0 67%);
  mask-image: linear-gradient(90deg, #000 0 52%, rgba(0, 0, 0, 0.72) 59%, transparent 66%);
  -webkit-mask-image: linear-gradient(90deg, #000 0 52%, rgba(0, 0, 0, 0.72) 59%, transparent 66%);
}

/* Visor Bear is redrawn inside a single observatory terrace with a physical
   telescope, floor contact, reflected light, and an open telemetry bay. */
.condition-clear .environment-plate {
  background-image: url("/assets/scenes/v08/observatory-visor-twilight.jpg");
  filter: none;
}

/* The first and last forty-five minutes of local daylight are real solar
   states. Bear stays inside the appropriate finished plate while only the
   unoccupied observation window reveals the matching twilight exposure. */
.phase-dawn.condition-clear .environment-plate {
  background-image: url("/assets/scenes/v08/observatory-visor-twilight.jpg");
  filter:
    brightness(var(--solar-brightness))
    saturate(var(--solar-saturate))
    contrast(var(--solar-contrast));
}

.phase-dusk.condition-clear .environment-plate {
  background-image: url("/assets/scenes/v08/observatory-visor-twilight.jpg");
  filter:
    brightness(var(--solar-brightness))
    saturate(var(--solar-saturate))
    contrast(var(--solar-contrast));
}

/* The alternate twilight exposure is revealed only inside the open window,
   so it reads as distant cloud movement rather than a layer over Bear. */
.phase-night.condition-clear .environment-plate-alt {
  background-image: url("/assets/scenes/observatory-clear-twilight.jpg");
  background-position: center center;
  background-size: cover;
  clip-path: polygon(0 0, 57% 0, 55% 37%, 51% 69%, 0 74%);
  mask-image: linear-gradient(90deg, #000 0 44%, rgba(0, 0, 0, 0.7) 52%, transparent 59%);
  -webkit-mask-image: linear-gradient(90deg, #000 0 44%, rgba(0, 0, 0, 0.7) 52%, transparent 59%);
}

.phase-dawn.condition-clear .environment-plate-alt,
.phase-dusk.condition-clear .environment-plate-alt {
  background-image: url("/assets/scenes/observatory-clear-twilight.jpg");
  background-position: center center;
  background-size: cover;
  clip-path: polygon(0 0, 57% 0, 55% 37%, 51% 69%, 0 74%);
  mask-image: linear-gradient(90deg, #000 0 44%, rgba(0, 0, 0, 0.7) 52%, transparent 59%);
  -webkit-mask-image: linear-gradient(90deg, #000 0 44%, rgba(0, 0, 0, 0.7) 52%, transparent 59%);
}

/* The source plates carry the characters and architecture. These two quiet
   layers let the real solar transition change the open window and wet floor
   without painting a blanket over the finished artwork. */
.phase-dawn.condition-clear .horizon-weather,
.phase-dusk.condition-clear .horizon-weather {
  opacity: var(--solar-horizon-opacity);
}

.phase-dawn.condition-clear .horizon-weather {
  background:
    linear-gradient(180deg, transparent 0 42%, rgba(255, 188, 139, 0.18) 72%, transparent),
    radial-gradient(ellipse at 44% 70%, rgba(250, 157, 194, 0.18), transparent 48%);
}

.phase-dusk.condition-clear .horizon-weather {
  background:
    linear-gradient(180deg, transparent 0 42%, rgba(177, 122, 255, 0.2) 72%, transparent),
    radial-gradient(ellipse at 58% 70%, rgba(208, 110, 225, 0.18), transparent 48%);
}

.phase-dawn.condition-clear .wet-reflections,
.phase-dusk.condition-clear .wet-reflections {
  opacity: var(--solar-reflection-opacity);
}

.phase-night.condition-clear.scene-owns-companion.motion-on .environment-plate-alt {
  animation: clear-night-window-loop var(--scene-window-cadence, 38s) ease-in-out infinite;
  will-change: opacity, transform;
}

.phase-dawn.condition-clear.scene-owns-companion.motion-on .environment-plate-alt {
  animation: clear-dawn-window-loop var(--scene-window-cadence, 42s) ease-in-out infinite;
  will-change: opacity, transform;
}

.phase-dusk.condition-clear.scene-owns-companion.motion-on .environment-plate-alt {
  animation: clear-dusk-window-loop var(--scene-window-cadence, 42s) ease-in-out infinite;
  will-change: opacity, transform;
}

/* Weather plates keep their baked character light. During the real local
   dawn/dusk window, these restrained casts only touch the open horizon and
   the floor reflection, so rain, snow, and storm scenes still feel lit by the
   same sun without washing a filter over Bear or GUGO. */
.phase-dawn.condition-rain .horizon-weather,
.phase-dusk.condition-rain .horizon-weather {
  opacity: calc(0.46 + var(--solar-weather-cast));
  clip-path: polygon(0 0, 63% 0, 60% 42%, 54% 72%, 0 78%);
  mask-image: linear-gradient(90deg, #000 0 48%, rgba(0, 0, 0, 0.74) 57%, transparent 66%);
  -webkit-mask-image: linear-gradient(90deg, #000 0 48%, rgba(0, 0, 0, 0.74) 57%, transparent 66%);
}

.phase-dawn.condition-rain .horizon-weather {
  background:
    linear-gradient(180deg, transparent 0 40%, rgba(255, 190, 145, 0.15) 72%, transparent),
    radial-gradient(ellipse at 42% 72%, rgba(255, 142, 176, 0.18), transparent 50%);
}

.phase-dusk.condition-rain .horizon-weather {
  background:
    linear-gradient(180deg, transparent 0 40%, rgba(139, 111, 235, 0.18) 72%, transparent),
    radial-gradient(ellipse at 54% 72%, rgba(192, 120, 241, 0.17), transparent 50%);
}

.phase-dawn.condition-rain .wet-reflections,
.phase-dusk.condition-rain .wet-reflections {
  opacity: calc(0.58 + var(--solar-weather-cast));
  clip-path: polygon(0 18%, 63% 18%, 59% 100%, 0 100%);
}

.phase-dawn.condition-snow .horizon-weather,
.phase-dusk.condition-snow .horizon-weather {
  opacity: calc(0.42 + var(--solar-weather-cast));
  clip-path: polygon(0 0, 70% 0, 67% 42%, 62% 72%, 0 78%);
  mask-image: linear-gradient(90deg, #000 0 53%, rgba(0, 0, 0, 0.7) 63%, transparent 72%);
  -webkit-mask-image: linear-gradient(90deg, #000 0 53%, rgba(0, 0, 0, 0.7) 63%, transparent 72%);
}

.phase-dawn.condition-snow .horizon-weather {
  background:
    linear-gradient(180deg, transparent 0 38%, rgba(255, 219, 181, 0.16) 72%, transparent),
    radial-gradient(ellipse at 50% 72%, rgba(211, 230, 255, 0.2), transparent 54%);
}

.phase-dusk.condition-snow .horizon-weather {
  background:
    linear-gradient(180deg, transparent 0 38%, rgba(140, 146, 237, 0.16) 72%, transparent),
    radial-gradient(ellipse at 54% 72%, rgba(173, 173, 255, 0.18), transparent 54%);
}

.phase-dawn.condition-snow .wet-reflections,
.phase-dusk.condition-snow .wet-reflections {
  opacity: calc(0.32 + var(--solar-weather-cast));
  clip-path: polygon(0 24%, 70% 24%, 66% 100%, 0 100%);
}

.phase-dawn.condition-storm .horizon-weather,
.phase-dusk.condition-storm .horizon-weather {
  opacity: calc(0.72 + var(--solar-weather-cast));
  clip-path: polygon(0 0, 60% 0, 57% 40%, 52% 72%, 0 80%);
  mask-image: linear-gradient(90deg, #000 0 44%, rgba(0, 0, 0, 0.72) 54%, transparent 64%);
  -webkit-mask-image: linear-gradient(90deg, #000 0 44%, rgba(0, 0, 0, 0.72) 54%, transparent 64%);
}

.phase-dawn.condition-storm .horizon-weather {
  background:
    linear-gradient(180deg, transparent 0 38%, rgba(255, 180, 129, 0.16) 70%, transparent),
    radial-gradient(ellipse at 40% 72%, rgba(227, 119, 163, 0.17), transparent 48%);
}

.phase-dusk.condition-storm .horizon-weather {
  background:
    linear-gradient(180deg, transparent 0 38%, rgba(123, 100, 223, 0.2) 70%, transparent),
    radial-gradient(ellipse at 48% 72%, rgba(181, 113, 242, 0.2), transparent 48%);
}

.phase-dawn.condition-storm .wet-reflections,
.phase-dusk.condition-storm .wet-reflections {
  opacity: calc(0.72 + var(--solar-weather-cast));
  clip-path: polygon(0 16%, 60% 16%, 57% 100%, 0 100%);
}

/* Overcast keeps Visor Bear inside the same physical terrace. The runtime
   window pass cools and softens the open sky without replacing the figure. */
.condition-clouds .environment-plate,
.condition-mist .environment-plate {
  background-image: url("/assets/scenes/v08/observatory-visor-twilight.jpg");
}

[data-scene-companion="cosmic"].condition-clear .environment-plate,
[data-scene-companion="cosmic"].condition-clouds .environment-plate,
[data-scene-companion="cosmic"].condition-mist .environment-plate {
  background-image: url("/assets/scenes/v08/observatory-cosmic-snow.jpg");
}

/*
 * Visor Bear is painted into the canonical source plate. Keep the alternate
 * plate inside the
 * left-hand sky and rain-streaked glass so the canonical art, its reflection,
 * and its floor contact never crossfade or move.
 */
.condition-clouds .environment-plate-alt,
.condition-mist .environment-plate-alt {
  background-image: url("/assets/scenes/observatory-overcast-loop-b.jpg");
  background-position: center center;
  background-size: cover;
  clip-path: polygon(0 0, 65% 0, 65% 36%, 60% 52%, 0 57%);
  mask-image: linear-gradient(90deg, #000 0 52%, rgba(0, 0, 0, 0.72) 59%, transparent 65%);
  -webkit-mask-image: linear-gradient(90deg, #000 0 52%, rgba(0, 0, 0, 0.72) 59%, transparent 65%);
}

.phase-day.condition-clouds .environment-plate,
.phase-night.condition-clouds .environment-plate {
  filter: none;
}

.phase-day.condition-clouds .environment-plate-alt,
.phase-night.condition-clouds .environment-plate-alt {
  filter: none;
}

.phase-day.condition-mist .environment-plate,
.phase-night.condition-mist .environment-plate {
  filter: brightness(0.86) saturate(0.8) contrast(0.94);
}

.phase-day.condition-mist .environment-plate-alt,
.phase-night.condition-mist .environment-plate-alt {
  filter: brightness(0.85) saturate(0.8) contrast(0.94);
}

/* The active companion is painted into each severe-weather observatory plate.
   Generic scenery stays out, while scene-aware atmosphere is composited in
   depth passes around the anchored figure. */
.scene-owns-companion .sky-color,
.scene-owns-companion .cloud-bank,
.scene-owns-companion .window-glow {
  display: none;
}

.scene-owns-companion .weather-canvas {
  display: block;
}

/* Every scene-native companion occupies the observatory's right bay. The
   forecast line is an architectural sill on the open side of the room, so it
   deliberately ends before it can write across Bear or GUGO. */
.scene-owns-companion .forecast-path {
  width: 72%;
}

.scene-owns-companion .forecast-stop:nth-child(1) {
  left: 10%;
}

.scene-owns-companion .forecast-stop:nth-child(2) {
  left: 30%;
}

.scene-owns-companion .forecast-stop:nth-child(3) {
  left: 50%;
}

.scene-owns-companion .forecast-stop:nth-child(4) {
  left: 68%;
}

.condition-snow .environment-plate {
  background-image: url("/assets/scenes/v08/observatory-cosmic-snow.jpg");
  filter: none;
}

.condition-snow .environment-plate-alt {
  background-image: url("/assets/scenes/observatory-snowfall-loop-b.jpg");
  background-position: center;
  background-size: cover;
  /* The alternate snowfall plate is a moving sky pass. End it above Bear's
     hat so it cannot erase, ghost, or double-expose the character painted
     into the base scene. */
  mask-image: linear-gradient(180deg, #000 0 34%, rgba(0, 0, 0, 0.52) 42%, transparent 51%);
  -webkit-mask-image: linear-gradient(180deg, #000 0 34%, rgba(0, 0, 0, 0.52) 42%, transparent 51%);
}

.condition-storm .environment-plate {
  background-image: url("/assets/scenes/v08/observatory-wizard-storm.jpg");
  filter: none;
}

.condition-storm .environment-plate-alt {
  background-image: url("/assets/scenes/observatory-stormfront-loop-b.jpg");
  background-position: center;
  background-size: cover;
  /* The loop plate has no GUGO in it. It can only breathe through the open
     left-hand weather bay, leaving the Wizard's painted room untouched. */
  clip-path: polygon(0 0, 53% 0, 57% 31%, 56% 52%, 51% 68%, 0 68%);
  mask-image: linear-gradient(90deg, #000 0 43%, rgba(0, 0, 0, 0.76) 50%, transparent 57%);
  -webkit-mask-image: linear-gradient(90deg, #000 0 43%, rgba(0, 0, 0, 0.76) 50%, transparent 57%);
  transition: opacity 90ms linear, transform 130ms ease-out;
}

/* The scene moves only when weather has physical movement. This is the slow
   parallax of looking through a window, not an idle animation pasted on top. */
.condition-rain.motion-on .environment-plate {
  animation: rain-window-drift 22s ease-in-out infinite alternate;
  will-change: transform;
}

.condition-rain.motion-on .environment-plate-alt {
  animation: rain-scene-cycle 20s ease-in-out infinite;
  will-change: opacity, transform;
}

.condition-snow.motion-on .environment-plate {
  animation: snow-window-drift 30s ease-in-out infinite alternate;
  will-change: transform;
}

.condition-snow.motion-on .environment-plate-alt {
  animation: snow-sky-loop var(--scene-window-cadence, 26s) ease-in-out infinite;
  will-change: opacity, transform;
}

.condition-clouds.motion-on .environment-plate-alt,
.condition-mist.motion-on .environment-plate-alt {
  animation: overcast-window-loop var(--scene-window-cadence, 34s) ease-in-out infinite;
  will-change: opacity, transform;
}

.condition-storm.motion-on .environment-plate {
  animation: storm-window-drift 16s ease-in-out infinite alternate;
  will-change: transform;
}

.condition-storm.motion-on .environment-plate-alt {
  animation: none;
  will-change: opacity, transform;
}

.condition-rain .horizon-weather,
.condition-storm .horizon-weather {
  opacity: 0.72;
}

.condition-rain .horizon-weather {
  opacity: 0.46;
}

.condition-snow .horizon-weather {
  opacity: 0.42;
}

.condition-rain .wet-reflections,
.condition-storm .wet-reflections {
  opacity: 0.72;
}

.condition-rain .wet-reflections {
  opacity: 0.58;
}

.condition-snow .wet-reflections {
  opacity: 0.32;
  background:
    linear-gradient(180deg, transparent 0 42%, rgba(210, 233, 255, 0.04) 56%, rgba(8, 14, 34, 0.14) 100%),
    radial-gradient(ellipse at 54% 88%, rgba(205, 228, 255, 0.1), transparent 32%);
}

.condition-snow .snow-settle {
  opacity: 0.88;
}

/* A storm strike lights the painted room through the canvas and CSS flash
   layers. Pull the safe, left-window loop away during that moment so the
   companion never becomes a double exposure. */
.condition-storm.is-striking .environment-plate-alt {
  opacity: 0;
}

.scene-owns-companion.motion-on .horizon-weather {
  animation: horizon-breathe 16s ease-in-out infinite alternate;
}

.scene-owns-companion.motion-on .wet-reflections {
  animation: reflection-shiver 13s ease-in-out infinite alternate;
}

.condition-snow.motion-on .snow-settle {
  animation: snow-settle-shift 19s ease-in-out infinite alternate;
}

/* The weather belongs around the painted companion, never under their feet.
   Holding the composed plate still keeps Bear and GUGO rooted in their own
   shot; wind, rain, snow, lightning, reflections, and fog provide the motion
   in foreground and middle-depth layers instead of making the character glide. */
.scene-owns-companion.motion-on .environment-plate:not(.environment-plate-alt) {
  animation: none;
  transform: scale(1.018);
  will-change: auto;
}

.condition-rain.scene-owns-companion.motion-on .environment-plate-alt {
  animation: rain-window-loop var(--scene-window-cadence, 27s) ease-in-out infinite;
  will-change: opacity, transform;
}

.condition-storm.scene-owns-companion.motion-on .environment-plate-alt {
  animation: storm-bay-loop var(--scene-window-cadence, 24s) ease-in-out infinite;
  will-change: opacity, transform;
}

.phase-day .environment-plate {
  filter: brightness(1.09) saturate(0.93);
}

.phase-day.condition-rain .environment-plate,
.phase-day.condition-snow .environment-plate,
.phase-day.condition-storm .environment-plate {
  filter: none;
}

.phase-day .sky-color {
  background:
    linear-gradient(90deg, rgba(12, 7, 24, 0.6), rgba(31, 14, 61, 0.1) 52%, rgba(255, 166, 107, 0.09)),
    linear-gradient(0deg, rgba(9, 5, 18, 0.46), transparent 42%);
}

.phase-dawn .sky-color {
  background:
    linear-gradient(90deg, rgba(15, 8, 28, 0.74), rgba(109, 48, 109, 0.2) 55%, rgba(255, 194, 122, 0.12)),
    linear-gradient(0deg, rgba(20, 8, 28, 0.48), transparent 44%);
}

.phase-dusk .sky-color {
  background:
    linear-gradient(90deg, rgba(9, 5, 20, 0.76), rgba(58, 23, 83, 0.27) 53%, rgba(237, 125, 189, 0.12)),
    linear-gradient(0deg, rgba(7, 4, 17, 0.57), transparent 43%);
}

.phase-dawn .window-glow {
  background:
    radial-gradient(ellipse at 64% 26%, rgba(255, 192, 122, 0.19), transparent 32%),
    radial-gradient(ellipse at 45% 102%, rgba(229, 126, 255, 0.12), transparent 49%);
}

.phase-dusk .window-glow {
  background:
    radial-gradient(ellipse at 71% 28%, rgba(225, 112, 211, 0.18), transparent 31%),
    radial-gradient(ellipse at 55% 102%, rgba(131, 99, 255, 0.16), transparent 50%);
}

.has-error .freshness-dot {
  background: var(--danger);
  box-shadow: 0 0 0.65rem rgba(255, 181, 174, 0.5);
}

.condition-clouds.motion-on .cloud-bank-far,
.condition-rain.motion-on .cloud-bank-far,
.condition-storm.motion-on .cloud-bank-far {
  animation: cloud-drift 24s ease-in-out infinite alternate;
}

.condition-clouds.motion-on .cloud-bank-near,
.condition-rain.motion-on .cloud-bank-near,
.condition-storm.motion-on .cloud-bank-near {
  animation: cloud-drift-near 17s ease-in-out infinite alternate;
}

.condition-mist.motion-on .fog-bank,
.condition-clouds.motion-on .fog-bank,
.condition-rain.motion-on .fog-bank,
.condition-snow.motion-on .fog-bank,
.condition-storm.motion-on .fog-bank {
  animation: fog-drift 19s ease-in-out infinite alternate;
}

.motion-on .orbit-comet {
  animation: orbit-travel 7s linear infinite;
}

.motion-on .forecast-stop.is-now .forecast-node {
  animation: current-pulse 2.8s ease-in-out infinite;
}

.motion-on .lightning.is-flashing {
  animation: lightning-flash 520ms ease-out 1;
}

@keyframes cloud-drift {
  from {
    transform: translate3d(-3rem, 0, 0);
  }
  to {
    transform: translate3d(4rem, -0.5rem, 0);
  }
}

@keyframes cloud-drift-near {
  from {
    transform: translate3d(0, 0, 0) scale(1.4);
  }
  to {
    transform: translate3d(-5rem, 0.75rem, 0) scale(1.46);
  }
}

@keyframes fog-drift {
  from {
    transform: translate3d(-3%, 0, 0) scaleX(1.08);
    opacity: var(--fog-rest-opacity, 0);
  }
  to {
    transform: translate3d(3%, 0.6rem, 0) scaleX(1.15);
    opacity: var(--fog-opacity, 0);
  }
}

@keyframes horizon-breathe {
  from {
    transform: translate3d(-2.5%, 0, 0) scaleX(1.08);
    opacity: 0.38;
  }
  to {
    transform: translate3d(2.5%, 0.45rem, 0) scaleX(1.15);
    opacity: 0.76;
  }
}

@keyframes reflection-shiver {
  from {
    transform: translate3d(-0.25%, 0, 0) scale3d(1.01, 0.99, 1);
  }
  to {
    transform: translate3d(0.25%, 0.12rem, 0) scale3d(1.018, 1.012, 1);
  }
}

@keyframes rain-window-drift {
  from {
    transform: scale(1.018) translate3d(-0.2%, -0.08%, 0);
  }
  to {
    transform: scale(1.03) translate3d(0.26%, 0.12%, 0);
  }
}

/* This is not a moving Bear plate. It is a low-amplitude change in the
   rainfront beyond the left window bay, paced slowly enough to remain calm on
   the always-on iPad display. */
@keyframes rain-window-loop {
  0%,
  100% {
    opacity: 0;
    transform: scale(1.02) translate3d(-0.16%, 0.06%, 0);
  }
  46%,
  58% {
    opacity: 0.22;
    transform: scale(1.042) translate3d(0.28%, -0.12%, 0);
  }
}

/* The stormfront shifts only in the empty bay to the left of Wizard GUGO.
   It is background weather advancing through the observatory window, not a
   camera move or a second character layer. */
@keyframes storm-bay-loop {
  0%,
  100% {
    opacity: 0;
    transform: scale(1.02) translate3d(-0.18%, 0.08%, 0);
  }
  45%,
  60% {
    opacity: 0.24;
    transform: scale(1.05) translate3d(0.42%, -0.16%, 0);
  }
}

@keyframes clear-night-window-loop {
  0%,
  100% {
    opacity: 0;
    transform: scale(1.018) translate3d(-0.12%, 0.04%, 0);
  }
  38%,
  58% {
    opacity: 0.14;
    transform: scale(1.038) translate3d(0.18%, -0.06%, 0);
  }
}

@keyframes clear-dawn-window-loop {
  0%,
  100% {
    opacity: 0.04;
    transform: scale(1.018) translate3d(-0.16%, 0.08%, 0);
  }
  46%,
  60% {
    opacity: 0.17;
    transform: scale(1.04) translate3d(0.22%, -0.08%, 0);
  }
}

@keyframes clear-dusk-window-loop {
  0%,
  100% {
    opacity: 0.05;
    transform: scale(1.022) translate3d(0.16%, -0.06%, 0);
  }
  42%,
  57% {
    opacity: 0.19;
    transform: scale(1.044) translate3d(-0.24%, 0.1%, 0);
  }
}

@keyframes snow-window-drift {
  from {
    transform: scale(1.04) translate3d(0.42%, 0.18%, 0);
  }
  to {
    transform: scale(1.065) translate3d(-0.52%, -0.22%, 0);
  }
}

@keyframes snow-sky-loop {
  0%,
  100% {
    opacity: 0;
    transform: scale(1.042) translate3d(0.2%, 0, 0);
  }
  48%,
  58% {
    opacity: 0.34;
    transform: scale(1.07) translate3d(-0.38%, 0.14%, 0);
  }
}

@keyframes overcast-window-loop {
  0%,
  100% {
    opacity: 0;
    transform: scale(1.018) translate3d(-0.12%, 0, 0);
  }

  48%,
  58% {
    opacity: 0.25;
    transform: scale(1.036) translate3d(0.25%, -0.1%, 0);
  }
}

@keyframes snow-settle-shift {
  from {
    transform: translate3d(-0.8%, 0, 0) scaleX(1.02);
  }
  to {
    transform: translate3d(0.72%, -0.12rem, 0) scaleX(1.06);
  }
}

@keyframes storm-window-drift {
  from {
    transform: scale(1.06) translate3d(-0.8%, 0.18%, 0);
  }
  to {
    transform: scale(1.09) translate3d(0.7%, -0.24%, 0);
  }
}

@keyframes rain-scene-cycle {
  0%,
  100% {
    opacity: 0;
    transform: scale(1.045) translate3d(-0.3%, 0.08%, 0);
  }
  44%,
  58% {
    opacity: 0.9;
    transform: scale(1.073) translate3d(0.62%, -0.18%, 0);
  }
}

@keyframes snow-scene-cycle {
  0%,
  100% {
    opacity: 0;
    transform: scale(1.04) translate3d(0.32%, -0.1%, 0);
  }
  44%,
  58% {
    opacity: 0.88;
    transform: scale(1.067) translate3d(-0.48%, 0.2%, 0);
  }
}

@keyframes storm-scene-cycle {
  0%,
  100% {
    opacity: 0;
    transform: scale(1.06) translate3d(-0.5%, 0.16%, 0);
  }
  44%,
  58% {
    opacity: 0.9;
    transform: scale(1.09) translate3d(0.62%, -0.22%, 0);
  }
}

@keyframes orbit-travel {
  to {
    stroke-dashoffset: -238;
  }
}

@keyframes current-pulse {
  0%,
  100% {
    box-shadow: 0 0 0.7rem currentColor;
    transform: scale(1);
  }
  50% {
    box-shadow: 0 0 1.5rem currentColor;
    transform: scale(1.1);
  }
}

@keyframes lightning-flash {
  0%,
  100% {
    opacity: 0;
  }
  18% {
    opacity: var(--lightning-peak, 0.52);
  }
  27% {
    opacity: var(--lightning-rest, 0.08);
  }
  38% {
    opacity: var(--lightning-echo, 0.34);
  }
}

a:focus,
button:focus {
  outline: 3px solid var(--forecast-amber);
  outline-offset: 3px;
}

@media (max-width: 70rem) {
  /* The snow plate is composed with Bear on the right. Bias the camera toward
     that side so an iPad or a phone in landscape keeps the whole scene-native
     character in frame instead of cropping it at the glass edge. */
  .condition-snow.scene-owns-companion .environment-plate,
  .condition-snow.scene-owns-companion .environment-plate-alt {
    background-position: 100% center;
  }

  .observatory-header {
    padding-right: 2.5rem;
    padding-left: 2.5rem;
  }

  /* Landscape iPads have room for the weather, not a competing status
     sentence. Keep the green signal and the one useful action cleanly inside
     the glass edge. */
  .header-status > span:not(.freshness-dot) {
    display: none;
  }

  .header-status {
    padding: 0.2rem 0.25rem 0.2rem 0.5rem;
    border: 1px solid rgba(244, 222, 255, 0.26);
    border-radius: 2rem;
    background: rgba(10, 5, 24, 0.4);
  }

  .settings-link {
    min-height: 2.45rem;
    margin-left: 0;
    background: rgba(12, 7, 27, 0.74);
    color: var(--moon-cream);
  }

  .weather-reading {
    left: 2.5rem;
    max-width: 45%;
  }

  .station-drawer {
    top: 5rem;
    right: 2.5rem;
  }

  .temperature {
    font-size: 7.3rem;
  }

  .condition-stack {
    margin-left: 1.35rem;
  }

  .weather-details {
    width: 23rem;
  }

  .forecast-orbit {
    right: 2%;
    left: 2%;
  }
}

/* On a full-height landscape iPad the fourth forecast label previously crossed
   into Bear or GUGO's painted bay. Reserve that physical side of the window for
   the resident of the scene, rather than only shortening the decorative line. */
@media (min-width: 50.0625rem) and (max-width: 70rem) and (min-height: 34.0625rem) {
  .scene-owns-companion .forecast-orbit {
    right: 29%;
    left: 2.5%;
  }
}

/* GUGO occupies more of the storm plate than Bear does in the snow and rain
   plates. Desktop forecast labels stop before his physical bay too, so the
   weather interface never reads as floating across the resident. */
@media (min-width: 70.0625rem) {
  .condition-storm.scene-owns-companion .forecast-orbit {
    right: 29%;
    left: 4.5%;
  }
}

@media (max-width: 50rem) {
  .observatory {
    height: 100%;
    min-height: 57rem;
  }

  .environment-plate {
    background-position: 59% center;
  }

  /* Portrait crops keep the scene-resident companion inside the glass while
     the factual readout remains on the open left side of the shot. */
  .scene-owns-companion .environment-plate {
    background-position: 70% center;
  }

  .condition-snow.scene-owns-companion .environment-plate {
    background-position: 72% center;
  }

  .condition-storm.scene-owns-companion .environment-plate {
    background-position: 66% center;
  }

  .observatory-header {
    padding: 1.5rem 1.5rem 1rem;
  }

  .header-status > span:not(.freshness-dot) {
    display: none;
  }

  /* The weather plate gets deliberately dark at night. On narrow screens the
     one remaining control needs a quiet, reliable backplate instead of relying
     on whichever cloud happens to sit behind it. */
  .header-status {
    padding: 0.2rem 0.25rem 0.2rem 0.5rem;
    border: 1px solid rgba(244, 222, 255, 0.26);
    border-radius: 2rem;
    background: rgba(10, 5, 24, 0.4);
  }

  .settings-link {
    min-height: 2.45rem;
    margin-left: 0;
    background: rgba(12, 7, 27, 0.74);
    color: var(--moon-cream);
  }

  .weather-reading {
    top: 7.5rem;
    left: 1.5rem;
    width: calc(100% - 3rem);
    max-width: none;
  }

  .station-drawer {
    top: 5.75rem;
    right: 1.5rem;
    left: 1.5rem;
    width: auto;
    max-width: none;
    max-height: calc(100% - 7rem);
  }

  .location-line {
    margin-bottom: 0.65rem;
  }

  .temperature {
    font-size: 6.4rem;
  }

  .condition-stack {
    margin-left: 1rem;
  }

  .weather-details {
    width: 21rem;
    max-width: 100%;
    margin-top: 1rem;
  }

  .forecast-orbit {
    bottom: 3.5rem;
    height: 11rem;
  }

  .scene-owns-companion .forecast-orbit {
    right: 31%;
    left: 2%;
  }

  .forecast-stop:nth-child(1) {
    left: 12%;
  }

  .forecast-stop:nth-child(2) {
    left: 38%;
  }

  .forecast-stop:nth-child(3) {
    left: 63%;
  }

  .forecast-stop:nth-child(4) {
    left: 88%;
  }

  .scene-owns-companion .forecast-stop:nth-child(1) {
    left: 10%;
  }

  .scene-owns-companion .forecast-stop:nth-child(2) {
    left: 29%;
  }

  .scene-owns-companion .forecast-stop:nth-child(3) {
    left: 48%;
  }

  .scene-owns-companion .forecast-stop:nth-child(4) {
    left: 66%;
  }

  .forecast-condition {
    display: none;
  }

  .observatory-footer {
    right: 1.5rem;
    left: 1.5rem;
  }

  .collection-credit {
    display: none;
  }
}

@media (max-width: 30rem) {
  .observatory {
    min-height: 52rem;
  }

  .observatory-header {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 0.5rem;
    padding: 1.3rem 0.85rem 1rem 1.5rem;
  }

  .wordmark {
    font-size: 1.05rem;
  }

  .header-status {
    flex: 0 0 auto;
    gap: 0.4rem;
    margin-left: 0;
  }

  .settings-link {
    min-width: 3.75rem;
    margin-left: 0;
    padding: 0 0.55rem;
    font-size: 0.75rem;
  }

  .weather-reading {
    top: 6rem;
  }

  .location-name {
    font-size: 0.76rem;
    letter-spacing: 0.22em;
  }

  .station-drawer {
    top: 4.75rem;
    right: 1rem;
    left: 1rem;
    padding: 1rem;
  }

  .temperature {
    font-size: 5.6rem;
  }

  .condition-stack {
    margin-left: 0.65rem;
  }

  .weather-glyph {
    height: 2.6rem;
  }

  .condition-label {
    font-size: 0.88rem;
  }

  .condition-storm.scene-owns-companion .weather-quip {
    max-width: 13rem;
  }

  .scene-preview {
    gap: 0.25rem;
    font-size: 0.57rem;
  }

  .scene-preview span {
    white-space: normal;
  }

  .weather-details div {
    padding-right: 0.75rem;
  }

  .weather-details div:nth-child(even) {
    padding-left: 0.9rem;
  }

  .weather-details dd {
    font-size: 0.9rem;
  }

  .forecast-stop {
    width: 4.5rem;
  }

  .scene-owns-companion .forecast-stop {
    width: 3.15rem;
  }

  .forecast-time {
    font-size: 0.72rem;
  }

  .forecast-temperature {
    font-size: 1rem;
  }

  .observatory-footer {
    font-size: 0.6rem;
  }
}

@media (max-height: 34rem) and (min-width: 42rem) {
  .observatory {
    height: 100%;
    min-height: 0;
  }

  .observatory-header {
    padding: 0.75rem 1.15rem 0;
  }

  .header-status > span:not(.freshness-dot) {
    display: none;
  }

  .weather-reading {
    top: 4.25rem;
    left: 1.25rem;
    width: min(19.75rem, 40vw);
  }

  .station-drawer {
    top: 4rem;
    right: 1rem;
    left: auto;
    width: 20rem;
    max-width: calc(100% - 2rem);
    max-height: calc(100% - 4.75rem);
    padding: 1rem;
  }

  .location-line {
    margin-bottom: 0.55rem;
  }

  .temperature {
    font-size: clamp(4.7rem, 8.7vw, 5.45rem);
  }

  .condition-stack {
    min-width: 6.5rem;
    margin-left: 0.75rem;
  }

  .weather-glyph {
    display: none;
  }

  .weather-details {
    width: min(19.5rem, 40vw);
    margin-top: 0.55rem;
    padding-top: 0.55rem;
  }

  .weather-details div {
    min-height: 2.25rem;
  }

  /* The short landscape viewport has no quiet air above the forecast rail.
     Keep the resident's quip for taller layouts instead of letting it
     collide with the live forecast labels. */
  .weather-quip {
    display: none;
  }

  .forecast-orbit {
    right: 1.15rem;
    bottom: 0.25rem;
    left: 44%;
    height: 7.1rem;
  }

  .scene-owns-companion .forecast-orbit {
    right: 29%;
    left: 1.15rem;
  }

  .forecast-path {
    height: 4.8rem;
  }

  .forecast-stop {
    width: 4.15rem;
  }

  .forecast-stop:nth-child(1) {
    bottom: 0.55rem;
  }

  .forecast-stop:nth-child(2) {
    bottom: 0;
  }

  .forecast-stop:nth-child(3) {
    bottom: 0.3rem;
  }

  .forecast-stop:nth-child(4) {
    bottom: 0.95rem;
  }

  .forecast-node {
    width: 0.85rem;
    height: 0.85rem;
    margin-bottom: 0.2rem;
  }

  .forecast-time {
    font-size: 0.68rem;
  }

  .forecast-temperature {
    font-size: 0.95rem;
  }

  .forecast-symbol,
  .forecast-condition {
    display: none;
  }

  .observatory-footer {
    display: none;
  }
}

@media (min-width: 70.0625rem) {
  .forecast-path {
    width: 78%;
  }

  .forecast-stop:nth-child(1) {
    left: 10%;
  }

  .forecast-stop:nth-child(2) {
    left: 31%;
  }

  .forecast-stop:nth-child(3) {
    left: 51%;
  }

  .forecast-stop:nth-child(4) {
    left: 68%;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
