/* Motion and loading for the v2 pages (Atlas Sheet).

   Two jobs, both done with opacity and a few pixels of transform only, so nothing is composited that the flat-ink
   system would not already composite, and nothing here touches layout:
     1. the loading screen: the atlas class ramp (the six vulnerability classes, taken from the AGRA mark) on the
        same paper as the page, so the next page arrives out of it without a seam;
     2. soft arrival: panels dim a little while Dash updates them, then settle back in, rather than popping.
   assets/atlas_motion.js adds the state classes. With no script the page is simply static and fully visible.
   Scoped to #atlas-loader and .atlas-v2, so the older pages are untouched. */

:root {
  /* Gentle ease-out (cubic). The earlier expo curve was nearly finished within 100 ms, which read as a snap. */
  --atlas-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --atlas-ease-io: cubic-bezier(0.45, 0, 0.55, 1);
  --atlas-paper: #F7F5EE;
  --atlas-ink: #14201A;
  --atlas-ink-3: #5F6B64;
  --atlas-hair: #B7BDAF;
}

/* ---------- the loading screen ---------- */
#atlas-loader { display: none; }
html.atlas-loading #atlas-loader {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--atlas-paper);
  opacity: 1;
  visibility: visible;
  /* If the script never runs, the screen still lets go after 30 s. */
  animation: atlas-failsafe 0s linear 30s forwards;
}
html.atlas-loading ._dash-loading { display: none; }   /* Dash's own plain "Loading..." text */
html.atlas-loading { background: var(--atlas-paper); }

/* The header band is drawn in the same place and height as the real one, so when the screen fades the page's header
   is already where this one stood. */
#atlas-loader .al-band {
  height: 85px;
  padding: 10px 28px 0 52px;
  border-bottom: 1px solid var(--atlas-hair);
  box-sizing: border-box;
}
#atlas-loader .al-band img { height: 44px; width: auto; display: block; }

#atlas-loader .al-center {
  position: absolute;
  left: 0; right: 0;
  top: calc(50% - 26px);
  display: grid;
  justify-items: center;
  gap: 18px;
}
#atlas-loader .al-ramp { display: flex; align-items: flex-end; gap: 6px; height: 40px; }
#atlas-loader .al-ramp i {
  display: block;
  width: 20px;
  height: 40px;
  border: 1px solid rgba(20, 32, 26, 0.38);
  box-sizing: border-box;
  transform-origin: 50% 100%;
  transform: scaleY(0.4);
  opacity: 0.6;
  /* one continuous swell per bar, a steady offset between neighbours, so the six read as a single travelling wave */
  animation: atlas-rise 1.8s var(--atlas-ease-io) infinite;
}
/* the six classes, pale lime to burnt clay. Negative delays so the wave is already running on the first frame. */
#atlas-loader .al-ramp i:nth-child(1) { background: #D9E7B4; animation-delay: -1800ms; }
#atlas-loader .al-ramp i:nth-child(2) { background: #AECB6B; animation-delay: -1650ms; }
#atlas-loader .al-ramp i:nth-child(3) { background: #6E9A22; animation-delay: -1500ms; }
#atlas-loader .al-ramp i:nth-child(4) { background: #EFCB4A; animation-delay: -1350ms; }
#atlas-loader .al-ramp i:nth-child(5) { background: #C9761F; animation-delay: -1200ms; }
#atlas-loader .al-ramp i:nth-child(6) { background: #9E3A26; animation-delay: -1050ms; }
#atlas-loader .al-label {
  margin: 0;
  font: 600 12px/1 "Poppins", system-ui, -apple-system, "Segoe UI", sans-serif;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--atlas-ink-3);
}

/* The bars and label go quickly while the paper behind them fades slowly, so the label never ghosts over the page. */
#atlas-loader .al-center { transition: opacity 180ms ease-out; }
#atlas-loader.is-done .al-center { opacity: 0; }
/* Once the screen has been let go, the bars stop, so nothing keeps animating behind the page. */
#atlas-loader.is-done .al-ramp i { animation-play-state: paused; }
@keyframes atlas-rise {
  0%, 100% { transform: scaleY(0.4); opacity: 0.6; }
  50%      { transform: scaleY(1);   opacity: 1; }
}
@keyframes atlas-failsafe { to { opacity: 0; visibility: hidden; } }

/* The first visit: the screen fades out once the page has drawn. */
html.atlas-loading #atlas-loader { transition: opacity 420ms var(--atlas-ease-io), visibility 0s linear 0s; }
html.atlas-loading #atlas-loader.is-done { opacity: 0; visibility: hidden; pointer-events: none; transition: opacity 420ms var(--atlas-ease-io), visibility 0s linear 420ms; }

/* ---------- soft arrival ---------- */
/* Nothing is dimmed or delayed while Dash updates: the old screen stays exactly as it was until the new one is ready,
   and the morph below carries one into the other. Only the cursor says that something is happening. */
body:has(.atlas-v2 [data-dash-is-loading="true"]), html:active-view-transition { cursor: progress; }

/* Settling in after an update: from the dimmed state, a few pixels up. */
/* The fallback for browsers without the morph: whatever changed fades up into place. */
@keyframes atlas-settle {
  from { opacity: 0.55; transform: translateY(8px); }
  to   { opacity: 1;                      transform: none; }
}
/* A page's first arrival: from nothing, staggered across the sheet by --atlas-delay, under the fading loader. */
@keyframes atlas-arrive {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
@keyframes atlas-fade { from { opacity: 0; } to { opacity: 1; } }

.atlas-v2 .atlas-settle { animation: atlas-settle 700ms var(--atlas-ease) both; }
.atlas-v2 .atlas-arrive { animation: atlas-arrive 800ms var(--atlas-ease) both; animation-delay: var(--atlas-delay, 0ms); }

/* The advisory list arrives as a list: the first few rows follow one another, capped so it never feels slow. */
.atlas-v2 .adapt-items > .adapt-item:nth-child(-n+8) { animation: atlas-arrive 700ms var(--atlas-ease) both; animation-delay: 120ms; }
.atlas-v2 .adapt-items > .adapt-item:nth-child(2) { animation-delay: 180ms; }
.atlas-v2 .adapt-items > .adapt-item:nth-child(3) { animation-delay: 240ms; }
.atlas-v2 .adapt-items > .adapt-item:nth-child(4) { animation-delay: 300ms; }
.atlas-v2 .adapt-items > .adapt-item:nth-child(5) { animation-delay: 360ms; }
.atlas-v2 .adapt-items > .adapt-item:nth-child(6) { animation-delay: 420ms; }
.atlas-v2 .adapt-items > .adapt-item:nth-child(7) { animation-delay: 480ms; }
.atlas-v2 .adapt-items > .adapt-item:nth-child(8) { animation-delay: 540ms; }

/* Reduced motion: no travel and no pulsing. Dimming and a short fade stay, because they still say "updating" and "done". */
@media (prefers-reduced-motion: reduce) {
  #atlas-loader .al-ramp i { animation: none; transform: none; opacity: 1; }
  html.atlas-loading #atlas-loader,
  html.atlas-loading #atlas-loader.is-done,
    .atlas-v2 .atlas-settle,
  .atlas-v2 .atlas-arrive,
  .atlas-v2 .adapt-items > .adapt-item:nth-child(-n+8) { animation: atlas-fade 180ms linear both; animation-delay: 0ms; }
}

/* ---------- morph (View Transitions) ----------
   The old screen is kept, Dash updates underneath, and the browser animates old into new. Regions named by the script
   glide to their new size and position; the rest cross-dissolves. One slow, even ease so it reads as a single movement. */
::view-transition-group(*) {
  animation-duration: 650ms;
  animation-timing-function: cubic-bezier(0.45, 0, 0.2, 1);
}
::view-transition-old(*),
::view-transition-new(*) {
  animation-duration: 650ms;
  animation-timing-function: cubic-bezier(0.45, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation-duration: 1ms; }
}
