/*
  Underspire kit: motion.
  Four levels. Feedback (a key, a field) is always on. Arrival happens once when a page first
  paints. Ambient light is slow and belongs to pages that are doors, never to text a person reads.
  Ceremony is the rare thing: the gate. The effects switch in the footer sets html[data-fx] to
  calm, standard or grand, and the operating system's reduced-motion setting always forces calm.
  Nothing here carries meaning: every state it shows is also a word or a shape.
*/

:root {
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --dur-arrive: 420ms;
}

@keyframes arrive {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}
@keyframes glint {
  from { transform: translateX(-140%) skewX(-18deg); }
  to { transform: translateX(340%) skewX(-18deg); }
}
@keyframes torch {
  0%, 100% { opacity: 1; }
  34% { opacity: .84; }
  58% { opacity: .96; }
  81% { opacity: .88; }
}
@keyframes drift {
  from { transform: scale(1.06) translate3d(-1.4%, 0, 0); }
  to { transform: scale(1.06) translate3d(1.4%, -1%, 0); }
}

/* The order a page's elements arrive in: .i1 first, .i8 last. */
.i1 { --i: 1; } .i2 { --i: 2; } .i3 { --i: 3; } .i4 { --i: 4; }
.i5 { --i: 5; } .i6 { --i: 6; } .i7 { --i: 7; } .i8 { --i: 8; }

/* Arrival: an element with .arrive settles in once, in the order of its --i. */
html:not([data-fx="calm"]) .arrive {
  animation: arrive var(--dur-arrive) var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * 70ms);
}

/* The brass sheen that crosses a primary key when it is pointed at or focused. */
html:not([data-fx="calm"]) .btn-primary { position: relative; overflow: hidden; }
html:not([data-fx="calm"]) .btn-primary::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 34%;
  background: linear-gradient(100deg, transparent, #ffffff59, transparent);
  transform: translateX(-140%) skewX(-18deg);
  pointer-events: none;
}
html:not([data-fx="calm"]) .btn-primary:hover::after,
html:not([data-fx="calm"]) .btn-primary:focus-visible::after { animation: glint 720ms var(--ease-out); }

/* Grand: lit lamps breathe, and the painting behind a hero drifts. Both stay under a hidden tab
   and an off-screen element because the page pauses them with .is-paused. */
html[data-fx="grand"] .lamp-on::after { animation: torch 5.4s ease-in-out infinite; }
html[data-fx="grand"] .hero-art { animation: drift 70s ease-in-out infinite alternate; }
html[data-fx="grand"] .is-paused, html[data-fx="grand"] .is-paused * { animation-play-state: paused !important; }

.embers { position: absolute; inset: 0; z-index: -1; width: 100%; height: 100%; pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  .arrive { animation: none !important; opacity: 1 !important; transform: none !important; }
  .hero-art { animation: none !important; }
}
