/* Nintendo / Wii-style playful motion */

:root {
  --nintendo-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --nintendo-soft: cubic-bezier(0.32, 0.72, 0, 1);
  --nintendo-press: cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

@keyframes nintendoPop {
  0% {
    opacity: 0;
    transform: scale(0.82) translateY(10px);
  }
  55% {
    opacity: 1;
    transform: scale(1.06) translateY(-3px);
  }
  100% {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

@keyframes nintendoBounce {
  0%, 100% { transform: translateY(0) scale(1); }
  35% { transform: translateY(-6px) scale(1.04); }
  65% { transform: translateY(2px) scale(0.98); }
}

@keyframes nintendoWiggle {
  0%, 100% { transform: rotate(0deg); }
  20% { transform: rotate(-4deg); }
  40% { transform: rotate(4deg); }
  60% { transform: rotate(-2deg); }
  80% { transform: rotate(2deg); }
}

@keyframes iconBob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-8px); }
}

@keyframes sunRock {
  0%, 100% { transform: rotate(-4deg); }
  50% { transform: rotate(4deg); }
}

@keyframes loadingBounce {
  0%, 100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.72;
    transform: scale(0.97);
  }
}

@keyframes hintBounce {
  0%, 100% { transform: translateY(0); opacity: 0.75; }
  50% { transform: translateY(-4px); opacity: 1; }
}

@keyframes tempPop {
  0% { transform: scale(0.88); }
  45% { transform: scale(1.05); }
  100% { transform: scale(1); }
}

@keyframes citySlideIn {
  0% {
    opacity: 0.6;
    transform: translateX(12px) scale(0.96);
  }
  60% {
    opacity: 1;
    transform: translateX(-3px) scale(1.03);
  }
  100% {
    opacity: 1;
    transform: translateX(0) scale(1);
  }
}

@keyframes detailStagger {
  0% {
    opacity: 0;
    transform: translateY(12px) scale(0.94);
  }
  100% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* Temperature moods on the big number (classes set from script.js) */
@keyframes tempFreezeIn {
  from { color: #f0c000; }
  to { color: #00e5ff; }
}

@keyframes tempShiver {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  20% { transform: translate(-1.2px, 0.6px) rotate(-0.35deg); }
  40% { transform: translate(1.1px, -0.5px) rotate(0.3deg); }
  60% { transform: translate(-0.9px, -0.6px) rotate(-0.25deg); }
  80% { transform: translate(1.2px, 0.5px) rotate(0.35deg); }
}

@keyframes tempHeatShake {
  0%, 100% { transform: translate(0, 0) rotate(0deg); }
  15% { transform: translate(calc(var(--heat-amp, 0.5px) * -0.8), calc(var(--heat-amp, 0.5px) * 0.5)) rotate(-0.5deg); }
  30% { transform: translate(var(--heat-amp, 0.5px), calc(var(--heat-amp, 0.5px) * -0.7)) rotate(0.6deg); }
  45% { transform: translate(calc(var(--heat-amp, 0.5px) * -1), calc(var(--heat-amp, 0.5px) * -0.4)) rotate(-0.4deg); }
  60% { transform: translate(calc(var(--heat-amp, 0.5px) * 0.9), calc(var(--heat-amp, 0.5px) * 0.6)) rotate(0.5deg); }
  80% { transform: translate(calc(var(--heat-amp, 0.5px) * -0.6), calc(var(--heat-amp, 0.5px) * 0.3)) rotate(-0.3deg); }
}

/* below freezing: starts yellow, chills to the low-temp cyan, then shivers */
.temp--freezing {
  color: #00e5ff;
  animation:
    tempFreezeIn 1.6s ease-in-out both,
    tempShiver 0.3s linear infinite 1.6s;
}

/* 95°F and up: tiny heat shake — JS scales --heat-amp/--heat-speed with the temp */
.temp--hot {
  animation: tempHeatShake var(--heat-speed, 0.4s) linear infinite;
}

/* while the squash-land pop plays, run it alongside the mood animation
   (a lone .anim-temp-pop would otherwise clobber the mood's animation) */
.anim-temp-pop.temp--freezing {
  animation:
    tempPop 0.6s var(--nintendo-spring),
    tempFreezeIn 1.6s ease-in-out both,
    tempShiver 0.3s linear infinite 1.6s;
}

.anim-temp-pop.temp--hot {
  animation:
    tempHeatShake var(--heat-speed, 0.4s) linear infinite,
    tempPop 0.6s var(--nintendo-spring);
}

/* One-shot utility classes (JS-triggered) */
.anim-pop {
  animation: nintendoPop 0.55s var(--nintendo-spring) both;
}

.anim-bounce-once {
  animation: nintendoBounce 0.5s var(--nintendo-spring);
}

.anim-wiggle {
  animation: nintendoWiggle 0.45s var(--nintendo-soft);
}

.anim-temp-pop {
  animation: tempPop 0.6s var(--nintendo-spring);
}

.anim-city-pop {
  animation: citySlideIn 0.55s var(--nintendo-spring);
}

.anim-tab-bounce {
  animation: nintendoBounce 0.45s var(--nintendo-spring);
}

/* Header tabs — Wii channel bounce */
.header-tab {
  transition:
    background 0.25s var(--nintendo-soft),
    color 0.25s var(--nintendo-soft),
    transform 0.35s var(--nintendo-spring);
}

.header-tab:hover:not(.active) {
  transform: translateY(-1px) scale(1.02);
}

.header-tab:active {
  transform: translateY(1px) scale(0.97);
  filter: brightness(0.92);
}

.header-tab.active {
  transform: scale(1.01);
}

/* City pill */
.header-city {
  transition: transform 0.4s var(--nintendo-spring), opacity 0.3s ease;
}

/* Search button — Wii channel lift + cyan rim bloom + squash press */
.search-row button {
  transition:
    filter 0.2s var(--nintendo-soft),
    transform 0.35s var(--nintendo-spring),
    box-shadow 0.25s var(--nintendo-soft),
    border-color 0.2s var(--nintendo-soft);
}

.search-row button:hover {
  filter: brightness(1.04);
  transform: translateY(-2px) scale(1.03);
  border-color: #4fd0fb;            /* calm rim shimmer */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 1),
    inset 0 -2px 4px rgba(54, 195, 242, 0.35),
    0 0 0 1.5px rgba(54, 195, 242, 0.60),   /* the one permitted glow: a single brighter ring */
    0 7px 18px rgba(0, 0, 0, 0.40);
}

/* squash on press only when the JS glow class is not yet active (avoids double squash on click) */
.search-row button:active:not(.search-press-feedback) {
  filter: brightness(0.96);
  animation: wiiSquashPress 0.4s var(--nintendo-spring);
}

/* Press glow peaks then eases into the searching halo (or resting shadow) */
@keyframes searchPressGlow {
  0%, 28% {
    box-shadow:
      inset 0 2px 5px rgba(20, 50, 110, 0.22),
      0 0 0 1.5px rgba(52, 190, 237, 0.70),
      0 1px 4px rgba(0, 0, 0, 0.30),
      0 0 8px 2px rgba(52, 190, 237, 0.75),
      0 0 22px 6px rgba(52, 190, 237, 0.55);
  }
  100% {
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.95),
      inset 0 -2px 3px rgba(54, 195, 242, 0.25),
      0 0 0 1.5px rgba(52, 190, 237, 0.55),
      0 2px 8px rgba(0, 0, 0, 0.28),
      0 0 10px 2px rgba(52, 190, 237, 0.42),
      0 0 18px 4px rgba(52, 190, 237, 0.26);
  }
}

.search-row button.search-press-feedback {
  animation:
    wiiSquashPress 0.4s var(--nintendo-spring),
    searchPressGlow 0.75s var(--nintendo-soft) forwards;
  filter: brightness(0.96);
}

.search-row button.search-press-feedback::before {
  transform: scaleY(0.72);
  opacity: 0.80;
}

/* Softer cyan halo while a search is in flight (matches searchPressGlow 100%) */
.search-row button.is-searching {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    inset 0 -2px 3px rgba(54, 195, 242, 0.25),
    0 0 0 1.5px rgba(52, 190, 237, 0.55),
    0 2px 8px rgba(0, 0, 0, 0.28),
    0 0 10px 2px rgba(52, 190, 237, 0.42),
    0 0 18px 4px rgba(52, 190, 237, 0.26);
  transition: box-shadow 0.35s var(--nintendo-soft);
}

.search-row button.is-searching:not(.search-press-feedback) {
  animation: none;
}

@keyframes wiiSquashPress {
  0%   { transform: translateY(0) scale(1, 1); }
  35%  { transform: translateY(3px) scale(1.06, 0.90); }
  70%  { transform: translateY(-1px) scale(0.97, 1.04); }
  100% { transform: translateY(0) scale(1, 1); }
}

/* gloss cap catches the light on press — scales down from its top edge */
.search-row button::before,
.history span::before {
  transform-origin: top center;
  transition:
    transform 0.18s var(--nintendo-press),
    opacity 0.18s var(--nintendo-press);
}

.search-row button:active::before,
.history span:active::before {
  transform: scaleY(0.72);
  opacity: 0.80;
}

.search-row input {
  transition:
    border 0.25s var(--nintendo-soft),
    box-shadow 0.35s var(--nintendo-spring),
    transform 0.35s var(--nintendo-spring);
}

.search-row input:focus {
  transform: scale(1.01);
}

/* History chips — same lift + rim bloom + squash press as the button */
.history span {
  transition:
    border-color 0.2s var(--nintendo-soft),
    box-shadow 0.3s var(--nintendo-soft),
    transform 0.35s var(--nintendo-spring);
}

.history span:hover {
  transform: translateY(-3px) scale(1.05);
  border-color: #4fd0fb;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 1),
    0 0 0 1.5px rgba(54, 195, 242, 0.55),
    0 5px 13px rgba(0, 0, 0, 0.34);
}

.history span:active {
  animation: wiiSquashPress 0.35s var(--nintendo-spring);
  box-shadow:
    inset 0 2px 4px rgba(20, 50, 110, 0.20),
    0 0 0 1px rgba(54, 195, 242, 0.45),
    0 1px 3px rgba(0, 0, 0, 0.26);
}

/* staggered pop-in when chips (re)render — like Wii channels populating.
   Reuses the existing nintendoPop keyframe; JS adds .history--enter on the container. */
.history--enter span {
  animation: nintendoPop 0.5s var(--nintendo-spring) backwards;
}

.history--enter span:nth-child(1) { animation-delay: 0.04s; }
.history--enter span:nth-child(2) { animation-delay: 0.10s; }
.history--enter span:nth-child(3) { animation-delay: 0.16s; }
.history--enter span:nth-child(4) { animation-delay: 0.22s; }
.history--enter span:nth-child(5) { animation-delay: 0.28s; }
.history--enter span:nth-child(6) { animation-delay: 0.34s; }

/* Loading pill — gentle bounce */
#loading:not(.hidden) {
  animation: loadingBounce 1.2s var(--nintendo-soft) infinite;
}

/* Weather card entrance (JS adds .anim-card-reveal on each search) */
.weather-card.anim-card-reveal {
  animation: nintendoPop 0.65s var(--nintendo-spring) both;
}

/* Floating weather icon */
.weather-img {
  animation: iconBob 3.2s var(--nintendo-soft) infinite;
}

/* Detail stats stagger on card reveal */
.weather-card.anim-card-reveal .detail {
  animation: detailStagger 0.45s var(--nintendo-spring) backwards;
}

.weather-card .detail:nth-child(1) { animation-delay: 0.05s; }
.weather-card .detail:nth-child(2) { animation-delay: 0.1s; }
.weather-card .detail:nth-child(3) { animation-delay: 0.15s; }
.weather-card .detail:nth-child(4) { animation-delay: 0.2s; }
.weather-card .detail:nth-child(5) { animation-delay: 0.25s; }
.weather-card .detail:nth-child(6) { animation-delay: 0.3s; }

/* Sun icons — playful sway */
.sun-icon {
  animation: sunRock 4s ease-in-out infinite;
  transform-origin: center bottom;
}

.sun-item:last-child .sun-icon {
  animation-delay: 1.5s;
}

/* Timestamp pill hover */
.timestamp {
  transition: transform 0.35s var(--nintendo-spring);
}

.timestamp:hover {
  transform: scale(1.04);
}

/* Forecast days */
.forecast-day {
  transition:
    transform 0.35s var(--nintendo-spring),
    box-shadow 0.35s var(--nintendo-soft);
}

.forecast-day:hover {
  transform: translateY(-8px) scale(1.02);
}

.forecast-day:active {
  transform: translateY(-2px) scale(0.97);
}

/* Day-card pop-in/pop-out is driven from script.js with the Web Animations
   API so the stagger can be sequenced against the window swipe. */

.forecast-icon {
  transition: transform 0.35s var(--nintendo-spring);
}

.forecast-day:hover .forecast-icon {
  animation: nintendoWiggle 0.5s var(--nintendo-soft);
}

.rain-icon {
  transition: transform 0.35s var(--nintendo-spring);
}

.forecast-day:hover .rain-icon {
  transform: scale(1.15) rotate(-6deg);
}

/* Forecast hint */
.forecast-hint:not(.hidden) {
  animation: hintBounce 2s var(--nintendo-soft) infinite;
}

/* Details panel pop (JS adds .anim-pop to card) */
.forecast-details .details-card.anim-pop {
  animation: nintendoPop 0.5s var(--nintendo-spring) both;
}

/* Error wiggle */
.error.anim-wiggle {
  animation: nintendoWiggle 0.5s var(--nintendo-soft);
}

.dock-btn {
  transition:
    transform 0.35s var(--nintendo-spring),
    box-shadow 0.3s var(--nintendo-soft),
    border-color 0.3s ease;
}

.dock-btn:active {
  animation: wiiSquashPress 0.4s var(--nintendo-spring);
}

/* CRT scan-line drift on the silver dock tray — gentler than alert chrome. */
.dock-bar::before {
  animation: dockScanDrift 14s linear infinite;
}

.dock-bar::after {
  animation: dockScanStatic 8s steps(8) infinite;
}

@keyframes dockScanDrift {
  0% { transform: translateY(0); }
  100% { transform: translateY(3px); }
}

@keyframes dockScanStatic {
  0%, 100% { opacity: 0.24; }
  50% { opacity: 0.32; }
}

/* maroon "As of" band pops in when the forecast tab activates */
.mobile-dock.dock--forecast .dock-band {
  animation: nintendoPop 0.45s var(--nintendo-spring) both;
}

/* inline forecast day detail pops open (accordion) */
.forecast-day-detail:not([hidden]) {
  animation: nintendoPop 0.45s var(--nintendo-spring) both;
}

/* accordion row highlight eases in/out */
.forecast-day {
  transition:
    transform 0.35s var(--nintendo-spring),
    box-shadow 0.35s var(--nintendo-soft),
    background-color 0.25s ease;
}

/* =========================================================================
   SEVERE WEATHER ALERTS — motion
   ========================================================================= */

/* Overlay menu pops in like a Wii channel; scrim fades */
.alert-overlay:not(.hidden):not(.alert-closing) {
  animation: alertScrimIn 0.45s var(--nintendo-soft) both;
}

/* letterbox bars slide in from the edges like console chrome */
.alert-overlay:not(.hidden):not(.alert-closing) .alert-top-bar {
  animation: alertBarDown 0.7s var(--nintendo-spring) both;
}

.alert-overlay:not(.hidden):not(.alert-closing) .alert-bottom-bar {
  animation: alertBarUp 0.7s var(--nintendo-spring) both;
}

/* closing: reverse the entrance — scrim fades, bars retract to the edges */
.alert-overlay.alert-closing {
  animation: alertScrimOut 0.55s var(--nintendo-soft) both;
}

.alert-overlay.alert-closing .alert-top-bar {
  animation: alertBarUpOut 0.55s var(--nintendo-soft) both;
}

.alert-overlay.alert-closing .alert-bottom-bar {
  animation: alertBarDownOut 0.55s var(--nintendo-soft) both;
}

@keyframes alertScrimIn {
  0% { opacity: 0; }
  100% { opacity: 1; }
}

@keyframes alertScrimOut {
  0% { opacity: 1; }
  100% { opacity: 0; }
}

@keyframes alertBarDown {
  0% { opacity: 0; transform: translateY(-100%); }
  100% { opacity: 1; transform: translateY(0); }
}

@keyframes alertBarUp {
  0% { opacity: 0; transform: translateY(100%); }
  100% { opacity: 1; transform: translateY(0); }
}

@keyframes alertBarUpOut {
  0% { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(-100%); }
}

@keyframes alertBarDownOut {
  0% { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(100%); }
}

/* Alert channels — shared pill press/hover + staggered entrance */
.alert-channel,
.alert-close,
.alert-back {
  transition:
    transform 0.35s var(--nintendo-spring),
    box-shadow 0.25s var(--nintendo-soft),
    border-color 0.2s var(--nintendo-soft);
}

.alert-channel:hover,
.alert-close:hover,
.alert-back:hover {
  transform: translateY(-2px) scale(1.02);
}

.alert-channel:active,
.alert-close:active,
.alert-back:active {
  animation: wiiSquashPress 0.4s var(--nintendo-spring);
}

.alert-channel::before,
.alert-close::before,
.alert-back::before {
  transform-origin: top center;
  transition:
    transform 0.18s var(--nintendo-press),
    opacity 0.18s var(--nintendo-press);
}

.alert-channel:active::before,
.alert-close:active::before,
.alert-back:active::before {
  transform: scaleY(0.72);
  opacity: 0.8;
}

.alert-channels .alert-channel {
  animation: nintendoPop 0.5s var(--nintendo-spring) backwards;
}

.alert-channels .alert-channel:nth-child(1) { animation-delay: 0.06s; }
.alert-channels .alert-channel:nth-child(2) { animation-delay: 0.12s; }
.alert-channels .alert-channel:nth-child(3) { animation-delay: 0.18s; }
.alert-channels .alert-channel:nth-child(4) { animation-delay: 0.24s; }
.alert-channels .alert-channel:nth-child(5) { animation-delay: 0.30s; }

/* Warning triangle — slow attention pulse (status indicator, not a control) */
.alert-tri {
  animation: alertTriPulse 2s var(--nintendo-soft) infinite;
}

.alert-badge {
  transition: transform 0.35s var(--nintendo-spring), box-shadow 0.25s var(--nintendo-soft);
}

.alert-badge:hover {
  transform: translateY(-2px) scale(1.03);
}

.alert-badge:active {
  transform: translateY(1px) scale(0.96);
}

@keyframes alertTriPulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}

/* CRT scan-line drift on letterbox chrome (decorative; transform-only per DESIGN.md) */
.alert-overlay:not(.hidden) .alert-top-bar::before,
.alert-overlay:not(.hidden) .alert-bottom-bar::before {
  animation: alertScanDrift 10s linear infinite;
}

@keyframes alertScanDrift {
  0% { transform: translateY(0); }
  100% { transform: translateY(4px); }
}

/* Static noise flicker on the highlight scan layer */
.alert-overlay:not(.hidden) .alert-top-bar::after,
.alert-overlay:not(.hidden) .alert-bottom-bar::after {
  animation: alertScanStatic 5s steps(10) infinite;
}

@keyframes alertScanStatic {
  0%, 100% { opacity: 0.45; }
  10% { opacity: 0.62; }
  22% { opacity: 0.38; }
  35% { opacity: 0.55; }
  48% { opacity: 0.42; }
  61% { opacity: 0.58; }
  74% { opacity: 0.36; }
  87% { opacity: 0.52; }
}

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

  .weather-img,
  .sun-icon,
  #loading,
  .forecast-hint {
    animation: none !important;
  }

  /* window swipe becomes an instant swap */
  .view-track {
    transition: none !important;
  }

  /* no shiver/shake; freezing keeps its static cyan color */
  .temp--freezing,
  .temp--hot {
    animation: none !important;
  }

  .header-tab:hover:not(.active),
  .search-row button:hover,
  .history span:hover,
  .forecast-day:hover {
    transform: none;
  }

  /* kill the squash press; the static press glow stays */
  .search-row button:active,
  .history span:active,
  .history--enter span {
    animation: none !important;
  }

  /* mobile dock + accordion: static states render identically */
  .dock-btn:active,
  .dock-bar::before,
  .dock-bar::after,
  .mobile-dock.dock--forecast .dock-band,
  .forecast-day-detail:not([hidden]) {
    animation: none !important;
  }

  .dock-bar::before,
  .dock-bar::after {
    transform: none !important;
    opacity: 0.28 !important;
  }

  .search-row button.search-press-feedback,
  .search-row button.is-searching {
    animation: none !important;
    filter: none !important;
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.95),
      inset 0 -2px 3px rgba(54, 195, 242, 0.25),
      0 0 0 1px rgba(54, 195, 242, 0.35),
      0 3px 9px rgba(0, 0, 0, 0.32) !important;
  }

  .search-row button.search-press-feedback::before,
  .history span::before {
    transition: none !important;
    transform: none !important;
    opacity: 1 !important;
  }

  /* alerts: kill pulse/slide/squash, keep the static chrome + pills */
  .alert-overlay:not(.hidden),
  .alert-overlay:not(.hidden) .alert-top-bar,
  .alert-overlay:not(.hidden) .alert-bottom-bar,
  .alert-overlay.alert-closing,
  .alert-overlay.alert-closing .alert-top-bar,
  .alert-overlay.alert-closing .alert-bottom-bar,
  .alert-channels .alert-channel,
  .alert-tri,
  .alert-channel:active,
  .alert-close:active,
  .alert-back:active {
    animation: none !important;
  }

  .alert-overlay:not(.hidden) .alert-top-bar::before,
  .alert-overlay:not(.hidden) .alert-bottom-bar::before {
    animation: none !important;
    transform: none !important;
  }

  .alert-overlay:not(.hidden) .alert-top-bar::after,
  .alert-overlay:not(.hidden) .alert-bottom-bar::after {
    animation: none !important;
    opacity: 0.55 !important;
  }

  .alert-channel:hover,
  .alert-close:hover,
  .alert-back:hover,
  .alert-badge:hover {
    transform: none;
  }

  .alert-channel::before,
  .alert-close::before,
  .alert-back::before {
    transition: none !important;
    transform: none !important;
    opacity: 1 !important;
  }
}
